Les espaces de noms montage permettent d'isoler la liste des montages vus par les processus dans chaque instance d’espace de noms. Ainsi, les processus dans chacune des instances d’espace de noms montage verront les hiérarchies distinctes d’un répertoire unique.
Les vues fournies par les fichiers /proc/pid/mounts, /proc/pid/mountinfo, et /proc/pid/mountstats (tous décrits dans proc(5)) correspondent à l’espace de noms montage dans lequel le processus avec le PID pid réside (tous les processus dans le même espace de noms montage voient la même chose dans ces fichiers).
Un nouvel espace de noms montage est créé en utilisant soit clone(2) ou unshare(2) avec l’attribut CLONE_NEWNS. Quand un nouvel espace de noms montage est créé, sa liste de montages est initialisée comme suit :
Des modifications ultérieures de la liste de montages (mount(2) et umount(2)) dans chaque espace de noms montage n’affecteront pas (par défaut) la liste de montages vue dans l’autre espace de noms (mais voir les explications ci-après sur les sous-arbres partagés).
Chaque montage est marqué (à l’aide de mount(2)) comme ayant un des types de propagation suivants :
Pour des explications sur le type de propagation assigné à un nouveau montage, consulter la section NOTES.
Le type de propagation est un réglage spécifique à chaque point de montage. Certains montages peuvent être marqués comme partagés (chaque montage partagé étant un membre d’un groupe de pairs distinct) tandis que d’autres sont privés (ou esclaves ou non liables).
Il est à noter que le type de propagation d’un montage détermine si les mount(2) et umount(2) de montages immédiatement sous le montage sont propagées. Par conséquent, le type de propagation n’affecte pas la propagation d’évènements pour les petits-enfants et les futurs montages de descendants supprimés. Ce qui se passe si le montage lui-même est démonté dépend du type de propagation en vigueur pour le parent du montage.
Des membres sont ajoutés à un groupe de pairs quand un montage est marqué comme partagé et soit :
Dans les deux cas, le nouveau montage rejoint le groupe de pairs dont le montage existant est membre.
Un nouveau groupe de pairs est aussi créé quand un montage enfant est créé sous un montage existant marqué comme partagé. Dans ce cas, le nouveau montage enfant est aussi marqué comme partagé et le nouveau groupe de pairs résultant est constitué de tous les montages qui sont répliqués sous les pairs des montages parents.
Un montage cesse d’être membre d’un groupe de pairs quand le montage est explicitement démonté ou quand le montage est implicitement démonté parce qu’un espace de noms montage est supprimé (parce qu’il n’a plus de processus membre).
Le type de propagation des montages dans l’espace de noms montage peut être obtenu à l’aide des « champs facultatifs » exposés dans /proc/pid/mountinfo (consulter proc(5) pour plus de détails sur ce fichier). Les étiquettes suivantes peuvent apparaitre dans ces champs facultatifs pour un enregistrement de ce fichier :
Si aucune de ces étiquettes n’est présente, alors c’est un montage privé.
sh1# mount --make-shared /mntS sh1# mount --make-private /mntP sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 77 61 8:17 / /mntS rw,relatime shared:1 83 61 8:15 / /mntP rw,relatime
Dans la sortie /proc/self/mountinfo, on voit que /mntS est un montage partagé dans le groupe de pairs 1 et que /mntP n’a pas d’étiquette facultative, indiquant que c’est un montage privé. Les deux premiers champs de chaque enregistrement dans ce fichier sont l’ID unique pour ce montage et l’ID de montage du montage parent. Ce fichier peut être inspecté ultérieurement pour vérifier que le montage parent de /mntS et /mntP est le répertoire racine /, qui est monté comme privé :
sh1# cat /proc/self/mountinfo | awk '$1 == 61' | sed 's/ - .*//' 61 0 8:2 / / rw,relatime
Dans un second terminal, créons un nouvel espace de noms montage où un deuxième interpréteur est exécuté et inspectons les montages :
$ PS1='sh2# ' sudo unshare -m --propagation unchanged sh sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 222 145 8:17 / /mntS rw,relatime shared:1 225 145 8:15 / /mntP rw,relatime
Le nouvel espace de noms montage reçoit une copie des montages initiaux d’espace de noms montage. Ces nouveaux montages conservent les mêmes types de propagation, mais ont des ID uniques de montage (l’option --propagation unchanged empêche unshare(1) de marquer tous les montages comme privés lors de la création d’un nouvel espace de noms montage, ce qui est réalisé par défaut).
Dans le second terminal, créons alors des sous-montages sous chacun des /mntS et /mntP et inspectons la configuration :
sh2# mkdir /mntS/a sh2# mount /dev/sdb6 /mntS/a sh2# mkdir /mntP/b sh2# mount /dev/sdb7 /mntP/b sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 222 145 8:17 / /mntS rw,relatime shared:1 225 145 8:15 / /mntP rw,relatime 178 222 8:22 / /mntS/a rw,relatime shared:2 230 225 8:23 / /mntP/b rw,relatime
Dans ce qui précède, on peut voir que /mntS/a a été créé comme partagé (héritant ce réglage de son montage parent) et que /mntP/b a été créé comme montage privé.
En retournant dans le premier terminal et en inspectant la configuration, on peut voir que le nouveau montage créé sous le montage partagé /mntS s’est propagé vers son montage pair (dans l’espace de noms montage initial), mais que le nouveau montage créé sous le montage privé /mntP ne s’est pas propagé :
sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 77 61 8:17 / /mntS rw,relatime shared:1 83 61 8:15 / /mntP rw,relatime 179 77 8:22 / /mntS/a rw,relatime shared:2
L’effet de l’asservissement peut être démontré en d’abord marquant deux montages comme partagés dans l’espace de noms montage initial :
sh1# mount --make-shared /mntX sh1# mount --make-shared /mntY sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 132 83 8:23 / /mntX rw,relatime shared:1 133 83 8:22 / /mntY rw,relatime shared:2
Dans un second terminal, créons un nouvel espace de noms montage et inspectons les montages :
sh2# unshare -m --propagation unchanged sh sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 168 167 8:23 / /mntX rw,relatime shared:1 169 167 8:22 / /mntY rw,relatime shared:2
Dans le nouvel espace de noms montage marquons un des montages comme esclave :
sh2# mount --make-slave /mntY sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 168 167 8:23 / /mntX rw,relatime shared:1 169 167 8:22 / /mntY rw,relatime master:2
Dans la sortie ci-dessus, nous voyons que /mntY est désormais un montage esclave qui reçoit les évènements de propagation du groupe de pairs partagé avec l’ID 2.
En continuant dans le nouvel espace de noms, créons des sous-montages sous chaque /mntX et /mntY :
sh2# mkdir /mntX/a sh2# mount /dev/sda3 /mntX/a sh2# mkdir /mntY/b sh2# mount /dev/sda5 /mntY/b
Si nous inspectons l’état des montages dans le nouvel espace de noms montage, nous voyons que /mntX/a a été créé comme nouveau montage partagé (héritant du réglage « partagé » de son montage parent) et que /mntY/b a été créé comme montage privé :
sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 168 167 8:23 / /mntX rw,relatime shared:1 169 167 8:22 / /mntY rw,relatime master:2 173 168 8:3 / /mntX/a rw,relatime shared:3 175 169 8:5 / /mntY/b rw,relatime
En retournant dans le premier terminal (dans l’espace de noms montage initial) nous voyons que le montage /mntX/a s’est propagé au pair (le /mntX partagé), mais que le montage /mntY/b ne s’est pas propagé :
sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 132 83 8:23 / /mntX rw,relatime shared:1 133 83 8:22 / /mntY rw,relatime shared:2 174 132 8:3 / /mntX/a rw,relatime shared:3
Créons maintenant un nouveau montage sous /mntY dans le premier interpréteur :
sh1# mkdir /mntY/c sh1# mount /dev/sda1 /mntY/c sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 132 83 8:23 / /mntX rw,relatime shared:1 133 83 8:22 / /mntY rw,relatime shared:2 174 132 8:3 / /mntX/a rw,relatime shared:3 178 133 8:1 / /mntY/c rw,relatime shared:4
Quand nous examinons les montages dans le second espace de noms montage, nous voyons que dans ce cas le nouveau montage s’est propagé au montage esclave et que le nouveau montage lui-même est un montage esclave (au groupe de pairs 4) :
sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 168 167 8:23 / /mntX rw,relatime shared:1 169 167 8:22 / /mntY rw,relatime master:2 173 168 8:3 / /mntX/a rw,relatime shared:3 175 169 8:5 / /mntY/b rw,relatime 179 169 8:1 / /mntY/c rw,relatime master:4
En supposant l’existence d’un système avec les montages suivants :
# mount | awk '{print $1, $2, $3}' /dev/sda1 on / /dev/sdb6 on /mntX /dev/sdb7 on /mntY
Supposons de plus que nous voulons de manière récursive monter lié (bind) le répertoire racine sous plusieurs répertoires home d’utilisateurs. Faisons-le pour le premier utilisateur et inspectons les montages :
# mount --rbind / /home/cecilia/ # mount | awk '{print $1, $2, $3}' /dev/sda1 on / /dev/sdb6 on /mntX /dev/sdb7 on /mntY /dev/sda1 on /home/cecilia /dev/sdb6 on /home/cecilia/mntX /dev/sdb7 on /home/cecilia/mntY
Lorsque nous répétons cette opération pour le second utilisateur, le problème de l’explosion commence à apparaitre :
# mount --rbind / /home/henry # mount | awk '{print $1, $2, $3}' /dev/sda1 on / /dev/sdb6 on /mntX /dev/sdb7 on /mntY /dev/sda1 on /home/cecilia /dev/sdb6 on /home/cecilia/mntX /dev/sdb7 on /home/cecilia/mntY /dev/sda1 on /home/henry /dev/sdb6 on /home/henry/mntX /dev/sdb7 on /home/henry/mntY /dev/sda1 on /home/henry/home/cecilia /dev/sdb6 on /home/henry/home/cecilia/mntX /dev/sdb7 on /home/henry/home/cecilia/mntY
Sous /home/henry, nous n'avons pas seulement ajouté récursivement les montages /mntX et /mntY, mais aussi les montages récursifs de ces répertoires sous /home/cecilia qui ont été créés dans l’étape précédente. Si nous répétons cela pour un troisième utilisateur, il devient évident que l’explosion est de nature exponentielle :
# mount --rbind / /home/otto # mount | awk '{print $1, $2, $3}' /dev/sda1 on / /dev/sdb6 on /mntX /dev/sdb7 on /mntY /dev/sda1 on /home/cecilia /dev/sdb6 on /home/cecilia/mntX /dev/sdb7 on /home/cecilia/mntY /dev/sda1 on /home/henry /dev/sdb6 on /home/henry/mntX /dev/sdb7 on /home/henry/mntY /dev/sda1 on /home/henry/home/cecilia /dev/sdb6 on /home/henry/home/cecilia/mntX /dev/sdb7 on /home/henry/home/cecilia/mntY /dev/sda1 on /home/otto /dev/sdb6 on /home/otto/mntX /dev/sdb7 on /home/otto/mntY /dev/sda1 on /home/otto/home/cecilia /dev/sdb6 on /home/otto/home/cecilia/mntX /dev/sdb7 on /home/otto/home/cecilia/mntY /dev/sda1 on /home/otto/home/henry /dev/sdb6 on /home/otto/home/henry/mntX /dev/sdb7 on /home/otto/home/henry/mntY /dev/sda1 on /home/otto/home/henry/home/cecilia /dev/sdb6 on /home/otto/home/henry/home/cecilia/mntX /dev/sdb7 on /home/otto/home/henry/home/cecilia/mntY
Le problème de l’explosion de montages dans le scénario précédent peut être évité en rendant chaque nouveau montage non liable. Ainsi les montages récursifs du répertoire racine ne répliqueront pas les montages non liables. Un tel montage pour le premier utilisateur peut être effectué ainsi :
# mount --rbind --make-unbindable / /home/cecilia
Avant d’aller plus loin, nous montrons que les montages non liables le sont effectivement :
# mkdir /mntZ
# mount --bind /home/cecilia /mntZ
mount: wrong fs type, bad option, bad superblock on /home/cecilia,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so.
Maintenant nous créons des montages bind récursifs non liables pour les deux autres utilisateurs :
# mount --rbind --make-unbindable / /home/henry # mount --rbind --make-unbindable / /home/otto
Un examen de la liste des montages permet de voir qu’il n’y a eu aucune explosion des montages parce que les montages non liables n’ont pas été répliqués sous chaque répertoire d’utilisateur :
# mount | awk '{print $1, $2, $3}' /dev/sda1 on / /dev/sdb6 on /mntX /dev/sdb7 on /mntY /dev/sda1 on /home/cecilia /dev/sdb6 on /home/cecilia/mntX /dev/sdb7 on /home/cecilia/mntY /dev/sda1 on /home/henry /dev/sdb6 on /home/henry/mntX /dev/sdb7 on /home/henry/mntY /dev/sda1 on /home/otto /dev/sdb6 on /home/otto/mntX /dev/sdb7 on /home/otto/mntY
| make-shared | make-slave | make-priv | make-unbind | ||
| shared | shared | slave/priv [1] | priv | unbind | |
| slave | slave+shared | slave [2] | priv | unbind | |
| slave+shared | slave+shared | slave | priv | unbind | |
| private | shared | priv [2] | priv | unbind | |
| unbindable | shared | unbind [2] | priv | unbind | |
Prenez note des détails suivants à propos de la table :
mount --bind A/a B/b
Ici, A est le montage source, B est le montage de destination, a est un chemin de sous-répertoire sous le point de montage A et b est un chemin de sous-répertoire sous le point de montage B. Le type de propagation du montage résultant, B/b, dépend des types de propagation des montages A et B, et cela est résumé dans la table suivante.
| source(A) | ||||||
| shared | private | slave | unbind | |||
| dest(B) | shared | shared | shared | slave+shared | non valable | |
| non partagé | shared | private | slave | non valable | ||
Remarquez qu’un bind récursif d’un sous-arbre suit les mêmes sémantiques que pour une opération bind sur chaque montage dans le sous-arbre (les montages non liables sont automatiquement élagués à la cible du montage cible).
Pour de plus amples explications, consulter Documentation/filesystems/sharedsubtree.rst dans l’arbre des sources du noyau.
mount --move A B/b
Ici, A est le montage source, B est le montage de destination et b est un chemin de sous-répertoire sous le point de montage B. Le type de propagation du montage résultant, B/b, dépend des types de propagation des montages A et B, et cela est résumé dans la table suivante.
| source(A) | ||||||
| shared | private | slave | unbind | |||
| dest(B) | shared | shared | shared | slave+shared | non valable | |
| non partagé | shared | private | slave | unbindable | ||
Remarque : déplacer un montage qui réside sous un montage partagé n’est pas autorisé.
Pour de plus amples explications, consulter Documentation/filesystems/sharedsubtree.rst dans l’arbre des sources du noyau.
mount device B/b
Ici, B est le montage de destination et b est un chemin de sous-répertoire sous le point de montage B. Le type de propagation du montage résultant, B/b, suit les mêmes règles que pour un montage bind où le type de propagation du montage source est toujours considéré comme privé.
umount A
Ici, A est un montage dans B/b, où B est le montage parent et b est un chemin de sous-répertoire sous le point de montage B. Si B est partagé, alors tous les montages les plus récemment montés dans b sur des montages qui reçoivent la propagation du montage B et qui n’ont pas de sous-montages sous eux sont démontés.
Dans l’exemple suivant, créons d’abord une chaine maitre-esclave à deux liens entre les montages /mnt, /tmp/etc et /mnt/tmp/etc. Ensuite la commande chroot(1) est utilisée pour rendre le point de montage /tmp/etc inaccessible à partir du répertoire racine, créant une situation où le maitre de /mnt/tmp/etc n’est pas accessible à partir du (nouveau) répertoire racine du processus.
D’abord mous montons lié (bind) le répertoire racine sur /mnt, puis nous montons lié /proc sous /mnt/proc de telle façon qu’après le chroot(1) ultérieur, le système de fichiers proc(5) demeure visible dans l’emplacement correct de l’environnement chrooté.
# mkdir -p /mnt/proc # mount --bind / /mnt # mount --bind /proc /mnt/proc
Ensuite, nous nous assurons que le montage /mnt est un montage partagé dans un nouveau groupe de pairs (sans aucun pair) :
# mount --make-private /mnt # Isolation de n’importe quel groupe de pairs précédent # mount --make-shared /mnt # cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//' 239 61 8:2 / /mnt ... shared:102 248 239 0:4 / /mnt/proc ... shared:5
Ensuite, nous montons lié /mnt/etc sur /tmp/etc :
# mkdir -p /tmp/etc # mount --bind /mnt/etc /tmp/etc # cat /proc/self/mountinfo | egrep '/mnt|/tmp/' | sed 's/ - .*//' 239 61 8:2 / /mnt ... shared:102 248 239 0:4 / /mnt/proc ... shared:5 267 40 8:2 /etc /tmp/etc ... shared:102
Initialement, ces deux montages sont dans le même groupe de pairs, mais nous rendons /tmp/etc esclave de /mnt/etc et nous rendons aussi /tmp/etc partagé, de telle façon qu’il puisse propager les évènements au prochain esclave dans la chaine :
# mount --make-slave /tmp/etc # mount --make-shared /tmp/etc # cat /proc/self/mountinfo | egrep '/mnt|/tmp/' | sed 's/ - .*//' 239 61 8:2 / /mnt ... shared:102 248 239 0:4 / /mnt/proc ... shared:5 267 40 8:2 /etc /tmp/etc ... shared:105 master:102
Ensuite nous montons lié /tmp/etc sur /mnt/tmp/etc. De nouveau, les deux montages sont initialement dans le même groupe de pairs, mais nous faisons alors de /mnt/tmp/etc un esclave de /tmp/etc :
# mkdir -p /mnt/tmp/etc # mount --bind /tmp/etc /mnt/tmp/etc # mount --make-slave /mnt/tmp/etc # cat /proc/self/mountinfo | egrep '/mnt|/tmp/' | sed 's/ - .*//' 239 61 8:2 / /mnt ... shared:102 248 239 0:4 / /mnt/proc ... shared:5 267 40 8:2 /etc /tmp/etc ... shared:105 master:102 273 239 8:2 /etc /mnt/tmp/etc ... master:105
De ce qui précède, nous voyons que /mnt est le maitre de l’esclave /tmp/etc, qui à son tour est le maitre de l’esclave /mnt/tmp/etc.
Puis nous effectuons un chroot(1) sur le répertoire /mnt, ce qui rend le montage avec l’ID 267 inaccessible à partir du (nouveau) répertoire racine :
# chroot /mnt
Lorsque nous examinons l’état des montages à l’intérieur de l’environnement chrooté, nous voyons ce qui suit :
# cat /proc/self/mountinfo | sed 's/ - .*//' 239 61 8:2 / / ... shared:102 248 239 0:4 / /proc ... shared:5 273 239 8:2 /etc /tmp/etc ... master:105 propagate_from:102
Ci-dessus, nous voyons que le montage avec l’ID 273 est un esclave dont le maitre est le groupe de pairs 105. Le point de montage pour ce maitre est inaccessible, et donc, une étiquette propagate_from est affichée, indiquant que le groupe de pairs dominant le plus proche (c’est-à-dire le montage accessible le plus proche dans la chaine esclave) est le groupe de pairs avec l’ID 102 (correspondant au point de montage /mnt avant que le chroot(1) soit réalisé).
Malgré le fait que le type de propagation par défaut pour le nouveau montage soit dans de nombreux cas MS_PRIVATE, MS_SHARED est en général plus utile. Pour cette raison, systemd(1) remonte automatiquement tous les montages en MS_SHARED au démarrage du système. Par conséquent, sur la plupart des systèmes modernes, le type de propagation par défaut est en pratique MS_SHARED.
Puisque lorsqu'on utilise unshare(1) pour créer un espace de noms montage, le but est couramment de fournir une isolation totale des montages dans le nouvel espace de noms, unshare(1) (depuis util-linux 2.27) à son tour inverse l’étape réalisée par systemd(1), en rendant tous les montages privés dans le nouvel espace de noms. C’est-à-dire que unshare(1) réalise l’équivalent de ce qui suit dans le nouvel espace de noms montage :
mount --make-rprivate /
Pour empêcher cela, on peut utiliser l’option --propagation unchanged de unshare(1).
Une application qui crée un nouvel espace de noms montage directement en utilisant clone(2) ou unshare(2) peut vouloir empêcher la propagation d’évènements de montage aux autres espaces de noms montage (comme cela est réalisé par unshare(1)). Cela peut être effectué en changeant le type de propagation de montages dans le nouvel espace de noms à MS_SLAVE ou MS_PRIVATE, en utilisant l'appel suivant :
mount(NULL, "/", MS_SLAVE | MS_REC, NULL);
Pour des explications sur les types de propagation lors de déplacements de montages (MS_MOVE) et de créations de montages liés (MS_BIND), consulter Documentation/filesystems/sharedsubtree.rst.
Documentation/filesystems/sharedsubtree.rst dans l’arbre des sources du noyau.
Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à