For speed and convenience of look-up, the nsfs device ID is looked up for the
first instance of a type of namespace, then copied to others of the same type
as they are spawned.
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
fs/namespace.c | 2 ++
fs/nsfs.c | 21 +++++++++++++++++++++
include/linux/ns_common.h | 1 +
include/linux/proc_ns.h | 1 +
ipc/namespace.c | 1 +
kernel/pid_namespace.c | 1 +
kernel/user_namespace.c | 1 +
kernel/utsname.c | 1 +
net/core/net_namespace.c | 2 ++
9 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/fs/namespace.c b/fs/namespace.c
index 82ef140..c680675 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2698,6 +2698,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct
mnt_namespace *ns,
old = ns->root;
new_ns = alloc_mnt_ns(user_ns);
+ new_ns->ns.dev = ns->ns.dev;
if (IS_ERR(new_ns))
return new_ns;
@@ -2762,6 +2763,7 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
struct mount *mnt = real_mount(m);
mnt->mnt_ns = new_ns;
new_ns->root = mnt;
+ new_ns->ns.dev = nsfs_dev();
list_add(&mnt->mnt_list, &new_ns->list);
} else {
mntput(m);
diff --git a/fs/nsfs.c b/fs/nsfs.c
index 1fcd529..cc785d3 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -4,6 +4,10 @@
#include <linux/proc_ns.h>
#include <linux/magic.h>
#include <linux/ktime.h>
+#include <linux/init_task.h>
+#include <linux/utsname.h>
+#include <linux/pid_namespace.h>
+#include <linux/ipc_namespace.h>
static struct vfsmount *nsfs_mnt;
@@ -158,6 +162,23 @@ void __init nsfs_init(void)
if (IS_ERR(nsfs_mnt))
panic("can't set nsfs up\n");
nsfs_mnt->mnt_sb->s_flags &= ~MS_NOUSER;
+ init_ipc_ns.ns.dev = init_uts_ns.ns.dev = init_pid_ns.ns.dev
+ = init_user_ns.ns.dev = nsfs_dev();
+}
+
+dev_t nsfs_dev(void)
+{
+ dev_t dev;
+
+ void nssb_to_dev(struct super_block *sb, void *arg){
+ dev_t *dev = arg;
+
+ if (sb->s_magic == NSFS_MAGIC)
+ *dev = sb->s_dev;
+ }
+
+ iterate_supers(nssb_to_dev, (void*)&dev);
+ return dev;
}
static DEFINE_IDA(ns_inum_ida);
diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h
index 85a5c8c..6701070 100644
--- a/include/linux/ns_common.h
+++ b/include/linux/ns_common.h
@@ -7,6 +7,7 @@ struct ns_common {
atomic_long_t stashed;
const struct proc_ns_operations *ops;
unsigned int inum;
+ dev_t dev;
};
#endif
diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h
index 721d0e2..904d9e7 100644
--- a/include/linux/proc_ns.h
+++ b/include/linux/proc_ns.h
@@ -71,4 +71,5 @@ extern int ns_get_name(char *buf, size_t size, struct task_struct
*task,
const struct proc_ns_operations *ns_ops);
extern void nsfs_init(void);
+extern dev_t nsfs_dev(void);
#endif /* _LINUX_PROC_NS_H */
diff --git a/ipc/namespace.c b/ipc/namespace.c
index 068caf1..b24da44 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -31,6 +31,7 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace
*user_ns,
kfree(ns);
return ERR_PTR(err);
}
+ ns->ns.dev = old_ns->ns.dev;
ns->ns.ops = &ipcns_operations;
atomic_set(&ns->count, 1);
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index a65ba13..691b9ac 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -108,6 +108,7 @@ static struct pid_namespace *create_pid_namespace(struct
user_namespace *user_ns
err = ns_alloc_inum(&ns->ns);
if (err)
goto out_free_map;
+ ns->ns.dev = parent_pid_ns->ns.dev;
ns->ns.ops = &pidns_operations;
kref_init(&ns->kref);
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 4109f83..ec29cd9 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -92,6 +92,7 @@ int create_user_ns(struct cred *new)
kmem_cache_free(user_ns_cachep, ns);
return ret;
}
+ ns->ns.dev = parent_ns->ns.dev;
ns->ns.ops = &userns_operations;
atomic_set(&ns->count, 1);
diff --git a/kernel/utsname.c b/kernel/utsname.c
index 831ea71..54c45e1 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -48,6 +48,7 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace
*user_ns,
return ERR_PTR(err);
}
+ ns->ns.dev = old_ns->ns.dev;
ns->ns.ops = &utsns_operations;
down_read(&uts_sem);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 70d3450..a706cdd 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -332,6 +332,7 @@ struct net *copy_net_ns(unsigned long flags,
mutex_lock(&net_mutex);
rv = setup_net(net, user_ns);
if (rv == 0) {
+ net->ns.dev = old_net->ns.dev;
rtnl_lock();
list_add_tail_rcu(&net->list, &net_namespace_list);
rtnl_unlock();
@@ -639,6 +640,7 @@ static int __init net_ns_init(void)
if (setup_net(&init_net, &init_user_ns))
panic("Could not setup the initial network namespace");
+ init_net.ns.dev = nsfs_dev();
rtnl_lock();
list_add_tail_rcu(&init_net.list, &net_namespace_list);
rtnl_unlock();
--
1.7.1