umount(8) from util-linux 2.23 (now -rc2) supports new command line options
--recursive and --all-targets. The new command
nsenter(1) opens doors to namespaces.
# umount /mnt/A
umount: /mnt/A: target is busy.
This is pretty common situation, the problem is obvious:
# findmnt -R /mnt/A
TARGET SOURCE FSTYPE OPTIONS
/mnt/A /dev/sdb1 ext2 rw,relatime,stripe=32
└─/mnt/A/B /dev/sdb2 ext2 rw,relatime,stripe=32
so you have to unmount /mnt/A/B before /mnt/A. In some cases especially in
scripts it could be a little bit tricky to umount all in the right order. The
user friendly solution is --recursive:
# umount --recursive /mnt/A
Note that this solution is not atomic and possible umount options (like --lazy)
are applied to all umount(2) calls.
The another improvement is the option --all-targets. It umounts all mountpoints
for the given filesystem (device) in the current namespace. This options is usable
in situations when the same device is mounted on more places. The option
--all-targets could be used together with the option --recursive.
# findmnt -R /dev/sdb1
TARGET SOURCE FSTYPE OPTIONS
/mnt/A /dev/sdb1 ext2 rw,relatime,stripe=32
└─/mnt/A/B /dev/sdb2 ext2 rw,relatime,stripe=32
/mnt/B /dev/sdb1 ext2 rw,relatime,stripe=32
/mnt/C /dev/sdb1 ext2 rw,relatime,stripe=32
verbose mode provides more details about the umount order:
# umount --recursive --all-targets --verbose /dev/sdb1
umount: /mnt/C (/dev/sdb1) unmounted
umount: /mnt/B (/dev/sdb1) unmounted
umount: /mnt/A/B (/dev/sdb2) unmounted
umount: /mnt/A (/dev/sdb1) unmounted
Note that /proc/self/mountinfo contains information about mountpoints hierarchy
as well as chronological order.
All these
umount(8) improvements have a small limitation --
umount(8) works with the
current namespace only. It means if you want to be really paranoid than you
should not expect that after --all-targets is the devices completely unmounted.
Fortunately we have a new command
nsenter(1) to enter the namespaces of the
other processes.
Let's create a session with unshared mount namespace:
# mount --bind --make-private /mnt/test /mnt/test
# unshare --mount
# mkdir /mnt/test/foo
# mount /dev/sdb1 /mnt/test/foo
# findmnt -R -o +PROPAGATION /mnt/test
/mnt/test /dev/sda4[/mnt/test] ext4 rw,relatime,data=ordered private
└─/mnt/test/foo /dev/sdb1 ext2 rw,relatime,stripe=32 private
# echo $$
28008
Note that --make-private is necessary if the parent is mounted as shared (this
is default for example on Fedora).
Another session (shell):
# findmnt -R /mnt/test
TARGET SOURCE FSTYPE OPTIONS
/mnt/test /dev/sda4[/mnt/test] ext4 rw,relatime,data=ordered
The /mnt/test/foo is invisible in this namespace, but we can enter the namespace by
nsenter(8) command and we can make changes in the namespace:
# nsenter --mount --target 28008
# mkdir /mnt/test/bar
# mount /dev/sdb2 /mnt/test/bar
# findmnt -R /mnt/test
TARGET SOURCE FSTYPE OPTIONS
/mnt/test /dev/sda4[/mnt/test] ext4 rw,relatime,data=ordered
├─/mnt/test/foo /dev/sdb1 ext2 rw,relatime,stripe=32
└─/mnt/test/bar /dev/sdb2 ext2 rw,relatime,stripe=32
# echo $$
29886
It means we have two sessions (shells with PIDs 28008 and 29886) that share
the same mount namespace.
The another example is to umount a directory in all namespaces:
for p in $(pidof bash); do
nsenter --mount --target $p -- umount --recursive /mnt/test
done
The command
nsenter(1) (as well as
unshare(1)) supports mount, uts, IPC, net,
PID and user namespaces.
Note that you can use
findmnt --task $pid
to list another mount namespaces.
nsenter(1) is necessary only if you want to
do changes to the namespaces.
2.23 highlights:
- mount(8) allows to use propagation flags together with another mount operations (e.g. mount --make-private /dev/sda1 /mnt)
- mount(8) allows to specify propagation flags in /etc/fstab by mount options (private,slave, ...)
- mount(8) supports new option x-mount.mkdir to create mountpoint directories
- findmnt(8) lists propagation flags (e.g. findmnt -o +PROPAGATION)
- unshare(1) and nsenter(1) execute shell if no program specified
Note that Linux kernel still does not allow to use propagation flags together with another mount operations. All is implemented in userspace by additional
mount(2) calls -- one call for one propagation flag, see strace output:
# strace -e mount mount --bind --make-private /mnt/test /mnt/test
mount("/mnt/test", "/mnt/test", 0x1886f10, MS_MGC_VAL|MS_BIND, NULL) = 0
mount("none", "/mnt/test", NULL, MS_PRIVATE, NULL) = 0