diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-10-09 18:25:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-09 22:25:49 -0400 |
commit | b8c20a9b85b057c850f63ee4c63531a356d8596a (patch) | |
tree | 474512d1a811633ea3150dd2bd884d11ed47b5d2 /fs/proc | |
parent | ad2a00e4b7e20ab03700b0bb13270b6cee45c6e0 (diff) |
fs/proc/task_mmu.c: reintroduce m->version logic
Add the "last_addr" optimization back. Like before, every ->show()
method checks !seq_overflow() and sets m->version = vma->vm_start.
However, it also checks that m_next_vma(vma) != NULL, otherwise it
sets m->version = -1 for the lockless "EOF" fast-path in m_start().
m_start() can simply do find_vma() + m_next_vma() if last_addr is
not zero, the code looks clear and simple and this case is clearly
separated from "scan vmas" path.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/task_mmu.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index fef398948462..c7228c2326d1 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -146,13 +146,24 @@ m_next_vma(struct proc_maps_private *priv, struct vm_area_struct *vma) | |||
146 | return vma->vm_next ?: priv->tail_vma; | 146 | return vma->vm_next ?: priv->tail_vma; |
147 | } | 147 | } |
148 | 148 | ||
149 | static void m_cache_vma(struct seq_file *m, struct vm_area_struct *vma) | ||
150 | { | ||
151 | if (m->count < m->size) /* vma is copied successfully */ | ||
152 | m->version = m_next_vma(m->private, vma) ? vma->vm_start : -1UL; | ||
153 | } | ||
154 | |||
149 | static void *m_start(struct seq_file *m, loff_t *ppos) | 155 | static void *m_start(struct seq_file *m, loff_t *ppos) |
150 | { | 156 | { |
151 | struct proc_maps_private *priv = m->private; | 157 | struct proc_maps_private *priv = m->private; |
158 | unsigned long last_addr = m->version; | ||
152 | struct mm_struct *mm; | 159 | struct mm_struct *mm; |
153 | struct vm_area_struct *vma; | 160 | struct vm_area_struct *vma; |
154 | unsigned int pos = *ppos; | 161 | unsigned int pos = *ppos; |
155 | 162 | ||
163 | /* See m_cache_vma(). Zero at the start or after lseek. */ | ||
164 | if (last_addr == -1UL) | ||
165 | return NULL; | ||
166 | |||
156 | priv->task = get_pid_task(priv->pid, PIDTYPE_PID); | 167 | priv->task = get_pid_task(priv->pid, PIDTYPE_PID); |
157 | if (!priv->task) | 168 | if (!priv->task) |
158 | return ERR_PTR(-ESRCH); | 169 | return ERR_PTR(-ESRCH); |
@@ -165,6 +176,13 @@ static void *m_start(struct seq_file *m, loff_t *ppos) | |||
165 | hold_task_mempolicy(priv); | 176 | hold_task_mempolicy(priv); |
166 | priv->tail_vma = get_gate_vma(mm); | 177 | priv->tail_vma = get_gate_vma(mm); |
167 | 178 | ||
179 | if (last_addr) { | ||
180 | vma = find_vma(mm, last_addr); | ||
181 | if (vma && (vma = m_next_vma(priv, vma))) | ||
182 | return vma; | ||
183 | } | ||
184 | |||
185 | m->version = 0; | ||
168 | if (pos < mm->map_count) { | 186 | if (pos < mm->map_count) { |
169 | for (vma = mm->mmap; pos; pos--) | 187 | for (vma = mm->mmap; pos; pos--) |
170 | vma = vma->vm_next; | 188 | vma = vma->vm_next; |
@@ -340,6 +358,7 @@ done: | |||
340 | static int show_map(struct seq_file *m, void *v, int is_pid) | 358 | static int show_map(struct seq_file *m, void *v, int is_pid) |
341 | { | 359 | { |
342 | show_map_vma(m, v, is_pid); | 360 | show_map_vma(m, v, is_pid); |
361 | m_cache_vma(m, v); | ||
343 | return 0; | 362 | return 0; |
344 | } | 363 | } |
345 | 364 | ||
@@ -617,6 +636,7 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) | |||
617 | mss.nonlinear >> 10); | 636 | mss.nonlinear >> 10); |
618 | 637 | ||
619 | show_smap_vma_flags(m, vma); | 638 | show_smap_vma_flags(m, vma); |
639 | m_cache_vma(m, vma); | ||
620 | return 0; | 640 | return 0; |
621 | } | 641 | } |
622 | 642 | ||
@@ -1471,6 +1491,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) | |||
1471 | seq_printf(m, " N%d=%lu", nid, md->node[nid]); | 1491 | seq_printf(m, " N%d=%lu", nid, md->node[nid]); |
1472 | out: | 1492 | out: |
1473 | seq_putc(m, '\n'); | 1493 | seq_putc(m, '\n'); |
1494 | m_cache_vma(m, vma); | ||
1474 | return 0; | 1495 | return 0; |
1475 | } | 1496 | } |
1476 | 1497 | ||