umount --lazy
umount(2)
フラグを設定するための呼び出しですMNT_DETACH
。umount(2)
こう言うと次のようになります。
「遅延マウント解除の実行:マウントポイントを新しいアクセスに使用できないようにし、すぐにマウントポイントとその下にマウントされているすべてのファイルシステムを切断し、マウントポイントを使用できなくします。実際のアンロードは使用中です。実行されます。
umount(8)
ファイルシステムが使用中です。
たとえば、開いているファイルがある場合、プロセスに作業ディレクトリがある場合、またはスワップファイルが使用中の場合です。
ところで、「新しいアクセスが不可能」とは、どういう意味ですか?一部のアプリケーションがchdir(2)
後で削除されたディレクトリに入り、正しく機能しているのを見たことがあります。
答え1
トム・ヘイルの答え続いて明確に説明します。
...ファイルシステムがアンマウントされているように見えますが、実際にはファイルの名前空間/階層から隠されているだけです。
- プロセスは開かれたファイル記述子を通して書き続けることができます。
- 相対パス名を使用して、マウントポイント内の作業ディレクトリを含むプロセスで書き込み用に新しいファイルまたは既存のファイルを開くことができます。
Tomの答えは本当にぴったりですが、もう一度強調すると次のようになります。
「新しいアクセスには使用できません」は、単にマウントポイントを含むパス名を解決できないことを意味します。
あなたはできます何もない新しいファイル/ディレクトリを開くことに加えて、マウントポイントを使用します。絶対パス経由。
あなたができる唯一のこと確認する呼び出し後に起こるのは、
umount(MNT_DETACH)
マウントポイントの下のコンテンツに名前でアクセスできないことです。
オプション名MNT_DETACH
もこの動作を説明します。マウントポイントディレクトリ階層から分離されますが、実際にマウントされたファイルシステムには何も起こりません。
考えると、これはやや明らかですが、現在の作業ディレクトリは本質的にそのディレクトリへの開かれたファイル参照ですが、カーネルによって保持されます。したがって:
chdir("/foo");
open("./bar.txt", O_RDONLY);
等しい
chdir("/foo");
openat(AT_FDCWD, "bar.txt", O_RDONLY);
これは次のとおりです。
int dirfd = open("/foo", O_RDONLY | O_DIRECTORY);
openat(dirfd, "bar.txt", O_RDONLY);
バインド解除とディレクトリオープン遅延のいくつかのテストを行いました。
- マウントポイントのディレクトリを参照するオープンファイル記述子がある場合:
getdents(2)
以下を呼び出してディレクトリの内容を読み取ることができます。openat(2)
そのディレクトリへの相対パスを使用して、そのディレクトリのファイルを開くことができます。
このプログラムは以下を示しています。
#define _GNU_SOURCE
#include <dirent.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mount.h>
static void
show_dir_listing(DIR *dir)
{
printf("Listing directory (by handle):\n");
rewinddir(dir);
for (;;) {
struct dirent *d;
errno = 0;
d = readdir(dir);
if (d == NULL) {
if (errno)
error(2, errno, "readdir failed");
break;
}
printf(" %s%s\n",
d->d_name,
(d->d_type == DT_DIR) ? "/" : "");
}
}
int main(int argc, char **argv)
{
const char *dirpath;
const char *filename;
DIR *dir;
int fd, rc;
if (argc < 3) {
fprintf(stderr, "Usage: %s DIR FILE\n",
program_invocation_short_name);
return 1;
}
dirpath = argv[1];
filename = argv[2];
printf("PID: %u\n", (unsigned int)getpid());
printf("Opening handle to %s\n", dirpath);
dir = opendir(dirpath);
if (dir == NULL)
error(2, errno, "opendir failed: %s", dirpath);
show_dir_listing(dir);
printf("\nLazy-unmounting %s\n\n", dirpath);
rc = umount2(dirpath, MNT_DETACH);
if (rc < 0)
error(2, errno, "umount2 failed");
show_dir_listing(dir);
/* Try to open by full path name */
{
char path[PATH_MAX];
path[0] = '\0';
strcat(path, dirpath);
strcat(path, "/");
strcat(path, filename);
printf("Trying to open(\"%s\")... ", path);
fd = open(path, O_RDONLY);
if (fd < 0) {
printf("Failed!\n");
}
else {
printf("Success: fd=%d\n", fd);
close(fd);
}
}
/* Try to openat relative to dir */
{
int dfd = dirfd(dir);
printf("Trying to openat(%d, \"%s\")... ", dfd, filename);
fd = openat(dfd, filename, O_RDONLY);
if (fd < 0) {
printf("Failed!\n");
}
else {
printf("Success: fd=%d\n", fd);
close(fd);
}
}
return 0;
}
テスト:
$ ls /tmp/to-be-bound/
bar.txt crackle.txt foo.txt pop.txt snap.txt
$ mkdir /tmp/readonly-bind
$ mount -o bind,ro /tmp/to-be-bound /tmp/readonly-bind
$ ls /tmp/readonly-bind/
bar.txt crackle.txt foo.txt pop.txt snap.txt
$ echo 'should fail' >> /tmp/readonly-bind/foo.txt
-bash: /tmp/readonly-bind/foo.txt: Read-only file system
$ sudo ./lazytest /tmp/readonly-bind foo.txt
PID: 21160
Opening handle to /tmp/readonly-bind
Listing directory (by handle):
./
../
pop.txt
crackle.txt
snap.txt
bar.txt
foo.txt
Lazy-unmounting /tmp/readonly-bind
Listing directory (by handle):
./
../
pop.txt
crackle.txt
snap.txt
bar.txt
foo.txt
Trying to open("/tmp/readonly-bind/foo.txt")... Failed!
Trying to openat(3, "foo.txt")... Success: fd=4