umountのMNT_FORCE
Rev.3を表示中。最新版はこちら。
MNT_FORCEのmanの説明です。使用中(busy)でも強制的にアンマウントを実行する。これを行うとデータを失う可能性がある。 (NFSマウント専用)
となっていますが、これも正しくないように思われます。MNT_FORCEは、sb->s_op->umount_begin()コールバック関数がコールされるかどうかの違いで、あとは通常のumountと処理は同じです。propagate_mount_busy()でそのファイルシステム配下が参照されていれば、MNT_FORCEでもumountできません。
umount_begin()コールバック関数が定義されているファイルシステムは、以下のファイルシステムで、nfsに限った事でありません。ただしその処理は、ファイルシステム依存ということですが。
nfs :ネットワークファイルシステム fuse :ユーザ空間ファイルシステム cifs :smb ceph :分散ストレージファイルシステム v9fs :plan9ファイルシステムnfsについてみてみると、どうやら該当ファイルシステムを実現するための掛かるプロセスを削除しているようです。上記のファイルシステムは、通常のファイルシステムと違って、ブロックデバイスの物理層とカーネルとして実装しているvfsと直接やり取りするわけにいきません。これらのファイルシステムとのやり取りは、その間にインターフェース的(ネットワーク等々)補完処理が介在します。その処理として必要なプロセスが起動されているわけです。従ってこれらのファイルシステムをumountするには、仲介してるこれらのプロセスを削除する必要があるわけです。
ただし、通常のumountでもこれ等のファイルシステムもアンマウントできます(たぶん。nfsで検証)。そうなるとsb->s_op->umount_begin()で行っていた、前処理はスキップすることになるわけで、そうなるとsb->s_op->umount_begin()の前処理は必要ないのって・・・?
static int do_umount(struct mount *mnt, int flags) { struct super_block *sb = mnt->mnt.mnt_sb; int retval; LIST_HEAD(umount_list); : if (flags & MNT_FORCE && sb->s_op->umount_begin) { sb->s_op->umount_begin(sb); } : if (&mnt->mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) { down_write(&sb->s_umount); if (!(sb->s_flags & MS_RDONLY)) retval = do_remount_sb(sb, MS_RDONLY, NULL, 0); up_write(&sb->s_umount); return retval; } down_write(&namespace_sem); br_write_lock(vfsmount_lock); event++; if (!(flags & MNT_DETACH)) shrink_submounts(mnt, &umount_list); retval = -EBUSY; if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { if (!list_empty(&mnt->mnt_list)) umount_tree(mnt, 1, &umount_list); retval = 0; } br_write_unlock(vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); return retval; }当初、sb->s_op->umount_begin()で該当プロセスの削除と同時に、マウント参照カウンタをデクリメントする事で、プロセスが参照していても、MNT_DETACHのようにunmountできるのでは。と解釈しました。で、nfsで検証してみましたが、そんな事はありませんでした。アンマウントできません。そうなると、 MNT_FORCEって、なんの為にあるの?って。今のレベルの理解では、使い道が分からない、どうでもいいオプションと言う事でしょうか。