$ unshare -rm
# mount --bind /tmp /
# awk '{ if ($2 == "/") print $0; }' < /proc/mounts
/dev/mapper/alan_dell_2016-fedora / ext4 rw,seclabel,relatime 0 0
tmpfs / tmpfs rw,seclabel,nosuid,nodev 0 0
/
이 새로운 마운트는 참조된 물리적 디렉토리를 변경하지 않습니다 . 당신은 또한 볼 수 있습니다 /proc/self/root
. 각 프로세스의 루트 디렉토리를 변경하면 됩니다 chroot
. 액세스하면 /
tmpfs가 아닌 ext4 루트 파일 시스템의 내용이 계속 표시됩니다.
# stat -f /tmp --format %T
tmpfs
# stat -f / --format %T
ext2/ext3
# ls -l -d -i /tmp
22161 drwxrwxrwt. 44 nfsnobody nfsnobody 1000 Jul 19 09:49 /tmp
# ls -l -d -i /
2 dr-xr-xr-x. 19 nfsnobody nfsnobody 4096 Jul 7 09:21 /
umount
tmpfs 마운트에서 실행되는 것을 제외하고. 어떻게 작동하나요? 이 두 가지 작업 유형의 차이점은 무엇인가요?
# umount /
# awk '{ if ($2 == "/") print $0; }' < /proc/mounts
/dev/mapper/alan_dell_2016-fedora / ext4 rw,seclabel,relatime 0 0
환경
$ uname -r # Kernel version
4.17.3-200.fc28.x86_64
시스템 호출 추적
나는 umount /
run under를 사용하여 이것을 반복하려고 시도했지만 strace -f
더 많은 깨달음을 보여주지 못했습니다. umount
호출만 umount2()
하고 플래그를 전달하지 않습니다(두 번째 인수는 0입니다).
# strace -f umount /
...
statfs("/", {f_type=EXT2_SUPER_MAGIC, f_bsize=4096, f_blocks=10288440, f_bfree=2384614, f_bavail=1856230, f_files=2621440, f_ffree=2253065, f_fsid={val=[1557883181, 1665775425]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_RELATIME}) = 0
stat("/sbin/umount.ext4", 0x7ffd79ccbb40) = -1 ENOENT (No such file or directory)
stat("/sbin/fs.d/umount.ext4", 0x7ffd79ccbb40) = -1 ENOENT (No such file or directory)
stat("/sbin/fs/umount.ext4", 0x7ffd79ccbb40) = -1 ENOENT (No such file or directory)
umount2("/", 0) = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
답변1
Linux v4.17을 살펴보면 umount
on 이 on /
과 동일하다고 말할 수 있을 것 같습니다 . "마운트 포인트 힙 상단"에 액세스합니다 .umount
/..
/..
# stat -f / --format %T
ext2/ext3
# stat -f /.. --format %T
tmpfs
이 모호한 동작은 ..
POSIX에서 허용되는 것 같습니다. "특별한 경우로 루트 디렉터리에 점(.)"이라고만 나와 있습니다.가능한루트 디렉터리 자체를 나타냅니다. ” (POSIX.1-2017, 섹션 4.13 “경로 이름 확인”).
이것을 일반화하고 umount
on 구현의 동작을 정의하려는 경우다른마운트 지점과의 비교는 ..
그리 좋지 않습니다. 매우 공식적인 정의처럼 들리지는 않지만 "힙의 마운트 지점 상단"이라는 용어는 여전히 적용됩니다.
커널 소스 코드
https://elixir.bootlin.com/linux/v4.17/source/fs/namei.c
path_mountpoint()
전화할 곳을 확인하세요 follow_mount()
.
/**
* path_mountpoint - look up a path to be umounted
* @nd: lookup context
* @flags: lookup flags
* @path: pointer to container for result
*
* Look up the given name, but don't attempt to revalidate the last component.
* Returns 0 and "path" will be valid on success; Returns error otherwise.
*/
static int
path_mountpoint(struct nameidata *nd, unsigned flags, struct path *path)
{
const char *s = path_init(nd, flags);
int err;
if (IS_ERR(s))
return PTR_ERR(s);
while (!(err = link_path_walk(s, nd)) &&
(err = mountpoint_last(nd)) > 0) {
s = trailing_symlink(nd);
if (IS_ERR(s)) {
err = PTR_ERR(s);
break;
}
}
if (!err) {
*path = nd->path;
nd->path.mnt = NULL;
nd->path.dentry = NULL;
follow_mount(path);
}
terminate_walk(nd);
return err;
}
님의 의견이 follow_mount()
질문과 관련이 있는 것 같습니다. follow_dotdot()
설문조사의 이 지점을 나타내는 주요 사용자를 언급합니다 .
/*
* Skip to top of mountpoint pile in refwalk mode for follow_dotdot()
*/
static void follow_mount(struct path *path)
{
while (d_mountpoint(path->dentry)) {
struct vfsmount *mounted = lookup_mnt(path);
if (!mounted)
break;
dput(path->dentry);
mntput(path->mnt);
path->mnt = mounted;
path->dentry = dget(mounted->mnt_root);
}
}
static int follow_dotdot(struct nameidata *nd)
..
나는 마운트 지점에서 그 상위 지점으로 이동하는 방법("점") 에 대해 생각해 왔습니다 /tmp/..
. 예를 들어 . 그러나 그렇게 하면 "마운트 지점 스택의 맨 위로 이동"할 수 있다는 점은 고려하지 않았습니다. /tmp
이는 최상위 설치가 원래 디렉터리를 포함하는 설치가 아닌 경우에도 발생합니다!