Pourquoi mount se produit-il sur un directory existant?

Un directory existant est nécessaire en tant que sharepoint assembly .

$ ls $ sudo mount /dev/sdb2 ./datadisk mount: mount point ./datadisk does not exist $ mkdir datadisk $ sudo mount /dev/sdb2 ./datadisk $ 

Je trouve cela déroutant car il recouvre le contenu existant du directory. Il y a deux contenus possibles du directory de sharepoint assembly qui peuvent être commutés de manière inattendue (pour un user qui n'effectue pas le assembly).

Pourquoi le mount ne se produit-il pas dans un nouveau directory? C'est ainsi que les systèmes d'exploitation charts affichent des supports amovibles. Il serait clair si le directory est monté (existe) ou pas monté (n'existe pas). Je suis à peu près sûr qu'il y a une bonne raison mais je n'ai pas encore pu le découvrir.

Ceci est un cas de détail d'implémentation qui a fui.

Dans un système UNIX, chaque directory est constitué d'une list de noms mappés aux numéros d' inode . Un inode contient des métadonnées indiquant au système s'il s'agit d'un file, d'un directory, d'un périphérique spécial, d'un canal nommé, etc. Si c'est un file ou un directory, il indique également au système où find le contenu du file ou du directory sur le disque. La plupart des inodes sont des files ou des directorys. L'option -i de ls listra les numéros d'inode.

Le assembly d'un système de files prend un inode de directory et place un drapeau sur la copy en memory du kernel pour dire «en fait, en regardant le contenu de ce directory, regarde plutôt cet autre système de files» (voir la diapositive 10 de cette présentation ). C'est relativement facile car cela change un seul élément de données.

Pourquoi ne crée-t-il pas une input de directory pour pointer vers le nouvel inode à la place? Il y a deux façons de mettre en œuvre cela, les deux ayant des inconvénients. L'un consiste à écrire physiquement un nouveau directory dans le système de files – mais cela échoue si le système de files est en lecture seule! L'autre consiste à append à chaque list de directorys une list de choses "supplémentaires" qui ne sont pas vraiment là. C'est fastidieux et potentiellement encourir un petit coup de performance sur chaque opération de file.

Si vous voulez des points de assembly créés dynamicment, le système automount peut le faire. Les filesystems spéciaux non-disque peuvent également créer des directorys à volonté, par exemple proc , sys , devfs et ainsi de suite.

Edit: voir aussi la réponse à Qu'est-ce qui se passe quand vous montez sur un dossier existant avec du contenu?

Si mount(2) exigeait la création d'un nouveau directory comme sharepoint assembly, vous ne pouviez rien monter sous un système de files en lecture seule. Ce serait stupide, donc nous pouvons l'exclure.

Si mount a optionnellement créé un nouveau directory pour être le sharepoint assembly, ce serait bizarre. Ce n'est pas comme si mount / unmount se produisait tout le time, alors mettre une logique supplémentaire dans le kernel pour faire ces deux étapes avec un seul appel système ne serait pas une accélération importante. Laissez-le simplement à l'user pour faire un appel système mkdir(2) s'il en veut un. La réponse de Dmitry souligne que le fait d'avoir mount(2) rend les deux choses non atomiques. Et vous voudriez un argument supplémentaire pour mount(2) avec des drapeaux de mode comme open(2) , pour O_CREAT , O_EXCL , etc. Ce serait juste idiot que de laisser l'espace user le faire.

Ou peut-être vous demandiez d'avoir mount(8) (le programme traditionnel qui fait des appels système mount(2) ) faire cela? Ce serait possible, mais il y a déjà un mkdir(1) parfaitement adapté à ce travail, et la design d'Unix est un bon petit outil qui peut être combiné. Si vous voulez un outil qui fait les deux, il est facile d'écrire un script shell pour build cet outil à partir de deux outils plus simples. (Ou, comme muru commenté, udisksctl déjà, donc vous n'avez pas à l'écrire). En outre, le mount(8) normal de Linux mount(8) de util-linux supporte mount -o x-mount.mkdir[=mode] x- pour les options de l'espace user, plutôt que des options à transmettre au système de files.


Maintenant, la question plus intéressante: pourquoi doit-il y avoir un directory sur le système de files parent du tout?

Comme la réponse de pjc50 indique (sans relation, même s'il a mes initiales!), Avoir des points de assembly dans les lists de directorys nécessiterait un contrôle supplémentaire sur chaque readdir() .

Avoir des points de assembly existent en tant que directorys dans le directory qui les contient (sur le parent FS) est un bon tour. readdir() n'a pas à remarquer que c'est un sharepoint assembly du tout. Cela ne se produit que si le sharepoint assembly est utilisé comme composant de path. Bien sûr, la résolution du path doit vérifier la table de assembly pour chaque composant du directory d'un path.

Le assembly sur un directory existant appelle à mount pratiquement atomiquement: il réussit ou échoue, du less du sharepoint vue de l'user. Si mount devait créer le sharepoint assembly lui-même, il aurait deux points de défaillance, ce qui rend impossible un return en arrière propre. Imaginez le scénario suivant:

  1. mount réussit à créer le sharepoint assembly
  2. mount essaie de monter un nouveau système de files dans ce directory, mais échoue
  3. mount tente de supprimer le sharepoint assembly, mais échoue

Le système se termine par un effet secondaire d'un mount défectueux.

En voici un autre:

  1. umount réussit à démonter un système de files
  2. umount essaie de supprimer le sharepoint assembly, mais échoue

Maintenant, faut-il returnner le succès ou l'échec?

Un autre cas qui peut se produire:

Lorsque vous démarrez, une image en lecture seule de base est chargée dans le directory racine. Donc, vous voudriez l'ignorer quand vous voudriez remonter la racine réelle. Vous pouvez donc imaginer que mount syscall échange simplement le sharepoint assembly ro sur rw .

Ici, imaginons que vous ayez un problème de système de files sur le sharepoint assembly racine, vous voudriez pouvoir essayer de le réparer. Avec le chevauchement des montures, vous pouvez démonter le système de files et utiliser fsck fourni dans l'image de base pour le résoudre.

Cette fonctionnalité peut également être utile dans les systèmes qui ont besoin d'une security forte pour faire le suivi du changement entre une partition ro et une partition rw .

Je me suis toujours demandé ça aussi.

Un wrapper simple tel que:

 #!/bin/sh eval "mkdir -p \"\$$#\"" /bin/mount "$@" 

enregistré en tant que script exécutable nommé mount dans un directory surchargeant /bin dans votre PATH devrait s'en occuper s'il vous dérange trop

(Avant d'exécuter le binary de mount proprement dit, il crée un directory nommé après le dernier argument à mount , si ce directory n'existe pas déjà.)


Sinon, si vous ne souhaitez pas que les invocations échouées de l'encapsuleur de mount créent des directorys, vous pouvez:

 #!/bin/sh set -e eval "lastArg=\"\$$#\"" test -d "$lastArg" || { mkdir "$lastArg"; madeDir=1; } /bin/mount "$@" || { test -z "$madeDir" || rmdir "$lastArg"; }