# 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.
- 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
# 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