The patch titled Subject: mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file-fix has been added to the -mm tree. Its filename is mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file-fix.patch This patch should soon appear at http://ozlabs.org/~akpm/mmots/broken-out/mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file-fix.patch and later at http://ozlabs.org/~akpm/mmotm/broken-out/mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file-fix.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next and is updated there every 3-4 working days ------------------------------------------------------ From: Vlastimil Babka <vbabka@xxxxxxx> Subject: mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file-fix >> Hmm IIUC seq_file also provides the buffer and handles feeding the data >> from there to the user process, which might have called read() with a smaller >> buffer than that. So I would rather not avoid the seq_file infrastructure. >> Or you're saying it could be converted to single_open()? Maybe, with more work. > > Prefereably yes. OK here it is. Sending as a new patch instead of delta, as that's easier to review - the delta is significant. Line stats wise it's the same. Again a bit less boilerplate thans to no special seq_ops, a bit more copy/paste in the open and release functions. But I guess it's better overall. Link: http://lkml.kernel.org/r/bf4525b0-fd5b-4c4c-2cb3-adee3dd95a48@xxxxxxx Reported-by: Daniel Colascione <dancol@xxxxxxxxxx> Signed-off-by: Vlastimil Babka <vbabka@xxxxxxx> Cc: Alexey Dobriyan <adobriyan@xxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- diff -puN fs/proc/internal.h~mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file-fix fs/proc/internal.h --- a/fs/proc/internal.h~mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file-fix +++ a/fs/proc/internal.h @@ -285,7 +285,6 @@ struct proc_maps_private { struct inode *inode; struct task_struct *task; struct mm_struct *mm; - struct mem_size_stats *rollup; #ifdef CONFIG_MMU struct vm_area_struct *tail_vma; #endif diff -puN fs/proc/task_mmu.c~mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file-fix fs/proc/task_mmu.c --- a/fs/proc/task_mmu.c~mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file-fix +++ a/fs/proc/task_mmu.c @@ -247,7 +247,6 @@ static int proc_map_release(struct inode if (priv->mm) mmdrop(priv->mm); - kfree(priv->rollup); return seq_release_private(inode, file); } @@ -417,12 +416,10 @@ struct mem_size_stats { unsigned long swap; unsigned long shared_hugetlb; unsigned long private_hugetlb; - unsigned long last_vma_end; u64 pss; u64 pss_locked; u64 swap_pss; bool check_shmem_swap; - bool finished; }; static void smaps_account(struct mem_size_stats *mss, struct page *page, @@ -803,29 +800,48 @@ static int show_smap(struct seq_file *m, static int show_smaps_rollup(struct seq_file *m, void *v) { struct proc_maps_private *priv = m->private; - struct mem_size_stats *mss = priv->rollup; + struct mem_size_stats mss; + struct mm_struct *mm; struct vm_area_struct *vma; + unsigned long last_vma_end = 0; + int ret = 0; - /* - * We might be called multiple times when e.g. the seq buffer - * overflows. Gather the stats only once. - */ - if (!mss->finished) { - for (vma = priv->mm->mmap; vma; vma = vma->vm_next) { - smap_gather_stats(vma, mss); - mss->last_vma_end = vma->vm_end; - } - mss->finished = true; + priv->task = get_proc_task(priv->inode); + if (!priv->task) + return -ESRCH; + + mm = priv->mm; + if (!mm || !mmget_not_zero(mm)) { + ret = -ESRCH; + goto out_put_task; + } + + memset(&mss, 0, sizeof(mss)); + + down_read(&mm->mmap_sem); + hold_task_mempolicy(priv); + + for (vma = priv->mm->mmap; vma; vma = vma->vm_next) { + smap_gather_stats(vma, &mss); + last_vma_end = vma->vm_end; } show_vma_header_prefix(m, priv->mm->mmap->vm_start, - mss->last_vma_end, 0, 0, 0, 0); + last_vma_end, 0, 0, 0, 0); seq_pad(m, ' '); seq_puts(m, "[rollup]\n"); - __show_smap(m, mss); + __show_smap(m, &mss); - return 0; + release_task_mempolicy(priv); + up_read(&mm->mmap_sem); + mmput(mm); + +out_put_task: + put_task_struct(priv->task); + priv->task = NULL; + + return ret; } #undef SEQ_PUT_DEC @@ -836,65 +852,50 @@ static const struct seq_operations proc_ .show = show_smap }; -static void *smaps_rollup_start(struct seq_file *m, loff_t *ppos) +static int pid_smaps_open(struct inode *inode, struct file *file) { - struct proc_maps_private *priv = m->private; - struct mm_struct *mm; - - if (*ppos != 0) - return NULL; + return do_maps_open(inode, file, &proc_pid_smaps_op); +} - priv->task = get_proc_task(priv->inode); - if (!priv->task) - return ERR_PTR(-ESRCH); +static int smaps_rollup_open(struct inode *inode, struct file *file) +{ + int ret; + struct proc_maps_private *priv; - mm = priv->mm; - if (!mm || !mmget_not_zero(mm)) - return NULL; + priv = kzalloc(sizeof(*priv), GFP_KERNEL_ACCOUNT); + if (!priv) + return -ENOMEM; - memset(priv->rollup, 0, sizeof(*priv->rollup)); + ret = single_open(file, show_smaps_rollup, priv); + if (ret) + goto out_free; + + priv->inode = inode; + priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); + if (IS_ERR(priv->mm)) { + ret = PTR_ERR(priv->mm); - down_read(&mm->mmap_sem); - hold_task_mempolicy(priv); + single_release(inode, file); + goto out_free; + } - return mm; -} + return 0; -static void *smaps_rollup_next(struct seq_file *m, void *v, loff_t *pos) -{ - (*pos)++; - vma_stop(m->private); - return NULL; +out_free: + kfree(priv); + return ret; } -static const struct seq_operations proc_pid_smaps_rollup_op = { - .start = smaps_rollup_start, - .next = smaps_rollup_next, - .stop = m_stop, - .show = show_smaps_rollup -}; - -static int pid_smaps_open(struct inode *inode, struct file *file) +static int smaps_rollup_release(struct inode *inode, struct file *file) { - return do_maps_open(inode, file, &proc_pid_smaps_op); -} + struct seq_file *seq = file->private_data; + struct proc_maps_private *priv = seq->private; -static int pid_smaps_rollup_open(struct inode *inode, struct file *file) -{ - struct seq_file *seq; - struct proc_maps_private *priv; - int ret = do_maps_open(inode, file, &proc_pid_smaps_rollup_op); + if (priv->mm) + mmdrop(priv->mm); - if (ret < 0) - return ret; - seq = file->private_data; - priv = seq->private; - priv->rollup = kmalloc(sizeof(*priv->rollup), GFP_KERNEL); - if (!priv->rollup) { - proc_map_release(inode, file); - return -ENOMEM; - } - return 0; + kfree(priv); + return single_release(inode, file); } const struct file_operations proc_pid_smaps_operations = { @@ -905,10 +906,10 @@ const struct file_operations proc_pid_sm }; const struct file_operations proc_pid_smaps_rollup_operations = { - .open = pid_smaps_rollup_open, + .open = smaps_rollup_open, .read = seq_read, .llseek = seq_lseek, - .release = proc_map_release, + .release = smaps_rollup_release, }; enum clear_refs_types { _ Patches currently in -mm which might be from vbabka@xxxxxxx are mm-page_alloc-actually-ignore-mempolicies-for-high-priority-allocations.patch mm-proc-pid-maps-remove-is_pid-and-related-wrappers.patch mm-proc-pid-smaps-factor-out-mem-stats-gathering.patch mm-proc-pid-smaps-factor-out-common-stats-printing.patch mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file.patch mm-proc-pid-smaps_rollup-convert-to-single-value-seq_file-fix.patch -- To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html