Warum geschieht das Einhängen über ein vorhandenes Verzeichnis?

52

Ein vorhandenes Verzeichnis wird als Einhängepunkt benötigt .

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

Ich finde es verwirrend, da es vorhandene Inhalte des Verzeichnisses überlagert. Es gibt zwei mögliche Inhalte des Mount-Point-Verzeichnisses, die möglicherweise unerwartet gewechselt werden (für einen Benutzer, der das Mount nicht ausführt).

Warum passiert das nicht mountin einem neu erstellten Verzeichnis? Auf diese Weise zeigen grafische Betriebssysteme Wechselmedien an. Es wäre klar, ob das Verzeichnis gemountet (existiert) oder nicht gemountet (existiert nicht) ist. Ich bin mir ziemlich sicher, dass es einen guten Grund gibt, aber ich konnte es noch nicht entdecken.

Melebius
quelle
1
Wenn Sie dieses Verhalten möchten, verwenden Sie udisksctl. Warum benutzen mount?
muru
1
Weil es der Weg von Unix ist. Weil es auf diese Weise flexibler ist und Sie dann überall montieren können. Durch das Anhängen an einem beliebigen Ort können Sie Ihre Server nach Bedarf erweitern, indem Sie beispielsweise einen neuen Datenträger für die Datenbankpartition abrufen, die Daten in der DB-Partition auf den neuen Datenträger verschieben und an der richtigen Stelle anbringen, um die DB-Daten zuzulassen mehr wachsen.
Rui F Ribeiro
8
Als historische Notiz, bevor Windows und Linux im Wesentlichen alle anderen Betriebssysteme zerstörten, gab es eine Firma namens Apollo. Sie haben ein Unix-ähnliches (besseres Design als Unix!) Betriebssystem geschrieben. Es wurden die Verzeichnisse erstellt, in die NFS-Exporte automatisch eingebunden wurden. In der Tat konnten Sie nicht in ein bereits vorhandenes Verzeichnis einbinden. HP kaufte Apollo, warf das Betriebssystem weg und verwendete Apollos 64-Bit-CPU als HP-PA. Apollos System von Remote Procedure Calls wurde zu OSFs DCE, das anscheinend in Windows weiterlebt. Wissen ist die halbe Miete!
Bruce Ediger
irgendwie passiert das auf meinem ubuntu 14.04.3 system. Ich habe noch nicht untersucht. Wenn meine SD-Karte eingelegt wird, landet sie auf einem Pfad, unter dem sich nichts befindet. Wenn ich es mounte und versuche, es manuell wieder zu mounten, ist der Fehler, den ich bekomme, dass es kein Verzeichnis am Mount-Punkt gibt.
Skaperen
2
@BruceEdiger better design than Unix![Zitieren benötigt]
Ruslan

Antworten:

51

Dies ist ein Fall eines Implementierungsdetails, das durchgesickert ist.

In einem UNIX-System besteht jedes Verzeichnis aus einer Liste von Namen, die Inode- Nummern zugeordnet sind. Eine Inode enthält Metadaten, die dem System mitteilen, ob es sich um eine Datei, ein Verzeichnis, ein spezielles Gerät, eine Named Pipe usw. handelt. Wenn es sich um eine Datei oder ein Verzeichnis handelt, teilt sie dem System auch mit, wo sich der Datei- oder Verzeichnisinhalt auf der Festplatte befindet. Die meisten Inodes sind Dateien oder Verzeichnisse. Die -iOption zum lsAuflisten von Inode-Nummern.

Beim Mounten eines Dateisystems wird ein Verzeichnis-Inode verwendet und in der In-Memory-Kopie des Kernels ein Flag gesetzt, das besagt: "Wenn Sie nach dem Inhalt dieses Verzeichnisses suchen, schauen Sie sich stattdessen dieses andere Dateisystem an" (siehe Folie 10 dieser Präsentation ). Dies ist relativ einfach, da ein einzelnes Datenelement geändert wird.

Warum wird kein Verzeichniseintrag erstellt, der auf den neuen Inode verweist? Sie können dies auf zwei Arten implementieren, die beide Nachteile haben. Eine besteht darin, ein neues Verzeichnis physisch in das Dateisystem zu schreiben - dies schlägt jedoch fehl, wenn das Dateisystem schreibgeschützt ist! Das andere ist, zu jedem Verzeichnislistenprozess eine Liste von "zusätzlichen" Dingen hinzuzufügen, die nicht wirklich vorhanden sind. Dies ist umständlich und kann bei jedem Dateivorgang zu einer geringen Leistungseinbuße führen.

Wenn Sie dynamisch erstellte Einhängepunkte wünschen, kann das automountSystem dies tun. Spezielle nicht-Disk - Dateisysteme können auch Verzeichnisse nach Belieben erstellen, zum Beispiel proc, sys, devfsund so weiter.

Bearbeiten: Siehe auch die Antwort auf Was passiert, wenn Sie einen vorhandenen Ordner mit Inhalten überladen?

pjc50
quelle
Es wird jedoch kein Flag für den Inode gesetzt. sudo mount --bind / /mnt ; ls /mnt/proc-> leer. Ich frage mich, wie es funktioniert.
Sourcejedi
Die genaue Operation ist in fs/namespace.c, denke ich; Ich kenne die Quelle nicht und wollte nicht zu lange mit dem Bohren bis ins Detail verbringen. Das "Flag on the Inode" habe ich aus der verlinkten Präsentation bekommen.
pjc50
2
@sourcejedi: bind mounts binden nur das Dateisystem, auf das Sie sich beziehen. Sie binden andere Dateisysteme, die darunter eingebunden sind, nicht rekursiv. Dies ist eine praktische Möglichkeit, durch Reittiere versteckten Müll zu finden. (ZB wenn ein Teil des Materials irgendwann auf dem Root-FS landete, /var/cacheals es /varnicht gemountet werden konnte.) Siehe auch path_resolution(7). (Ältere Linux-Manpages hatten diese Manpage in Abschnitt 2, wie die.net) IDK, wie Linux tatsächlich intern arbeitet, um die Überprüfung jeder Verzeichniskomponente als möglichen Mount zu optimieren. Vielleicht diesen VFS-Eintrag im Cache anheften?
Peter Cordes
2
Richtig, das ist mein Punkt ... Also fs/namei.cruft (Pfad -> Inode-Suche) trotzdem namespace.c auf lookup_mnt(). Auf dem Eintrag befindet sich ein Flag (Verzeichnis-Cache-Eintrag). Aber das ist nur eine Optimierung, auch als Implementierungsdetail bekannt. Es sagt Ihnen nicht, welches Dateisystem dort gemountet ist; Sie müssen in der Einfassungstabelle schauen. (Weitere Implementierungsdetails finden Sie unter m_hash (). Zumindest unter Linux werden zusätzliche Zeichenfolgenvergleiche vermieden, und AFAICS schafft es gleichzeitig, Dentrys über z. B. Bind-Mounts hinweg wiederzuverwenden, da sie von Assistenten geschrieben wurden.)
Sourcejedi
1
@PeterCordes: man 8 mount: mount --bind foo foo. Der Bind- mountAufruf hängt nur (einen Teil) eines einzelnen Dateisystems an, nicht mögliche Submounts. Die gesamte Dateihierarchie einschließlich dermount --rbind olddir newdir
Submounts
19

Wenn die Erstellung eines neuen Verzeichnisses als Einhängepunkt mount(2) erforderlich ist, können Sie unter einem schreibgeschützten Dateisystem nichts einhängen. Das wäre dumm, also können wir das ausschließen.

Wenn mount optional ein neues Verzeichnis als Mountpoint erstellen würde, wäre das seltsam. Es ist nicht so, dass das Ein- und Aushängen ständig passiert. Daher wäre es keine wichtige Beschleunigung, zusätzliche Logik in den Kernel zu integrieren, um diese beiden Schritte mit einem einzigen Systemaufruf auszuführen. Überlassen Sie es einfach dem Benutzerraum, um einen mkdir(2)Systemaufruf zu tätigen , wenn dies gewünscht wird. Die Antwort von Dmitry weist darauf hin, dass mount(2)es nicht atomar wäre , wenn man beide Dinge tun würde. Und würden Sie an ein zusätzliches Argument wollen mount(2)mit Modus - Flags wie open(2)nimmt, für O_CREAT, O_EXCLusw. Es wäre einfach albern sein im Vergleich zu lassen User-Space tun es.

Oder haben Sie sich gefragt, mount(8)ob (das traditionelle Programm, das mount(2)Systemaufrufe ausführt) dies tun soll? Das wäre möglich, aber es gibt bereits ein perfektes mkdir(1)Werkzeug für den Job, und im Design von Unix dreht sich alles um gute kleine Werkzeuge, die kombiniert werden können. Wenn Sie ein Tool suchen, das beides kann, ist es einfach, ein Shell-Skript zu schreiben, um dieses Tool aus zwei einfacheren Tools zu erstellen. (Oder, wie muru bemerkte, udisksctltut dies bereits, so dass Sie es nicht schreiben müssen.) Außerdem mount(8)unterstützt Linuxs Standard von util-linux die mount -o x-mount.mkdir[=mode]Verwendung seiner x-Syntax für Optionen für den Benutzerbereich anstelle von Optionen, die an das Dateisystem übergeben werden sollen.


Nun die interessantere Frage: Warum muss es überhaupt ein Verzeichnis im übergeordneten Dateisystem geben?

Wie die Antwort von pjc50 zeigt (keine Beziehung, obwohl er meine Initialen hat!), Würde es dann eine zusätzliche Überprüfung erfordern, wenn Mount-Punkte in Verzeichnislisten angezeigt werden readdir().

Mount-Punkte als Verzeichnisse in dem Verzeichnis zu haben, das sie enthält (auf dem übergeordneten FS), ist ein netter Trick. readdir()muss nicht bemerken, dass es sich überhaupt um einen Einhängepunkt handelt. Dies geschieht nur, wenn der Einhängepunkt als Pfadkomponente verwendet wird. Die Pfadauflösung muss natürlich die Mount-Tabelle für jede Verzeichniskomponente eines Pfades überprüfen.

Peter Cordes
quelle
1
If mount(2) required the creation of a new directory to be the mount point, you couldn't mount anything under a read-only filesystem. That would be dumb- Ich würde es schlauer finden: Aus der Sicht des Benutzers sollte sich ein schreibgeschütztes Dateisystem nicht ändern, aber das Zulassen von Mounts bedeutet, dass dies möglich ist
Izkata,
2
@Izkata: Wenn ein Dateisystem schreibgeschützt ist, bedeutet dies nicht, dass der gesamte Unterbaum des VFS eingefroren ist. Es könnte Symlinks geben, die auf Lese- / Schreibverzeichnisse verweisen, oder es könnte bereits Lese- / Schreib-Mount-Punkte enthalten, als die übergeordnete fs erneut gemountet wurde ro. Es gibt viele Anwendungsfälle für schreibgeschützte Dateisysteme, in denen Ihr Argument keinen Sinn ergibt.
Peter Cordes
2
man 8 mount: x-mount.mkdir[=mode] Erlaubt das Erstellen eines Zielverzeichnisses (Mountpoint). Der optionale Argumentmodus gibt den Dateisystemzugriffsmodus an, der mkdir(2)in der Oktalnotation verwendet wird. Der Standardmodus ist 0755. Diese Funktionalität wird nur für Root-Benutzer unterstützt.
mikeserv
Ich sehe keine wichtigen Anwendungsfälle von Nur-Lese-Dateisystemen mit eingebundenen Schreib-Lese-Dateisystemen, insbesondere nicht in den frühen Unix-Versionen. @ PeterCordes
Kubanczyk
@kubanczyk: Nur-Lese-Root-Dateisystem mit einem Lese-Schreib- /tmpund /home. Oder schreibgeschütztes NFS-Mounted /usrmit einem lokalen /usr/localMounted. Oder allgemeiner gesagt, ein gemeinsames schreibgeschütztes Bild, über dem ein modifizierbarer Teil montiert ist. (Lokale Modifikationen an einem Nur-Lese-Image können auch auf Dateibasis mit benutzerdefinierten Dateisystemen wie Overlayfs oder anderen Union-Dateisystemen für Linux durchgeführt werden, die auf bootfähigen LiveCD- Images verwendet werden.) Ich habe anfangs an den Root-FS gedacht, auf dem RO ursprünglich installiert war booten, aber machen es rw kann vor anderen Reittieren passieren.
Peter Cordes
12

Das Mounten in ein vorhandenes Verzeichnis ruft mountpraktisch atomar auf: Zumindest aus Benutzersicht gelingt dies oder schlägt fehl. Wenn mountder Mountpunkt selbst erstellt werden müsste, hätte er zwei Fehlerquellen, sodass ein sauberes Rollback nicht garantiert werden kann. Stellen Sie sich folgendes Szenario vor:

  1. mount erstellt den Mountpoint erfolgreich
  2. mount versucht, ein neues Dateisystem in dieses Verzeichnis einzuhängen, schlägt jedoch fehl
  3. mount versucht, den Mountpoint zu entfernen, schlägt jedoch fehl

Das System hat die Nebenwirkung eines fehlgeschlagenen mount.

Hier ist ein anderes:

  1. umount Hängt ein Dateisystem erfolgreich ab
  2. umount versucht, den Mountpoint zu entfernen, schlägt jedoch fehl

Nun sollte umountErfolg oder Misserfolg zurückkehren?

Dmitry Grigoryev
quelle
5
mounthat 8 verschiedene Rückkehrcodes für Fehler, die auch kombiniert werden können. Es könnte einfach ein weiteres hinzufügen, wenn das Entfernen des Verzeichnisses fehlschlägt. man7.org/linux/man-pages/man8/mount.8.html#RETURN_CODES
Chaos
8
Ich denke, das OP fragt, warum der Einhängepunkt überhaupt ein vorhandenes Verzeichnis sein muss, nicht, warum der mountSystemaufruf es nicht erstellt. Obwohl das vielleicht nur meine Interpretation / Erwartung dessen war, was das OP meiner Meinung nach fragen sollte, oder was ich gefragt hätte, wenn ich gefragt hätte.
Peter Cordes
3

Ein weiterer Fall, der auftreten kann:

Beim Booten wird ein schreibgeschütztes Basisimage in das Stammverzeichnis geladen. Sie möchten es also überschreiben, wenn Sie eine echte Wurzel schlagen möchten. Sie können sich also vorstellen, dass mount syscall nur den roMountpoint zu vertauscht rw.

Stellen Sie sich vor, Sie haben ein Dateisystemproblem auf dem Root-Mountpoint und möchten versuchen, es zu reparieren. Mit Mount-Überlappung können Sie das Dateisystem aushängen und das fsckbereitgestellte Basis-Image zur Lösung verwenden.

Diese Funktion kann auch in Systemen nützlich sein, die eine hohe Sicherheit benötigen, um Änderungen zwischen einer roPartition und einer anderen rwnachzuverfolgen.

alexises
quelle
1
Ich bin nicht sicher, wie dies die Frage beantwortet. Weisen Sie darauf hin, dass Sie bei mount Bedarf ein neues Verzeichnis am Speicherort des Mountpunkts erstellen und nichts über ein schreibgeschütztes Dateisystem mounten können? Der erste Absatz ist verwirrend: So funktioniert Linux initrd nicht. Es verwendet den pivot_rootSystemaufruf, um die Root-Fs zu ändern, und nicht nur, um mehr Daten darüber zu laden. Das machte es schwierig, Ihrer Logik in den nächsten Absätzen zu folgen, weil ich dachte, Sie sprachen darüber pivot_root(2).
Peter Cordes
2
@PeterCordes - Linux hat seit vielen Jahren keine initrd mehr verwendet : Wenn ein anderes Root-Gerät gewechselt wird, würde initrd pivot_rootund dann umountdie Ramdisk. Aber initramfs ist rootfs: Sie können es weder pivot_rootrootfs noch aushängen . Löschen Sie stattdessen alles aus rootfs find -xdev / -exec rm {} \;, um Speicherplatz freizugeben ( ), hängen Sie rootfs mit dem neuen root ( cd /newmount; mount --move . /; chroot .) über, hängen Sie stdin / stdout / stderr an das neue / dev / console und execdas neueinit
mikeserv 26.12.15
@mikeserv: Ordentlich! Ich hatte nicht bemerkt, dass sich der grundlegende Mechanismus zum Wechseln der Roots geändert hatte, als wir anfingen, initramfs anstelle von initrd zu verwenden. Aus der Perspektive eines Administrators, der sicherstellt, dass die richtigen Kernelmodule darin landen, sind sie identisch mit>. <. Ich denke immer noch, dass dies die Frage nicht wirklich gut beantwortet . Anscheinend wird die Interpretation "Mount unter einem Rof ist unmöglich" vorausgesetzt, und es wird ein sehr spezifischer Problemfall angegeben (was unwahrscheinlich erscheint, weil initramfs beim Booten nicht schreibgeschützt gemountet ist. Und selbst wenn dies der Fall ist, kann es einfach erneut gemountet werden -schreiben, ohne das cpio.gz-Bild zu beeinflussen.)
Peter Cordes
@ PeterCordes - ich verstehe diese Antwort nicht wirklich. Ich habe gerade Ihren Kommentar gesehen - das initramfs ist ein Dateisystem - es kann wirklich nie schreibgeschützt sein - sein fs-Cache ist inkarniert.
mikeserv
2

Das habe ich mich auch immer gefragt.

Ein einfacher Wrapper wie:

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

Das Speichern als ausführbares Skript mit dem Namen mountin einem Verzeichnis, das /binIhren PATH überschreibt, sollte dies berücksichtigen, wenn es Sie zu sehr stört

(Bevor die eigentliche mountBinärdatei ausgeführt wird, wird ein Verzeichnis erstellt, das nach dem letzten Argument von to benannt ist mount, sofern ein solches Verzeichnis noch nicht vorhanden ist.)


Wenn Sie nicht möchten, dass fehlgeschlagene Aufrufe des mountWrappers Verzeichnisse erstellen, können Sie Folgendes tun:

#!/bin/sh
set -e
eval "lastArg=\"\$$#\""
test -d "$lastArg" || { mkdir "$lastArg"; madeDir=1; }
/bin/mount "$@"  ||  {  test -z "$madeDir" || rmdir "$lastArg"; }
PSkocik
quelle
Sollte der mountBefehl dann nicht das so erstellte Verzeichnis verwenden?
muru
1
@muru Das macht die letzte Zeile.
PSkocik
Oh, du meinst also, es sollte so verwendet werden mount /dev/foo /some/path:? Ich nahm an, dass es so funktionieren würde udisksctl, also würden Sie rennen mount /dev/foo.
muru
4
Sie können das letzte cmdline-Argument ohne evalzu erweitern $#mit erhalten "${@:-1}". Ich habe dies mit DASH getestet, da ich denke, dass es nichts anderes unterstützt, als POSIX sh zu unterstützen. /bin/dash -c 'echo ${@:-1}' foo bardruckt bar.
Peter Cordes
1
Sie können man -o x-mount.mkdir...
mikeserv