All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 9/10] vfs: shared subtree automounter helper functions
@ 2005-09-16 18:26 Ram
  0 siblings, 0 replies; only message in thread
From: Ram @ 2005-09-16 18:26 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel
  Cc: linuxram, akpm, viro, miklos, mike, bfields, serue

Patch that makes the automounter helper functions aware of the propagations
associated with mounts.

Signed by Ram Pai (linuxram@us.ibm.com)

 fs/namespace.c        |   73 +++++++++++++++++++-------------------------------
 fs/pnode.c            |    8 ++++-
 include/linux/pnode.h |    2 -
 3 files changed, 35 insertions(+), 48 deletions(-)

Index: 2.6.13.sharedsubtree/fs/namespace.c
===================================================================
--- 2.6.13.sharedsubtree.orig/fs/namespace.c
+++ 2.6.13.sharedsubtree/fs/namespace.c
@@ -220,17 +220,10 @@ struct vfsmount *clone_mnt(struct vfsmou
 		mnt->mnt_root = dget(root);
 		mnt->mnt_mountpoint = mnt->mnt_root;
 		mnt->mnt_parent = mnt;
 		mnt->mnt_namespace = current->namespace;
 		mnt->mnt_master = mntget(old);
-
-		/* stick the duplicate mount on the same expiry list
-		 * as the original if that was on one */
-		spin_lock(&vfsmount_lock);
-		if (!list_empty(&old->mnt_expire))
-			list_add(&mnt->mnt_expire, &old->mnt_expire);
-		spin_unlock(&vfsmount_lock);
 	}
 	return mnt;
 }
 
 static void inline clean_propagation_reference(struct vfsmount *mnt)
@@ -341,40 +334,18 @@ struct seq_operations mounts_op = {
  * open files, pwds, chroots or sub mounts that are
  * busy.
  */
 int may_umount_tree(struct vfsmount *mnt)
 {
-	struct list_head *next;
-	struct vfsmount *this_parent = mnt;
-	int actual_refs;
-	int minimum_refs;
+	int actual_refs = 0;
+	int minimum_refs = 0;
+	struct vfsmount *p;
 
 	spin_lock(&vfsmount_lock);
-	actual_refs = atomic_read(&mnt->mnt_count);
-	minimum_refs = 2;
-      repeat:
-	next = this_parent->mnt_mounts.next;
-      resume:
-	while (next != &this_parent->mnt_mounts) {
-		struct vfsmount *p =
-		    list_entry(next, struct vfsmount, mnt_child);
-
-		next = next->next;
-
+	for (p = mnt; p; p = next_mnt(p, mnt)) {
 		actual_refs += atomic_read(&p->mnt_count);
 		minimum_refs += 2;
-
-		if (!list_empty(&p->mnt_mounts)) {
-			this_parent = p;
-			goto repeat;
-		}
-	}
-
-	if (this_parent != mnt) {
-		next = this_parent->mnt_child.next;
-		this_parent = this_parent->mnt_parent;
-		goto resume;
 	}
 	spin_unlock(&vfsmount_lock);
 
 	if (actual_refs > minimum_refs)
 		return -EBUSY;
@@ -401,10 +372,24 @@ void do_detach_mount(struct vfsmount *mn
 	spin_unlock(&vfsmount_lock);
 	mntput(mnt);
 	spin_lock(&vfsmount_lock);
 }
 
+static void update_expiry_list(struct vfsmount *mnt)
+{
+	struct vfsmount *master, *m;
+	for (m = mnt; m; m = next_mnt(m, mnt)) {
+		master = m->mnt_master;
+		if (master) {
+			if (!list_empty(&master->mnt_expire))
+				list_add(&m->mnt_expire, &master->mnt_expire);
+			mntput(master);
+			m->mnt_master = NULL;
+		}
+	}
+}
+
 /**
  * may_umount - check if a mount point is busy
  * @mnt: root of mount
  *
  * This is called to check if a mount point has any
@@ -416,13 +401,16 @@ void do_detach_mount(struct vfsmount *mn
  * give false negatives. The main reason why it's here is that we need
  * a non-destructive way to look for easily umountable filesystems.
  */
 int may_umount(struct vfsmount *mnt)
 {
-	if (atomic_read(&mnt->mnt_count) > 2)
-		return -EBUSY;
-	return 0;
+	int ret = 0;
+	spin_lock(&vfsmount_lock);
+	if (propagate_mount_busy(mnt, 2))
+		ret = -EBUSY;
+	spin_unlock(&vfsmount_lock);
+	return ret;
 }
 
 EXPORT_SYMBOL(may_umount);
 
 static void umount_tree(struct vfsmount *mnt)
@@ -727,11 +715,11 @@ static void commit_attach_recursive_mnt(
 			list_del_init(&nextmnt->mnt_mounts);
 			list_add_tail(&m->mnt_list, &nextmnt->mnt_list);
 		}
 
 		spin_lock(&vfspnode_lock);
-		propagate_commit_mount(m);
+		propagate_commit_mount(m, move);
 		spin_unlock(&vfspnode_lock);
 
 		if (!move && (master = m->mnt_master)) {
 			m->mnt_master = NULL;
 			if (IS_MNT_SHARED(master))
@@ -891,11 +879,11 @@ static int attach_recursive_mnt(struct v
 		spin_lock(&vfsmount_lock);
 		attach_mnt(source_mnt, nd);
 		list_add_tail(&mnt_list_head, &source_mnt->mnt_list);
 		list_splice(&mnt_list_head, dest_mnt->mnt_namespace->list.prev);
 		if (!move)
-			clean_propagation_reference(source_mnt);
+			update_expiry_list(source_mnt);
 		spin_unlock(&vfsmount_lock);
 		goto out;
 	}
 
 	p = NULL;
@@ -1066,15 +1054,10 @@ static int do_loopback(struct nameidata 
 		else
 			mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
 	}
 
 	if (mnt) {
-		/* stop bind mounts from expiring */
-		spin_lock(&vfsmount_lock);
-		list_del_init(&mnt->mnt_expire);
-		spin_unlock(&vfsmount_lock);
-
 		err = graft_tree(mnt, nd);
 		if (err) {
 			spin_lock(&vfsmount_lock);
 			clean_propagation_reference(mnt);
 			umount_tree(mnt);
@@ -1298,17 +1281,17 @@ static void expire_mount(struct vfsmount
 
 	/*
 	 * Check that it is still dead: the count should now be 2 - as
 	 * contributed by the vfsmount parent and the mntget above
 	 */
-	if (atomic_read(&mnt->mnt_count) == 2) {
+	if (!propagate_mount_busy(mnt, 2)) {
 		struct nameidata old_nd;
 
 		/* delete from the namespace */
 		list_del_init(&mnt->mnt_list);
 		mnt->mnt_namespace = NULL;
-		detach_mnt(mnt, &old_nd);
+		propagate_umount(mnt);
 		spin_unlock(&vfsmount_lock);
 		path_release(&old_nd);
 
 		/*
 		 * Now lay it to rest if this was the last ref on the superblock
Index: 2.6.13.sharedsubtree/fs/pnode.c
===================================================================
--- 2.6.13.sharedsubtree.orig/fs/pnode.c
+++ 2.6.13.sharedsubtree/fs/pnode.c
@@ -258,14 +258,15 @@ static struct vfsmount *skip_propagation
  * commit the operations done by propagate_prepare_mount()
  * @mnt: the root of the mount tree.
  * 'vfspnode_lock' need not be held before calling this function, if the
  * propogation tree is local to the caller.
  */
-int propagate_commit_mount(struct vfsmount *mnt)
+int propagate_commit_mount(struct vfsmount *mnt, int move)
 {
 	struct vfsmount *m;
 	LIST_HEAD(mnt_list_head);
+	struct vfsmount *master = move ? mnt : mnt->mnt_master;
 
 	list_add_tail(&mnt_list_head, &mnt->mnt_list);
 	while (!list_empty(&mnt_list_head)) {
 		m = list_entry(mnt_list_head.next, struct vfsmount, mnt_list);
 		list_del_init(&m->mnt_list);
@@ -273,12 +274,15 @@ int propagate_commit_mount(struct vfsmou
 
 		if (IS_MNT_SHARED(m->mnt_parent))
 			set_mnt_shared(m);
 		else if (m != mnt)
 			CLEAR_MNT_SHARED(m);
-	}
 
+		if (((move && m != mnt) || !move) && master &&
+		    !list_empty(&master->mnt_expire))
+			list_add(&m->mnt_expire, &master->mnt_expire);
+	}
 	return 0;
 }
 
 /*
  * abort the operations done by propagate_prepare_mount()
Index: 2.6.13.sharedsubtree/include/linux/pnode.h
===================================================================
--- 2.6.13.sharedsubtree.orig/include/linux/pnode.h
+++ 2.6.13.sharedsubtree/include/linux/pnode.h
@@ -56,11 +56,11 @@ int do_make_slave(struct vfsmount *);
 int do_make_shared(struct vfsmount *);
 int do_make_private(struct vfsmount *);
 int do_make_unclonable(struct vfsmount *);
 void pnode_merge_mount(struct vfsmount *, struct vfsmount *);
 void pnode_slave_mount(struct vfsmount *, struct vfsmount *);
-int propagate_commit_mount(struct vfsmount *);
+int propagate_commit_mount(struct vfsmount *, int);
 int propagate_abort_mount(struct vfsmount *);
 int propagate_prepare_mount(struct vfsmount *, struct dentry *,
 			    struct vfsmount *);
 int propagate_umount(struct vfsmount *);
 int propagate_mount_busy(struct vfsmount *, int);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-09-16 18:28 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-16 18:26 [RFC PATCH 9/10] vfs: shared subtree automounter helper functions Ram

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.