This patch will show the hierarchy of pid namespace under /proc/pidns like: /proc/pidns ├── hierarchy │ ├── pidns4026532399 │ │ ├── pidns -> /proc/2863/ns/pid │ │ └── pidns4026532515 │ │ └── pidns -> /proc/10611/ns/pid │ └── pidns4026532504 │ └── pidns -> /proc/4450/ns/pid └── refresh a) hierarchy dir: use to show hierarchy infomation using dir and symlinks. dirs are named as pidns($inum) a symlink is created under pidns($inum), and linked to that pid namespace. b) refresh trigger key. We need to write sth to /proc/nspid/refresh, then we could get hierarchy info under /proc/pidns/hierarchy. Signed-off-by: Chen Hanxiao <chenhanxiao@xxxxxxxxxxxxxx> --- fs/proc/Kconfig | 6 ++ fs/proc/Makefile | 1 + fs/proc/pidns_hierarchy.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 fs/proc/pidns_hierarchy.c diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig index 2183fcf..e2e2292 100644 --- a/fs/proc/Kconfig +++ b/fs/proc/Kconfig @@ -71,3 +71,9 @@ config PROC_PAGE_MONITOR /proc/pid/smaps, /proc/pid/clear_refs, /proc/pid/pagemap, /proc/kpagecount, and /proc/kpageflags. Disabling these interfaces will reduce the size of the kernel by approximately 4kb. + +config PROC_PID_HIERARCHY + bool "Enable /proc/pidns_hierarchy support" if EXPERT + depends on PROC_FS + help + Show pid namespace hierarchy infomation diff --git a/fs/proc/Makefile b/fs/proc/Makefile index 239493e..733599b 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile @@ -29,3 +29,4 @@ proc-$(CONFIG_PROC_KCORE) += kcore.o proc-$(CONFIG_PROC_VMCORE) += vmcore.o proc-$(CONFIG_PRINTK) += kmsg.o proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o +proc-$(CONFIG_PROC_PID_HIERARCHY) += pidns_hierarchy.o diff --git a/fs/proc/pidns_hierarchy.c b/fs/proc/pidns_hierarchy.c new file mode 100644 index 0000000..d35340f --- /dev/null +++ b/fs/proc/pidns_hierarchy.c @@ -0,0 +1,161 @@ +/* + * proc_pidns_hierarchy.c -- handles pidns hierarchy + * + * Copyright 2014 + */ + +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/proc_fs.h> +#include <linux/module.h> +#include <linux/list.h> +#include <linux/slab.h> +#include <linux/pid_namespace.h> + +/* + * The /proc/pidns directory + */ + +#define BASE_DIR "pidns" /* Subdir in /proc */ +#define HIERARCHY_DIR "pidns/hierarchy" /* hierarchy dir */ +#define REFRESH_KEY "pidns/refresh" /* refresh key */ +#define NAME "pidns_hierarchy" /* Module name */ + +static LIST_HEAD(pidns_list); +static DEFINE_RWLOCK(pidns_lock); +static struct proc_dir_entry *proc_root; + +struct ns_pid_list { + struct pid *pid; + struct list_head list; +}; + +static void free_pidns_list(struct list_head *head) +{ + struct ns_pid_list *tmp, *pos; + + list_for_each_entry_safe(pos, tmp, head, list) { + list_del(&pos->list); + kfree(pos); + } +} + +/* + * Only add pids with different ns + */ +static int +ns_pid_list_really_add(struct pid *pid) +{ + struct ns_pid_list *tmp, *pos; + + list_for_each_entry_safe(pos, tmp, &pidns_list, list) + if (ns_of_pid(pid) == ns_of_pid(pos->pid)) + return 0; + + return 1; +} + +static int +ns_pid_list_add(struct pid *pid) +{ + struct ns_pid_list *ent; + + ent = kmalloc(sizeof(*ent), GFP_KERNEL); + if (!ent) + return -ENOMEM; + ent->pid = pid; + if (ns_pid_list_really_add(pid)) + list_add_tail(&ent->list, &pidns_list); + + return 0; +} + +static void print_list(void) +{ + struct ns_pid_list *tmp, *pos; + struct proc_dir_entry *parent, *parent_new; + struct pid_namespace *ns, *curr_ns; + struct pid *pid; + char name_buf[16], pid_buf[32]; + int i, k; + + curr_ns = task_active_pid_ns(current); + + list_for_each_entry_safe(pos, tmp, &pidns_list, list) { + pid = pos->pid; + k = -1; + ns = pid->numbers[pid->level].ns; + /* Check whether pid has relationship with current ns */ + for (; ns != NULL; ns = ns->parent) + if (ns == curr_ns) + k = curr_ns->level; + if (k == -1) + continue; + parent = proc_root; + for (i = k + 1; i <= pid->level; i++) { + ns = pid->numbers[i].ns; + snprintf(name_buf, 16, "pidns%u", + pid->numbers[i].ns->proc_inum); + snprintf(pid_buf, 32, "/proc/%u/ns/pid", + pid->numbers[0].nr); + /* don't duplicate ns dirs */ + parent_new = proc_uniq_dir(parent, name_buf); + if (!parent_new) { + parent_new = proc_mkdir(name_buf, parent); + proc_symlink("pidns", parent_new, pid_buf); + } + parent = parent_new; + } + } +} + +void proc_pidns_list(void) +{ + struct pid *pid; + struct task_struct *task = &init_task; + + remove_proc_subtree(HIERARCHY_DIR, NULL); + proc_root = proc_mkdir(HIERARCHY_DIR, NULL); + free_pidns_list(&pidns_list); + + do { + pid = task_pid(task); + if (pid) { + if (pid->level > 0) + ns_pid_list_add(pid); + } + } while ((task = next_task(task)) != &init_task); + + print_list(); + printk(KERN_INFO "refresh finished\n"); +} + +ssize_t proc_pidns_refresh_switch(struct file *file, const char __user *buf, + size_t size, loff_t *ppos) +{ + write_lock(&pidns_lock); + proc_pidns_list(); + write_unlock(&pidns_lock); + return 1; +} + +static const struct file_operations proc_pidns_refresh_fops = { + .write = proc_pidns_refresh_switch, +}; + +static int __init pidns_hierarchy_init(void) +{ + + if (!proc_mkdir(BASE_DIR, NULL)) + return -ENOMEM; + proc_root = proc_mkdir(HIERARCHY_DIR, NULL); + if (!proc_root) + return -ENOMEM; + + proc_create(REFRESH_KEY, S_IWUGO, + NULL, &proc_pidns_refresh_fops); + printk(KERN_INFO "%s: loaded successfully\n", NAME); + + return 0; +} +fs_initcall(pidns_hierarchy_init); -- 1.9.0 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/containers