La sortie de la version stable 3.0 du noyau Linux vient d’être annoncée par Linus Torvalds. Le nouveau noyau est, comme d’habitude, téléchargeable sur les serveurs du site kernel.org.

Ce changement de numérotation du noyau est l’occasion de tirer un coup de chapeau aux 176 extralucides du sondage LinuxFr de janvier 2010 qui avaient deviné que ce noyau 3.0 sortirait cette année. Bravo à eux !

Le détail des évolutions et des nouveautés se trouve dans la seconde partie de la dépêche.

PS : Merci à Michel Barret pour avoir contribué à cette dépêche en ajoutant la référence au sondage Linux 3.0.

Sommaire

La phase de test

RC-1

la version RC-1 a été annoncée par Linus :

« Yeah ! Allons‐y pour les interminables discussions à propos de la numérotation du noyau (encore une fois).

J’ai décidé de sauter le pas et de nommer la prochaine version « Linux 3.0 ». Elle sera disponible à une date assez rapprochée de l’anniversaire des 20 ans, pour que je puisse utiliser ça comme excuse. Mais bon, honnêtement, la vraie raison, c’est que je ne suis plus vraiment capable de compter jusqu’à 40.

Nous avions discuté de cette nouvelle numérotation lors des derniers sommets annuels du noyau, et il y avait un plan pour en discuter à nouveau cette année. Mais bon, soyons réalistes, à quoi cela sert-il d’être aux commandes si je ne peux pas prendre une décision sans organiser un référendum ?

Donc, je vais juste me mettre en mode mâle dominant et re‐numéroter le truc. Vous allez adorer ça.

D’un autre côté, ma dominance ne s’étend malheureusement pas sur tous les scripts et les Makefiles , donc le noyau résiste et il s’intitule lui‐même « 3.0.0-rc1 ». Nous aurons les 6 ou 7 semaines habituelles pour arriver à le soumettre et pour nettoyer les scripts de façon à ce que la version finale soit juste « 3.0 ». L’équipe en charge de « -stable » pourra utiliser le troisième chiffre pour ses versions.

Alors, quels sont les grands changements ?

RIEN DU TOUT. Absolument rien du tout. Le 3.0 est juste là pour re‐numéroter, et ici nous ne faisons pas un truc à la KDE 4 ou à la GNOME 3. Pas d’incompatibilités, pas de nouvelles fonctions effrayantes, rien de tout ça. Nous avons fait des sorties basées sur des dates depuis plusieurs années maintenant et cela n’a rien à voir avec des nouvelles fonctions. Si vous voulez vraiment une excuse pour cette re‐numérotation vous devriez vous baser sur les dates (20 ans) et pas sur autre chose.

Pas de changement d’API, pas de changement d’ABI, pas de nouvelles fonctionnalités magiques. Juste la lente et laborieuse progression habituelle. En plus des modifications de pilotes, nous avons quelques nettoyages du VFS, des corrections sur la mémoire virtuelle, un début de consolidation de l’architecture ARM (yeah !) et en général tout ceci est supposé être un cycle très classique et normal.

En fait, je pense que ça va être une version du type « Linus est vraiment super ch*ant », et je vais être très strict sur ce que j’accepte pendant la période de stabilisation. C’est parce que je vais voyager la semaine prochaine avec un portable Atom tout lent et que vous aurez intérêt à vraiment me convaincre de l’intérêt de votre patch, puisque ce genre de machine n’est pas le truc le plus impressionnant qui ait jamais été construit. On peut s’en sortir avec le workflow git habituel, mais pour ce qui est de compiler, ce n’est pas vraiment ce à quoi je suis habitué.

Donc, soyez sympas avec moi et envoyez‐moi uniquement des patches importants. Comme ça, la prochaine version n’aura pas simplement un numéro flambant neuf, mais ce sera également un bon noyau.

Ok ? Alors allez-y testez ! »

RC-2

C’est le six juin dernier que Linus a décidé de faire paraître la version RC-2 :

« Vous connaissez tous la procédure maintenant : nouvelle semaine, nouvelle -RC.

Tout a été relativement calme, bien que la mise à jour de Btrfs soit plus grosse que ce que j’espérais. À part ça, il y a surtout des corrections de pilotes, aussi quelques patches pour UBIFS et également une poignée de marche arrière, du fait de certaines régressions.

J’espère que les choses vont rester calmes. Bien entendu, ce calme est peut‐être dû au fait que les gens ont, eux aussi, beaucoup voyagé. Donc, on verra, et autant espérer que tout ira bien.

En plus, je n’ai pas été super pressé de répondre à toutes les demandes d’intégration, donc j’ai encore des requêtes dans ma boîte e‐mail. »

RC-3

Après ses problèmes de réseau lors de son voyage de retour de la convention Linux au Japon, c’est le 13 juin que la troisième version candidate a été annoncée par Linus :

« Qu’avons‐nous là‐dedans ? Plus de trucs que dans la RC-2. Je ne suis certainement pas le seul à être allé au Japon pour la LinuxCon, ou alors il y a un autre truc qui a soudainement réveillé les gens.

Il s’agit surtout de corrections d’une ligne, mais il y a quelques trucs un peu plus gros : pilotes vidéo Radeon, mise à jour DRI, Btrfs, correction de la gestion Sparc LEON (et gestion PCI). D’autres petits trucs concernant NILFS2 et Ceph, et aussi ESA/390 (S/390) et ARM.

À part cela, ce sont juste des mises à jour de pilotes un peu partout.

Comme d’habitude, je demande aux gens de bien tester tout ça. »

RC-4

Réglé comme une horloge, Linus a envoyé son courriel d’annonce de la RC-4 le 20 juin :

« Encore une fois, il y a surtout de petites corrections d’une ligne et quelques changements dans DRM (et md).

Et aussi des patchs pour des régressions de performances : RCU n’a pas besoin de threads (et ne pas les utiliser corrige certains problèmes de performances sous des charges spécifiques) et la conversion des “spinlocks” en “mutexes” pour anon_vma a provoqué des soucis de montée en charge et a dû être corrigée. »

RC-5

La version RC-5 a été annoncée par Linus le 27 juin :

« Pas grand chose d’excitant là‐dedans.

Le truc le plus notable est peut‐être le fait que seulement un quart des changements concernent les pilotes. Les systèmes de fichiers représentent plus que ça (40 %) : Btrfs, CIFS, ext4, JBD2, NFS, ils sont tous là.

Et on trouve aussi tous les petits changements un peu partout. Comme, par exemple, des corrections d’échecs de compilation (pour être honnête vous devez activer quelques options ésotériques et désactiver NUMA pour rencontrer ce bogue, mais bon). Il y a encore quelques soucis en « staging » avec des correctifs en attente d’intégration. »

RC-6

Le 4 juillet, jour de la fête de l’indépendance aux États‐Unis, Linus a rendu disponible la version RC-6 du noyau :

« Joyeuse fête de l’indépendance pour tous les américains qui bossent sur le noyau là dehors.

Il n’y a pas grand chose à dire sur cette RC-6. La plus grosse partie, et de loin, c’est l’inclusion du pilote Intel isci. J’ai un peu hésité à son sujet, mais bon, ce n’est pas comme si ça allait causer des régressions pour des utilisateurs de Linux, donc pourquoi pas.

Et puis, franchement, Christoph Hellwig a dit des choses flatteuses sur ce pilote à deux reprises, ce qui est très inhabituel. Cela peut vouloir dire que ce pilote est génial. Bien entendu, il est bien plus probable que des aliens venus de l’espace soient juste en train de tester secrètement leur drogue euphorisante sur Christoph. Ou alors, il s’adoucit avec l’âge.

À part ce pilote isci, le reste est juste constitué de petites corrections. On en arrive au point où je commence à songer à sortir le noyau 3.0, parce que tout est vraiment calme et que les correctifs n’ont pas été révolutionnairement excitants. Quelques trucs sur le DRM (Radeon et Intel) seront peut‐être remarqués par plus de gens, mais le reste tend à être assez ésotérique.

Bon, maintenant, je me barre pour faire des “s’mores”. »

RC-7

Linus, après avoir hésité, a finalement décidé de sortir une ultime version candidate le 11 juillet dernier :

« J’avais dit que la RC-6 serait sans doute la dernière. J’ai menti.

Les choses ont été assez calmes, mais il y avait quand même suffisamment de trucs pour que je veuille une autre RC. Et puis nous avons quelques soucis avec les changements dans le RCU qui posent des problèmes quand l’ordonnanceur n’a pas été complètement initialisé. Donc, voici la RC-7, même si elle n’a peut‐être pas encore été répliquée sur les miroirs au moment ou j’écris.

Il n’y a pas grand chose à en dire. Des mises à jour de pilotes (nous sommes revenus au ratio habituel avec deux tiers pour les pilotes), quelques changements dans media et CIFS, et aussi des améliorations de détail sur vmscan. »

Un léger retard

Alors que Linus avait prévu de sortir le noyau 3.0 le lundi 18 juillet, il a finalement préféré attendre un peu en raison de problèmes de dernière minute.

C’est d’abord Hugh Dickins qui a trouvé un bogue difficile à mettre en évidence et assez compliqué à corriger dans la fonction de résolution de noms. Une fois cela résolu, c’est Paul McKenney qui s’est manifesté sur la LKML et qui a signalé avoir découvert plusieurs dysfonctionnements dans le code RCU du noyau.

Le temps pour Linus d’intégrer les patches proposés et de demander aux gens de tester via son nouveau compte Google+ rutilant, le planning soigneusement orchestré était bon à jeter aux orties.

Ces retards auront un impact sur le prochain noyau, puisque Linus avait prévu de partir en vacances juste après la fin de la période d’intégration des nouveautés du futur Linux 3.1. Il a envoyé un e‐mail récapitulatif pour expliquer la situation et laisser entendre qu’il sera particulièrement féroce envers les malheureux qui n’enverront pas leurs patches assez tôt.

Les nouveautés

Cleancache

Le patch cleancache, qui repose sur le mécanisme Transcendant memory évoqué dans la dépêche du noyau précédent, a été intégré dans Linux 3.0.

Pour bien comprendre le rôle de cleancache, il faut d’abord jeter un très bref regard sur la gestion de la mémoire.

Il y a en premier lieu une division entre la mémoire physique — la RAM — et la mémoire virtuelle qui présente aux applications un espace d’adressage qui leur est propre. Comme les deux sortes de mémoires sont divisées en pages, il faut des tables de correspondance entre une page physique et une page virtuelle. Ces tables sont nommées, de façon fort originale, des page tables.

On peut marquer les pages mémoires en mettant des drapeaux particuliers. Par exemple, si le drapeau « dirty » est appliqué, cela signifie qu’une application a voulu écrire des données et a utilisé la fonction write() . Le noyau a copié ces données dans des pages mémoire en leur mettant un drapeau « dirty ». Ces pages ne doivent donc pas être réutilisées tant que les données n’auront pas été effectivement écrites sur le disque dur.

Évidemment, à l’inverse, les pages ayant le drapeau « clean » sont disponibles pour être utilisées à tout moment.

Quand la pression mémoire est trop importante, alors les pages en statut « clean » peuvent être « enlevées » de la mémoire physique. Ce mécanisme d’éviction (memory reclaiming) va enregistrer les pages dans leur espace de stockage particulier. Cet espace, nommé backing store, c’est tout simplement le disque ou la partition d’échange (swap) de la machine.

C’est ici qu’intervient le patch « cleancache » écrit par Dan Magenheimer. En cas d’éviction d’une page mémoire clean par l’algorithme dédié, alors le mécanisme cleancache va jouer le rôle d’un victim cache, c’est‐à‐dire qu’il va accueillir les pages retirées de la mémoire pour les stocker dans un espace à accès plus rapide que le backing store sous‐jacent.

Maintenant, on comprend mieux ce nom de « cleancache », puisqu’il s’agit simplement d’un mécanisme de cache pour les pages ayant le drapeau « clean » ;-).

Alors évidemment, une première question se pose : si on stocke les pages victimes d’éviction dans un cache, cela signifie qu’on a de la place disponible, non ? Alors, pourquoi ont‐elles été choisies par le mécanisme de memory reclaiming qui n’intervient qu’en cas de manque de mémoire ?

La réponse est que cleancache n’utilise pas la mémoire classique. L’idée est de se servir d’un espace de stockage intermédiaire, n’importe lequel, puisque cleancache est agnostique envers son réservoir sous‐jacent. Le noyau Linux 3.0 permet ainsi d’utiliser la mémoire de l’hyperviseur si on tourne avec Xen, ou bien encore le mécanisme zcache de mémoire compressée. D’autres mécanismes sont en cours de développement, comme par exemple un SSD qui se place entre la RAM et le disque dur. Ce SSD servirait ainsi pour stocker les pages de cleancache afin de pouvoir y accéder bien plus rapidement qu’en cas d’appel au très lent disque dur.

Si on regarde la documentation, on voit que cleancache a été conçu pour s’interfacer avec le mécanisme VFS. Les systèmes de fichiers qui veulent utiliser ce mécanisme doivent effectuer un appel à cleancache_init_fs() lors du montage initial. À l’heure actuelle, les systèmes de fichiers ext3, ext4, Btrfs et OCFS2 peuvent utiliser cleancache (évidemment, dans le cas où l’option CONFIG_CLEANCACHE a été choisie lors du build).

Lors de l’éviction d’une page par le noyau, la fonction cleancache_put_page() sera appelée pour entreposer la page dans la zone de cache spéciale de cleancache. Si par la suite il s’avère que le noyau a besoin de cette page, il va, avant de lancer une coûteuse requête vers le disque dur, effectuer une recherche rapide via cleancache_get_page() . En cas de succès, c’est‐à‐dire si la page était toujours présente dans le cache, on peut gagner un temps précieux et augmenter largement les performances.

Comme l’indique Dan Magenheimer :

En réalité, cleancache remplace des opérations d’entrées‐sorties qui impactent le disque par des opérations de copie mémoire qui impactent le processeur. Sur des vieux systèmes ayant un seul processeur et une mémoire lente, cleancache ne sert pas à grand chose. Sur les nouvelles machines multi‐cœurs, spécialement dans un environnement virtualisé, le mécanisme a alors une grande utilité.

Afin de garder un œil sur cette fonction et de vérifier son apport en termes de performances, diverses statistiques sont accessibles dans le répertoire « /sys/kernel/mm/cleancache » . On y trouve :

succ_gets , le nombre d’appels à cleancache_get_page() ayant réussi (la page était dans le cache) ;

, le nombre d’appels à ayant réussi (la page était dans le cache) ; failed_gets , le nombre d’appels à cleancache_get_page() ayant échoué (la page n’était pas dans le cache) ;

, le nombre d’appels à ayant échoué (la page n’était pas dans le cache) ; puts , le nombre d’appels total fait à cleancache_put_page() pour déposer une page dans le cache ;

, le nombre d’appels total fait à pour déposer une page dans le cache ; flushes, le nombre d’appels total fait à cleancache_flush_page() pour retirer une page du cache.

Cleancache, en association avec le patch Transcendant memory, est un mécanisme très générique et adaptable, et il est probable que nous commençons à peine à profiter de ses bénéfices dans le noyau Linux 3.0.

L’arrivée dans les prochaines années des RAM non‐volatiles (qu’elles soient à base de memristors ou de verre de chalcogénure), permet d’imaginer un espace de stockage intermédiaire plus lent que la RAM, mais plus rapide que les disques (même SSD). Ce serait certainement une situation idéale pour la technique cleancache introduite dans ce noyau.

Améliorations de Btrfs

Après la décision de Fedora d’utiliser Btrfs par défaut dans sa prochaine version 16, il est peut‐être temps de réaliser un point de situation global sur ce très moderne système de fichiers. L’occasion est belle car, selon Chris Mason, les patches Btrfs intégrés dans le noyau Linux 3.0 sont les plus importants depuis le début du développement du système de fichiers.

C’est en juin 2007 que Chris a annoncé sur la liste de diffusion la naissance de Btrfs. L’idée était de créer un nouveau système de fichiers ultra‐moderne et profitant de toutes les dernières idées, sans être contraint par un quelconque souci de rétro‐compatibilité avec l’existant. C’est sans doute l’aiguillon de ZFS, disponible dans Solaris à partir de 2005, qui a poussé les développeurs Linux à lancer l’écriture d’un système de fichiers plus avancé que la série des ext2/3/4, et plus pérenne que ReiserFS.

Si l’on en croit l’excellent historique de Btrfs écrit par Valérie Aurora, tout est parti d’une idée du chercheur Ohad Rodeh, qui a trouvé un moyen élégant de combiner les avantages des « arbres B » (B‐trees) et du « Copy‐On‐Write » (COW). Les arbres B sont un moyen de représenter les données d’un système de fichiers ou d’une base de données dans un arbre dont chaque nœud possède plus d’une clé. C’est une technique très efficace, mais, jusqu’à la percée théorique de Rodeh, les arbres B ne pouvaient pas être combinés avec la technique d’optimisation connue sous le nom de Copy‐On‐Write. Avec le COW, si des données sont écrites sur un bloc mémoire, alors les nouvelles données seront enregistrées sur une copie au lieu de l’être sur l’original. Ensuite, les méta‐données pointant sur le bloc sont modifiées de manière atomique, afin de prendre en compte les nouvelles données. On a ainsi un mécanisme transactionnel efficace et tellement rapide qu’on peut même abandonner la technique de « journalisation ».

Le problème de mixage des arbres B avec le COW est que dans un arbre B les « feuilles » sont liées entre elles. Quand l’emplacement de la première feuille change suite à une opération d’écriture (puisque le COW implique la copie du bloc à un autre endroit), alors la feuille adjacente doit changer son lien, ce qui implique via COW une copie à un autre endroit… et bis repetita avec toutes les feuilles de l’arbre ! Bien entendu, comme vous pouvez l’imaginer, ce n’est pas très bon pour les performances de devoir réécrire tout l’arbre du système de fichiers à chaque modification d’une feuille…

L’idée d’Ohad Rodeh (décrite dans ce fichier PDF de la conférence USENIX) est d’utiliser un B+tree à la place d’un classique B‐tree. Les feuilles ne sont plus liées irrémédiablement entre elles, et on peut inventer des algorithmes astucieux pour traverser l’arbre. Rodeh ajoute des techniques comme la « fusion et séparation pro‐active des nœuds », et on obtient au final ce que Valérie Aurora qualifie de :

« structure de données simple, robuste et générique qui prend en compte de façon très efficace les extends (groupes de blocs de données contigus) dans un système de fichiers COW. »

Chris Mason a été frappé par la puissance et l’élégance de ce concept, et il a décidé de baser toute l’architecture de Btrfs sur cette idée. Il a choisi d’implémenter l’intégralité des « objets » du système (inodes, données des fichiers, répertoires, bitmaps) comme étant des nœuds ou des feuilles de l’arbre B. De cette façon, on n’écrit qu’un seul code qui est utilisé partout, et on peut avoir toutes les fonctions utiles (sommes de contrôle, snapshots, compression, etc.) qui s’appliquent à ce code unifié. On peut également profiter d’avantages en termes d’efficacité de stockage et de temps d’accès. Les autres systèmes stockent un seul type d’objet par bloc, ce qui est peu efficace, puisqu’on perd de la place dans le bloc et qu’on doit consulter plusieurs blocs pour avoir toutes les méta‐données. La stratégie de Btrfs rassemble tout dans une structure qui optimise l’espace disque et le temps d’accès.

Valérie Aurora a travaillé plusieurs années sur ZFS dans l’équipe de développement de Sun. Elle est donc particulièrement bien placée pour émettre un jugement solide en comparant ces deux systèmes de fichiers. La citation est un peu longue, mais elle a le mérite de la franchise :

« La conception de Btrfs est d’une grande élégance et d’une belle généricité […] Les gens me posent souvent des questions au sujet de ZFS et Btrfs. D’un certain point de vue, les deux systèmes sont très similaires : ce sont des systèmes de fichiers COW avec sommes de contrôles, gestion de périphériques multiples et des instantanés (snapshots) accessibles en écriture.

Selon un autre point de vue, ils sont extrêmement différents : Btrfs organise tout sur le disque en termes d’extents dans un arbre B qui contient toutes les données. ZFS organise tout sur le disque en termes d’arbres de pointeurs vers les blocs, avec des tailles de blocs en fonction de la taille de l’objet.

Donc la liste des fonctions des deux semble très similaire, mais les implémentations sont complètement différentes. C’est un peu comme le cas de l’évolution convergente entre les marsupiaux et les mammifères. Une souris marsupiale et une souris mammifère semblent complètement identiques vues de l’extérieur, mais leur implémentation interne est quelque peu différente !

À mon avis, l’architecture de base de Btrfs est mieux adaptée au stockage de données que celle de ZFS.

Un des problèmes majeurs de l’approche de ZFS à avoir un ensemble de blocs de tailles différentes, concerne la fragmentation. Chaque objet ne peut contenir que des blocs d’une seule taille. On peut facilement se retrouver avec un fichier formé à partir de blocs de 64 Kio qui doit grossir d’un bloc, alors qu’il n’y a plus de blocs de 64 Kio disponibles (alors qu’il y en a encore beaucoup de 512 octets, de 4 Kio, de 128 Kio, etc.).

Pour résoudre ce problème, nous (les développeurs de ZFS) avons inventé des façons de créer des gros blocs à partir de plus petits (gang blocks), et beaucoup d’autres contournements assez vilains. Pour notre défense, à cette époque, les arbres B et la technique COW semblaient radicalement incompatibles.

Par contraste, l’approche Btrfs qui place tous les items dans l’arbre B est extrêmement flexible et efficace en termes d’espace de stockage. »

Depuis sa présentation initiale en 2007, le système de fichiers Btrfs a beaucoup évolué, et il propose de nombreuses fonctions modernes parmi lesquelles on peut citer :

notion de « sous‐volumes » qui permet, au sein du système de fichiers, d’avoir un arbre séparé contenant des répertoires et des fichiers. Les instantanés (snapshots en anglais, une photographie à un instant donné du système de fichiers) sont simplement des sous‐volumes accessibles en écriture via COW ;

sommes de contrôle des données et méta‐données ;

agrandissement et réduction de taille des volumes ;

ajout et suppression de volumes ;

fonctions de compression transparente ;

fonctions RAID intégrées.

Pour le noyau Linux 3.0, Chris Mason a décrit les changements présents dans sa branche de développement. Il y en avait tellement qu’il a dû envoyer une nouvelle bordée de patches au moment de la RC-2 (ce qui lui a valu la traditionnelle engueulade de la part de Linus).

Une des modifications les plus importantes est le patch de Miao Xie qui réécrit la fonction d’insertion des méta‐données dans les inodes. Intitulé « Delayed Inode Items Operation », ce patch vise à améliorer les temps de création et suppression de fichiers. L’insertion de méta‐données dans le B+tree étant coûteuse, le nouveau code introduit une double liste qui stockera les opérations au lieu de bloquer, et ensuite le travail sera effectué par un thread spécifique (worker).

Selon le banc d’essai passé par Miao Xie :

création de 50 000 fichiers : avant le patch : 1,096 108, après le patch : 0,932 899 (soit un gain d’environ 15 %) ;

suppression de 50 000 fichiers : avant le patch : 1,510 403, après le patch : 1,215 732 (soit un gain d’environ 20 %).



On peut également citer le patch de Li Zefan qui implémente un cache pour les numéros d’inodes, afin de ne pas risquer d’en tomber à court sur les machines 32 bits.

Il y a aussi le patch d’Arne Jansen qui ajoute la prise en charge des fonctions de scrubbing. En gros, cela va permettre d’ordonner au noyau (via un ioctl) de vérifier les sommes de contrôles des extents et des superblocs présents sur le volume de stockage. En cas d’erreur (perte d’intégrité), une copie saine sera recherchée dans les volumes sauvegardés et une correction automatique sera effectuée. Selon les commentaires présents dans le code, ce travail sera complété dans une prochaine version pour ajouter des fonctions de « readahead » plus avancées (meilleures performances) et des fonctions de rapport en cas d’erreur irréparable.

Chris Mason a écrit un patch qui permet l’auto‐défragmentation de fichiers en cas d’accès aléatoires en écriture. Le patch permet de détecter ces accès particuliers et s’occupe de mettre les fichiers dans la liste pour une défragmentation automatique. Cette fonction s’active via « mount -o auto_defrag » et elle est décrite comme particulièrement adaptées pour des fichiers de taille réduite comme on peut en trouver dans des base de données du type SQLite ou Berkeley_DB.

Si on ajoute à ça la gestion de cleancache, le gros travail de nettoyage de code de David Sterba (17 patches pour 310 lignes en plus et 3 253 lignes en moins) et les efforts d’optimisation des performances entrepris par Josef Bacik et listés dans le courriel de Chris Mason, on comprend que le système de fichiers Btrfs présent dans le noyau Linux 3.0 a été grandement amélioré. La seule pièce manquante pour le choix définitif de Btrfs par défaut dans Fedora 16 ne concerne pas vraiment le noyau, puisqu’il s’agit d’ajouter un programme de vérification du type fsck . Selon Josef Bacik, cet outil est déjà écrit et il est en phase de vérification intensive :

L’outil de fsck est presque prêt. Une partie des raisons pour lesquelles cela prend autant de temps, c’est qu’il est très bien testé. Donc, quand il sera rendu disponible, il aura vérifié plusieurs centaines de systèmes de fichiers corrompus afin de s’assurer qu’il fonctionne correctement.

POSIX Alarm timer

Deux nouvelles interfaces d’accès à l’horloge RTC du BIOS font leur entrée dans le noyau Linux 3.0.

Cette horloge RTC est bien pratique, puisqu’elle permet de réveiller automatiquement la machine quand elle est en veille ou en hibernation, par exemple pour faire une sauvegarde au milieu de la nuit ou pour enregistrer une émission. Pour cela, il suffit à une application d’écrire dans « /sys/class/rtc/rtc0/wakealarm » pour indiquer la date et l’heure du réveil souhaité. L’horloge RTC reste à l’heure même si l’ordinateur hiberne et, juste au moment voulu, elle génère un signal pour réveiller la machine et passer la main au programme utilisateur.

L’ennui c’est qu’il s’agit d’une interface bas niveau et qu’une seule application peut programmer le réveil de l’ordinateur. C’est le premier arrivé qui gagne ! Si l’on veut à la fois programmer une sauvegarde, puis l’enregistrement d’une émission, alors il faut ruser. On peut s’en sortir en faisant coopérer les applications et en jouant avec cron , mais ça devient beaucoup plus compliqué.

L’idéal ce serait que les applications signalent simplement leurs besoins dans une sorte de file d’attente (timerqueue), et que le noyau s’occupe tout seul du travail consistant à réveiller la machine au moment spécifié le plus proche dans le temps. Le programme en espace utilisateur envoie un rtc_timer dans la queue au lieu de parler directement à l’horloge RTC. Cette fonction si pratique de « virtualisation » de l’horloge RTC (puisqu’on passe par une couche intermédiaire) est entrée dans le noyau à partir de la version 2.6.38.

Maintenant il faut s’attaquer à la partie visible par les applications. Comment leur proposer une interface simple qui cache tous les horribles petits détails bas niveau comme, par exemple, les désynchronisations entre l’horloge RTC et l’heure système ? Quelle est la meilleure solution pour donner suffisamment d’informations aux applications, tout en ayant une API robuste et sûre ?

C’est une question délicate, car toute interface vers des applications en espace utilisateur devient, une fois publiée, absolument intangible. Si l’on fait du mauvais travail au début, il est très difficile de corriger les choses par la suite, puisque cela risque de casser la compatibilité avec les applications.

Dans ces cas‐là, il est toujours utile de regarder autour de soi pour voir quelles sont les solutions adoptées par les autres systèmes.

Par exemple, l’équipe d’Android a déjà développé plusieurs nouvelles interfaces d’horloges pour son système (un téléphone se met souvent en veille automatique, et il a besoin de sortir de cet état à des moment bien précis). Pourquoi ne pas réutiliser ce travail ?

Malheureusement, au lieu de participer au développement dans la branche principale, ils ont codé dans leur coin des choses assez peu orthodoxes du type ANDROID_ALARM_RTC ou ANDROID_ALARM_SYSTEMTIME , ou encore ANDROID_ALARM_ELAPSED_REALTIME . Ces interfaces n’utilisent pas du tout « /sys/class/rtc/* » , elles passent par un tout nouveau périphérique en mode bloc « /dev/alarm » et envoient des commandes via un ioctl.

Évidemment, pour rajouter un peu de bonheur dans le cœur des développeurs Linux, certaines de ces interfaces réinventent la roue et reprennent en partie des concepts qui existent déjà dans le noyau ( CLOCK_REALTIME et CLOCK_MONOTONIC ). Seule l’interface ANDROID_ALARM_ELAPSED_REALTIME est intéressante et nouvelle, puisque non seulement elle compte le temps qui s’est écoulé depuis le démarrage du système, mais surtout, elle tient compte des phases de veille et d’hibernation dans son calcul. C’est un avantage par rapport au classique CLOCK_MONOTONIC qui compte le temps à partir de zéro depuis le démarrage du système, mais qui s’arrête de compter quand la machine hiberne.

Le développeur John Stultz s’est donc inspiré du travail intégré dans Android, et il a codé deux nouveaux types d’horloges pour Linux 3.0.

La première, CLOCK_REALTIME_ALARM , étend la classique CLOCK_REALTIME , qui ne faisait que donner l’heure RTC, et ajoute la possibilité de réveiller l’ordinateur. La seconde horloge se nomme CLOCK_BOOTTIME_ALARM et elle copie les fonctions d’ ANDROID_ALARM_ELAPSED_REALTIME . On a donc un compteur qui s’incrémente depuis zéro à partir du démarrage du système et qui ne s’interrompt pas lors des phases de veille et d’hibernation.

Ces horloges sont implémentées par dessus le mécanisme de virtualisation qui avait été introduit dans le 2.6.38, et, contrairement au code d’Android, elles utilisent l’interface classique POSIX et parlent à l’horloge RTC sous‐jacente en utilisant les évènements rtc_timer décrits plus haut.

C’est donc une belle avancée pour Linux, mais cela ouvre également des perspectives pour les développeurs d’Android. Ils avaient développé des interfaces dans leur coin parce que le noyau ne leur proposait pas ce dont ils avaient besoin. Maintenant que CLOCK_REALTIME_ALARM et CLOCK_BOOTTIME_ALARM sont dans la branche principale, pourquoi ne pas simplement les utiliser, puisqu’elles offrent les mêmes fonctions que le code spécifique d’Android ?

John Stultz a parlé aux développeurs de Google, et, selon lui, il semble qu’une simplification et qu’un large partage de code soit devenu maintenant possible.

Suppression de prefetch

Les appels à la fonction prefetch() qui parsemaient le noyau ont été en grande partie retirés dans cette version 3.0. Le travail de nettoyage va sans doute se poursuivre dans les versions futures, car les tests ont montré que les gains en performances qui étaient espérés avec cette fonction ne sont pas au rendez‐vous.

La fonction prefetch() est ce que l’on nomme une « micro‐optimisation ». C’est‐à‐dire que son rôle est d’améliorer à la marge les performances du noyau en complexifiant un petit peu le code. Bien entendu, chaque micro‐optimisation est le résultat d’un calcul coût‐bénéfice assez spéculatif : est‐ce que le gain en performances justifie la complexité qui est ajoutée dans le code et qui risque d’introduire des bogues et de la charge de maintenance ?

Les développeurs du noyau savent parfaitement que les performances d’une machine dépendent de façon cruciale de la mémoire cache (voir l’article d’Ulrich Drepper sur ce sujet). La différence de temps d’accès entre une mémoire cache gravée sur le processeur et une barrette de RAM externe est tellement gigantesque, que tout défaut de cache réduit de façon importante les performances. Il faut donc que le code du noyau fasse le maximum pour que la gestion du cache soit la plus efficace possible.

Pour cela, des appels à prefetch() ont été ajoutés dans plusieurs endroits du noyau. Par exemple, quand des listes chaînées sont utilisées, on va utiliser prefetch() pour charger en avance l’item suivant de la liste. Le processeur sera toujours en train de traiter l’élément n de la liste, mais, grâce à ce chargement anticipé, l’élément n + 1 aura été appelé en avance de phase et sera, soit sur le chemin vers le processeur, soit déjà au chaud dans la mémoire cache. On perd ainsi moins de temps à interroger la RAM et à se rouler les pouces en attendant sa réponse.

Les macros existantes dans le noyau Linux, comme list_for_each par exemple, incorporent donc un appel à cette fonction de pré‐chargement en tant que micro‐optimisation permettant d’accélérer le traitement des listes chaînées.

La fonction prefetch() est, on le voit, une idée simple, naturelle et non controversée. Le problème c’est qu’en réalité il s’avère qu’elle dégrade les performances !

Tout cela vient du fait que les processeurs modernes sont des monstres d’ingénierie, avec un « budget transistor » absolument indécent. Pour augmenter les performances, les têtes pensantes des labos d’AMD, Intel ou IBM ont bien compris qu’optimiser le chargement de la mémoire cache était crucial. Tous les CPU modernes incorporent donc des unités matérielles de pré‐chargement des données. Ce prefetcher matériel observe donc les accès mémoire et il arrive à distinguer des schémas récurrents (patterns) qui vont lui permettre de pré‐charger les données en avance de phase. Chaque constructeur garde jalousement le secret sur le fonctionnement exact de ces unités matérielles de pre‐fetch (la documentation est très succincte), mais le résultat est là : le processeur fait du bon travail et parvient de lui‐même à optimiser le fonctionnement de la mémoire cache en pré‐chargeant efficacement les données.

À ce stade un problème se profile à l’horizon : si le processeur est déjà capable de faire du pré‐chargement, alors à quoi est‐ce que ça sert d’ajouter des appels à prefetch() partout dans le code ? On risque plutôt de perturber les flux de données en interférant avec le délicat travail du processeur.

C’est cette réflexion qui a conduit Andi Kleen, dès septembre 2010, à proposer son patch de nettoyage des appels à prefetch() .

Andi s’est penché sur cette question pour évaluer l’apport réel du pré‐chargement codé dans le noyau. Il a parlé avec des ingénieurs CPU, et la conclusion est sans ambiguïté :

Le retour de la part des concepteurs de CPU, c’est qu’ils n’aiment pas quand nous utilisons des appels explicites à prefetch() , à moins qu’il n’y ait une très bonne raison de le faire.

Si l’on ajoute le fait que les appels de pré‐chargement augmentent la pression sur les registres du processeur et que le code généré par les compilateurs est souvent de moins bonne qualité quand il y a des appels à prefetch() , alors le résultat du calcul coût‐bénéfice change du tout au tout.

L’ennui c’est que le patch d’Andi de septembre dernier n’a pas suscité une réaction d’enthousiasme démesurée sur la liste de diffusion du noyau. En fait, il n’y a pas eu de réaction du tout, à part un e‐mail de Paul Moore disant en substance : « Ouais, pourquoi pas ? ».

Il ne faut pas oublier que la LKML se caractérise par un déluge de courriels, et il n’est pas rare de voir ainsi des propositions rester sans suite. C’est au développeur qui a créé le patch d’insister et de défendre son travail inlassablement pour obtenir une réaction de ses pairs. Dans le cas d’espèce, Andi n’a pas insisté et son nettoyage des appels à prefetch() n’a pas été intégré dans la branche principale du noyau.

Tout change le 19 mai 2011 avec un e‐mail de Linus intitulé « Software prefetching considered harmful ». Avec son style fleuri habituel, le leader du noyau détaille les tests qu’il a effectués et tout le bien qu’il pense de la fonction de pré‐chargement :

J’ai passé un peu de temps ces derniers jours à regarder les performances du noyau sur une tâche que j’effectue en permanence : « make » sur un répertoire qui est déjà complètement « buildé ». Donc, il n’y a pas le coût de la compilation, juste le coût de _vérification_ de ce qui doit être compilé.

Il s’avère que « make » est franchement lent comme un goret (quoi de neuf là‐dedans ?), mais que cette charge est assez intensive pour le noyau. On passe un bon paquet de temps à faire de la résolution de noms. Et nous sommes bons en matière de résolution de nom… sauf si je veux activer SELinux sans perdre les avantages de la résolution via RCU. Dans ce cas de figure, SELinux suce des fœtus d’ânes à travers une paille.

Quoi qu’il en soit la fonction la plus consommatrice est celle qui utilise le prefetch logiciel pour les listes de hachage. Le profil montre clairement que l’instruction de prefetch est de loin la plus grande coupable.

Et ce n’est pas à cause des défauts de cache. En réalité, la suppression du prefetch AUGMENTE LES PERFORMANCES.

Je ne blague pas. C’est juste une merde. C’est une immonde merde qui nous coûte 0,5 % de performance sur un simple banc d’essai de « make » du noyau sur l’un des processeurs les plus communs qui existent.

Sérieusement.

Le patch qui accompagne le courriel indigné de Linus supprime donc la fonction de pré‐chargement des listes de hashes (hlist) et relance l’intérêt pour mener des investigations sur la fonction prefetch() . Ingo Molnar s’est engagé dans une phase de test intensive à l’aide de l’outil perf pour comprendre clairement ce qui se passait.

Le résultat de ses investigations a été résumé dans un message très détaillé dont j’extrais la conclusion :

- Depuis des années, les gens ajoutent des instructions de prefetch à l’aveuglette, sans tester et sans prouver qu’il y a vraiment un gain. Nous devrions réexaminer tout cela soigneusement.

- Le processeur est fondamentalement plus efficace que le logiciel dans le domaine du pré‐chargement. Nos fameuses instructions se révèlent diminuer les performances.

- Les tests, via les perf‐events, sont la voie à suivre. Ils se sont révélés très utiles pour moi, afin d’analyser la situation. Et je n’ai même pas eu à me préoccuper de quel modèle de CPU était utilisé lors des tests. C’est un énorme avantage à mon avis.

Après la diatribe de Linus et les analyses d’Ingo (qui va jusqu’à dire que « les pré‐chargements sont absolument toxiques »), il était clair que la fonction prefetch() du noyau n’allait pas en sortir indemne. En septembre 2010, Andi Kleen avait été un précurseur incompris, mais aujourd’hui la nécessité d’agir est devenue évidente.

Dans le nouveau noyau Linux 3.0, la fonction prefetch() a donc été retirée des listes de hashs et des listes chaînées. Les pilotes commencent également à être nettoyés eux aussi.

Le gain induit par ces changements est marginal (entre 0,5 et 1 %), mais là n’est pas l’important. Ce qui compte, c’est que le code est maintenant plus simple, plus maintenable et que la taille d’une image noyau est un peu réduite (Andi Kleen avait chiffré le gain à 10 Kio). Ce qui compte surtout, c’est que les outils de diagnostic intégrés au noyau ( perf et ses amis) permettent maintenant de se pencher efficacement sur les micro‐optimisations du noyau et d’évaluer leur apport réel.

Ingo Molnar, l’un des auteurs de perf , n’est évidemment pas neutre quand il défend son bébé. Mais il a raison de souligner les gains que cela permet :

Durant ces dix dernières années, nous avons souffert d’un niveau d’aveuglement croissant en ce qui concerne l’analyse des performances x86. Nos outils se sont lentement détériorés, les processeurs sont devenus de plus en plus intelligents et parallèles, et c’était de plus en plus difficile de comprendre ce qui se passait.

Mais nous avons maintenant de meilleurs outils (clin d’œil :) et un modèle de supervision plus performant (clin d’œil :), et les gens recommencent à se plonger dans les petits détails. Je pense que nous avons de bonnes chances d’améliorer encore les performances du noyau et de les maintenir à ce niveau.

Un JIT pour BPF

Le code de la pile réseau du noyau Linux 3.0 contient désormais un compilateur à la volée (JIT) qui permet d’accélérer le traitement des paquets réseau du filtre Berkeley Packet Filter.

Le filtre BPF (Berkeley Packet Filter), présenté à la conférence USENIX de 1993, est un outil qui permet à un logiciel en espace utilisateur de spécifier, via des filtres, les paquets pour lesquels il éprouve un intérêt. BPF a été rapidement intégré directement dans le noyau Linux qui y a gagné la possibilité de filtrer en amont les paquets du réseau et de n’envoyer vers l’application que le strict nécessaire dont elle a besoin.

Ainsi, on gagne en performances car on bloque les paquets inutiles dans le noyau dès le début, avant d’avoir à les envoyer vers l’espace utilisateur.

Parmi les logiciels qui reposent sur BPF, on peut citer ngrep , Wireshark ou encore tcpdump , qui servent à capturer et analyser des paquets réseau. Ils utilisent BPF en positionnant un filtre précis qui ne va laisser passer que ce qui est intéressant. Ces logiciels reçoivent ainsi un flux « propre » puisque débarrassé de tous les paquets qui ne correspondent pas à leurs critères de recherche.

Évidemment, on comprend que les performances de BPF dans le noyau sont assez critiques, puisqu’il va devoir examiner les paquets un par un et déterminer s’ils correspondent ou pas aux conditions paramétrées dans le filtre.

Pour Linux 3.0, l’idée d’Éric Dumazet a consisté à ajouter au code de BPF (lisible dans « net/core/filter.c ») un mécanisme de génération de code à la volée (Just‐in‐time compilation). Chaque instruction du filtre va être transformée en assembleur, et le programme qui en résulte traite chaque paquet réseau pour voir s’il correspond aux conditions de test.

Si vous prenez la peine de regarder le code de BPF, vous verrez (ligne 190) que c’est essentiellement un gros switch() qui énumère tous les cas possibles d’instructions. Cette organisation du code rend plus facile son remplacement par un JIT. Le patch d’Éric va permettre de remplacer chaque instruction du filtre BPF désiré par une séquence d’instructions x86. Le programme résultant, qui utilise une zone mémoire spéciale, est alors appelé pour analyser à pleine vitesse chaque paquet réseau.

Par défaut, ce compilateur JIT de BPF est désactivé, et il vous faudra faire un petit « echo 1 >/proc/sys/net/core/bpf_jit_enable » , si vous voulez profiter de ses bienfaits. Précisons que l’implémentation, comme tout code en assembleur, est dépendante de l’architecture du processeur. Pour l’instant, seule l’architecture x86_64 est supportée par le compilateur JIT, mais il est possible (probable ?) que les futurs noyaux verront arriver un code gérant d’autres architectures.

Éric Dumazet a testé le gain potentiel qu’apporte son patch en regardant ce qui se passe quand tcpdump doit analyser dix millions de paquets UDP avec un filtre très basique (commande time /root/udpflood -f -l 10000000 10.2.2.1 ).

La machine est un quadri‐cœur Intel E5540 cadencé à 2,53 GHz, voici les temps obtenus :

sans tcpdump : 7,941 s ;

: ; avec tcpdump , mais sans le JIT : 10,165 s ;

, mais sans le JIT : ; avec tcpdump et le JIT activé : 9,615 s.

On gagne donc 0,55 secondes sur un traitement de dix millions de paquets, ce qui se traduit par un gain d’environ 50 nanosecondes par paquet. Et encore, ce n’est que pour un filtre ultra-basique (voir l’e‐mail d’Éric), et les gains devraient être supérieurs quand la complexité du filtre augmente.

Éric Dumazet étant un très gros contributeur de la pile réseau du noyau Linux, j’ai profité de l’entrée de ce patch pour lui poser quelques questions (micro‐entretien datant du 14 juin dernier) :

LinuxFr.org : Bonjour Éric. J’ai vu que ton patch ajoutant un JIT pour BPF allait faire partie des nouveautés de la version 3.0, et je voudrais savoir si tu pouvais répondre à quelques questions pour les lecteurs de LinuxFr.

Éric Dumazet : Je suis à Toronto en ce moment pour la Netconf 2011, je profite d’une pause café pour te répondre. ;)

LinuxFr.org : Es-tu es le seul hacker du noyau chez SFR ? Es‐tu es payé à plein temps pour travailler sur la branche principale ?

Éric Dumazet : À ma connaissance je suis le seul « hacker chez SFR », mais je ne suis pas payé pour cela.

Je travaille chez SFR Business Team, Services Hébergés, pour des clients entreprise qui ont des problématiques générales, et il m’arrive d’utiliser mon expertise Linux dans des cas particuliers.

LinuxFr.org : C’est un peu surprenant que tu ne sois pas payé par SFR pour travailler sur le noyau. Pourtant quand on regarde les articles de statistiques de LWN ou de remword, on voit que tes patches sont portés au crédit de SFR.

Bizarre. Je me demande comment ils choisissent de compter les contributions des entreprises ?

Éric Dumazet : C’est très simple : quand un particulier a une adresse « générique », en @gmail.com , et qu’il contribue de façon significative à Linux, il reçoit un e‐mail lui demandant pour quelle entreprise il travaille. ;)

Il se trouve que je suis en effet un gros contributeur Linux, et donc j’ai eu des demandes pour préciser ce point. Par exemple, SFR finance mon déplacement à Toronto, donc mon employeur participe, lui aussi, à l’effort commun qu’est Linux. ;)

LinuxFr.org : Est‐il est prévu d’étendre le JIT pour d’autres architectures ? Serait‐ce facile à faire ?

Éric Dumazet : Pour le moment rien n’est prévu, mais ce serait assez simple. Il suffit d’une connaissance assez basique du jeu d’instructions du CPU, je dirais que quelques jours de travail par architecture devraient suffire. Il faut, bien entendu, une machine pour les tests, et un peu de savoir‐faire.

LinuxFr.org : Ce mécanisme de JIT n’est-il envisageable que pour BPF, ou bien est‐ce que cela aurait du sens de faire la même chose pour iptables ?

Éric Dumazet : J’ai l’intention de parler de ce sujet demain, justement. La boucle principale d’ iptables peut en effet profiter du JIT, qui peut ensuite appeler des helpers externes (pour les matches ou targets qui contiennent du code qui ne nécessite pas de faire de l’inline).

Le gros intérêt de JIT pour iptables serait d’éviter d’avoir une copie de la table par CPU, comme c’est le cas actuellement, car le « code iptables » est mélangé avec les compteurs bytes/packets par règle.

LinuxFr.org : D’après les commentaires sur LWN, il semble que FreeBSD utilise une technique de JIT similaire pour BPF. Est‐ce que tu t’es inspiré de ça pour ton code ? De manière générale, est‐ce que tu regardes les systèmes BSD pour les comparer avec Linux ?

Éric Dumazet : Je suis au courant, mais je ne regarde pas le code de FreeBSD : je préfère que les développements Linux soient « self contained », pour éviter des contaminations pouvant poser problème de droits d’auteur.

LinuxFr.org : Sur quoi travailles‐tu pour les prochaines versions du noyau ?

Éric Dumazet : Je travaille actuellement (et de façon générale) sur des optimisations.

Par exemple, les prochaines machines pourront disposer de 40 cœurs et 80 threads, et des problèmes de contention surviennent souvent. Par exemple, cette semaine, j’ai proposé un patch qui améliore les performances sur une machine de ce type, dans un contexte « memcached » haute performance.

Ce patch a permis une augmentation d’au moins 200 % des performances sur un prototype d’Intel.

LinuxFr.org : Merci pour tes réponses, et merci surtout pour tes contributions au noyau.

En bref

Appel système sendmmsg

L’appel système classique recvmsg() permet de recevoir un message sur un socket réseau. Comme pour tous les syscalls, franchir la séparation entre espace utilisateur et espace noyau est une opération coûteuse, et les développeurs cherchent à optimiser cette opération. Dans le noyau 2.6.33, le développeur Arnaldo Carvalho de Melo a eu l’idée de créer un nouvel appel système (nommée recvmmsg() ) permettant de recevoir plusieurs messages d’un seul coup, au lieu d’être limité à un unique message. Avec cette solution, on peut effectuer plus de travail à chaque franchissement de la barrière noyau-espace utilisateur.

Nous voyons maintenant arriver dans Linux 3.0 la contrepartie de ce patch, puisqu’Anton Blanchard a pris la peine d’écrire la même variante dopée aux stéroïdes de l’appel système sendmsg() habituel. Le nom est explicite et vous avez déjà compris que sendmsg() sert à envoyer des messages sur un socket réseau, au lieu d’en recevoir. Le nouveau noyau accueille donc le nouvel appel sendmmsg() qui n’est plus limité à l’envoi d’un seul message à la fois (mm, c’est pour multiple messages).

Cela permet de réduire les coûts des appels systèmes (syscall overhead), et le gain en performances est très notable, puisque, selon les tests d’Anton, on peut aller jusqu’à + 20 % de débit sur des paquets UDP et + 30 % sur des paquets bruts (raw socket).

Commande ping

Puisque nous sommes dans les paquets réseau, on peut noter que le noyau Linux 3.0 permet maintenant d’utiliser ping sans avoir les droits root . Il s’agissait à l’origine d’un patch implémenté par la distribution Openwall dans sa valeureuse quête d’un monde sans binaires à changement d’utilisateur setuid (set user id) dangereux. Selon Solar Designer, cet ajout est le résultat d’un examen attentif des alternatives et il a été finalement décidé que la meilleure solution était d’ajouter au noyau un nouveau type de socket nommé IPPROTO_ICMP .

Le nom est un peu trompeur, puisqu’il n’est pas question de prendre en charge tout le protocole ICMP. En réalité, le socket est extrêmement restreint et, dans cette implémentation, la seule chose qui peut passer, ce sont les messages de type ECHO (c’est‐à‐dire qu’il ne peut qu’envoyer des messages de type ICMP_ECHO et recevoir des réponses ICMP_ECHOREPLY ).

Le patch de Vasiliy Kulikov (qui est un des résultats de l'initiative visant à renforcer la sécurité de Linux) détaille fort bien la problématique derrière cet ajout et indique que, pour des raisons de réduction de la surface d’attaque du noyau, cette option est désactivée par défaut.

Si une distribution choisit d’utiliser cette possibilité, alors, avec ce socket IPPROTO_ICMP et un binaire ping « patché » comme ici, il deviendra possible d’utiliser ping sans avoir des droits superutilisateur.

Hop, un binaire setuid de moins !

Pilotes graphiques

Dans le domaine des pilotes DRM du noyau, on note assez peu de changements en ce qui concerne Intel. Les nouveautés concernent essentiellement le cœur graphique des futures puces Ivy Bridge qui est d’ores et déjà supporté dans cette version Linux 3.0 (1 - 2). De la même manière, le PCH (Platform Controller Hub) de type Panther Point, le successeur des Cougar Point de l’architecture Nehalem, est lui aussi pris en charge par le noyau.

Le pilote spécifique destiné aux puces GMA500 (Poulsbo) continue d’être amélioré par Alan Cox. Cette fois, c’est son architecture même qui change, puisqu’il se base sur GEM et non plus sur TTM. Après cette réorganisation, Alan estime que le pilote GMA500 est d’une qualité suffisante pour quitter la branche staging dès le prochain noyau 3.1.

Côté AMD, c’est la nouvelle architecture Fusion de type Llano qui arrive dans cette version. On trouve également plusieurs patches écrits par Alex Deucher, afin de nettoyer le code et d’améliorer le support de la norme DisplayPort.

Enfin, en ce qui concerne le pilote Nouveau, on trouve le début du support de pmpeg sur les puces NV40 (série GeForce 6) et NV84/G84 (cela permet d’utiliser le cœur graphique pour le décodage des flux MPEG). Dave Airlie continue également de travailler sur la technologie Optimus, afin de pouvoir basculer entre une puce graphique intégrée et la carte graphique externe au processeur.

Ext4 creuse des trous

Dans sa version 2.6.38, le noyau Linux avait gagné la possibilité de « creuser des trous » au sein des fichiers (hole punching). Cette désallocation d’une partie de l’espace d’un fichier est utilisée dans divers scénario de virtualisation. Par exemple, au démarrage, un système hôte alloue un espace contigu à son système invité (guest) pour ensuite, en cas de besoin, récupérer les zones non utilisées au sein du fichier en faisant appel à FALLOC_FL_PUNCH_HOLE .

Alors que cette fonction n’était jusqu’à présent utilisable que sur les systèmes de fichiers XFS et OCFS2, le nouveau noyau 3.0 ajoute la compatibilité avec ext4. Les patches d’Allison Henderson (1 - 2 - 3 - 4 - 5) sont plus complexes que ce qui avait été initialement prévu, et il a fallu sept versions successives pour obtenir l’assentiment des sourcilleux gardiens du noyau. L’avantage, quand on se casse la tête et qu’on teste tout pour satisfaire un cerbère grognon, c’est que, par le plus bienheureux des hasards, on peut trouver des vieux bogues. Allison a pu ainsi ajouter à son tableau de chasse la correction d’une fonction qui s’est révélée donner de faux résultats et l’éradication d’un dangereux déréférencement de pointeur NULL.

Ordonnanceur réseau QFQ

Un nouvel algorithme d’ordonnancement des paquets réseau a été ajouté à la longue liste de ceux déjà présents dans le noyau Linux. Ces ordonnanceurs sont là pour implémenter une politique de traitement des paquets un peu plus subtile que le très bourrin premier‐arrivé‐premier‐servi ( NET_SCH_FIFO ).

On peut, par exemple, privilégier l’équité (Fair Queueing schedulers) entre les flots de paquets, mais cela se fait au détriment de la vitesse de traitement. On peut aussi choisir la rapidité (Priority based schedulers), mais alors la garantie de service ne s’appliquera qu’aux flots ayant la plus haute priorité, et les autres seront laissés pour compte.

Le petit nouveau se nomme « Quick Fair Queueing » et il ambitionne d’être équitable, tout en étant rapide. L’article des chercheurs italiens Fabio Checconi, Paolo Valente et Luigi Rizzo donne tous les détails sur ce nouvel algorithme et affirme qu’il est entre 2,5 et 3 fois plus rapide que les algorithmes existants qui ont les mêmes garanties de service.

C’est le développeur Stephen Hemminger qui, en se basant sur un code antérieur de Fabio Checconi, a écrit le patch qui est finalement entré dans le noyau 3.0.

À noter que l’ordonnanceur QFQ ( NET_SCH_QFQ ) est déjà présent dans le pare‐feu de FreeBSD nommé ipfw (voir la présentation issue de BSDCan2010).

Xen

Les derniers patches permettant au noyau Linux d’être parfaitement fonctionnel en mode Dom0 sous l’hyperviseur Xen ont été intégrés dans la branche principale.

Konrad Rzeszutek Wilk explique clairement sur son blog que cette intégration a été une tâche de très longue haleine. Xen a adopté une licence libre en 2002 et la première version publique est sortie en 2004, mais pendant des années les développeurs n’ont pas vraiment travaillé pour rejoindre la branche principale du noyau. La priorité était de fournir des offres commerciales en choisissant une certaine version du noyau, et en ne proposant qu’une compatibilité spécifique avec cette version. Si l’on ajoute le fait que les développeurs Linux poussaient les hauts cris en voyant le code de Xen et ne voulaient pas entendre parler d’un monstro‐patch, on comprend que la fusion dans la branche principale n’était pas à l’ordre du jour.

Au fil des années, les auteurs de Xen se sont quand même rendus compte que leur modèle devenait intenable et qu’ils passaient un temps infini à réadapter leur patch. Il valait mieux chercher à intégrer le noyau pour que cette compatibilité ne soit plus un problème. En plus, les développeurs Linux avaient intégré dès le 2.6.20 la machine virtuelle KVM, qui était reconnue comme étant beaucoup plus propre et simple. Cette concurrence de KVM (voir l’excellent article de Heise Online) a provoqué un déclin d’intérêt pour Xen, et ses développeurs ont décidé qu’il était devenu indispensable de finir l’intégration dans la branche principale.

Il leur a donc fallu accepter les critiques des mainteneurs Linux (corriger, entre autres, les monstrueux « #ifdef LINUX_VERSION_2_4_3 » ou « #ifdef LINUX_VERSION_2_6_18 » qui parsemaient le code) et aussi découper proprement leurs patches.

Le mode invité de Xen (DomU) a pu être intégré à partir du 2.6.23, mais il manquait encore le mode hôte (Dom0), et il a fallu continuer de corriger patiemment tous les défauts signalés sur la LKML.

Depuis la version 2.6.37, il est devenu possible de démarrer le système en Dom0 sous Xen, mais il manquait encore les indispensables pilotes génériques qui permettent à Xen de fonctionner réellement.

Le pilote réseau générique netback est entré dans le 2.6.39 et, finalement, le pilote générique en mode bloc rejoint la branche principale à l’occasion de cette version 3.0.

Les développeurs de Citrix ont alors pu pousser des cris de joie et célébrer dignement ce succès sur leurs blogs (1 - 2 - 3). La stratégie consistant à envoyer des patches courts, propres et pas trop invasifs a fini par payer.

Maintenant, il va falloir continuer le travail, puisque cette intégration s’est effectuée au prix d’une réduction des fonctions qui existent dans les produits commerciaux Xen (pas de mise en veille, par exemple, ni de flux USB envoyés aux systèmes invités).

SMEP

Dans le même esprit que le fameux bit NX (qui marque les pages accessibles en écriture, afin qu’elles ne soient pas exécutables), les futurs processeurs Intel auront un bit de sécurité nommé SMEP. Cette fonction « Supervisor Mode Execution Protection » (évoquée dans ce journal LinuxFr) va générer une erreur quand le noyau essaiera d’exécuter du code depuis une page marquée avec le bit user. Les patches du développeur Intel Fenghua Yu permettent d’activer ou de désactiver à volonté cette fonction pour les processeur ayant le drapeau X86_FEATURE_SMEP (il suffit de passer « nosmep » en paramètre lors de l’amorçage du système).

Le bit SMEP vise à rendre la vie plus difficile aux vils pirates informatiques qui parviennent à dévier le flux d’exécution du noyau vers une page en espace utilisateur contenant leur code de prise de contrôle (payload). Avec cette sécurité supplémentaire qu’offre SMEP, il ne sera plus possible d’exécuter ce code se trouvant en espace utilisateur.

Dan Rosenberg, spécialiste de la sécurité du noyau, explique bien sur son blog que SMEP reprend en partie les fonctions du module PAX_UDEREF , qui fait partie du patch « grsecurity/PaX ». Bien entendu, PAX_UDEREF utilise une autre technique — la segmentation — qui est purement logicielle. Cela veut dire qu’il y a un impact sur les performances et que le code n’est pas prêt de rentrer dans la branche principale, car il est très invasif. SMEP est un petit peu moins complet que PAX_UDEREF , mais le fait qu’il s’appuie sur une fonction intégrée dans les processeurs à venir lui permet d’être très simple et complètement transparent du point de vue des performances.

Namespace

Le patch d’Eric Biederman améliorant la gestion des espaces de nommage (name spaces) a été accepté dans le nouveau noyau. Ce travail vise à améliorer la gestion des conteneurs, c’est‐à‐dire des groupes de processus qui ont leur propre vue privée sur les ressources du noyau, le réseau ou bien encore les systèmes de fichiers.

D’habitude quand on parle de conteneurs, le problème consiste à les isoler au maximum, chacun dans son propre espace de nommage distinct. Pour ce patch, c’est le contraire, puisqu’Eric a créé un mécanisme pour permettre à d’autres processus, extérieurs au namespace du conteneur, d’interagir avec cet espace de noms.

Il a expliqué dans un e‐mail quelle utilité cela pouvait avoir ; par exemple, pour avoir des démons qui écoutent via des sockets dans plusieurs espaces de noms à la fois.

Pour cela, il est maintenant possible d’interagir avec un namespace particulier en le désignant via le fichier « /proc/self/ns » et en affectant un processus à un espace de noms avec l’appel setns() .

Eric s’est prévalu de l’accord des développeurs travaillant sur les conteneurs et a expliqué que ses patches allaient faciliter leur travail en permettant une meilleure administration des espaces de noms.

La seule petite alerte s’est déroulée quand, le 21 juin dernier, Eric a envoyé à Linus une « demande de pull » pour corriger quelques erreurs dans son patch précédent. Comme l’objet du courriel était « nsfd fixes », Linus a été déconcerté et s’est demandé ce que venait faire le serveur NFS là‐dedans. Une fois le problème élucidé (il ne s’agissait pas de nFSd mais bien de nSFd comme dans Name Space File Descriptors), il a eu à endurer le courroux du mainteneur du noyau :

OK, c’est encore plus dingue que ce que je croyais.

Eric, merci d’arrêter d’utiliser des combinaisons aléatoires de lettres qui n’ont aucune signification pour personne à part toi. OK ?

Si tu ne veux pas te donner la peine d’écrire quelques lettres de plus et de rendre les choses lisibles, pourquoi est‐ce que tu devrais t’attendre à ce que les autres passent du temps à lire tes e‐mails ?

La contrition silencieuse étant l’une des meilleures défenses face à un Linus grognon, c’est la stratégie qu’a choisie Eric pour faire passer son patch.

Attributs étendus dans tmpfs

tmpfs (Temporary File System) est un système de fichiers particulier et simplifié qui n’existe que de façon temporaire en mémoire. Tout ce qui est stocké dessus disparaît lors d’un redémarrage de la machine. Fedora utilise par exemple intensivement tmpfs pour sa procédure de construction (build) de paquets RPM, et c’est à cette occasion qu’un souci est apparu. Depuis quelque temps, la tendance est d’utiliser les capacités POSIX sur les fichiers (POSIX file capabilities) pour augmenter la sécurité de certains paquets. Ces capacités reposent sur les attributs étendus ( xattr ) des systèmes de fichiers, puisque c’est là que sont stockées les capacités POSIX des fichiers. Les responsables Fedora ont donc simplement voulu introduire ces capacités sur les fichiers dans leur procédure de construction qui utilise tmpfs .

À ce stade, vous commencez certainement à soupçonner l’horrible vérité : tmpfs ne gère pas les attributs étendus, donc les capacités non plus, et par conséquent, il n’est pas possible de l’utiliser pour construire les paquets qui nécessitent ces capacités. Le drame…

Le développeur Eric Paris s’est donc retroussé les manches pour coder la gestion des attributs étendus nécessaires (uniquement ceux appartenant aux espaces de noms security.* et trusted.* ) et a placer ça sous l’option de configuration CONFIG_TMPFS_XATTR .

À partir de ce noyau Linux 3.0, il est donc maintenant parfaitement possible de gérer les capacités POSIX sur un système de fichiers tmpfs , et les responsables du build de Fedora ont retrouvé la paix de l’esprit et la sérénité de l’âme.

Unification ARM

Le noyau Linux 3.0 intègre le tout début du travail visant à mieux unifier le code de l’architecture ARM.

Depuis la polémique et les menaces proférées par Linus en avril dernier, la décision a été prise de rationaliser le code de l’architecture ARM, qui était devenu un joyeux dépotoir. Les développeurs du marché de l’embarqué sont connus pour avoir des pratiques sataniques perverses différentes par rapport au reste de la communauté du noyau. Les variantes entre les plates‐formes sont légions, tandis que le délai avant la mise sur le marché (time to market) est un facteur absolument crucial. Cela implique que les « bonnes pratiques » de réutilisation du code et de factorisation des développements sont assez peu respectées, et que les doublons de pilotes prolifèrent. Après que Linus eut sifflé la fin de la récréation, il fut décidé de mettre en place une structure de données dédiée (un device tree) pour décrire chaque carte ARM et chaque SoC (système mono‐puce).

Les patches intégrés jusqu’à présent sont modestes (préparation du device tree 1 - 2 et regroupement du code 1 - 2 - 3), mais les prochains noyaux verront l’intégration du gros du travail.

En tout cas, les foudres torvaldiennes ont été détournées, puisque Linus a signalé dans son entretien avec Greg Kroah‐Hartman qu’il était content d’avoir gueulé un bon coup et de constater que cela avait porté ses fruits.

WoWLAN

Le « Wake on LAN » (WoL), c’est tout simplement la possibilité de réveiller son ordinateur à distance en lui envoyant un message spécifique via le réseau. C’est une fonctionnalité fort utile, puisqu’on peut ainsi économiser de l’énergie en laissant une machine distante profondément endormie en veille ACPI S3. Dès qu’on en a besoin, il suffit de lui envoyer le paquet magique (une trame Ethernet contenant « FF FF FF FF FF FF » suivi par seize répétitions de l’adresse MAC de l’ordinateur cible) pour qu’elle sorte de son sommeil, telle une Cendrillon moderne.

Dans cette nouvelle version 3.0, le noyau Linux offre une prise en charge basique de la nouvelle fonction WoWLAN dans la pile Wi‐Fi générique. Rien à voir avec World of Warcraft, puisqu’en réalité, le WoWLAN (Wake on Wireless LAN) fait la même chose que le « Wake on LAN » classique, mais sans les fils !

Les patches de Johannes Berg (1 - 2) introduisent plusieurs « déclencheurs » (triggers) pour le réveil, car un réseau sans fil est plus complexe qu’un classique réseau Ethernet. Outre le traditionnel réveil avec le paquet magique ( NL80211_WOWLAN_TRIG_MAGIC_PKT ), on peut aussi utiliser la fonction de réveil automatique en cas de déconnexion ( NL80211_WOWLAN_TRIG_DISCONNECT ) ou en cas d’envoi de plusieurs paquets selon un schéma bien spécifique ( NL80211_WOWLAN_TRIG_PKT_PATTERN ).

Pilote Kinect

Une version préliminaire d’un pilote Kinect a été intégrée dans le noyau 3.0 dans le sous‐répertoire « gspca » qui accueille les webcams.

Kinect est un périphérique construit par Microsoft et destiné à être utilisé en complément de la console de jeu Xbox_360. Il permet la détection des mouvements et offre donc une interaction qui n’est plus basée sur l’utilisation d’une manette de jeu, mais sur les gestes du joueur.

La détection visuelle s’effectue via deux capteurs complémentaires : un capteur CCD couleur classique et un capteur CMOS monochrome renforcé par un laser infrarouge. Le laser a une résolution très grossière, mais il est juste utilisé pour évaluer la profondeur de la scène (depth map).

Le pilote présent dans Linux 3.0 est écrit par Antonio Ospite qui s’est basé sur du code issu du projet OpenKinect. Il permet de gérer le flux vidéo du capteur CCD couleur, ainsi que le flux vidéo du capteur CMOS monochrome. En revanche, il ne permet pas encore de récupérer les informations venant du laser IR, et il est donc pour l’instant incapable de générer une depth map.

Les futures versions du noyau verront l’intégration des fonctions manquantes une fois que le code OpenKinect aura été suffisamment nettoyé et mis aux normes strictes de Linux.

Redémarrage et UEFI

Le noyau 3.0 embarque plusieurs modifications concernant le redémarrage du système et la compatibilité UEFI. C’est Matthew Garrett (alias mjg59) qui s’est attaché à revoir en détail ce code sensible, afin de minimiser les conséquences de l’incurie des constructeurs. Bien souvent, ces derniers ne testent que pour Windows, et un redémarrage effectué sous Linux risque de ne pas se dérouler correctement. Dans son patch, Matthew explique qu’il a réordonné la séquence de redémarrage afin qu’elle corresponde à l’ordre de Windows, et que cette modification corrige des soucis de redémarrage avec, par exemple, certains portables Thinkpad.

Dans sa courageuse quête, mjg59 s’est également plongé dans le monde merveilleux de la compatibilité UEFI. Vous connaissez sans doute cette norme d’Intel destinée à remplacer le bon vieux BIOS de nos machines… Mais connaissez‐vous l’origine du nom ?

Réponse de Matthew dans son commit Git :

UEFI veut dire « Unified Extensible Firmware Interface » et on peut l’interpréter ainsi : firmware est un ancien mot africain signifiant « Pourquoi faire un truc de qualité, quand on peut le faire tellement pourri que les enfants pleureront et que les adultes se recroquevilleront devant vous ? », tandis que UEI est la version celtique de « Le DOS nous manque, alors on l’a gravé dans votre ROM ».

Le nouveau noyau accueille plusieurs patches visant à corriger les dysfonctionnements d’une couche UEFI mal écrite par le constructeur de la carte mère. Auparavant, le code du noyau Linux s’en tenait strictement à la norme, mais il a fallu ajouter des rustine correctrices, car, pour reprendre encore une fois les mots de Matthew :

Nous avons été d’une naïveté charmante en croyant que la spécification avait une quelconque importance dans le monde réel.

Savoir si encore plus de patches vont être intégrés dans les futures versions est assez difficile à deviner. Linus Torvalds a l’air de penser qu’il faut se contenter d’interagir le moins possible avec UEFI. Quand mjg59 a suggéré qu’UEFI mangeait 1 Mio à l’amorçage et qu’il devrait être possible d’écrire des patches permettant de récupérer cette mémoire, Linus a été clair :

Peu importe si cette mémoire est difficile à récupérer. Nous n’avons qu’à la laisser où elle est. UEFI est une abomination aux yeux de Dieu, et je suis foutrement sûr que nous ne devrions pas nous mettre en quatre pour corriger toutes ses stupidités.

Putains de co#%ards qui croient que nous voulons une interface extensible, alors que ce que nous voulons c’est l’interface la plus réduite possible et pas cette folie qu’est UEFI !

Optimisations de perf

Le développeur Lin Ming, qui travaille chez Intel, a introduit une optimisation dans le code de l’outil de profilage perf . C’est la commande « perf probe » qui est concernée, celle qui permet d’insérer des sondes (kprobe) au sein du code noyau pour l’instrumenter et évaluer les flux de données. Le fonctionnement précédent pouvait être lent quand il s’agissait de retrouver les noms de fonctions à sonder. Le nouveau chemin rapide de recherche (fastpath) permet de retrouver le nom en interrogeant directement la section « debug_pubnames » du format DWARF.

Avant d’accepter le patch, Ingo Molnar, toujours curieux, a demandé une quantification du gain, pour voir si l’ajout de ce fastpath en valait la peine. Les résultats sont assez impressionnants, puisque Lin Ming a annoncé les chiffres suivants pour la fonction find_probes() dans son message de commit :

avant application du patch : 848 490 844 cycles pour 0,355 secondes ;

après application du patch : 205 684 469 cycles pour 0,086 secondes.

Compilation et Warnings

Pour les milliards de barbus parmi vous qui méprisent les paquets pré‐compilés de leur distribution et qui préfèrent se mitonner un noyau aux petits oignons, il est bon de savoir que le Makefile du noyau Linux 3.0 a été modifié par Sam Ravnborg.

Auparavant, les fous qui osaient passer l’option « W=1 » lors du build (pour pouvoir voir tous les warnings émis par GCC) étaient submergés par un tsunami d’alertes diverses et variées. C’est, certes, assez comique de lire qu’il y a eu 92 919 alertes lors de la compilation, mais le charme s’émousse très rapidement. Après tout, quand on passe « W=1 » , c’est pour voir s’il n’y aurait pas quelque chose à corriger, alors il vaudrait mieux pouvoir filtrer les alertes non significatives et se concentrer sur les choses importantes.

C’est précisément l’objet du patch de Sam qui introduit une hiérarchie dans ce qui n’était auparavant qu’une soupe indifférenciée. Il y a maintenant trois niveaux différents qui donnent les résultats suivants :

avec « W=1 » : 4 859 alertes (les alertes qui pourraient éventuellement être importantes) ;

: 4 859 alertes (les alertes qui pourraient éventuellement être importantes) ; avec « W=2 » : 1 394 alertes (les alertes moins importantes) ;

: 1 394 alertes (les alertes moins importantes) ; avec « W=3 » : 86 666 alertes (les alertes ésotériques et probablement sans la moindre conséquence).

Le détail des options GCC de chaque niveau est visible ici. Sam Ravnborg a annoncé que son patch allait lui permettre de compiler systématiquement en mode « W=1 » et de creuser un peu les alertes, alors qu’avant il était découragé par le « bruit » que générait cette option.

Bien entendu, pour les masochistes nostalgiques, il est toujours possible de passer à « W=123 » pour retrouver le comportement précédent.

Belette strike back

Enfin, last but not least, avec ce passage en version 3.0, Linus a décidé qu’il était temps de changer également le nom par défaut du noyau. Après le célèbre « Flesh‐Eating Bats with Fangs » (Chauves‐souris mangeuses de chair avec des crocs) du noyau 2.6.36, il va maintenant falloir s’habituer à « Sneaky Weasel » (Belette sournoise) comme nom de code de Linux 3.0.

Cette bestiole est effectivement d’une sournoiserie peu commune, puisque c’est la seconde fois qu’elle fait son apparition, après la peu ragoûtante « Pink Farting Weasel » (Belette rose péteuse) du 2.6.23-rc4.

Statistiques et regard rétrospectif sur la série 2.6.x

Avec le passage à Linux 3.0, c’est une page de l’histoire du noyau qui se tourne.

Certes, ce changement de numérotation a été effectué uniquement pour simplifier les choses. Certes, le préfixe 2.6 n’avait plus guère de sens. Certes, le mode de développement de Linux reste ce qu’il était auparavant, et aucune technique révolutionnaire n’est intégrée. Il n’empêche que le passage à la version 3.0 est symbolique, et que cela représente une occasion de se retourner et de mesurer le chemin parcouru.

En ce qui concerne le cycle particulier du noyau 3.0, il faut bien dire qu’il n’a pas grand chose de remarquable. Boring à souhait, comme les aime Linus. Tout juste un peu plus calme que d’habitude, puisqu’on compte un peu plus de 9 000 patches écrits par 1 110 développeurs, pour un gain net d’environ 113 000 lignes de code dans l’arbre des sources. La seule spécificité un peu notable de ce cycle est le fait que le développeur le plus prolifique s’avère être employé par Microsoft : K. Y. Srinivasan a posté sur la LKML pas moins de 343 patches de nettoyage et de correction du pilote de virtualisation Hyper-V !

Comme le souligne avec un brin de perfidie Jonathan Corbet : « C’est impressionnant de voir combien de patches sont nécessaires pour nettoyer un pilote qui fait moins de 15 000 lignes de code. »

Même si la métrique du nombre de patches est criticable, j’ajouterais que le pilote Hyper-V de Microsoft, au moment de rentrer dans la branche staging en 2009, avait déjà subi une vigoureuse phase de nettoyage de plus de 200 patches écrits par Greg Kroah‐Hartman pour le rendre conforme au style de codage Linux.

Toujours est‐il que, pour ce cycle, la conséquence de cette incongruité statistique, c’est qu’en termes de patches, Microsoft apparaît en cinquième position des firmes ayant contribué à ce noyau Linux 3.0.

Toutefois, l’honneur est sauf, puisque Red Hat, Intel, Novell et IBM restent devant. :-)

Si l’on prend un peu de recul et qu’on regarde les statistiques de la série complète des 2.6.x, alors les chiffres deviennent plus intéressants. En lisant le document ODS de statistiques globales réalisé par Greg Kroah‐Hartman, on peut mieux se rendre compte de l’évolution quantitative qui s’est déroulée durant cette période.

La sortie officielle du noyau 2.6.0 a été annoncée par Linus le 18 décembre 2003. À cette époque lointaine et héroïque, il y avait dans l’arbre des sources seulement 15 007 fichiers pour un total de 5 929 913 lignes. Le noyau 2.6.39, dernier représentant de la glorieuse série des 2.6.x, est apparu sur les serveurs de kernel.org le 18 mai 2011. Ce beau bébé faisait 14 533 662 lignes réparties dans 36 706 fichiers.

En près de sept ans et demi, le noyau Linux a donc plus que doublé le nombre de ses fichiers (× 2,44), et il a également plus que doublé le nombre de ses lignes de code (× 2,45).

Et encore, ces chiffres émanent du document de Greg et ne prennent pas en compte le cycle du noyau 3.0, ni même les nombreux noyaux 2.5.x qui peuvent être considérés comme des versions candidates du 2.6.0. Si l’on adopte ce point de vue, plus large que la stricte limitation aux noyaux ayant le préfixe 2.6.x, alors les statistiques sont encore plus frappantes : 291 664 patches contribués par 8 078 développeurs différents et, en 9 ans et demi, un ajout d’environ 10,5 millions de lignes de code par rapport au noyau 2.4 !

Ces chiffres reflètent l’incroyable succès du modèle de développement progressivement choisi pour le noyau Linux dans la série 2.6.x. Le remplacement des simples courriels envoyés à Linus par l’utilisation de BitKeeper, puis de Git. La fin des version quasi‐figées, comme le 2.4.x, et le choix d’une progression rapide, avec des nouvelles versions stables qui sortent tous les trois mois. Tout ceci fonctionne très bien et représente un grand progrès par rapport au modèle précédent.

Au fil des années, le processus s’est même affiné : nous avons maintenant des versions spécifiques du noyau qui sont maintenues à long terme, la fameuse branche stable de Greg Kroah‐Hartman. Pour résoudre le problème récurrent des pilotes qui vivent en dehors de la mainline, la solution d’une antichambre spéciale a été retenue : c’est la fameuse branche staging, qui est également maintenue par Greg Kroah‐Hartman.

Tiens, je m’aperçois qu’entre son document ODS de statistiques et ses diverses tâches de mainteneur, on retrouve souvent le nom de Greg Kroah‐Hartman dans ce texte. Afin de finir dignement cette dépêche, pourquoi ne pas en profiter pour lui poser quelques questions ? Après tout, il fait partie des chevaliers de la table ronde de Linux, puisqu’il a été identifié dans un article de LWN comme étant l’un des très rares contributeurs ayant envoyé au moins un patch dans chaque version depuis le 2.6.0.

Mais un pico‐entretien alors, parce que Greg a une charge de travail absolument colossale !

LinuxFr.org : Bonjour Greg. J’écris un article sur le noyau pour le site LinuxFr.org. Est‐ce que tu es OK pour que je t’interroge rapidement au sujet du modèle de développement ?

Greg Kroah‐Hartman : Tu peux toujours poser tes questions, n’hésite pas.

LinuxFr.org : De nos jours, avec la puissance de Git, cela semble incroyable que les anciennes versions du noyau aient pu sortir sans aucun gestionnaire de code. Comment était‐ce à l’époque ? Est‐ce que tu peux décrire cet âge des ténèbres du noyau ?

Greg K‐H : Ce n’était pas du tout « l’âge des ténèbres », et ce mode de développement marchait très correctement. C’est juste qu’à l’époque nous ne réalisions pas que nous aurions pu aller encore plus vite que ce que nous faisions alors. :)

LinuxFr.org : Est‐ce que tu peux nous décrire la situation actuelle du Linux Driver Project que tu as créé ? Est‐ce que c’est un succès ?

Greg K‐H : Je pense que c’est un succès du fait qu’il n’existe pas, à l’heure actuelle et à ma connaissance, de périphérique sans pilote Linux. Il s’est avéré que nous n’avions pas réellement de nouveaux pilotes à écrire pour ce projet, juste des tonnes de pilotes qui existaient en dehors de la branche principale et que nous devions intégrer proprement. Donc, nous avons réorienté notre effort vers la partie staging, qui contient les pilotes qui n’ont pas la qualité « normale » des autres parties du noyau. Ils restent là, et après qu’ils ont été nettoyés, ils peuvent enfin migrer vers leur « vraie » section dans le noyau. Si tu regardes l’effort de développement qui est consacré à cette portion du noyau, tu verras à quel point c’est actif (des milliers de patches par version).

LinuxFr.org : Si tu devais résumer tout le cycle 2.6.x, que dirais‐tu ? Quelle est la principale réussite ?

Greg K‐H : Tu veux que je te résume huit années en quelques phrases ? Eh, désolé, mais ça ne va pas être possible. :)

Que penses‐tu de : « Nous faisons maintenant des sorties à périodicité fixe, avec un nouveau noyau stable tous les trois mois, et nous avons une procédure en place pour assurer le maintien des vieux noyaux, tandis que le nouveau est développé en vue de la prochaine version. » ?

En résumé, notre modèle de développement est bien meilleur maintenant, notre rythme d’intégration des changements est incroyable et nous continuons à augmenter le nombre de contributeurs à chaque version.

LinuxFr.org : Après Git, après la branche staging, quelle est la prochaine étape pour encore améliorer le mode de développement du noyau ?

Greg K‐H : Qu’est‐ce qui ne va pas dans notre mode de développement actuel et qui a besoin d’être amélioré ? Sérieusement, j’aimerais le savoir. Nous évaluons en permanence notre façon de travailler et nous faisons des changements en fonction des problèmes que nous rencontrons.

LinuxFr.org : En dépit des réussites du cycle 2.6.x, les systèmes à base de noyau Linux n’ont pas percé sur le bureau. Est‐ce que la communauté de développement du noyau peut y faire quelque chose, ou bien est‐ce une question qui relève essentiellement de l’espace utilisateur ?

Greg K‐H : C’est essentiellement un problème lié aux constructeurs. À part quelques exceptions, ils ne veulent pas fournir Linux sur leurs machines pour leurs clients, et cela pour des raisons économiques plutôt valables.

Cela va simplement prendre du temps, mais je ne suis pas inquiet, nous ne sommes pas près de disparaître. :)

LinuxFr.org : Pour finir, une question personnelle. Tu es le mainteneur du sous‐système USB, du sous‐système « driver core », de sysfs , etc.. Tu es aussi responsable de la série stable et de la branche staging. Tu donnes de nombreuses conférences sur le noyau. Comment est‐il possible de faire face à autant de tâches à la fois ?

Greg K‐H : Oh, n’oublie pas que j’ai aussi un vrai travail à faire en même temps. :)

Je ne sais pas comment c’est possible. Une bonne gestion du temps peut‐être ? Est‐ce qu’un oiseau peut expliquer aux autres comment il est possible de voler ? C’est juste une réponse naturelle à ce qu’il a besoin de faire.

LinuxFr.org : OK Greg, merci pour tes réponses et bon vol pour toi et pour les noyaux 3.x. ;-)

Aller plus loin