Re: 2.6.6-rc2-mm1

From: raven
Date: Thu Apr 22 2004 - 10:32:10 EST



This is a second attempt at a patch to address Christophs' concerns.

It assumes a 2.6.6-rc2-mm1 tree.

- renamed autofs4_may_umount to __may_umount_tree, made it static
and moved it to namespace.c.
- added stub function may_umount_tree with description
- altered may_umount to use above stub function and added
little description
- added may_umount_tree prototype to fs.h
- removed the EXPORT_SYMBOL for vfsmount_lock
- updated expire.c to suit

Andrew,

This is the entire patch again. I hope this won't cause to much
hastle.

diff -Nur linux-2.6.6-rc1-mm1.orig/fs/autofs4/expire.c linux-2.6.6-rc1-mm1/fs/autofs4/expire.c
--- linux-2.6.6-rc1-mm1.orig/fs/autofs4/expire.c 2004-04-20 23:35:14.000000000 +0800
+++ linux-2.6.6-rc1-mm1/fs/autofs4/expire.c 2004-04-22 21:06:09.000000000 +0800
@@ -45,47 +45,6 @@
return 1;
}

-/* Sorry I can't solve the problem without using counts either */
-static int autofs4_may_umount(struct vfsmount *mnt)
-{
- struct list_head *next;
- struct vfsmount *this_parent = mnt;
- int actual_refs;
- int minimum_refs;
-
- 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;
-
- 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);
-
- DPRINTK(("autofs4_may_umount: done actual = %d, minimum = %d\n",
- actual_refs, minimum_refs));
-
- return actual_refs > minimum_refs;
-}
-
/* Check a mount point for busyness return 1 if not busy, otherwise */
static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
{
@@ -108,7 +67,7 @@
goto done;

/* The big question */
- if (autofs4_may_umount(mnt) == 0)
+ if (may_umount_tree(mnt) == 0)
status = 1;
done:
DPRINTK(("autofs4_check_mount: returning = %d\n", status));
--- linux-2.6.6-rc1-mm1.orig/fs/namespace.c 2004-04-20 22:08:41.000000000 +0800
+++ linux-2.6.6-rc1-mm1/fs/namespace.c 2004-04-22 21:06:09.000000000 +0800
@@ -37,8 +37,6 @@
/* spinlock for vfsmount related operations, inplace of dcache_lock */
spinlock_t vfsmount_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;

-EXPORT_SYMBOL(vfsmount_lock);
-
static struct list_head *mount_hashtable;
static int hash_mask, hash_bits;
static kmem_cache_t *mnt_cache;
@@ -262,16 +260,85 @@
.show = show_vfsmnt
};

-/*
+static int __may_umount_tree(struct vfsmount *mnt, int root_mnt_only)
+{
+ struct list_head *next;
+ struct vfsmount *this_parent = mnt;
+ int actual_refs;
+ int minimum_refs;
+
+ spin_lock(&vfsmount_lock);
+ actual_refs = atomic_read(&mnt->mnt_count);
+ minimum_refs = 2;
+
+ if (root_mnt_only) {
+ spin_unlock(&vfsmount_lock);
+ if (actual_refs > minimum_refs)
+ return -EBUSY;
+ return 0;
+ }
+
+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;
+
+ 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;
+
+ return 0;
+}
+
+/**
+ * may_umount_tree - check if a mount tree is busy
+ * @mnt: root of mount tree
+ *
+ * This is called to check if a tree of mounts has any
+ * open files, pwds, chroots or sub mounts that are
+ * busy.
+ */
+int may_umount_tree(struct vfsmount *mnt)
+{
+ return __may_umount_tree(mnt, 0);
+}
+
+EXPORT_SYMBOL(may_umount_tree);
+
+/**
+ * may_umount - check if a mount point is busy
+ * @mnt: root of mount
+ *
+ * This is called to check if a mount point has any
+ * open files, pwds, chroots or sub mounts. If the
+ * mount has sub mounts this will return busy
+ * regardless of whether the sub mounts are busy.
+ *
* Doesn't take quota and stuff into account. IOW, in some cases it will
* 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;
+ return __may_umount_tree(mnt, 1);
}

EXPORT_SYMBOL(may_umount);
--- linux-2.6.6-rc1-mm1.orig/include/linux/fs.h 2004-04-20 22:08:51.000000000 +0800
+++ linux-2.6.6-rc1-mm1/include/linux/fs.h 2004-04-22 21:58:11.000000000 +0800
@@ -1127,6 +1127,7 @@
extern int register_filesystem(struct file_system_type *);
extern int unregister_filesystem(struct file_system_type *);
extern struct vfsmount *kern_mount(struct file_system_type *);
+extern int may_umount_tree(struct vfsmount *);
extern int may_umount(struct vfsmount *);
extern long do_mount(char *, char *, char *, unsigned long, void *);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/