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:
- 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 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.
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.