From: Ram <linuxram@us.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org,
viro@parcelfarce.linux.theplanet.co.uk,
Andrew Morton <akpm@osdl.org>,
mike@waychison.com, bfields@fieldses.org,
Miklos Szeredi <miklos@szeredi.hu>
Subject: [RFC PATCH 5/8] umount a shared/private/slave/unclone tree
Date: Fri, 08 Jul 2005 03:25:55 -0700 [thread overview]
Message-ID: <1120817714.30164.51.camel@localhost> (raw)
In-Reply-To: <1120816600.30164.25.camel@localhost>
[-- Attachment #1: Type: text/plain, Size: 66 bytes --]
Adds ability to unmount a shared/slave/unclone/private tree
RP
[-- Attachment #2: umount.patch --]
[-- Type: text/x-patch, Size: 8880 bytes --]
Adds ability to unmount a shared/slave/unclone/private tree
RP
Signed by Ram Pai (linuxram@us.ibm.com)
fs/namespace.c | 62 +++++++++++++++++++++++------
fs/pnode.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/fs.h | 2
include/linux/pnode.h | 2
4 files changed, 157 insertions(+), 13 deletions(-)
Index: 2.6.12/fs/namespace.c
===================================================================
--- 2.6.12.orig/fs/namespace.c
+++ 2.6.12/fs/namespace.c
@@ -344,6 +344,7 @@ struct seq_operations mounts_op = {
* open files, pwds, chroots or sub mounts that are
* busy.
*/
+//TOBEFIXED
int may_umount_tree(struct vfsmount *mnt)
{
struct list_head *next;
@@ -386,6 +387,20 @@ resume:
EXPORT_SYMBOL(may_umount_tree);
+int mount_busy(struct vfsmount *mnt)
+{
+ struct vfspnode *parent_pnode;
+
+ if (mnt == mnt->mnt_parent || !IS_MNT_SHARED(mnt->mnt_parent))
+ return do_refcount_check(mnt, 2);
+
+ parent_pnode = mnt->mnt_parent->mnt_pnode;
+ BUG_ON(!parent_pnode);
+ return pnode_mount_busy(parent_pnode,
+ mnt->mnt_mountpoint,
+ mnt->mnt_root, mnt);
+}
+
/**
* may_umount - check if a mount point is busy
* @mnt: root of mount
@@ -401,13 +416,25 @@ EXPORT_SYMBOL(may_umount_tree);
*/
int may_umount(struct vfsmount *mnt)
{
- if (atomic_read(&mnt->mnt_count) > 2)
- return -EBUSY;
- return 0;
+ return (!mount_busy(mnt));
}
EXPORT_SYMBOL(may_umount);
+void do_detach_mount(struct vfsmount *mnt)
+{
+ struct nameidata old_nd;
+ if (mnt != mnt->mnt_parent) {
+ detach_mnt(mnt, &old_nd);
+ path_release(&old_nd);
+ }
+ list_del_init(&mnt->mnt_list);
+ list_del_init(&mnt->mnt_fslink);
+ spin_unlock(&vfsmount_lock);
+ mntput(mnt);
+ spin_lock(&vfsmount_lock);
+}
+
void umount_tree(struct vfsmount *mnt)
{
struct vfsmount *p;
@@ -422,20 +449,35 @@ void umount_tree(struct vfsmount *mnt)
mnt = list_entry(kill.next, struct vfsmount, mnt_list);
list_del_init(&mnt->mnt_list);
list_del_init(&mnt->mnt_fslink);
- if (mnt->mnt_parent == mnt) {
- spin_unlock(&vfsmount_lock);
+ if (mnt->mnt_parent != mnt &&
+ IS_MNT_SHARED(mnt->mnt_parent)) {
+ struct vfspnode *parent_pnode
+ = mnt->mnt_parent->mnt_pnode;
+ BUG_ON(!parent_pnode);
+ pnode_umount(parent_pnode,
+ mnt->mnt_mountpoint,
+ mnt->mnt_root);
} else {
- struct nameidata old_nd;
- detach_mnt(mnt, &old_nd);
- spin_unlock(&vfsmount_lock);
- path_release(&old_nd);
+ if (IS_MNT_SHARED(mnt) || IS_MNT_SLAVE(mnt)) {
+ BUG_ON(!mnt->mnt_pnode);
+ pnode_disassociate_mnt(mnt);
+ }
+ do_detach_mount(mnt);
}
- mntput(mnt);
- spin_lock(&vfsmount_lock);
}
}
-static int do_umount(struct vfsmount *mnt, int flags)
+/*
+ * return true if the refcount is greater than count
+ */
+int do_refcount_check(struct vfsmount *mnt, int count)
+{
+
+ int mycount = atomic_read(&mnt->mnt_count);
+ return (mycount > count);
+}
+
+int do_umount(struct vfsmount *mnt, int flags)
{
struct super_block * sb = mnt->mnt_sb;
int retval;
@@ -516,7 +558,7 @@ static int do_umount(struct vfsmount *mn
spin_lock(&vfsmount_lock);
}
retval = -EBUSY;
- if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) {
+ if (flags & MNT_DETACH || !mount_busy(mnt)) {
if (!list_empty(&mnt->mnt_list))
umount_tree(mnt);
retval = 0;
@@ -858,7 +900,9 @@ detach_recursive_mnt(struct vfsmount *so
detach_mnt(source_mnt, nd);
for (m = source_mnt; m; m = next_mnt(m, source_mnt)) {
+ spin_lock(&vfspnode_lock);
list_del_init(&m->mnt_pnode_mntlist);
+ spin_unlock(&vfspnode_lock);
}
return;
}
Index: 2.6.12/fs/pnode.c
===================================================================
--- 2.6.12.orig/fs/pnode.c
+++ 2.6.12/fs/pnode.c
@@ -228,6 +228,124 @@ pnode_add_member_mnt(struct vfspnode *pn
pnode_add_mnt(pnode, mnt, 0);
}
+static int
+vfs_busy(struct vfsmount *mnt, struct dentry *dentry, struct dentry *rootdentry,
+ struct vfsmount *origmnt)
+{
+ struct vfsmount *child_mnt;
+ int ret=0;
+
+ spin_unlock(&vfsmount_lock);
+ child_mnt = lookup_mnt(mnt, dentry, rootdentry);
+ spin_lock(&vfsmount_lock);
+
+ if (!child_mnt)
+ return 0;
+
+ if (list_empty(&child_mnt->mnt_mounts)) {
+ if (origmnt == child_mnt)
+ ret = do_refcount_check(child_mnt, 3);
+ else
+ ret = do_refcount_check(child_mnt, 2);
+ }
+ mntput(child_mnt);
+ return ret;
+}
+
+int
+pnode_mount_busy(struct vfspnode *pnode, struct dentry *mntpt, struct dentry *root,
+ struct vfsmount *mnt)
+{
+ int ret=0,traversal;
+ struct vfsmount *slave_mnt, *member_mnt, *t_m;
+ struct pcontext context;
+
+ context.start = pnode;
+ context.pnode = NULL;
+ while(pnode_next(&context)) {
+ traversal = context.traversal;
+ pnode = context.pnode;
+ if(traversal == PNODE_UP) {
+ // traverse member vfsmounts
+ spin_lock(&vfspnode_lock);
+ list_for_each_entry_safe(member_mnt,
+ t_m, &pnode->pnode_vfs, mnt_pnode_mntlist) {
+ spin_unlock(&vfspnode_lock);
+ if ((ret = vfs_busy(member_mnt, mntpt, root, mnt)))
+ goto out;
+ spin_lock(&vfspnode_lock);
+ }
+ list_for_each_entry_safe(slave_mnt,
+ t_m, &pnode->pnode_slavevfs, mnt_pnode_mntlist) {
+ spin_unlock(&vfspnode_lock);
+ if ((ret = vfs_busy(slave_mnt, mntpt, root, mnt)))
+ goto out;
+ spin_lock(&vfspnode_lock);
+ }
+ spin_unlock(&vfspnode_lock);
+ }
+ }
+out:
+ return ret;
+}
+
+int
+vfs_umount(struct vfsmount *mnt, struct dentry *dentry, struct dentry *rootdentry)
+{
+ struct vfsmount *child_mnt;
+
+ spin_unlock(&vfsmount_lock);
+ child_mnt = lookup_mnt(mnt, dentry, rootdentry);
+ spin_lock(&vfsmount_lock);
+ mntput(child_mnt);
+ if (child_mnt && list_empty(&child_mnt->mnt_mounts)) {
+ do_detach_mount(child_mnt);
+ if (child_mnt->mnt_pnode)
+ pnode_disassociate_mnt(child_mnt);
+ }
+ return 0;
+}
+
+int
+pnode_umount(struct vfspnode *pnode, struct dentry *dentry,
+ struct dentry *rootdentry)
+{
+ int ret=0,traversal;
+ struct vfsmount *slave_mnt, *member_mnt, *t_m;
+ struct pcontext context;
+
+ context.start = pnode;
+ context.pnode = NULL;
+ while(pnode_next(&context)) {
+ traversal = context.traversal;
+ pnode = context.pnode;
+ if(traversal == PNODE_UP) {
+ // traverse member vfsmounts
+ spin_lock(&vfspnode_lock);
+ list_for_each_entry_safe(member_mnt,
+ t_m, &pnode->pnode_vfs, mnt_pnode_mntlist) {
+ spin_unlock(&vfspnode_lock);
+ if ((ret = vfs_umount(member_mnt,
+ dentry, rootdentry)))
+ goto out;
+ spin_lock(&vfspnode_lock);
+ }
+ list_for_each_entry_safe(slave_mnt,
+ t_m, &pnode->pnode_slavevfs, mnt_pnode_mntlist) {
+ spin_unlock(&vfspnode_lock);
+ if ((ret = vfs_umount(slave_mnt,
+ dentry, rootdentry)))
+ goto out;
+ spin_lock(&vfspnode_lock);
+ }
+ spin_unlock(&vfspnode_lock);
+ }
+ }
+out:
+ return ret;
+}
+
+
void
pnode_add_slave_mnt(struct vfspnode *pnode, struct vfsmount *mnt)
{
Index: 2.6.12/include/linux/fs.h
===================================================================
--- 2.6.12.orig/include/linux/fs.h
+++ 2.6.12/include/linux/fs.h
@@ -1216,11 +1216,14 @@ extern struct vfsmount *kern_mount(struc
extern int may_umount_tree(struct vfsmount *);
extern int may_umount(struct vfsmount *);
extern long do_mount(char *, char *, char *, unsigned long, void *);
+extern int do_umount(struct vfsmount *, int);
extern struct vfsmount *do_attach_prepare_mnt(struct vfsmount *,
struct dentry *, struct vfsmount *, int );
extern void do_attach_real_mnt(struct vfsmount *);
extern struct vfsmount *do_make_mounted(struct vfsmount *, struct dentry *);
extern int do_make_unmounted(struct vfsmount *);
+extern void do_detach_mount(struct vfsmount *);
+extern int do_refcount_check(struct vfsmount *, int );
extern int vfs_statfs(struct super_block *, struct kstatfs *);
Index: 2.6.12/include/linux/pnode.h
===================================================================
--- 2.6.12.orig/include/linux/pnode.h
+++ 2.6.12/include/linux/pnode.h
@@ -67,6 +67,9 @@ put_pnode(struct vfspnode *pnode)
void __init pnode_init(unsigned long );
struct vfspnode * pnode_alloc(void);
+void pnode_free(struct vfspnode *);
+int pnode_is_busy(struct vfspnode *);
+int pnode_umount_vfs(struct vfspnode *, struct dentry *, struct dentry *, int);
void pnode_add_slave_mnt(struct vfspnode *, struct vfsmount *);
void pnode_add_member_mnt(struct vfspnode *, struct vfsmount *);
void pnode_del_slave_mnt(struct vfsmount *);
@@ -79,5 +82,7 @@ int pnode_make_unmounted(struct vfspnod
int pnode_prepare_mount(struct vfspnode *, struct vfspnode *, struct dentry *,
struct vfsmount *, struct vfsmount *);
int pnode_real_mount(struct vfspnode *, int);
+int pnode_umount(struct vfspnode *, struct dentry *, struct dentry *);
+int pnode_mount_busy(struct vfspnode *, struct dentry *, struct dentry *, struct vfsmount *);
#endif /* KERNEL */
#endif /* _LINUX_PNODE_H */
next prev parent reply other threads:[~2005-07-08 10:26 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1120816072.30164.10.camel@localhost>
2005-07-08 10:25 ` [RFC PATCH 0/8] shared subtree Ram
[not found] ` <1120816229.30164.13.camel@localhost>
2005-07-08 10:25 ` [RFC PATCH 1/8] share/private/slave a subtree Ram
2005-07-08 11:17 ` Pekka Enberg
2005-07-08 12:19 ` Roman Zippel
2005-07-08 12:26 ` Pekka J Enberg
2005-07-08 12:46 ` Roman Zippel
2005-07-08 12:58 ` Pekka J Enberg
2005-07-08 13:34 ` Roman Zippel
2005-07-08 16:17 ` Pekka Enberg
2005-07-08 16:33 ` share/private/slave a subtree - define vs enum Bryan Henderson
2005-07-08 16:57 ` Roman Zippel
2005-07-08 17:16 ` Bryan Henderson
2005-07-08 18:21 ` Pekka J Enberg
2005-07-08 19:11 ` Roman Zippel
2005-07-08 19:33 ` Pekka Enberg
2005-07-08 19:59 ` Roman Zippel
2005-07-10 18:21 ` Pekka Enberg
2005-07-10 18:40 ` randy_dunlap
2005-07-10 19:14 ` Roman Zippel
2005-07-11 6:37 ` Pekka J Enberg
2005-07-11 17:13 ` Horst von Brand
2005-07-11 17:57 ` Roman Zippel
2005-07-10 19:16 ` Vojtech Pavlik
2005-07-11 17:18 ` Horst von Brand
2005-07-08 19:38 ` Ram
2005-07-08 22:12 ` Bryan Henderson
2005-07-10 10:55 ` Denis Vlasenko
2005-07-08 18:03 ` Wichert Akkerman
2005-07-08 18:10 ` Mike Waychison
2005-07-08 18:15 ` Wichert Akkerman
2005-07-08 20:23 ` Mike Waychison
2005-07-10 21:57 ` Pavel Machek
2005-07-08 16:29 ` [RFC PATCH 1/8] share/private/slave a subtree Ram
2005-07-08 14:32 ` Miklos Szeredi
2005-07-08 16:19 ` Ram
2005-07-08 16:51 ` Miklos Szeredi
2005-07-08 17:52 ` Ram
2005-07-08 19:49 ` Miklos Szeredi
2005-07-14 1:27 ` Ram
2005-07-18 11:06 ` shared subtrees implementation writeup Miklos Szeredi
2005-07-18 17:18 ` Ram Pai
[not found] ` <1120816355.30164.16.camel@localhost>
2005-07-08 10:25 ` [RFC PATCH 2/8] unclone a subtree Ram
[not found] ` <1120816436.30164.19.camel@localhost>
2005-07-08 10:25 ` [RFC PATCH 3/8] bind/rbind a shared/private/slave/unclone tree Ram
[not found] ` <1120816521.30164.22.camel@localhost>
2005-07-08 10:25 ` [RFC PATCH 4/8] move " Ram
[not found] ` <1120816600.30164.25.camel@localhost>
2005-07-08 10:25 ` Ram [this message]
[not found] ` <1120816720.30164.28.camel@localhost>
2005-07-08 10:26 ` [RFC PATCH 6/8] clone a namespace containing " Ram
[not found] ` <1120816835.30164.31.camel@localhost>
2005-07-08 10:26 ` [RFC PATCH 7/8] automounter support for shared/slave/private/unclone Ram
2005-07-08 10:26 ` [RFC PATCH 8/8] pnode.c optimization Ram
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1120817714.30164.51.camel@localhost \
--to=linuxram@us.ibm.com \
--cc=akpm@osdl.org \
--cc=bfields@fieldses.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mike@waychison.com \
--cc=miklos@szeredi.hu \
--cc=viro@parcelfarce.linux.theplanet.co.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).