]> err.no Git - linux-2.6/blobdiff - fs/proc/root.c
pid namespaces: make proc have multiple superblocks - one for each namespace
[linux-2.6] / fs / proc / root.c
index 5834a744c2a96fec843290a83a38c090f34618d5..94e9d734384e1fb3023e779ce8a58ea37097b11f 100644 (file)
 #include <linux/bitops.h>
 #include <linux/smp_lock.h>
 #include <linux/mount.h>
+#include <linux/pid_namespace.h>
 
 #include "internal.h"
 
-struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
+struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver;
+
+static int proc_test_super(struct super_block *sb, void *data)
+{
+       return sb->s_fs_info == data;
+}
+
+static int proc_set_super(struct super_block *sb, void *data)
+{
+       struct pid_namespace *ns;
+
+       ns = (struct pid_namespace *)data;
+       sb->s_fs_info = get_pid_ns(ns);
+       return set_anon_super(sb, NULL);
+}
 
 static int proc_get_sb(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
+       int err;
+       struct super_block *sb;
+       struct pid_namespace *ns;
+       struct proc_inode *ei;
+
        if (proc_mnt) {
                /* Seed the root directory with a pid so it doesn't need
                 * to be special in base.c.  I would do this earlier but
                 * the only task alive when /proc is mounted the first time
                 * is the init_task and it doesn't have any pids.
                 */
-               struct proc_inode *ei;
                ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode);
                if (!ei->pid)
                        ei->pid = find_get_pid(1);
        }
-       return get_sb_single(fs_type, flags, data, proc_fill_super, mnt);
+
+       if (flags & MS_KERNMOUNT)
+               ns = (struct pid_namespace *)data;
+       else
+               ns = current->nsproxy->pid_ns;
+
+       sb = sget(fs_type, proc_test_super, proc_set_super, ns);
+       if (IS_ERR(sb))
+               return PTR_ERR(sb);
+
+       if (!sb->s_root) {
+               sb->s_flags = flags;
+               err = proc_fill_super(sb);
+               if (err) {
+                       up_write(&sb->s_umount);
+                       deactivate_super(sb);
+                       return err;
+               }
+
+               ei = PROC_I(sb->s_root->d_inode);
+               if (!ei->pid) {
+                       rcu_read_lock();
+                       ei->pid = get_pid(find_pid_ns(1, ns));
+                       rcu_read_unlock();
+               }
+
+               sb->s_flags |= MS_ACTIVE;
+               ns->proc_mnt = mnt;
+       }
+
+       return simple_set_mnt(mnt, sb);
+}
+
+static void proc_kill_sb(struct super_block *sb)
+{
+       struct pid_namespace *ns;
+
+       ns = (struct pid_namespace *)sb->s_fs_info;
+       kill_anon_super(sb);
+       put_pid_ns(ns);
 }
 
 static struct file_system_type proc_fs_type = {
        .name           = "proc",
        .get_sb         = proc_get_sb,
-       .kill_sb        = kill_anon_super,
+       .kill_sb        = proc_kill_sb,
 };
 
 void __init proc_root_init(void)
@@ -54,15 +112,16 @@ void __init proc_root_init(void)
        err = register_filesystem(&proc_fs_type);
        if (err)
                return;
-       proc_mnt = kern_mount(&proc_fs_type);
+       proc_mnt = kern_mount_data(&proc_fs_type, &init_pid_ns);
        err = PTR_ERR(proc_mnt);
        if (IS_ERR(proc_mnt)) {
                unregister_filesystem(&proc_fs_type);
                return;
        }
+
        proc_misc_init();
-       proc_net = proc_mkdir("net", NULL);
-       proc_net_stat = proc_mkdir("net/stat", NULL);
+
+       proc_net_init();
 
 #ifdef CONFIG_SYSVIPC
        proc_mkdir("sysvipc", NULL);
@@ -79,9 +138,7 @@ void __init proc_root_init(void)
        proc_device_tree_init();
 #endif
        proc_bus = proc_mkdir("bus", NULL);
-#ifdef CONFIG_SYSCTL
        proc_sys_init();
-#endif
 }
 
 static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
@@ -161,7 +218,5 @@ EXPORT_SYMBOL(create_proc_entry);
 EXPORT_SYMBOL(remove_proc_entry);
 EXPORT_SYMBOL(proc_root);
 EXPORT_SYMBOL(proc_root_fs);
-EXPORT_SYMBOL(proc_net);
-EXPORT_SYMBOL(proc_net_stat);
 EXPORT_SYMBOL(proc_bus);
 EXPORT_SYMBOL(proc_root_driver);