# [Tip] De l'art de gérer ses sources de noyaux

## TGL

J'sais pas vous mais moi, en ce moment, j'ai d'installé development-sources, mm-sources, gentoo-dev-sources. Les version grimpent vite, je suis en ~arch, j'update souvent, y'a des paquets pour chaque -rc, bref je me retrouve facilement avec 3 ou 4 nouveaux répertoires de sources par semaine. C'est parfois pénible...

* nettoyage:

Tous correspondent à des SLOT différents, donc les séances de nettoyage ressemblent typiquement à ça: 

```
% emerge -C =development-sources-2.6.2_rc1  =development-sources-2.6.2-rc2  =mm-sources-2.6.2_rc2-r1
```

 bref c'est chiant à taper, et en plus ça nettoie pas grand chose vu que ça ne supprime pas les fichiers compilés, donc on doit de toute façon aojuter un coup de  

```
% rm -rf /usr/src/linux-2.6.2-rc1 /usr/src/linux-2.6.2-rc2 /usr/src/linux-2.6.2-rc2-mm1
```

Ma façon de procéder est donc plutôt la suivante:

 - d'abord supprimer les répertoires dont on ne veut plus

 - ensuite, nettoyer automatiquement les paquets. Pour ça, j'utilise un petit script qui supprime les paquets correspondants à des sources effacées:  

```
#!/bin/bash

#/usr/local/sbin/clean-kernels

PROG=`basename ${0}`

if [ ! `whoami` = "root" ]; then

   echo "Error: you must be root." >&2

   exit 1

fi

if [ $# -gt 1 ] ; then

   echo "Usage: $PROG [-p]" >&2

   exit 1

fi

if [ $# -eq 1 ] ; then

   if [ "$1" == "-p" ]; then

      pretend="-p"

   else

      echo "Usage: $PROG [-p]" >&2

      exit 1

   fi

else

   pretend=""

fi

kdirs="$(find /usr/src -maxdepth 1 -type d -name "linux-[0-9]*")"

find_pkgs() {

   for d in /var/db/pkg/sys-kernel/* ; do

      if [ -f ${d}/CONTENTS ] ; then

         if grep -q /usr/src/linux ${d}/CONTENTS ; then

            if ( for k in ${kdirs} ; do 

                    grep -qx "dir ${k}" ${d}/CONTENTS && exit 1 

                 done

                 exit 0 )

            then

               echo "${d}"

            fi

         fi

      fi

   done | sed 's:/var/db/pkg/:=:'

}

kpgs=$(find_pkgs)

if [ -n "${kpgs}" ]; then

   /usr/bin/emerge -C ${pretend} `find_pkgs`

   exit $?

else

   echo "No kernel packages to clean was found."

   exit 0

fi
```

* /usr/src/linux :

Pareil, à chaque fois qu'on change de noyau, on doit se cogner un lien symbolique /usr/src/linux (important au moins si on veut emerger des drivers pour ce noyau). Comme je suis une grosse flemme et que refaire ce lien à la main me gonfle, j'utilise une petite fonction bash, définie dans mon /root/.bash_profile: 

```
### setkernel: change the /usr/src/linux symlink.

### See also completion function in /etc/bash_completion.d/tgl

setkernel() {

   if [ $# -lt 1 ] ; then

      echo "Usage: setkernel <version>" >&2

      return 1

   fi

   version="$1"

   if [ ! -d "/usr/src/linux-${version}" ] ; then

      echo "Error: not found /usr/src/linux-${version}" >&2

      return 1

   fi

   rm -f /usr/src/linux

   ln -sf ./linux-${version} /usr/src/linux

   # never realy understood what linux-beta was for, but anyway...

   rm -f /usr/src/linux-beta

   ln -sf ./linux-${version} /usr/src/linux-beta

   return 0

}
```

  Et comme je suis encore plus flemmard que vous pouvez le croire, si si, j'insiste, j'ai une fonction de complétion pour bash qui me propose juste les versions disponibles. Vous pouvez mettre ça dans un fichier quelconque, dans /etc/bash_completion.d (de préférence un fichier à vous, pour pas être gêné par les mises à jours des fichiers officiels). Ça suppose bien sûr que vous ayez d'installé le paquet bash-completion, mais vous l'avez, non? 

```

# setkernel <version>

# (function from /root/.bash_profile)

_setkernel()

{

   local cur versions

   versions=$( find /usr/src -maxdepth 1 -type d -name "linux-*" \

      | sed -e 's:/usr/src/linux\-::' )

   cur=${COMP_WORDS[COMP_CWORD]}

   COMPREPLY=( $( compgen -W "$versions" -- $cur ) )

   return 0

}

complete -F _setkernel setkernel
```

Voilà, c'est tout, pas grand chose en fait mais un système un tout petit peu plus confortable encore  :Wink: Last edited by TGL on Thu Jan 20, 2005 2:56 pm; edited 1 time in total

----------

## Apolonius

Ce que je trouve très pénible sous gentoo est la désinstallation des kernel par un emerge -C, c'est bien trop long comparé à un rm -rf /usr/linux-*.

----------

## TGL

 *Apolonius wrote:*   

> Ce que je trouve très pénible sous gentoo est la désinstallation des kernel par un emerge -C, c'est bien trop long comparé à un rm -rf /usr/linux-*.

 

Exactement. Mais le problème des "rm -rf", c'est que ça ne dit pas à portage que le paquet tu n'en veux plus. D'où mon script de nettoyage: toi tu fais juste des rm, et le script se charge des unmerge.

Ou bien tu parles en termes de performances peut-être ? Déso, je viens seulement de comprendre. Alors oui, dans certains cas, un unmerge de noyau me prend 10 minutes contre pas grand chose pour un simple "rm -rf". Tu sais ce qui provoque la plus grande part de cette différence ? C'est l'affichage de la liste des 12000 fichiers nettoyés.  :Smile: 

Python est lent pour les opération d'entrée/sortie (d'un ordre de grandeur pas négligeable, genre 10 fois plus lent que perl dans des benchs que j'avais vu et dont la simplicité ne saurait mentir), et surtout la plupart des terminaux sous X sont carrément _affreusement_ lents. Compare un unmerge de kernel dans un gnome-terminal avec la même chose dans une console linux non-framebufferisée, c'est flagrant.

Une solution si tu ne veux pas aller en console est de faire ton unmerge avec un ">/dev/null" (ou un "> fichier.log"). Ça se ressent très nettement. Une autre solution serait de rendre emerge plus silencieux quand on lui file l'option "-q". Ça c'est bug #37491.

----------

## Apolonius

J'ai remarqué que les kernels sont bcp + longs à désinstaller qu'à installer lorsqu'on passe par emerge. Comment expliques-tu cette différence de temps ?

----------

## TGL

Comment je l'explique ? Mal.  :Rolling Eyes: 

Quand on vire le dump de la liste des fichiers, il n'y a plus vraiment de différence visible. Donc c'est bien toujours cette histoire d'affichage. Mais en fait, le surcoût de temps de cet affichage à l'air de beaucoup dépendre de ce qui est fait en même temps : si tu fais en python une boucle pour afficher 12000 ligne de test, même dans un gnome-terminal, ça ne prend si longtemps... Donc je sais pas trop, je suppose que le problème est surtout quand il y a des changements de contexte pour chacun des fichiers unmergés (genre: d'abord executer qlqs lignes de python, ensuite forker un "rm", ensuite revenir à python pour faire print, et enfin passer au terminal pour qu'il affiche la ligne - enfin je dit ça au pif, j'ai pas le code sous le nez), ou qqch comme ça. Si ça se trouve, un changement de contexte en moins par étape au merge, et ça bourre tout de suite plus. 

Dans le genre bizarrerie, on peut remarquer que suivant le scheduler (noyau 2.4, 2.6, 2.4-ck) utilisé et la priorité (niceness) donnée à emerge, on obtient des perfs bien différentes, même si on a rien d'autre qui tourne (alors qu'un processus nicé est censé choper un max de cpu si il est tout seul, et puis c'est tout), ou encore que suivant le nice, virer la sortie standard peut aussi faire baisser les perfs (parceque le noyau ne voit pas le processus comme interactif, et donc n'utilise pas les même quantum de temps dans le scheduling, ce genre de truc). Bref, c'est encore bien mystérieux tout ça, et je me contente du coup d'appliquer des recettes qui pour moi marche bien (mon patch pour le mode quiet, en niçant pas trop emerge).

----------

## Apolonius

Merci pour tes explications.

Pourquoi ne pas proposer une sorte d'emerge simplifié pour les kernels, qui ne copierait pas la liste des fichiers ?. Autant, cette liste (CONTENTS) est utile pour les autres ebuilds car elle permet de savoir si des fichiers ont été remplacés, autant ce n'est pas utile pour les kernels parce que la bonne vieille technique du symlink /usr/src/linux permet d'éviter ce genre de désagrément.   

 Je dois avouer que je ne connais pas portage ni python, il est possible qu'il y ait de bonnes raisons de ne pas procéder ainsi qui m'échappent.

----------

## TGL

Ah, le merge brutal... 

<mode="ma vie">

Tu vois, c'est précisement une idée que j'ai eu il y a qlqs mois. En gros, je m'étais dit «Quand on sait pertinement qu'un package est le seul à installer des fichiers dans un certain répertoire, alors on peut merger ce répertoire avec un simple "cp -R" et le supprimer avec un simple "rm -rf"». J'ai implémenté un assez gros patch pour portage pour mettre en oeuvre cette idée. J'appellais ça des "chemins sombres", parceque c'était des chemins le long desquels portage était aveugle, et ils étaient déclarés comme tels par les ebuilds. Y'avait en fait pas mal de choses aux quelles faire attention:

 - il fallait enregistrer ces chemins pour chaque paquet pour pouvoir les effacer

 - il fallait aussi les enregistrer globablement pour le système, pour être sûr qu'aucun paquet n'allait mettre des fichier dans un chemin déclaré sombre par un autre paquet

 - la mise à jour d'un paquet ayant des chemin sombre devait être précédée par la suppression des chemins sombres des paquet de version antérieur qu'il remplaçait, en tenant compte des SLOT de paquet

 - le tout devait être optionnel, mais être sûr quand même malgré des activation/désactivation successives

 - ...

J'ai bossé quelques jours là dessus, et j'étais content du résultat. Le boost de performances pour les paquets pathologiques comme les sources de noyaux (mais aussi d'autres comme les docs de Java, les classes d'Eclipse, etc.) était significatif, et le truc était je pense très sûr, même en cas de corruption de la base des paquets installés ou de l'index global (la redondance, y'a que ça de vrai pour faire des trucs qui tiennent la route à long termes sur des systèmes ou le root peut faire de fausses manips). J'ai même documenté la chose.

Et puis avant de la soumettre à bugzilla, je me suis dit qu'avec des benchs se serait plus convainquant. Par soucis d'équité, parceque le merge des chemins sombres se fesait sans lister son contenu dans le terminal, j'ai fait mes benchs avec la sortie redirigée sur /dev/null. Et bah le gain de performance est tout de suite passé d'un truc énorme à pas grand chose, pas assez pour que le jeu en vaille la chandelle. Ça n'était de merger intelligement les fichiers qui ralentissait emerge, mais bien de les lister dans le terminal. L'idée n'étais pas complètement fausse, mais pas vraiment intérressante. Je n'ai donc jamais soumis le patch, et je m'en suis un peu voulu quand même de n'avoir pensé à ça avant de faire le code...

Et du coup après c'est pour ça que j'ai fait les patchs du bug que je te citais plus haut, pour accélerer portage en le rendant moins verbeux. En plus à l'usage je trouve ça plus joli, moins scotchant surtout, et puis je ne perds plus les message importants (" * blablabla"), bref finallement je suis content. Mais quand même, sur le coup, je m'étais bien mordu les doigts.

</mode>

----------

## Apolonius

C'est cool. Ton post m'a fait comprendre l'interêt de ton patch https://bugs.gentoo.org/show_bug.cgi?id=37491

----------

## fidzysss

 *Quote:*   

> 
> 
> J'ai remarqué que les kernels sont bcp + longs à désinstaller qu'à installer lorsqu'on passe par emerge. Comment expliques-tu cette différence de temps ?
> 
> 

 

a priori je pense que c'est parce que dans le cas d'une installation, portage fais pas gaffe si il écrase un fichier, il se contente de les copiers. Mais quand il désinstalle, il vérifie si la le fichier a pas été modifier depuis.

C'est à vérifier mais ca pourrait éviter la différence de temps.

----------

## TGL

 *fidzysss wrote:*   

> a priori je pense que c'est parce que dans le cas d'une installation, portage fais pas gaffe si il écrase un fichier, il se contente de les copiers. Mais quand il désinstalle, il vérifie si la le fichier a pas été modifier depuis.

 

Bof bof, la quantité de boulot est à peu près la même quand même, parceque quand il merge il doit préparer les infos (date, md5...) pour le fichier CONTENTS. Niveau accès fichiers, on a :

- au merge: un stat, un calcul de md5 et un renommage ou déplacement ;

- à l'unmerge: un stat, un calcul de md5, et une suppression. 

Ça revient à peu près au même, ce qui se confirme par des temps similaires quand on vire le listage des fichiers dans le terminal.

----------

