]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/namespace.c
[SCSI] don't use __GFP_DMA for sense buffers if not required
[linux-2.6-omap-h63xx.git] / fs / namespace.c
index fd999cab7b57c07b7729aabb3d96d938e3d8f0d1..06083885b21e85314e3a196d13c7822dcc7c6e9d 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include "pnode.h"
+#include "internal.h"
 
 /* spinlock for vfsmount related operations, inplace of dcache_lock */
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
@@ -245,7 +246,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
                        list_add(&mnt->mnt_slave, &old->mnt_slave_list);
                        mnt->mnt_master = old;
                        CLEAR_MNT_SHARED(mnt);
-               } else {
+               } else if (!(flag & CL_PRIVATE)) {
                        if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old))
                                list_add(&mnt->mnt_share, &old->mnt_share);
                        if (IS_MNT_SLAVE(old))
@@ -320,22 +321,16 @@ EXPORT_SYMBOL(mnt_unpin);
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
        struct mnt_namespace *n = m->private;
-       struct list_head *p;
-       loff_t l = *pos;
 
        down_read(&namespace_sem);
-       list_for_each(p, &n->list)
-               if (!l--)
-                       return list_entry(p, struct vfsmount, mnt_list);
-       return NULL;
+       return seq_list_start(&n->list, *pos);
 }
 
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
        struct mnt_namespace *n = m->private;
-       struct list_head *p = ((struct vfsmount *)v)->mnt_list.next;
-       (*pos)++;
-       return p == &n->list ? NULL : list_entry(p, struct vfsmount, mnt_list);
+
+       return seq_list_next(v, &n->list, pos);
 }
 
 static void m_stop(struct seq_file *m, void *v)
@@ -350,7 +345,7 @@ static inline void mangle(struct seq_file *m, const char *s)
 
 static int show_vfsmnt(struct seq_file *m, void *v)
 {
-       struct vfsmount *mnt = v;
+       struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
        int err = 0;
        static struct proc_fs_info {
                int flag;
@@ -377,6 +372,10 @@ static int show_vfsmnt(struct seq_file *m, void *v)
        seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
        seq_putc(m, ' ');
        mangle(m, mnt->mnt_sb->s_type->name);
+       if (mnt->mnt_sb->s_subtype && mnt->mnt_sb->s_subtype[0]) {
+               seq_putc(m, '.');
+               mangle(m, mnt->mnt_sb->s_subtype);
+       }
        seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
        for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
                if (mnt->mnt_sb->s_flags & fs_infop->flag)
@@ -401,7 +400,7 @@ struct seq_operations mounts_op = {
 
 static int show_vfsstat(struct seq_file *m, void *v)
 {
-       struct vfsmount *mnt = v;
+       struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
        int err = 0;
 
        /* device */
@@ -495,7 +494,7 @@ void release_mounts(struct list_head *head)
 {
        struct vfsmount *mnt;
        while (!list_empty(head)) {
-               mnt = list_entry(head->next, struct vfsmount, mnt_hash);
+               mnt = list_first_entry(head, struct vfsmount, mnt_hash);
                list_del_init(&mnt->mnt_hash);
                if (mnt->mnt_parent != mnt) {
                        struct dentry *dentry;
@@ -747,6 +746,26 @@ Enomem:
        return NULL;
 }
 
+struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry)
+{
+       struct vfsmount *tree;
+       down_read(&namespace_sem);
+       tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE);
+       up_read(&namespace_sem);
+       return tree;
+}
+
+void drop_collected_mounts(struct vfsmount *mnt)
+{
+       LIST_HEAD(umount_list);
+       down_read(&namespace_sem);
+       spin_lock(&vfsmount_lock);
+       umount_tree(mnt, 0, &umount_list);
+       spin_unlock(&vfsmount_lock);
+       up_read(&namespace_sem);
+       release_mounts(&umount_list);
+}
+
 /*
  *  @source_mnt : mount tree to be attached
  *  @nd         : place the mount tree @source_mnt is attached
@@ -882,6 +901,9 @@ static int do_change_type(struct nameidata *nd, int flag)
        int recurse = flag & MS_REC;
        int type = flag & ~MS_REC;
 
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        if (nd->dentry != nd->mnt->mnt_root)
                return -EINVAL;
 
@@ -1173,7 +1195,7 @@ static void expire_mount_list(struct list_head *graveyard, struct list_head *mou
 
        while (!list_empty(graveyard)) {
                LIST_HEAD(umounts);
-               mnt = list_entry(graveyard->next, struct vfsmount, mnt_expire);
+               mnt = list_first_entry(graveyard, struct vfsmount, mnt_expire);
                list_del_init(&mnt->mnt_expire);
 
                /* don't do anything if the namespace is dead - all the
@@ -1409,7 +1431,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
                mnt_flags |= MNT_RELATIME;
 
        flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
-                  MS_NOATIME | MS_NODIRATIME | MS_RELATIME);
+                  MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT);
 
        /* ... and get the mountpoint */
        retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
@@ -1441,17 +1463,16 @@ dput_out:
  * Allocate a new namespace structure and populate it with contents
  * copied from the namespace of the passed in task structure.
  */
-struct mnt_namespace *dup_mnt_ns(struct task_struct *tsk,
+static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
                struct fs_struct *fs)
 {
-       struct mnt_namespace *mnt_ns = tsk->nsproxy->mnt_ns;
        struct mnt_namespace *new_ns;
        struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
        struct vfsmount *p, *q;
 
        new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
        if (!new_ns)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        atomic_set(&new_ns->count, 1);
        INIT_LIST_HEAD(&new_ns->list);
@@ -1465,7 +1486,7 @@ struct mnt_namespace *dup_mnt_ns(struct task_struct *tsk,
        if (!new_ns->root) {
                up_write(&namespace_sem);
                kfree(new_ns);
-               return NULL;
+               return ERR_PTR(-ENOMEM);;
        }
        spin_lock(&vfsmount_lock);
        list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
@@ -1509,36 +1530,21 @@ struct mnt_namespace *dup_mnt_ns(struct task_struct *tsk,
        return new_ns;
 }
 
-int copy_mnt_ns(int flags, struct task_struct *tsk)
+struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
+               struct fs_struct *new_fs)
 {
-       struct mnt_namespace *ns = tsk->nsproxy->mnt_ns;
        struct mnt_namespace *new_ns;
-       int err = 0;
-
-       if (!ns)
-               return 0;
 
+       BUG_ON(!ns);
        get_mnt_ns(ns);
 
        if (!(flags & CLONE_NEWNS))
-               return 0;
+               return ns;
 
-       if (!capable(CAP_SYS_ADMIN)) {
-               err = -EPERM;
-               goto out;
-       }
-
-       new_ns = dup_mnt_ns(tsk, tsk->fs);
-       if (!new_ns) {
-               err = -ENOMEM;
-               goto out;
-       }
+       new_ns = dup_mnt_ns(ns, new_fs);
 
-       tsk->nsproxy->mnt_ns = new_ns;
-
-out:
        put_mnt_ns(ns);
-       return err;
+       return new_ns;
 }
 
 asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name,
@@ -1805,7 +1811,7 @@ static void __init init_mount_tree(void)
        set_fs_root(current->fs, ns->root, ns->root->mnt_root);
 }
 
-void __init mnt_init(unsigned long mempages)
+void __init mnt_init(void)
 {
        struct list_head *d;
        unsigned int nr_hash;
@@ -1815,7 +1821,7 @@ void __init mnt_init(unsigned long mempages)
        init_rwsem(&namespace_sem);
 
        mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount),
-                       0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL, NULL);
+                       0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
 
        mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);