\newpage

Des particularités de `mount`  {#mount}
=============================

## Les points de montage

Au premier abord, les points de montage dans l'arborescence d'un système de
fichiers n'ont pas l'air d'être remplis de notions complexes : un répertoire
peut être le point d'entrée d'un montage vers la partition d'un disque
physique... ou d'une partition virtuelle, comme nous l'avons vu au TP
précédent.

Mais avez-vous déjà essayé de monter la même partition d'un disque physique à
deux endroits différents de votre arborescence ?

Si pour plein de raisons on pouvait se dire que cela ne devrait pas être
autorisé, ce problème s'avère être à la base de beaucoup de fonctionnalités
intéressantes. Le noyau va finalement décorréler les notions de montage,
d'accès et d'accroches dans l'arborescence : et par exemple, une partition ne
sera plus forcément démontée après un appel à `umount(2)`, mais le sera
seulement lorsque cette partition n'aura plus d'accroches dans aucune
arborescence.

La commande `findmnt(1)`, des
[`util-linux`](https://www.kernel.org/pub/linux/utils/util-linux/) nous permet
d'avoir une vision arborescente des points de montage en cours d'utilisation.

<div lang="en-US">
```
TARGET                          SOURCE      FSTYPE     OPTIONS
/                               /dev/sda1   ext4       rw,relatime,data=ordered
├─/proc                         proc        proc       rw,nosuid,nodev,noexec,relatime
├─/sys                          sysfs       sysfs      rw,nosuid,nodev,noexec,relatime
│ ├─/sys/kernel/security        securityfs  securityfs rw,nosuid,nodev,noexec,relatime
│ ├─/sys/firmware/efi/efivars   efivarfs    efivarfs   ro,relatime
│ └─/sys/fs/cgroup              cgroup_root tmpfs      rw,nosuid,nodev,noexec,relatime,size=10240k,mode=755
│   ├─/sys/fs/cgroup/unified    none        cgroup2    rw,nosuid,nodev,noexec,relatime
│   ├─/sys/fs/cgroup/cpuset     cpuset      cgroup     rw,nosuid,nodev,noexec,relatime,cpuset
│   ├─/sys/fs/cgroup/cpu        cpu         cgroup     rw,nosuid,nodev,noexec,relatime,cpu
│   ├─/sys/fs/cgroup/cpuacct    cpuacct     cgroup     rw,nosuid,nodev,noexec,relatime,cpuacct
│   ├─/sys/fs/cgroup/blkio      blkio       cgroup     rw,nosuid,nodev,noexec,relatime,blkio
│   ├─/sys/fs/cgroup/memory     memory      cgroup     rw,nosuid,nodev,noexec,relatime,memory
│   ├─/sys/fs/cgroup/devices    devices     cgroup     rw,nosuid,nodev,noexec,relatime,devices
│   ├─/sys/fs/cgroup/freezer    freezer     cgroup     rw,nosuid,nodev,noexec,relatime,freezer
│   ├─/sys/fs/cgroup/net_cls    net_cls     cgroup     rw,nosuid,nodev,noexec,relatime,net_cls
│   ├─/sys/fs/cgroup/perf_event perf_event  cgroup     rw,nosuid,nodev,noexec,relatime,perf_event
│   ├─/sys/fs/cgroup/net_prio   net_prio    cgroup     rw,nosuid,nodev,noexec,relatime,net_prio
│   └─/sys/fs/cgroup/pids       pids        cgroup     rw,nosuid,nodev,noexec,relatime,pids
├─/dev                          devtmpfs    devtmpfs   rw,nosuid,size=10240k,nr_inodes=486250,mode=755
│ ├─/dev/pts                    devpts      devpts     rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000
│ ├─/dev/shm                    tmpfs       tmpfs      rw
│ └─/dev/mqueue                 mqueue      mqueue     rw,nosuid,nodev,noexec,relatime
├─/home                         /dev/sda3   ext4       rw,nosuid,nodev,relatime,data=ordered
├─/run                          tmpfs       tmpfs      rw,nosuid,nodev,noexec,mode=755
└─/tmp                          tmpfs       tmpfs      rw,nosuid,nodev,noexec,relatime
```
</div>

## `bind`

Lorsque l'on souhaite monter à un deuxième endroit (ou plus) une partition, on
utilise le *bind mount* :

<div lang="en-US">
```
  mount --bind olddir newdir
```
</div>

Lorsque l'on souhaite `chroot` dans un système complet (par exemple lorsqu'on
l'installe ou qu'on le répare via un *live CD*), il est nécessaire de dupliquer
certains points de montage, tels que `/dev`, `/proc` et `/sys`.

Sans monter ces partitions, vous ne serez pas en mesure d'utiliser le système
dans son intégralité : vous ne pourrez pas monter les partitions indiquées par
le `/etc/fstab`, vous ne pourrez pas utiliser `top` ou `ps`, `sysctl` ne pourra
pas accorder les paramètres du noyau, ...

Pour que tout cela fonctionne, nous aurons besoin, au préalable, d'exécuter les
commandes suivantes :

<div lang="en-US">
```
  cd newroot
  mount --bind /dev dev
  mount --bind /proc proc
  mount --bind /sys sys
```
</div>

En se `chroot`ant à nouveau dans cette nouvelle racine, tous nos outils
fonctionneront comme prévu.

Tous ? ... en fait non. Si l'on jette un œil à `findmnt(1)`, nous constatons
par exemple que `/sys/fs/cgroup` dans notre nouvelle racine est vide, alors que
celui de notre machine hôte contient bien les répertoires de nos *cgroups*.

`--bind` va se contenter d'attacher le système de fichiers (ou au moins une
partie de celui-ci) à un autre endroit, sans se préoccuper des points de
montages sous-jacents. Pour effectuer cette action récursivement, et donc
monter au nouvel emplacement le système de fichier ainsi que tous les points
d'accroche qu'il contient, il faut utiliser `--rbind`. Il serait donc plus
correct de lancer :

<div lang="en-US">
```
  cd newroot
  mount --rbind /dev dev
  mount -t proc none proc
  mount --rbind /sys sys
```
</div>


## Les montages parfumés

On distingue quatre variétés de répercution des montages pour un sous-arbre :
partagé, esclave, privé et non-attachable.

Chacun va agir sur la manière dont seront propagées les nouvelles accroches au
sein d'un système de fichiers attaché à plusieurs endroits.


### partagé -- *shared mount*

Dans une montage partagé, une nouvelle accroche sera propagée parmi tous les
systèmes de fichiers de ce partage (on parle de *peer group*).

<div lang="en-US">
```shell
  # Création de nos répertoires de travail
  mkdir /mnt/test-shared

  # On s'assure que le dossier que l'on va utiliser pour nos tests utilise bien la politique shared
  mount --make-shared /tmp

  # Duplication de l'accroche, sans s'occuper des éventuels sous-accroches
  mount --bind /tmp /mnt/test-shared
```
</div>

Si l'on attache un nouveau point de montage dans `/tmp` ou dans
`/mnt/test-shared`, avec la politique `shared`, l'accroche sera propagée :

<div lang="en-US">
```shell
  mkdir /mnt/test-shared/toto
  mount -t tmpfs none /mnt/test-shared/toto
```
</div>

Un coup de `findmnt` nous montre l'existence de deux nouveaux points de
montage. À `/mnt/test-shared/toto`, mais également à `/tmp/toto`.


### esclave -- *slave mount*

De la même manière que lorsque la propagation est partagée, cette politique
propagera, mais seulement dans un sens. Le point de montage déclaré comme
esclave ne propagera pas ses nouveaux points de montage à son *maître*.

<div lang="en-US">
```shell
  # Suite de l'exemple précédent
  cd /mnt/test-slave

  # Duplication de l'accroche, sans s'occuper des éventuels sous-accroches
  mount --bind /mnt/test-shared /mnt/test-slave

  # On rend notre dossier esclave
  mount --make-slave /mnt/test-slave
```
</div>

Si l'on effectue un montage dans `/mnt/test-shared` :

<div lang="en-US">
```shell
  mkdir /mnt/test-shared/foo
  mount -t tmpfs none /mnt/test-shared/foo
```
</div>

Le point de montage apparaît bien sous `/mnt/test-slave/foo`. Par contre :

<div lang="en-US">
```shell
  mkdir /mnt/test-slave/bar
  mount -t tmpfs none /mnt/test-slave/bar
```
</div>

Le nouveau point de montage n'est pas propagé dans `/mnt/test-shared/bar`.


### privé -- *private mount*

C'est le mode le plus simple : ici les points de montage ne sont tout
simplement pas propagés.

Pour forcer un point d'accroche à ne pas propager et à ne pas recevoir de
propagation, on utilise l'option suivante :

<div lang="en-US">
```shell
  mount --make-private mountpoint
```
</div>


### non-attachable -- *unbindable mount*

Ce mode interdira tout tentative d'attache à un autre endroit.

<div lang="en-US">
```shell
  mount --make-unbindable /mnt/test-slave
```
</div>

Il ne sera pas possible de faire :

<div lang="en-US">
```shell
  mkdir /mnt/test-unbindable
  mount --bind /mnt/test-slave /mnt/test-unbindable
```
</div>


### Parfums récursifs

Les options que nous venons de voir s'appliquent sur un point de montage. Il
existe les mêmes options pour les appliquer en cascade sur les points d'attache
contenus dans leur sous-arbre :

<div lang="en-US">
```
  mount --make-rshared mountpoint
  mount --make-rslave mountpoint
  mount --make-rprivate mountpoint
  mount --make-runbindable mountpoint
```
</div>


## `bind` de dossiers et de fichiers

Il n'est pas nécessaire que le point d'accroche que l'on cherche à dupliquer
pointe sur un point de montage (c'est-à-dire, dans la plupart des cas : une
partition ou un système de fichiers virtuel). Il peut parfaitement pointer sur
un dossier, et même sur un simple fichier, à la manière d'un *hardlink*, mais
que l'on pourrait faire entre plusieurs partitions et qui ne persisterait pas au
redémarrage.

Nous verrons dans la partie *namespace* réseau, une utilisation d'attache sur
un fichier.


## Déplacer un point de montage

À tout moment, il est possible de réorganiser les points de montage, en les
déplaçant. Comme cela se fait sans démonter de partition, il est possible de le
faire même si un fichier est en cours d'utilisation. Il faut cependant veiller
à ce que les programmes susceptibles d'aller chercher un fichier à l'ancien
emplacement soient prévenu du changement.

On utilise pour cela l'option `--move` de `mount(8)` :

<div lang="en-US">
```shell
  mount --move olddir newdir
```
</div>

Par exemple :

<div lang="en-US">
```shell
  mount --move /dev /newroot/dev
```
</div>

Il est courant de faire appel à cette option lorsque l'on souhaite changer la
racine de notre système de fichiers: par exemple pour passer de l'*initramfs* au
système démarré, de notre système hôte au système d'un conteneur, ...


## Aller plus loin

Voici quelques articles qui valent le détour, en lien avec les points de
montage :

* [Shared subtree](https://lwn.net/Articles/159077) et la
  [documentation du noyau associée](https://kernel.org/doc/Documentation/filesystems/sharedsubtree.txt) ;
* [Mount namespaces and shared subtrees](https://lwn.net/Articles/689856) ;
* [Mount namespaces, mount propagation, and unbindable mounts](https://lwn.net/Articles/690679).
