From: linuxram@us.ibm.com (Ram)
To: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org
Cc: linuxram@us.ibm.com, akpm@osdl.org, viro@ftp.linux.org.uk,
miklos@szeredi.hu, mike@waychison.com, bfields@fieldses.org,
serue@us.ibm.com
Subject: [RFC PATCH 9/10] vfs: shared subtree automounter helper functions
Date: Fri, 16 Sep 2005 11:26:20 -0700 [thread overview]
Message-ID: <20050916182620.GA28546@RAM> (raw)
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);
reply other threads:[~2005-09-16 18:27 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20050916182620.GA28546@RAM \
--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=serue@us.ibm.com \
--cc=viro@ftp.linux.org.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).