A single seq_operations/file_operations pair can handle maps, smaps, and numa_maps files. Just the generic ->open() needs to look at pid_entry_name() and initialize priv->show() accordingly. Signed-off-by: Oleg Nesterov <oleg@xxxxxxxxxx> --- fs/proc/base.c | 8 ++-- fs/proc/internal.h | 3 +- fs/proc/task_mmu.c | 123 +++++++++++++++++++++------------------------------- 3 files changed, 54 insertions(+), 80 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 81d372c..4018a86 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2585,7 +2585,7 @@ static const struct pid_entry tgid_base_stuff[] = { ONE("statm", S_IRUGO, proc_pid_statm), REG("maps", S_IRUGO, proc_pid_maps_operations), #ifdef CONFIG_NUMA - REG("numa_maps", S_IRUGO, proc_pid_numa_maps_operations), + REG("numa_maps", S_IRUGO, proc_pid_maps_operations), #endif REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations), LNK("cwd", proc_cwd_link), @@ -2596,7 +2596,7 @@ static const struct pid_entry tgid_base_stuff[] = { REG("mountstats", S_IRUSR, proc_mountstats_operations), #ifdef CONFIG_PROC_PAGE_MONITOR REG("clear_refs", S_IWUSR, proc_clear_refs_operations), - REG("smaps", S_IRUGO, proc_pid_smaps_operations), + REG("smaps", S_IRUGO, proc_pid_maps_operations), REG("pagemap", S_IRUSR, proc_pagemap_operations), #endif #ifdef CONFIG_SECURITY @@ -2924,7 +2924,7 @@ static const struct pid_entry tid_base_stuff[] = { REG("children", S_IRUGO, proc_tid_children_operations), #endif #ifdef CONFIG_NUMA - REG("numa_maps", S_IRUGO, proc_pid_numa_maps_operations), + REG("numa_maps", S_IRUGO, proc_pid_maps_operations), #endif REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations), LNK("cwd", proc_cwd_link), @@ -2934,7 +2934,7 @@ static const struct pid_entry tid_base_stuff[] = { REG("mountinfo", S_IRUGO, proc_mountinfo_operations), #ifdef CONFIG_PROC_PAGE_MONITOR REG("clear_refs", S_IWUSR, proc_clear_refs_operations), - REG("smaps", S_IRUGO, proc_pid_smaps_operations), + REG("smaps", S_IRUGO, proc_pid_maps_operations), REG("pagemap", S_IRUSR, proc_pagemap_operations), #endif #ifdef CONFIG_SECURITY diff --git a/fs/proc/internal.h b/fs/proc/internal.h index c162db2..17091c9 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -270,6 +270,7 @@ extern int proc_remount(struct super_block *, int *, char *); struct proc_maps_private { struct pid *pid; bool is_tgid; + int (*show)(struct seq_file *m, void *v); struct task_struct *task; struct mm_struct *mm; #ifdef CONFIG_MMU @@ -283,8 +284,6 @@ struct proc_maps_private { struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode); extern const struct file_operations proc_pid_maps_operations; -extern const struct file_operations proc_pid_numa_maps_operations; -extern const struct file_operations proc_pid_smaps_operations; extern const struct file_operations proc_clear_refs_operations; extern const struct file_operations proc_pagemap_operations; diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 7618ef8..4ef991a 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -222,26 +222,6 @@ static void m_stop(struct seq_file *m, void *v) } } -static int proc_maps_open(struct inode *inode, struct file *file, - const struct seq_operations *ops, int psize) -{ - struct proc_maps_private *priv = __seq_open_private(file, ops, psize); - - if (!priv) - return -ENOMEM; - - priv->pid = proc_pid(inode); - priv->is_tgid = is_tgid_pid_entry(PROC_I(inode)->pid_entry); - priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); - if (IS_ERR(priv->mm)) { - int err = PTR_ERR(priv->mm); - seq_release_private(inode, file); - return err; - } - - return 0; -} - static int proc_map_release(struct inode *inode, struct file *file) { struct seq_file *seq = file->private_data; @@ -352,30 +332,9 @@ done: static int show_pid_map(struct seq_file *m, void *v) { show_map_vma(m, v); - m_cache_vma(m, v); return 0; } -static const struct seq_operations proc_pid_maps_op = { - .start = m_start, - .next = m_next, - .stop = m_stop, - .show = show_pid_map -}; - -static int pid_maps_open(struct inode *inode, struct file *file) -{ - return proc_maps_open(inode, file, &proc_pid_maps_op, - sizeof(struct proc_maps_private)); -} - -const struct file_operations proc_pid_maps_operations = { - .open = pid_maps_open, - .read = seq_read, - .llseek = seq_lseek, - .release = proc_map_release, -}; - /* * Proportional Set Size(PSS): my share of RSS. * @@ -602,30 +561,9 @@ static int show_pid_smap(struct seq_file *m, void *v) mss.nonlinear >> 10); show_smap_vma_flags(m, vma); - m_cache_vma(m, vma); return 0; } -static const struct seq_operations proc_pid_smaps_op = { - .start = m_start, - .next = m_next, - .stop = m_stop, - .show = show_pid_smap -}; - -static int pid_smaps_open(struct inode *inode, struct file *file) -{ - return proc_maps_open(inode, file, &proc_pid_smaps_op, - sizeof(struct proc_maps_private)); -} - -const struct file_operations proc_pid_smaps_operations = { - .open = pid_smaps_open, - .read = seq_read, - .llseek = seq_lseek, - .release = proc_map_release, -}; - /* * We do not want to have constant page-shift bits sitting in * pagemap entries and are about to reuse them some time soon. @@ -1406,27 +1344,64 @@ static int show_pid_numa_map(struct seq_file *m, void *v) seq_printf(m, " N%d=%lu", nid, md->node[nid]); out: seq_putc(m, '\n'); - m_cache_vma(m, vma); return 0; } +#endif /* CONFIG_NUMA */ -static const struct seq_operations proc_pid_numa_maps_op = { - .start = m_start, - .next = m_next, - .stop = m_stop, - .show = show_pid_numa_map, +static int m_show(struct seq_file *m, void *v) +{ + struct proc_maps_private *priv = m->private; + priv->show(m, v); + m_cache_vma(m, v); + return 0; +} + +static const struct seq_operations proc_pid_maps_op = { + .start = m_start, + .next = m_next, + .stop = m_stop, + .show = m_show, }; -static int pid_numa_maps_open(struct inode *inode, struct file *file) +static int proc_maps_open(struct inode *inode, struct file *file) { - return proc_maps_open(inode, file, &proc_pid_numa_maps_op, - sizeof(struct numa_maps_private)); + const char *name = pid_entry_name(PROC_I(inode)->pid_entry); + int psize = sizeof(struct proc_maps_private); + int (*show)(struct seq_file *m, void *v); + struct proc_maps_private *priv; + + if (strcmp(name, "maps") == 0) + show = show_pid_map; + else if (strcmp(name, "smaps") == 0) + show = show_pid_smap; + else if (strcmp(name, "numa_maps") == 0) { + show = show_pid_numa_map; + psize = sizeof(struct numa_maps_private); + } + else + BUG(); + + priv = __seq_open_private(file, &proc_pid_maps_op, psize); + if (!priv) + return -ENOMEM; + + priv->show = show; + priv->pid = proc_pid(inode); + priv->is_tgid = is_tgid_pid_entry(PROC_I(inode)->pid_entry); + priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); + if (IS_ERR(priv->mm)) { + int err = PTR_ERR(priv->mm); + seq_release_private(inode, file); + return err; + } + + return 0; } -const struct file_operations proc_pid_numa_maps_operations = { - .open = pid_numa_maps_open, +const struct file_operations proc_pid_maps_operations = { + .open = proc_maps_open, .read = seq_read, .llseek = seq_lseek, .release = proc_map_release, }; -#endif /* CONFIG_NUMA */ + -- 1.5.5.1 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html