Tanky WooRSS

Linux mount bind vs rbind and umount rbind

13 Jul 2013
这篇博客是从旧博客 WordPress 迁移过来,内容可能存在转换异常。

最近注意到mount的选项里, 有一个--bind, 还有一个--rbind

man 手册上有相关介绍:

The  bind  mount  call  attaches only (part of) a single filesystem, not possible submounts. The entire file hierarchy
including submounts is attached a second place using

mount --rbind olddir newdir

or shortoption

mount -R olddir newdir

刚开始对 submounts 的真实含义不是很清楚.

Google 搜 mount bind vs rbind 也没搜到什么结果, 还好在 StackOverflow 上搜到一篇帖子, 是讨论如何 loop 模式挂载. 其中 这个答案 讲的很详细.

(再次赞下 SOF, 现在对国内的技术社区是没什么好感了, 基本也就泡 SOF.)

关于 rbind, r 的意思就是 recursive, 也就是递归挂载.

举个例子:

现在在 /mnt 目录下有三个子目录, /mnt/old & /mnt/new & /mnt/bind_old, 执行:
mkdir /mnt/old/bind_old
mount --bind /mnt/bind_old /mnt/old/bind_old
现在 /mnt/bind_old 就以 bind方式 挂载到 /mnt/old/bind_old 上了
touch /mnt/bind_old/hello
然后在 /mnt/old/bind_old 目录下也有 hello 文件了
接着把 /mnt/old bind挂载到 /mnt/new 上:
mount --bind /mnt/old /mnt/new
进入 /mnt/new 目录, 可以看到 /mnt/old 自己的 bind_old 目录
但是 /mnt/old/bind_old 目录下并没有 hello 文件
说明在 /mnt/new 目录里, /mnt/bind_old 并没有被挂载上
这就是 rbind 发挥作用的地方了
bind 方式只挂载当前的目录, 但是目录中的子挂载目录不被递归挂载上去, 而 rbind 就可以
umount /mnt/new
mount --rbind /mnt/old /mnt/new
这时就可以看到 /mnt/new/bind_old 下的 hello 文件了

但是, 在最后 umount /mnt/new 的时候, 无法 umount, 提示说 /mnt/new 正在被使用, lsof 查看 /mnt/new, 发现很多文件都被使用了, 但是看不出来是什么程序占用了. (我的 /mnt 和 / 是在一个分区, 其实这个就是 lsof / 的结果)

网上也有很多关于 can not umount rbind 的文章, 后来看到了一篇博客里写了原因.

因为 mount 可以 递归挂载, 但是 umount 不能 递归卸载. 就导致了这样.

我先前知道是递归挂载后, 就以为用 rbind 可以把 /mnt/old bind到 /mnt/new 后, 同时识别 /mnt/old 下的 /mnt/old/bind_old, 现在才发现错了.

/proc/mounts 里可以发现, 递归挂载实际上是:

mount --bind /mnt/old /mnt/new
mount --bind /mnt/bind_old /mnt/new/bind_old

这样就知道为啥无法 umount /mnt/new 了, 因为还有一个 /mnt/new/bind_old 在挂载着在.

umount /mnt/new/bind_old
umount /mnt/new

这样就可以 umount /mnt/new 了.