]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/namespace.c
[PATCH] autofs4: change may_umount* functions to boolean
[linux-2.6-omap-h63xx.git] / fs / namespace.c
index ce97becff4611c0fae4e90ce655bd8cffe850c77..bf478addb852b70c1ec036e33100f93031c5dc6b 100644 (file)
@@ -43,9 +43,9 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
 
 static int event;
 
-static struct list_head *mount_hashtable;
+static struct list_head *mount_hashtable __read_mostly;
 static int hash_mask __read_mostly, hash_bits __read_mostly;
-static kmem_cache_t *mnt_cache;
+static kmem_cache_t *mnt_cache __read_mostly;
 static struct rw_semaphore namespace_sem;
 
 /* /sys/fs */
@@ -399,6 +399,44 @@ struct seq_operations mounts_op = {
        .show   = show_vfsmnt
 };
 
+static int show_vfsstat(struct seq_file *m, void *v)
+{
+       struct vfsmount *mnt = v;
+       int err = 0;
+
+       /* device */
+       if (mnt->mnt_devname) {
+               seq_puts(m, "device ");
+               mangle(m, mnt->mnt_devname);
+       } else
+               seq_puts(m, "no device");
+
+       /* mount point */
+       seq_puts(m, " mounted on ");
+       seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
+       seq_putc(m, ' ');
+
+       /* file system type */
+       seq_puts(m, "with fstype ");
+       mangle(m, mnt->mnt_sb->s_type->name);
+
+       /* optional statistics */
+       if (mnt->mnt_sb->s_op->show_stats) {
+               seq_putc(m, ' ');
+               err = mnt->mnt_sb->s_op->show_stats(m, mnt);
+       }
+
+       seq_putc(m, '\n');
+       return err;
+}
+
+struct seq_operations mountstats_op = {
+       .start  = m_start,
+       .next   = m_next,
+       .stop   = m_stop,
+       .show   = show_vfsstat,
+};
+
 /**
  * may_umount_tree - check if a mount tree is busy
  * @mnt: root of mount tree
@@ -421,9 +459,9 @@ int may_umount_tree(struct vfsmount *mnt)
        spin_unlock(&vfsmount_lock);
 
        if (actual_refs > minimum_refs)
-               return -EBUSY;
+               return 0;
 
-       return 0;
+       return 1;
 }
 
 EXPORT_SYMBOL(may_umount_tree);
@@ -443,10 +481,10 @@ EXPORT_SYMBOL(may_umount_tree);
  */
 int may_umount(struct vfsmount *mnt)
 {
-       int ret = 0;
+       int ret = 1;
        spin_lock(&vfsmount_lock);
        if (propagate_mount_busy(mnt, 2))
-               ret = -EBUSY;
+               ret = 0;
        spin_unlock(&vfsmount_lock);
        return ret;
 }
@@ -494,7 +532,7 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
                p->mnt_namespace = NULL;
                list_del_init(&p->mnt_child);
                if (p->mnt_parent != p)
-                       mnt->mnt_mountpoint->d_mounted--;
+                       p->mnt_mountpoint->d_mounted--;
                change_mnt_propagation(p, MS_PRIVATE);
        }
 }
@@ -1325,30 +1363,20 @@ dput_out:
        return retval;
 }
 
-int copy_namespace(int flags, struct task_struct *tsk)
+/*
+ * Allocate a new namespace structure and populate it with contents
+ * copied from the namespace of the passed in task structure.
+ */
+struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
 {
        struct namespace *namespace = tsk->namespace;
        struct namespace *new_ns;
        struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
-       struct fs_struct *fs = tsk->fs;
        struct vfsmount *p, *q;
 
-       if (!namespace)
-               return 0;
-
-       get_namespace(namespace);
-
-       if (!(flags & CLONE_NEWNS))
-               return 0;
-
-       if (!capable(CAP_SYS_ADMIN)) {
-               put_namespace(namespace);
-               return -EPERM;
-       }
-
        new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL);
        if (!new_ns)
-               goto out;
+               return NULL;
 
        atomic_set(&new_ns->count, 1);
        INIT_LIST_HEAD(&new_ns->list);
@@ -1362,7 +1390,7 @@ int copy_namespace(int flags, struct task_struct *tsk)
        if (!new_ns->root) {
                up_write(&namespace_sem);
                kfree(new_ns);
-               goto out;
+               return NULL;
        }
        spin_lock(&vfsmount_lock);
        list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
@@ -1396,8 +1424,6 @@ int copy_namespace(int flags, struct task_struct *tsk)
        }
        up_write(&namespace_sem);
 
-       tsk->namespace = new_ns;
-
        if (rootmnt)
                mntput(rootmnt);
        if (pwdmnt)
@@ -1405,12 +1431,39 @@ int copy_namespace(int flags, struct task_struct *tsk)
        if (altrootmnt)
                mntput(altrootmnt);
 
-       put_namespace(namespace);
-       return 0;
+       return new_ns;
+}
+
+int copy_namespace(int flags, struct task_struct *tsk)
+{
+       struct namespace *namespace = tsk->namespace;
+       struct namespace *new_ns;
+       int err = 0;
+
+       if (!namespace)
+               return 0;
+
+       get_namespace(namespace);
+
+       if (!(flags & CLONE_NEWNS))
+               return 0;
+
+       if (!capable(CAP_SYS_ADMIN)) {
+               err = -EPERM;
+               goto out;
+       }
+
+       new_ns = dup_namespace(tsk, tsk->fs);
+       if (!new_ns) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       tsk->namespace = new_ns;
 
 out:
        put_namespace(namespace);
-       return -ENOMEM;
+       return err;
 }
 
 asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name,