Make /proc/self/mounts(tats) use seq_list_xxx helpers
[linux-2.6-block.git] / fs / namespace.c
index fde8553faa7661677e2210d65620b753eceddaf8..c811a94e4c88066c929d6924633e6099efde3114 100644 (file)
@@ -53,9 +53,8 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
 
 struct vfsmount *alloc_vfsmnt(const char *name)
 {
-       struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL);
+       struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
        if (mnt) {
-               memset(mnt, 0, sizeof(struct vfsmount));
                atomic_set(&mnt->mnt_count, 1);
                INIT_LIST_HEAD(&mnt->mnt_hash);
                INIT_LIST_HEAD(&mnt->mnt_child);
@@ -321,22 +320,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)
@@ -351,7 +344,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;
@@ -368,6 +361,7 @@ static int show_vfsmnt(struct seq_file *m, void *v)
                { MNT_NOEXEC, ",noexec" },
                { MNT_NOATIME, ",noatime" },
                { MNT_NODIRATIME, ",nodiratime" },
+               { MNT_RELATIME, ",relatime" },
                { 0, NULL }
        };
        struct proc_fs_info *fs_infop;
@@ -377,6 +371,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 +399,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 +493,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;
@@ -882,6 +880,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 +1174,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
@@ -1405,9 +1406,11 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
                mnt_flags |= MNT_NOATIME;
        if (flags & MS_NODIRATIME)
                mnt_flags |= MNT_NODIRATIME;
+       if (flags & MS_RELATIME)
+               mnt_flags |= MNT_RELATIME;
 
        flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
-                  MS_NOATIME | MS_NODIRATIME);
+                  MS_NOATIME | MS_NODIRATIME | MS_RELATIME);
 
        /* ... and get the mountpoint */
        retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
@@ -1439,10 +1442,9 @@ 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;
@@ -1507,36 +1509,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(int 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;
-
-       if (!capable(CAP_SYS_ADMIN)) {
-               err = -EPERM;
-               goto out;
-       }
-
-       new_ns = dup_mnt_ns(tsk, tsk->fs);
-       if (!new_ns) {
-               err = -ENOMEM;
-               goto out;
-       }
+               return ns;
 
-       tsk->nsproxy->mnt_ns = new_ns;
+       new_ns = dup_mnt_ns(ns, new_fs);
 
-out:
        put_mnt_ns(ns);
-       return err;
+       return new_ns;
 }
 
 asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name,