Zusammengefasst: Wenn Sie eine Datei montieren binden /tmp/a
oben auf /tmp/b
in 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 bmount
Folgenden 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 unshare
Shell:
# 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/b
Datei 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 mv
Befehl 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:
- 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?
- 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 exec
funktioniert durch Binden der Montage /etc/netns/${NAMESPACE}/resolv.conf
auf /etc/resolv.conf
. Wenn der Inode von /etc/resolv.conf
durch resolvconf (8) geändert oder systemd aufgelöst wird, ist die Aktualisierung /etc/resolv.conf
für den im Namespace ausgeführten Prozess sichtbar.
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.