# unshare -m
# mount --bind / /mnt
# cd /mnt
# chroot .
# pivot_root . mnt
pivot_root: failed to change root from `.' to `mnt': Device or resource busy
为什么会失败?我正在按照 的指示进行操作man 2 pivot_mount
。
ivot_root() 可能会也可能不会更改使用旧根目录的任何进程或线程的当前根目录和当前工作目录。 ivot_root() 的调用者必须确保根目录或当前工作目录位于旧根目录的进程在任何一种情况下都能正确运行。确保这一点的一个简单方法是在调用pivot_root()之前将其根目录和当前工作目录更改为new_root。
我不明白这与记录的 EBUSY 错误有何匹配。
错误
ivot_root() 可能会返回(在 errno 中)stat(2) 返回的任何错误。此外,它可能会返回:
忙碌 new_root 或 put_old 位于当前根文件系统上,或者文件系统已安装在 put_old 上。
答案1
联机帮助页的这一部分具有误导性。通常您需要不同的顺序,如 中所述man 8 pivot_root
。
cd new_root # chdir(new_root);
pivot_root . put_old # pivot_root(".", put_old);
exec chroot . # chroot(".");
这似乎是另一个微妙的细节pivot_root
。虽然重点pivot_root
是重新排列挂载命名空间,内核代码似乎是说它移动的根文件系统是由每个进程的根决定的,这是chroot
设置的。
结果,我们遇到了错误“new_root 或 put_old 位于当前根文件系统上”。
pivot_root
为了使其发挥作用,这个微妙的细节是必要的根本不在现代 Linux 上。如果它被定义为在挂载命名空间的根挂载上工作,它会尝试移动rootfs
您所使用的特殊文件系统。正常情况下看不到。但这是不允许的,因为 rootfs 必须始终是命名空间的根挂载。
我们可以pivot_root
通过继续下面的示例来确认这种方式是否有效。
# unshare -m
# mount --bind / /mnt
# cd /mnt
# chroot /mnt
# pivot_root . mnt
pivot_root: failed to change root from `.' to `mnt': Device or resource busy
# exit # leave chroot
# mount --bind . mnt
# cd mnt
# mount --bind /proc proc
# findmnt | grep mnt
└─/mnt /dev/mapper/alan_dell_2016-fedora ext4 rw,relatime,seclabel
└─/mnt /dev/mapper/alan_dell_2016-fedora ext4 rw,relatime,seclabel
└─/mnt/proc proc proc rw,nosuid,nodev,noexec,relatime
# chroot /mnt # re-enter chroot
# cd /mnt
# pivot_root . mnt # this one works
# exit # leave chroot
# findmnt | grep mnt
└─/mnt /dev/mapper/alan_dell_2016-fedora ext4 rw,relatime,seclabel
├─/mnt/mnt /dev/mapper/alan_dell_2016-fedora ext4 rw,relatime,seclabel
└─/mnt/proc /dev/mapper/alan_dell_2016-fedora[/proc] ext4 rw,relatime,seclabel
第二个pivot_root
电话有效。但它对挂载命名空间的根没有任何影响。从外面看chroot
,它交换了/mnt
和/mnt/mnt
。