umountのMNT_DETACH
Rev.3を表示中。最新版はこちら。
MNT_DETACHのmanの説明です。遅延アンマウントを行う。マウントポイントに対する新規のアクセスは 不可能となり、実際のアンマウントはマウントポイントがビジーで なくなった時点で行う。
となっていますが、この説明は正しくありません。MNT_DETACHでumountすると、そのファイルシステムが参照されていようがいまいが、umountした時点で実際にアンマウントします。unmountしたファイルシステムを参照しているプロセスは、そのファイルシステム内において、相対パスによる参照することが可能で、これは同一ファイルシステム内で相対パスでのファイル参照は、マウント情報の参照が必要ないからです。しかし絶対パスでの参照できません。絶対パスで参照すると、そのumountしたファイルシステムを抜け出して、確かにumountしたファイルシステムを参照しなくなったと言うことで、このタイミングで実際にumountされるために参照できないものと。という間違った解釈です。MNT_DETACHは遅延アンマウントとなっていますが、unmountした時点で実際にアンマウントしています。
意味合い的には、MNT_FORCEとすべきかと思いますが、MNT_FORCEはNFSに掛かる処理となり、フラグ名から想像する機能と違います。これ等のオプションの命名は実装からみると疑問の余地があります。
MNT_DETACHオプション時、mnt->mnt_listにリストされているmnt配下のファイルシステムを、問答無用にumount_listに抜き出して、release_mounts()でアンマウントします。ちなみに通常のアンマウントも同じ処理となりますが、ただしpropagate_mount_busy()で配下のファイルシステムが参照されているなら(参照カウンタが2以上)、-EBUSYとなるわけです。
static int do_umount(struct mount *mnt, int flags) { struct super_block *sb = mnt->mnt.mnt_sb; int retval; LIST_HEAD(umount_list); retval = security_sb_umount(&mnt->mnt, flags); if (retval) return retval; : 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; }
補足
umountするファイルシステムがプロセスのrootで(&mnt->mnt == current->fs->root.mnt)、MNT_DETACHでない場合、そのファイルシステムがread-only(通常のマウント)でないなら、MS_RDONLYで再マウントします。read-onlyなら何もしません(エラーとなりません。)。しかしMNT_DETACHなら、このケースでもアンマウントします。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;