Introduce proc_get_ns_by_fd() so that get_net_ns_by_fd() becomes
one-liner. It will have another CLONE_NEWPID user soon.

TODO: proc_get_ns_by_fd() can share some code with proc_ns_fget().

Signed-off-by: Oleg Nesterov <o...@redhat.com>
---
 fs/nsfs.c                |   24 ++++++++++++++++++++++++
 include/linux/proc_ns.h  |    3 +++
 kernel/pid_namespace.c   |    6 ++++++
 net/core/net_namespace.c |   23 +++++++----------------
 4 files changed, 40 insertions(+), 16 deletions(-)

diff --git a/fs/nsfs.c b/fs/nsfs.c
index 99521e7..72474ca 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -136,6 +136,30 @@ out_invalid:
        return ERR_PTR(-EINVAL);
 }
 
+void *proc_get_ns_by_fd(int fd, int type)
+{
+       struct fd f;
+       struct ns_common *ns;
+       void *ret;
+
+       f = fdget(fd);
+       if (!f.file)
+               return ERR_PTR(-EBADF);
+
+       ret = ERR_PTR(-EINVAL);
+       if (f.file->f_op != &ns_file_operations)
+               goto put;
+
+       ns = get_proc_ns(file_inode(f.file));
+       if (ns->ops->type != type || !ns->ops->get_type)
+               goto put;
+
+       ret = ns->ops->get_type(ns);
+put:
+       fdput(f);
+       return ret;
+}
+
 static const struct super_operations nsfs_ops = {
        .statfs = simple_statfs,
        .evict_inode = nsfs_evict,
diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h
index 42dfc61..d956f89 100644
--- a/include/linux/proc_ns.h
+++ b/include/linux/proc_ns.h
@@ -16,6 +16,7 @@ struct proc_ns_operations {
        struct ns_common *(*get)(struct task_struct *task);
        void (*put)(struct ns_common *ns);
        int (*install)(struct nsproxy *nsproxy, struct ns_common *ns);
+       void *(*get_type)(struct ns_common *ns);
 };
 
 extern const struct proc_ns_operations netns_operations;
@@ -66,6 +67,8 @@ static inline int ns_alloc_inum(struct ns_common *ns)
 #define ns_free_inum(ns) proc_free_inum((ns)->inum)
 
 extern struct file *proc_ns_fget(int fd);
+extern void *proc_get_ns_by_fd(int fd, int type);
+
 #define get_proc_ns(inode) ((struct ns_common *)(inode)->i_private)
 extern void *ns_get_path(struct path *path, struct task_struct *task,
                        const struct proc_ns_operations *ns_ops);
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index a65ba13..0c87393 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -388,12 +388,18 @@ static int pidns_install(struct nsproxy *nsproxy, struct 
ns_common *ns)
        return 0;
 }
 
+static void *pidns_get_type(struct ns_common *ns)
+{
+       return get_pid_ns(to_pid_ns(ns));
+}
+
 const struct proc_ns_operations pidns_operations = {
        .name           = "pid",
        .type           = CLONE_NEWPID,
        .get            = pidns_get,
        .put            = pidns_put,
        .install        = pidns_install,
+       .get_type       = pidns_get_type,
 };
 
 static __init int pid_namespaces_init(void)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 572af00..6465dc0 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -420,22 +420,7 @@ EXPORT_SYMBOL_GPL(__put_net);
 
 struct net *get_net_ns_by_fd(int fd)
 {
-       struct file *file;
-       struct ns_common *ns;
-       struct net *net;
-
-       file = proc_ns_fget(fd);
-       if (IS_ERR(file))
-               return ERR_CAST(file);
-
-       ns = get_proc_ns(file_inode(file));
-       if (ns->ops == &netns_operations)
-               net = get_net(container_of(ns, struct net, ns));
-       else
-               net = ERR_PTR(-EINVAL);
-
-       fput(file);
-       return net;
+       return proc_get_ns_by_fd(fd, CLONE_NEWNET);
 }
 
 #else
@@ -955,11 +940,17 @@ static int netns_install(struct nsproxy *nsproxy, struct 
ns_common *ns)
        return 0;
 }
 
+static void *netns_get_type(struct ns_common *ns)
+{
+       return get_net(to_net_ns(ns));
+}
+
 const struct proc_ns_operations netns_operations = {
        .name           = "net",
        .type           = CLONE_NEWNET,
        .get            = netns_get,
        .put            = netns_put,
        .install        = netns_install,
+       .get_type       = netns_get_type,
 };
 #endif
-- 
1.5.5.1


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to