]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.18.103/proc-revert-proc-pid-maps-annotation.patch
Linux 4.14.95
[thirdparty/kernel/stable-queue.git] / releases / 3.18.103 / proc-revert-proc-pid-maps-annotation.patch
1 From 65376df582174ffcec9e6471bf5b0dd79ba05e4a Mon Sep 17 00:00:00 2001
2 From: Johannes Weiner <hannes@cmpxchg.org>
3 Date: Tue, 2 Feb 2016 16:57:29 -0800
4 Subject: proc: revert /proc/<pid>/maps [stack:TID] annotation
5
6 From: Johannes Weiner <hannes@cmpxchg.org>
7
8 commit 65376df582174ffcec9e6471bf5b0dd79ba05e4a upstream.
9
10 Commit b76437579d13 ("procfs: mark thread stack correctly in
11 proc/<pid>/maps") added [stack:TID] annotation to /proc/<pid>/maps.
12
13 Finding the task of a stack VMA requires walking the entire thread list,
14 turning this into quadratic behavior: a thousand threads means a
15 thousand stacks, so the rendering of /proc/<pid>/maps needs to look at a
16 million combinations.
17
18 The cost is not in proportion to the usefulness as described in the
19 patch.
20
21 Drop the [stack:TID] annotation to make /proc/<pid>/maps (and
22 /proc/<pid>/numa_maps) usable again for higher thread counts.
23
24 The [stack] annotation inside /proc/<pid>/task/<tid>/maps is retained, as
25 identifying the stack VMA there is an O(1) operation.
26
27 Siddesh said:
28 "The end users needed a way to identify thread stacks programmatically and
29 there wasn't a way to do that. I'm afraid I no longer remember (or have
30 access to the resources that would aid my memory since I changed
31 employers) the details of their requirement. However, I did do this on my
32 own time because I thought it was an interesting project for me and nobody
33 really gave any feedback then as to its utility, so as far as I am
34 concerned you could roll back the main thread maps information since the
35 information is available in the thread-specific files"
36
37 Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
38 Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
39 Cc: Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com>
40 Cc: Shaohua Li <shli@fb.com>
41 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
42 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
43 Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
44 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
45
46 ---
47 Documentation/filesystems/proc.txt | 9 +----
48 fs/proc/task_mmu.c | 66 ++++++++++++-------------------------
49 fs/proc/task_nommu.c | 49 +++++++++++----------------
50 include/linux/mm.h | 3 -
51 mm/util.c | 27 ---------------
52 5 files changed, 48 insertions(+), 106 deletions(-)
53
54 --- a/Documentation/filesystems/proc.txt
55 +++ b/Documentation/filesystems/proc.txt
56 @@ -334,7 +334,7 @@ address perms offset dev in
57 a7cb1000-a7cb2000 ---p 00000000 00:00 0
58 a7cb2000-a7eb2000 rw-p 00000000 00:00 0
59 a7eb2000-a7eb3000 ---p 00000000 00:00 0
60 -a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack:1001]
61 +a7eb3000-a7ed5000 rw-p 00000000 00:00 0
62 a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
63 a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6
64 a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6
65 @@ -366,7 +366,6 @@ is not associated with a file:
66
67 [heap] = the heap of the program
68 [stack] = the stack of the main process
69 - [stack:1001] = the stack of the thread with tid 1001
70 [vdso] = the "virtual dynamic shared object",
71 the kernel system call handler
72
73 @@ -374,10 +373,8 @@ is not associated with a file:
74
75 The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint
76 of the individual tasks of a process. In this file you will see a mapping marked
77 -as [stack] if that task sees it as a stack. This is a key difference from the
78 -content of /proc/PID/maps, where you will see all mappings that are being used
79 -as stack by all of those tasks. Hence, for the example above, the task-level
80 -map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
81 +as [stack] if that task sees it as a stack. Hence, for the example above, the
82 +task-level map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
83
84 08048000-08049000 r-xp 00000000 03:00 8312 /opt/test
85 08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test
86 --- a/fs/proc/task_mmu.c
87 +++ b/fs/proc/task_mmu.c
88 @@ -243,23 +243,29 @@ static int do_maps_open(struct inode *in
89 sizeof(struct proc_maps_private));
90 }
91
92 -static pid_t pid_of_stack(struct proc_maps_private *priv,
93 - struct vm_area_struct *vma, bool is_pid)
94 +/*
95 + * Indicate if the VMA is a stack for the given task; for
96 + * /proc/PID/maps that is the stack of the main task.
97 + */
98 +static int is_stack(struct proc_maps_private *priv,
99 + struct vm_area_struct *vma, int is_pid)
100 {
101 - struct inode *inode = priv->inode;
102 - struct task_struct *task;
103 - pid_t ret = 0;
104 + int stack = 0;
105 +
106 + if (is_pid) {
107 + stack = vma->vm_start <= vma->vm_mm->start_stack &&
108 + vma->vm_end >= vma->vm_mm->start_stack;
109 + } else {
110 + struct inode *inode = priv->inode;
111 + struct task_struct *task;
112
113 - rcu_read_lock();
114 - task = pid_task(proc_pid(inode), PIDTYPE_PID);
115 - if (task) {
116 - task = task_of_stack(task, vma, is_pid);
117 + rcu_read_lock();
118 + task = pid_task(proc_pid(inode), PIDTYPE_PID);
119 if (task)
120 - ret = task_pid_nr_ns(task, inode->i_sb->s_fs_info);
121 + stack = vma_is_stack_for_task(vma, task);
122 + rcu_read_unlock();
123 }
124 - rcu_read_unlock();
125 -
126 - return ret;
127 + return stack;
128 }
129
130 static void
131 @@ -315,8 +321,6 @@ show_map_vma(struct seq_file *m, struct
132
133 name = arch_vma_name(vma);
134 if (!name) {
135 - pid_t tid;
136 -
137 if (!mm) {
138 name = "[vdso]";
139 goto done;
140 @@ -328,21 +332,8 @@ show_map_vma(struct seq_file *m, struct
141 goto done;
142 }
143
144 - tid = pid_of_stack(priv, vma, is_pid);
145 - if (tid != 0) {
146 - /*
147 - * Thread stack in /proc/PID/task/TID/maps or
148 - * the main process stack.
149 - */
150 - if (!is_pid || (vma->vm_start <= mm->start_stack &&
151 - vma->vm_end >= mm->start_stack)) {
152 - name = "[stack]";
153 - } else {
154 - /* Thread stack in /proc/PID/maps */
155 - seq_pad(m, ' ');
156 - seq_printf(m, "[stack:%d]", tid);
157 - }
158 - }
159 + if (is_stack(priv, vma, is_pid))
160 + name = "[stack]";
161 }
162
163 done:
164 @@ -1510,19 +1501,8 @@ static int show_numa_map(struct seq_file
165 seq_path(m, &file->f_path, "\n\t= ");
166 } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
167 seq_puts(m, " heap");
168 - } else {
169 - pid_t tid = pid_of_stack(proc_priv, vma, is_pid);
170 - if (tid != 0) {
171 - /*
172 - * Thread stack in /proc/PID/task/TID/maps or
173 - * the main process stack.
174 - */
175 - if (!is_pid || (vma->vm_start <= mm->start_stack &&
176 - vma->vm_end >= mm->start_stack))
177 - seq_puts(m, " stack");
178 - else
179 - seq_printf(m, " stack:%d", tid);
180 - }
181 + } else if (is_stack(proc_priv, vma, is_pid)) {
182 + seq_puts(m, " stack");
183 }
184
185 if (is_vm_hugetlb_page(vma))
186 --- a/fs/proc/task_nommu.c
187 +++ b/fs/proc/task_nommu.c
188 @@ -123,23 +123,26 @@ unsigned long task_statm(struct mm_struc
189 return size;
190 }
191
192 -static pid_t pid_of_stack(struct proc_maps_private *priv,
193 - struct vm_area_struct *vma, bool is_pid)
194 +static int is_stack(struct proc_maps_private *priv,
195 + struct vm_area_struct *vma, int is_pid)
196 {
197 - struct inode *inode = priv->inode;
198 - struct task_struct *task;
199 - pid_t ret = 0;
200 -
201 - rcu_read_lock();
202 - task = pid_task(proc_pid(inode), PIDTYPE_PID);
203 - if (task) {
204 - task = task_of_stack(task, vma, is_pid);
205 + struct mm_struct *mm = vma->vm_mm;
206 + int stack = 0;
207 +
208 + if (is_pid) {
209 + stack = vma->vm_start <= mm->start_stack &&
210 + vma->vm_end >= mm->start_stack;
211 + } else {
212 + struct inode *inode = priv->inode;
213 + struct task_struct *task;
214 +
215 + rcu_read_lock();
216 + task = pid_task(proc_pid(inode), PIDTYPE_PID);
217 if (task)
218 - ret = task_pid_nr_ns(task, inode->i_sb->s_fs_info);
219 + stack = vma_is_stack_for_task(vma, task);
220 + rcu_read_unlock();
221 }
222 - rcu_read_unlock();
223 -
224 - return ret;
225 + return stack;
226 }
227
228 /*
229 @@ -181,21 +184,9 @@ static int nommu_vma_show(struct seq_fil
230 if (file) {
231 seq_pad(m, ' ');
232 seq_path(m, &file->f_path, "");
233 - } else if (mm) {
234 - pid_t tid = pid_of_stack(priv, vma, is_pid);
235 -
236 - if (tid != 0) {
237 - seq_pad(m, ' ');
238 - /*
239 - * Thread stack in /proc/PID/task/TID/maps or
240 - * the main process stack.
241 - */
242 - if (!is_pid || (vma->vm_start <= mm->start_stack &&
243 - vma->vm_end >= mm->start_stack))
244 - seq_printf(m, "[stack]");
245 - else
246 - seq_printf(m, "[stack:%d]", tid);
247 - }
248 + } else if (mm && is_stack(priv, vma, is_pid)) {
249 + seq_pad(m, ' ');
250 + seq_printf(m, "[stack]");
251 }
252
253 seq_putc(m, '\n');
254 --- a/include/linux/mm.h
255 +++ b/include/linux/mm.h
256 @@ -1242,8 +1242,7 @@ int set_page_dirty_lock(struct page *pag
257 int clear_page_dirty_for_io(struct page *page);
258 int get_cmdline(struct task_struct *task, char *buffer, int buflen);
259
260 -extern struct task_struct *task_of_stack(struct task_struct *task,
261 - struct vm_area_struct *vma, bool in_group);
262 +int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t);
263
264 extern unsigned long move_page_tables(struct vm_area_struct *vma,
265 unsigned long old_addr, struct vm_area_struct *new_vma,
266 --- a/mm/util.c
267 +++ b/mm/util.c
268 @@ -185,36 +185,11 @@ void __vma_link_list(struct mm_struct *m
269 }
270
271 /* Check if the vma is being used as a stack by this task */
272 -static int vm_is_stack_for_task(struct task_struct *t,
273 - struct vm_area_struct *vma)
274 +int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t)
275 {
276 return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
277 }
278
279 -/*
280 - * Check if the vma is being used as a stack.
281 - * If is_group is non-zero, check in the entire thread group or else
282 - * just check in the current task. Returns the task_struct of the task
283 - * that the vma is stack for. Must be called under rcu_read_lock().
284 - */
285 -struct task_struct *task_of_stack(struct task_struct *task,
286 - struct vm_area_struct *vma, bool in_group)
287 -{
288 - if (vm_is_stack_for_task(task, vma))
289 - return task;
290 -
291 - if (in_group) {
292 - struct task_struct *t;
293 -
294 - for_each_thread(task, t) {
295 - if (vm_is_stack_for_task(t, vma))
296 - return t;
297 - }
298 - }
299 -
300 - return NULL;
301 -}
302 -
303 #if defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT)
304 void arch_pick_mmap_layout(struct mm_struct *mm)
305 {