aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYordan Karadzhov (VMware) <y.karadz@gmail.com>2021-10-25 14:52:53 +0300
committerYordan Karadzhov (VMware) <y.karadz@gmail.com>2021-11-05 13:53:03 +0200
commit86ac460cc300463d6e89c67185f8a85036d26ccc (patch)
treea031fcf0fd26e732e7aa4f8a6cc842d49a1d1520
parent1b128723e0a3ecb71a4adf289786b85906256776 (diff)
downloadlinux-86ac460cc300463d6e89c67185f8a85036d26ccc.tar.gz
namespacefs: Add methods to create/remove PID namespace directories
Each existing namespace on the system will be represented by a corresponding directory in namespacesfs. When a namespace is created a new directory will be added. When a namespace is destroyed, its corresponding directory will be removed. The hierarchy of the directories will follow the hierarchy of the namespaces. As a first step towards this, here we add methods for creating/removing PID namespace directories. For the moment the PID namespace directory contains only one file called 'tasks'. This is a read only pseudo file that provides the list of PIDs of all tasks enclosed into the namespace. Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
-rw-r--r--fs/namespacefs/inode.c79
-rw-r--r--include/linux/namespacefs.h32
-rw-r--r--include/linux/ns_common.h4
3 files changed, 108 insertions, 7 deletions
diff --git a/fs/namespacefs/inode.c b/fs/namespacefs/inode.c
index 338694f3e5d643..2f897daf30d7e8 100644
--- a/fs/namespacefs/inode.c
+++ b/fs/namespacefs/inode.c
@@ -150,16 +150,16 @@ static struct dentry *_create(const char *name, struct dentry *parent,
return ERR_PTR(-ESTALE);
}
-struct dentry *namespacefs_create_file(const char *name,
- struct dentry *parent,
- const struct file_operations *fops,
- void *data)
+static struct dentry * namespacefs_create_file(const char *name,
+ struct dentry *parent,
+ const struct file_operations *fops,
+ void *data)
{
return _create(name, parent, fops, data);
}
-struct dentry *namespacefs_create_dir(const char *name,
- struct dentry *parent)
+static struct dentry *namespacefs_create_dir(const char *name,
+ struct dentry *parent)
{
return _create(name, parent, NULL, NULL);
}
@@ -169,7 +169,7 @@ static void _remove_one(struct dentry *d)
_release_namespacefs();
}
-void namespacefs_remove_dir(struct dentry *dentry)
+static void namespacefs_remove_dir(struct dentry *dentry)
{
if (IS_ERR_OR_NULL(dentry))
return;
@@ -249,6 +249,71 @@ static int idr_seq_open(struct file *file, struct idr *idr,
return 0;
}
+static inline int pid_seq_show(struct seq_file *m, void *v)
+{
+ struct pid *pid = v;
+ seq_printf(m, "%d\n", pid_nr(pid));
+ return 0;
+}
+
+static const struct seq_operations pid_seq_ops = {
+ .start = idr_seq_start,
+ .next = idr_seq_next,
+ .stop = idr_seq_stop,
+ .show = pid_seq_show,
+};
+
+static int pid_seq_open(struct inode *inode, struct file *file)
+{
+ struct idr *idr = inode->i_private;
+ return idr_seq_open(file, idr, &pid_seq_ops);
+}
+
+static const struct file_operations tasks_fops = {
+ .open = pid_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = idr_seq_release,
+};
+
+static int _create_inod_dir(struct ns_common *ns, struct dentry *parent_dentry)
+{
+ char *dir = kasprintf(GFP_KERNEL, "%u", ns->inum);
+
+ if (!dir)
+ return -ENOMEM;
+
+ ns->dentry = namespacefs_create_dir(dir, parent_dentry);
+ kfree(dir);
+ if (IS_ERR(ns->dentry))
+ return PTR_ERR(ns->dentry);
+
+ return 0;
+}
+
+int namespacefs_create_pid_ns_dir(struct pid_namespace *ns)
+{
+ int err = _create_inod_dir(&ns->ns, ns->parent->ns.dentry);
+ struct dentry *dentry;
+
+ if (err)
+ return err;
+
+ dentry = namespacefs_create_file("tasks", ns->ns.dentry,
+ &tasks_fops, &ns->idr);
+ if (IS_ERR(dentry)) {
+ dput(ns->ns.dentry);
+ return PTR_ERR(dentry);
+ }
+
+ return 0;
+}
+
+void namespacefs_remove_pid_ns_dir(struct pid_namespace *ns)
+{
+ namespacefs_remove_dir(ns->ns.dentry);
+}
+
static int __init namespacefs_init(void)
{
int err;
diff --git a/include/linux/namespacefs.h b/include/linux/namespacefs.h
new file mode 100644
index 00000000000000..020bf5bbb3b534
--- /dev/null
+++ b/include/linux/namespacefs.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * namespacefs.h - a pseudo file system for examining namespaces.
+ */
+
+#ifndef _NAMESPACEFS_H_
+#define _NAMESPACEFS_H_
+
+#ifdef CONFIG_NAMESPACE_FS
+
+#include <linux/fs.h>
+
+int namespacefs_create_pid_ns_dir(struct pid_namespace *ns);
+
+void namespacefs_remove_pid_ns_dir(struct pid_namespace *ns);
+
+#else
+
+static inline int
+namespacefs_create_pid_ns_dir(struct pid_namespace *ns)
+{
+ return 0;
+}
+
+static inline void
+namespacefs_remove_pid_ns_dir(struct pid_namespace *ns)
+{
+}
+
+#endif /* CONFIG_NAMESPACE_FS */
+
+#endif
diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h
index 0f1d024bd95826..1dec75c51b2c52 100644
--- a/include/linux/ns_common.h
+++ b/include/linux/ns_common.h
@@ -11,6 +11,10 @@ struct ns_common {
const struct proc_ns_operations *ops;
unsigned int inum;
refcount_t count;
+
+#ifdef CONFIG_NAMESPACE_FS
+ struct dentry *dentry;
+#endif /* CONFIG_NAMESPACE_FS */
};
#endif