Warum verschwinden Linux-Bindungs-Mounts, wenn sich der Inode des Mount-Punkts ändert?

7

Zusammengefasst: Wenn Sie eine Datei montieren binden /tmp/aoben auf /tmp/bin einem neuen Mount - Namespace, aber dann der Inode von /tmp/bÄnderungen in der übergeordneten Namespace, montiert die bind verschwindet im Kind - Namespace. Ich versuche zu verstehen warum.

mount (8) bietet nicht die Möglichkeit, Mount-Dateien (nur Verzeichnisse) zu binden. Für die Reproduktion ist daher eine zusätzliche ausführbare Datei erforderlich, die den erforderlichen Mount (2) -Syscall ausgeben kann. Hier ist ein einfaches Beispiel (im bmountFolgenden bezeichnet):

#include <sys/mount.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("requires exactly 2 args\n");
        return 1;
    }

    int err = mount(argv[1], argv[2], "none", MS_BIND, NULL);
    if (err == 0) {
        return 0;
    } else {
        printf("mount error (%d): %s\n", errno, strerror(errno));
        return 1;
    }
}

Richten Sie den Testfall ein:

# echo a > /tmp/a; echo b > /tmp/b; echo c > /tmp/c;
# ls -ldi /tmp/a /tmp/b /tmp/c
11403315 -rw-r--r-- 1 root root 2 Jan 19 13:34 /tmp/a                                                               
11403422 -rw-r--r-- 1 root root 2 Jan 19 13:34 /tmp/b
11403452 -rw-r--r-- 1 root root 2 Jan 19 13:34 /tmp/c

Nun in einer separaten Shell:

# unshare -m /bin/bash
# bmount /tmp/a /tmp/b
# ls -ldi /tmp/a /tmp/b /tmp/c
11403315 -rw-r--r-- 1 root root 2 Jan 19 13:34 /tmp/a
11403315 -rw-r--r-- 1 root root 2 Jan 19 13:34 /tmp/b
11403452 -rw-r--r-- 1 root root 2 Jan 19 13:34 /tmp/c
# cat /tmp/b
a
# grep "\/tmp\/" /proc/self/mounts
[redacted] /tmp/b ext4 rw,relatime,errors=remount-ro,data=ordered 0 0

In der Originalschale:

# mv /tmp/c /tmp/b
# ls -ldi /tmp/a /tmp/b /tmp/c
ls: cannot access '/tmp/c': No such file or directory                                                               
11403315 -rw-r--r-- 1 root root 2 Jan 19 13:34 /tmp/a                                                               
11403452 -rw-r--r-- 1 root root 2 Jan 19 13:34 /tmp/b

In der unshareShell:

# ls -ldi /tmp/a /tmp/b /tmp/c
ls: cannot access '/tmp/c': No such file or directory
11403315 -rw-r--r-- 1 root root 2 Jan 19 13:34 /tmp/a
11403452 -rw-r--r-- 1 root root 2 Jan 19 13:34 /tmp/b
# cat /tmp/b
c
# grep "\/tmp\/" /proc/self/mounts
#

Der Bind-Mount ist stillschweigend verschwunden, und die /tmp/bDatei des zugrunde liegenden Dateisystems ist jetzt im Namespace sichtbar.

Ich habe hier einen Artikel von lwn.net gefunden, der eine Änderung der Semantik beschreibt: Vor 2013 schlug der mvBefehl rename(2)auf dem Mount-Punkt fehl EBUSY, aber das Verhalten wurde so geändert, dass er erfolgreich war, und dann wurde der Mount entfernt. Das relevante Kernel-Commit scheint 8ed936b5671 zu sein .

Die Fragen, die ich habe, sind:

  1. Warum wird die Halterung bei einem Inode-Wechsel entfernt? Handelt es sich nur um ein Implementierungsdetail des Montagesystems, bei dem der Montagepunkt eher durch einen Zahnersatz als durch einen einfachen Pfad identifiziert wird?
  2. Gibt es eine Möglichkeit, Bindungs-Mounts zu erstellen, die weniger "spröde" sind, da sie nicht von Dateisystemoperationen außerhalb ihres Namespace überschrieben oder entfernt werden können?

Ein Fall, in dem dies in der Praxis relevant ist, ist ip-netns (8) ; ip netns execfunktioniert durch Binden der Montage /etc/netns/${NAMESPACE}/resolv.confauf /etc/resolv.conf. Wenn der Inode von /etc/resolv.confdurch resolvconf (8) geändert oder systemd aufgelöst wird, ist die Aktualisierung /etc/resolv.conffür den im Namespace ausgeführten Prozess sichtbar.

Shivaram Lingamneni
quelle

Antworten:

5

Dies ist Mount Propagation. Linux aktiviert es standardmäßig nicht, systemd jedoch. Wenn Sie nicht möchten, dass Mounts und Unmounts in den neuen Namespace übertragen werden, können Sie z mount --make-rprivate /. B. darin ausgeführt werden.. Erzähler: Dies ist keine Mount-Propagierung.

Warum wird die Halterung bei einem Inode-Wechsel entfernt? Handelt es sich nur um ein Implementierungsdetail des Montagesystems, bei dem der Montagepunkt eher durch einen Zahnersatz als durch einen einfachen Pfad identifiziert wird?

Ich würde sagen, dass der einzige Unterschied, den Sie zwischen rm b; mv c bund erwarten können mv c b, darin besteht, dass es bzu keinem Zeitpunkt möglich ist, zu beobachten, dass er nicht existiert. Ich würde dies als eine Funktion beschreiben, die absichtlich entwickelt oder gewartet wurde ... Ich bin mir nicht sicher, inwieweit dies für das historische Mehrbenutzer-Unix-System zutrifft, aber es wurde sicherlich verwendet, um beispielsweise Software-Updates zu unterstützen auf einem laufenden System.

Ich ... kann mir genau eine andere spezifische Funktion vorstellen, die für das implementiert wurde, was Sie als "Inode-Änderung" bezeichnen - dies wurde widerwillig getan und ist dateisystemspezifisch.

sourcejedi
quelle
2
FWIW, das rename()Verhalten , auf das Sie sich beziehen, wo es atomar ersetzt wird, gibt es seit mindestens SVR4 und frühen Ausgaben des ursprünglichen BSD, so dass es auch in historischen Systemen ziemlich solide vorhanden ist. Das Verhalten selbst wurde längst in POSIX (ich bin mir ziemlich sicher, dass es in der ursprünglichen Spezifikation enthalten war) und in der Single Unix-Spezifikation als obligatorischer Bestandteil der VFS-API kodifiziert.
Austin Hemmelgarn
Entschuldigung, ich bin verwirrt: Wollen Sie damit sagen , dass die Bindungs-Mounts nicht verschwinden , wenn ich mount --make-rprivate /in die unshare -mShell laufe ? Ich kann das nicht reproduzieren.
Shivaram Lingamneni
Hmm, ich denke du hast recht, dieser Teil der Antwort ist völlig falsch.
Sourcejedi
Sie können nicht verhindern, dass das Löschen von Dateien von einer Ansicht eines tmpfs zu einer anderen Ansicht desselben tmpfs weitergegeben wird. Es sind die gleichen tmpfs mit den gleichen Dateien. Außer in dem Sinne, dass Sie das gesamte Verzeichnis, das die zu löschende Datei enthält, ausblenden können, indem Sie sie überhängen.
Sourcejedi