patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / namespace.c
index fa8b30e..9bd40b9 100644 (file)
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/mount.h>
+#include <linux/vs_base.h>
+
 #include <asm/uaccess.h>
+#include <asm/unistd.h>
 
 extern int __init init_rootfs(void);
 
@@ -36,6 +39,7 @@ static inline int sysfs_init(void)
 
 /* spinlock for vfsmount related operations, inplace of dcache_lock */
 spinlock_t vfsmount_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+
 static struct list_head *mount_hashtable;
 static int hash_mask, hash_bits;
 static kmem_cache_t *mnt_cache; 
@@ -262,7 +266,65 @@ struct seq_operations mounts_op = {
        .show   = show_vfsmnt
 };
 
-/*
+/**
+ * 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)
+{
+       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);
+
+       if (actual_refs > minimum_refs)
+               return -EBUSY;
+
+       return 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.
@@ -427,6 +489,8 @@ out:
        return retval;
 }
 
+#ifdef __ARCH_WANT_SYS_OLDUMOUNT
+
 /*
  *     The 2.0 compatible umount. No flags. 
  */
@@ -436,6 +500,8 @@ asmlinkage long sys_oldumount(char __user * name)
        return sys_umount(name,0);
 }
 
+#endif
+
 static int mount_is_safe(struct nameidata *nd)
 {
        if (capable(CAP_SYS_ADMIN))
@@ -1168,9 +1234,7 @@ void __init mnt_init(unsigned long mempages)
        int i;
 
        mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount),
-                                       0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-       if (!mnt_cache)
-               panic("Cannot create vfsmount cache");
+                       0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
 
        order = 0; 
        mount_hashtable = (struct list_head *)