Filesystem mounted on top of â/â is inaccessible - so why can it be unmounted with âumount /â?

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
$ 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
This new mount does not change the physical directory which / refers to. See also /proc/self/root. Changing the per-process root directory is what what chroot does. When I access /, it still shows the contents of my ext4 root filesystem, not the tmpfs:
# 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 /
Except that umount operates on the tmpfs mount. How does this work - what is the difference between these two types of operation?
# umount /
# awk ' if ($2 == "/") print $0; ' < /proc/mounts
/dev/mapper/alan_dell_2016-fedora / ext4 rw,seclabel,relatime 0 0
Environment
$ uname -r # Kernel version
4.17.3-200.fc28.x86_64
System call trace
I tried repeating this with umount / run under strace -f, but it doesn't show anything more illuminating. umount just calls umount2(), and it doesn't pass any flags (the second parameter is zero).
# 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) = 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 +++
linux mount
add a comment |Â
up vote
1
down vote
favorite
$ 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
This new mount does not change the physical directory which / refers to. See also /proc/self/root. Changing the per-process root directory is what what chroot does. When I access /, it still shows the contents of my ext4 root filesystem, not the tmpfs:
# 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 /
Except that umount operates on the tmpfs mount. How does this work - what is the difference between these two types of operation?
# umount /
# awk ' if ($2 == "/") print $0; ' < /proc/mounts
/dev/mapper/alan_dell_2016-fedora / ext4 rw,seclabel,relatime 0 0
Environment
$ uname -r # Kernel version
4.17.3-200.fc28.x86_64
System call trace
I tried repeating this with umount / run under strace -f, but it doesn't show anything more illuminating. umount just calls umount2(), and it doesn't pass any flags (the second parameter is zero).
# 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) = 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 +++
linux mount
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
$ 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
This new mount does not change the physical directory which / refers to. See also /proc/self/root. Changing the per-process root directory is what what chroot does. When I access /, it still shows the contents of my ext4 root filesystem, not the tmpfs:
# 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 /
Except that umount operates on the tmpfs mount. How does this work - what is the difference between these two types of operation?
# umount /
# awk ' if ($2 == "/") print $0; ' < /proc/mounts
/dev/mapper/alan_dell_2016-fedora / ext4 rw,seclabel,relatime 0 0
Environment
$ uname -r # Kernel version
4.17.3-200.fc28.x86_64
System call trace
I tried repeating this with umount / run under strace -f, but it doesn't show anything more illuminating. umount just calls umount2(), and it doesn't pass any flags (the second parameter is zero).
# 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) = 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 +++
linux mount
$ 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
This new mount does not change the physical directory which / refers to. See also /proc/self/root. Changing the per-process root directory is what what chroot does. When I access /, it still shows the contents of my ext4 root filesystem, not the tmpfs:
# 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 /
Except that umount operates on the tmpfs mount. How does this work - what is the difference between these two types of operation?
# umount /
# awk ' if ($2 == "/") print $0; ' < /proc/mounts
/dev/mapper/alan_dell_2016-fedora / ext4 rw,seclabel,relatime 0 0
Environment
$ uname -r # Kernel version
4.17.3-200.fc28.x86_64
System call trace
I tried repeating this with umount / run under strace -f, but it doesn't show anything more illuminating. umount just calls umount2(), and it doesn't pass any flags (the second parameter is zero).
# 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) = 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 +++
linux mount
edited Jul 19 at 12:10
asked Jul 19 at 10:15
sourcejedi
18k22375
18k22375
add a comment |Â
add a comment |Â
 1 Answer
 1
 
active
oldest
votes
up vote
2
down vote
accepted
Looking inside Linux v4.17, I think we can say umount on / is equivalent to umount on /... And /.. accesses the "top of [the] mountpoint pile".
# stat -f / --format %T
ext2/ext3
# stat -f /.. --format %T
tmpfs
This obscure behaviour of .. seems to be permitted by POSIX. It only says "As a special case, in the root directory, dot-dot may refer to the root directory itself." (POSIX.1-2017, section 4.13 "Pathname Resolution").
If you want to generalize this and define the behaviour implemented by umount on other mount points, making a comparison with .. does not work so well. The term "top of [the] mountpoint pile" still applies, although it doesn't sound like a very formal definition :).
Kernel source code
https://elixir.bootlin.com/linux/v4.17/source/fs/namei.c
See where path_mountpoint() calls 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;
The comment for follow_mount() sounded like it was relevant to the question. And it mentions follow_dotdot() as the main user, which suggested this line of investigation.
/*
 * 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)
I had been thinking about how .. ("dotdot") could traverse from a mount point to its parent, e.g. /tmp/... But I hadn't previously considered that doing so might "skip to [the] top of [the] mountpoint pile". This happens even if the top mount isn't the one that contains the original /tmp directory!
add a comment |Â
 1 Answer
 1
 
active
oldest
votes
 1 Answer
 1
 
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Looking inside Linux v4.17, I think we can say umount on / is equivalent to umount on /... And /.. accesses the "top of [the] mountpoint pile".
# stat -f / --format %T
ext2/ext3
# stat -f /.. --format %T
tmpfs
This obscure behaviour of .. seems to be permitted by POSIX. It only says "As a special case, in the root directory, dot-dot may refer to the root directory itself." (POSIX.1-2017, section 4.13 "Pathname Resolution").
If you want to generalize this and define the behaviour implemented by umount on other mount points, making a comparison with .. does not work so well. The term "top of [the] mountpoint pile" still applies, although it doesn't sound like a very formal definition :).
Kernel source code
https://elixir.bootlin.com/linux/v4.17/source/fs/namei.c
See where path_mountpoint() calls 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;
The comment for follow_mount() sounded like it was relevant to the question. And it mentions follow_dotdot() as the main user, which suggested this line of investigation.
/*
 * 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)
I had been thinking about how .. ("dotdot") could traverse from a mount point to its parent, e.g. /tmp/... But I hadn't previously considered that doing so might "skip to [the] top of [the] mountpoint pile". This happens even if the top mount isn't the one that contains the original /tmp directory!
add a comment |Â
up vote
2
down vote
accepted
Looking inside Linux v4.17, I think we can say umount on / is equivalent to umount on /... And /.. accesses the "top of [the] mountpoint pile".
# stat -f / --format %T
ext2/ext3
# stat -f /.. --format %T
tmpfs
This obscure behaviour of .. seems to be permitted by POSIX. It only says "As a special case, in the root directory, dot-dot may refer to the root directory itself." (POSIX.1-2017, section 4.13 "Pathname Resolution").
If you want to generalize this and define the behaviour implemented by umount on other mount points, making a comparison with .. does not work so well. The term "top of [the] mountpoint pile" still applies, although it doesn't sound like a very formal definition :).
Kernel source code
https://elixir.bootlin.com/linux/v4.17/source/fs/namei.c
See where path_mountpoint() calls 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;
The comment for follow_mount() sounded like it was relevant to the question. And it mentions follow_dotdot() as the main user, which suggested this line of investigation.
/*
 * 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)
I had been thinking about how .. ("dotdot") could traverse from a mount point to its parent, e.g. /tmp/... But I hadn't previously considered that doing so might "skip to [the] top of [the] mountpoint pile". This happens even if the top mount isn't the one that contains the original /tmp directory!
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Looking inside Linux v4.17, I think we can say umount on / is equivalent to umount on /... And /.. accesses the "top of [the] mountpoint pile".
# stat -f / --format %T
ext2/ext3
# stat -f /.. --format %T
tmpfs
This obscure behaviour of .. seems to be permitted by POSIX. It only says "As a special case, in the root directory, dot-dot may refer to the root directory itself." (POSIX.1-2017, section 4.13 "Pathname Resolution").
If you want to generalize this and define the behaviour implemented by umount on other mount points, making a comparison with .. does not work so well. The term "top of [the] mountpoint pile" still applies, although it doesn't sound like a very formal definition :).
Kernel source code
https://elixir.bootlin.com/linux/v4.17/source/fs/namei.c
See where path_mountpoint() calls 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;
The comment for follow_mount() sounded like it was relevant to the question. And it mentions follow_dotdot() as the main user, which suggested this line of investigation.
/*
 * 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)
I had been thinking about how .. ("dotdot") could traverse from a mount point to its parent, e.g. /tmp/... But I hadn't previously considered that doing so might "skip to [the] top of [the] mountpoint pile". This happens even if the top mount isn't the one that contains the original /tmp directory!
Looking inside Linux v4.17, I think we can say umount on / is equivalent to umount on /... And /.. accesses the "top of [the] mountpoint pile".
# stat -f / --format %T
ext2/ext3
# stat -f /.. --format %T
tmpfs
This obscure behaviour of .. seems to be permitted by POSIX. It only says "As a special case, in the root directory, dot-dot may refer to the root directory itself." (POSIX.1-2017, section 4.13 "Pathname Resolution").
If you want to generalize this and define the behaviour implemented by umount on other mount points, making a comparison with .. does not work so well. The term "top of [the] mountpoint pile" still applies, although it doesn't sound like a very formal definition :).
Kernel source code
https://elixir.bootlin.com/linux/v4.17/source/fs/namei.c
See where path_mountpoint() calls 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;
The comment for follow_mount() sounded like it was relevant to the question. And it mentions follow_dotdot() as the main user, which suggested this line of investigation.
/*
 * 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)
I had been thinking about how .. ("dotdot") could traverse from a mount point to its parent, e.g. /tmp/... But I hadn't previously considered that doing so might "skip to [the] top of [the] mountpoint pile". This happens even if the top mount isn't the one that contains the original /tmp directory!
edited Jul 19 at 12:00
answered Jul 19 at 11:23
sourcejedi
18k22375
18k22375
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f457173%2ffilesystem-mounted-on-top-of-is-inaccessible-so-why-can-it-be-unmounted-wi%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password