要約すると、新しいマウント名前空間の_/tmp/a
_の上にファイル_/tmp/b
_をバインドマウントした場合、親の名前空間で_/tmp/b
_のiノードが変更されると、子名前空間。その理由を理解しようとしています。
mount(8)は、個別のファイル(ディレクトリのみ)をバインドする機能を公開していません。そのため、これを再現するには、必要なmount(2)syscallを発行できる追加の実行可能ファイルが必要です。簡単な例を次に示します(以下ではbmount
と呼びます)。
_#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;
}
}
_
テストケースを設定します。
_# 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
_
今、別のシェルで:
_# 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
_
元のシェルの場合:
_# 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
_
unshare
シェル内:
_# 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
#
_
バインドマウントがサイレントに消え、基になるファイルシステムの_/tmp/b
_ファイルが名前空間内に表示されるようになりました。
ここでセマンティクスの変更を説明する lwn.netの記事 を見つけました:2013年以前は、マウントポイントでのmv
コマンドのrename(2)
はEBUSY
ですが、動作が変更されて成功し、マウントが削除されました。関連するカーネルコミットは 8ed936b5671 のようです。
私が持っている質問は:
これが実際に関連する1つのケースは、 ip-netns(8) ;です。 _ip netns exec
_は、_/etc/netns/${NAMESPACE}/resolv.conf
_の上に_/etc/resolv.conf
_をバインドマウントすることで機能します。 _/etc/resolv.conf
_のiノードがresolvconf(8)またはsystemd-resolvedによって変更された場合、更新された_/etc/resolv.conf
_は名前空間内で実行されているプロセスに表示されます。
これがマウントの伝播です。 Linuxはデフォルトでそれを有効にしませんが、systemdは有効にします。マウントとアンマウントを新しい名前空間に反映させたくない場合は、次のようにできます。実行。ナレーター:これはマウントの伝播ではありません。mount --make-rprivate /
その中。
Iノードの変更時にマウントが削除されるのはなぜですか?マウントポイントが単純なパスではなく、dentryによって識別される、マウントシステムの実装の詳細にすぎませんか?
あなたが期待できる唯一の違いはrm b; mv c b
およびmv c b
は、どの時点でもb
が存在しないことを確認することはできないということです。私はこれを意図的に設計または保守された機能として説明します...これが歴史的なマルチユーザーUnixシステムにどの程度当てはまるかはわかりませんが、確かに信頼されるようになりました。実行中のシステムでのソフトウェア更新をサポートします。
私は...考えることができます 「iノードの変更」と呼ばれるもののために実装されたもう1つの特定の機能 -これはしぶしぶ行われ、ファイルシステム固有です。