diff options
author | Yordan Karadzhov (VMware) <y.karadz@gmail.com> | 2021-10-25 14:52:53 +0300 |
---|---|---|
committer | Yordan Karadzhov (VMware) <y.karadz@gmail.com> | 2021-11-05 13:53:03 +0200 |
commit | 86ac460cc300463d6e89c67185f8a85036d26ccc (patch) | |
tree | a031fcf0fd26e732e7aa4f8a6cc842d49a1d1520 | |
parent | 1b128723e0a3ecb71a4adf289786b85906256776 (diff) | |
download | linux-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.c | 79 | ||||
-rw-r--r-- | include/linux/namespacefs.h | 32 | ||||
-rw-r--r-- | include/linux/ns_common.h | 4 |
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 |