Branch data Line data Source code
1 : : /*
2 : : * linux/fs/proc/array.c
3 : : *
4 : : * Copyright (C) 1992 by Linus Torvalds
5 : : * based on ideas by Darren Senn
6 : : *
7 : : * Fixes:
8 : : * Michael. K. Johnson: stat,statm extensions.
9 : : * <johnsonm@stolaf.edu>
10 : : *
11 : : * Pauline Middelink : Made cmdline,envline only break at '\0's, to
12 : : * make sure SET_PROCTITLE works. Also removed
13 : : * bad '!' which forced address recalculation for
14 : : * EVERY character on the current page.
15 : : * <middelin@polyware.iaf.nl>
16 : : *
17 : : * Danny ter Haar : added cpuinfo
18 : : * <dth@cistron.nl>
19 : : *
20 : : * Alessandro Rubini : profile extension.
21 : : * <rubini@ipvvis.unipv.it>
22 : : *
23 : : * Jeff Tranter : added BogoMips field to cpuinfo
24 : : * <Jeff_Tranter@Mitel.COM>
25 : : *
26 : : * Bruno Haible : remove 4K limit for the maps file
27 : : * <haible@ma2s2.mathematik.uni-karlsruhe.de>
28 : : *
29 : : * Yves Arrouye : remove removal of trailing spaces in get_array.
30 : : * <Yves.Arrouye@marin.fdn.fr>
31 : : *
32 : : * Jerome Forissier : added per-CPU time information to /proc/stat
33 : : * and /proc/<pid>/cpu extension
34 : : * <forissier@isia.cma.fr>
35 : : * - Incorporation and non-SMP safe operation
36 : : * of forissier patch in 2.1.78 by
37 : : * Hans Marcus <crowbar@concepts.nl>
38 : : *
39 : : * aeb@cwi.nl : /proc/partitions
40 : : *
41 : : *
42 : : * Alan Cox : security fixes.
43 : : * <alan@lxorguk.ukuu.org.uk>
44 : : *
45 : : * Al Viro : safe handling of mm_struct
46 : : *
47 : : * Gerhard Wichert : added BIGMEM support
48 : : * Siemens AG <Gerhard.Wichert@pdb.siemens.de>
49 : : *
50 : : * Al Viro & Jeff Garzik : moved most of the thing into base.c and
51 : : * : proc_misc.c. The rest may eventually go into
52 : : * : base.c too.
53 : : */
54 : :
55 : : #include <linux/types.h>
56 : : #include <linux/errno.h>
57 : : #include <linux/time.h>
58 : : #include <linux/kernel.h>
59 : : #include <linux/kernel_stat.h>
60 : : #include <linux/tty.h>
61 : : #include <linux/string.h>
62 : : #include <linux/mman.h>
63 : : #include <linux/proc_fs.h>
64 : : #include <linux/ioport.h>
65 : : #include <linux/uaccess.h>
66 : : #include <linux/io.h>
67 : : #include <linux/mm.h>
68 : : #include <linux/hugetlb.h>
69 : : #include <linux/pagemap.h>
70 : : #include <linux/swap.h>
71 : : #include <linux/smp.h>
72 : : #include <linux/signal.h>
73 : : #include <linux/highmem.h>
74 : : #include <linux/file.h>
75 : : #include <linux/fdtable.h>
76 : : #include <linux/times.h>
77 : : #include <linux/cpuset.h>
78 : : #include <linux/rcupdate.h>
79 : : #include <linux/delayacct.h>
80 : : #include <linux/seq_file.h>
81 : : #include <linux/pid_namespace.h>
82 : : #include <linux/ptrace.h>
83 : : #include <linux/tracehook.h>
84 : : #include <linux/user_namespace.h>
85 : :
86 : : #include <asm/pgtable.h>
87 : : #include <asm/processor.h>
88 : : #include "internal.h"
89 : :
90 : : static inline void task_name(struct seq_file *m, struct task_struct *p)
91 : : {
92 : : int i;
93 : : char *buf, *end;
94 : : char *name;
95 : : char tcomm[sizeof(p->comm)];
96 : :
97 : 24180 : get_task_comm(tcomm, p);
98 : :
99 : 24180 : seq_puts(m, "Name:\t");
100 : 24180 : end = m->buf + m->size;
101 : 24180 : buf = m->buf + m->count;
102 : : name = tcomm;
103 : : i = sizeof(tcomm);
104 [ + - ]: 240222 : while (i && (buf < end)) {
105 : 240222 : unsigned char c = *name;
106 : 240222 : name++;
107 : 240222 : i--;
108 : 240222 : *buf = c;
109 [ + + ]: 240222 : if (!c)
110 : : break;
111 [ - + ]: 216042 : if (c == '\\') {
112 : 0 : buf++;
113 [ # # ]: 0 : if (buf < end)
114 : 0 : *buf++ = c;
115 : 0 : continue;
116 : : }
117 [ - + ]: 216042 : if (c == '\n') {
118 : 0 : *buf++ = '\\';
119 [ # # ]: 0 : if (buf < end)
120 : 0 : *buf++ = 'n';
121 : 0 : continue;
122 : : }
123 : 216042 : buf++;
124 : : }
125 : 24180 : m->count = buf - m->buf;
126 : 24180 : seq_putc(m, '\n');
127 : : }
128 : :
129 : : /*
130 : : * The task state array is a strange "bitmap" of
131 : : * reasons to sleep. Thus "running" is zero, and
132 : : * you can test for combinations of others with
133 : : * simple bit tests.
134 : : */
135 : : static const char * const task_state_array[] = {
136 : : "R (running)", /* 0 */
137 : : "S (sleeping)", /* 1 */
138 : : "D (disk sleep)", /* 2 */
139 : : "T (stopped)", /* 4 */
140 : : "t (tracing stop)", /* 8 */
141 : : "Z (zombie)", /* 16 */
142 : : "X (dead)", /* 32 */
143 : : };
144 : :
145 : : static inline const char *get_task_state(struct task_struct *tsk)
146 : : {
147 : 49162 : unsigned int state = (tsk->state | tsk->exit_state) & TASK_REPORT;
148 : :
149 : : BUILD_BUG_ON(1 + ilog2(TASK_REPORT) != ARRAY_SIZE(task_state_array)-1);
150 : :
151 : 98324 : return task_state_array[fls(state)];
152 : : }
153 : :
154 : : static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
155 : : struct pid *pid, struct task_struct *p)
156 : : {
157 : : struct user_namespace *user_ns = seq_user_ns(m);
158 : : struct group_info *group_info;
159 : : int g;
160 : : struct fdtable *fdt = NULL;
161 : : const struct cred *cred;
162 : : pid_t ppid, tpid;
163 : :
164 : : rcu_read_lock();
165 : : ppid = pid_alive(p) ?
166 [ + - ]: 24180 : task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
167 : : tpid = 0;
168 [ + - ]: 24180 : if (pid_alive(p)) {
169 : : struct task_struct *tracer = ptrace_parent(p);
170 [ - + ]: 24180 : if (tracer)
171 : : tpid = task_pid_nr_ns(tracer, ns);
172 : : }
173 : 24180 : cred = get_task_cred(p);
174 : 24180 : seq_printf(m,
175 : : "State:\t%s\n"
176 : : "Tgid:\t%d\n"
177 : : "Ngid:\t%d\n"
178 : : "Pid:\t%d\n"
179 : : "PPid:\t%d\n"
180 : : "TracerPid:\t%d\n"
181 : : "Uid:\t%d\t%d\t%d\t%d\n"
182 : : "Gid:\t%d\t%d\t%d\t%d\n",
183 : : get_task_state(p),
184 : : task_tgid_nr_ns(p, ns),
185 : : task_numa_group_id(p),
186 : : pid_nr_ns(pid, ns),
187 : : ppid, tpid,
188 : : from_kuid_munged(user_ns, cred->uid),
189 : : from_kuid_munged(user_ns, cred->euid),
190 : : from_kuid_munged(user_ns, cred->suid),
191 : : from_kuid_munged(user_ns, cred->fsuid),
192 : : from_kgid_munged(user_ns, cred->gid),
193 : : from_kgid_munged(user_ns, cred->egid),
194 : : from_kgid_munged(user_ns, cred->sgid),
195 : : from_kgid_munged(user_ns, cred->fsgid));
196 : :
197 : : task_lock(p);
198 [ + - ]: 24180 : if (p->files)
199 : 24180 : fdt = files_fdtable(p->files);
200 [ + - ]: 24180 : seq_printf(m,
201 : : "FDSize:\t%d\n"
202 : : "Groups:\t",
203 : : fdt ? fdt->max_fds : 0);
204 : : rcu_read_unlock();
205 : :
206 : 24180 : group_info = cred->group_info;
207 : : task_unlock(p);
208 : :
209 [ + + ]: 30957 : for (g = 0; g < group_info->ngroups; g++)
210 : 6777 : seq_printf(m, "%d ",
211 : 6777 : from_kgid_munged(user_ns, GROUP_AT(group_info, g)));
212 : : put_cred(cred);
213 : :
214 : 24180 : seq_putc(m, '\n');
215 : : }
216 : :
217 : 0 : void render_sigset_t(struct seq_file *m, const char *header,
218 : : sigset_t *set)
219 : : {
220 : : int i;
221 : :
222 : 120912 : seq_puts(m, header);
223 : :
224 : : i = _NSIG;
225 : : do {
226 : : int x = 0;
227 : :
228 : 2055504 : i -= 4;
229 [ + + ]: 2055504 : if (sigismember(set, i+1)) x |= 1;
230 [ + + ]: 2055504 : if (sigismember(set, i+2)) x |= 2;
231 [ + + ]: 1934592 : if (sigismember(set, i+3)) x |= 4;
232 [ + + ]: 1934592 : if (sigismember(set, i+4)) x |= 8;
233 : 1934592 : seq_printf(m, "%x", x);
234 [ + + ]: 1934592 : } while (i >= 4);
235 : :
236 : 120912 : seq_putc(m, '\n');
237 : 120912 : }
238 : :
239 : 0 : static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
240 : : sigset_t *catch)
241 : : {
242 : : struct k_sigaction *k;
243 : : int i;
244 : :
245 : 49162 : k = p->sighand->action;
246 [ + + ]: 3195530 : for (i = 1; i <= _NSIG; ++i, ++k) {
247 [ + + ]: 3146368 : if (k->sa.sa_handler == SIG_IGN)
248 : : sigaddset(ign, i);
249 [ + + ]: 1047716 : else if (k->sa.sa_handler != SIG_DFL)
250 : : sigaddset(catch, i);
251 : : }
252 : 49162 : }
253 : :
254 : : static inline void task_sig(struct seq_file *m, struct task_struct *p)
255 : : {
256 : : unsigned long flags;
257 : : sigset_t pending, shpending, blocked, ignored, caught;
258 : : int num_threads = 0;
259 : : unsigned long qsize = 0;
260 : : unsigned long qlim = 0;
261 : :
262 : : sigemptyset(&pending);
263 : : sigemptyset(&shpending);
264 : : sigemptyset(&blocked);
265 : : sigemptyset(&ignored);
266 : : sigemptyset(&caught);
267 : :
268 [ + - ]: 24180 : if (lock_task_sighand(p, &flags)) {
269 : 24180 : pending = p->pending.signal;
270 : 24180 : shpending = p->signal->shared_pending.signal;
271 : 24180 : blocked = p->blocked;
272 : 24180 : collect_sigign_sigcatch(p, &ignored, &caught);
273 : : num_threads = get_nr_threads(p);
274 : : rcu_read_lock(); /* FIXME: is this correct? */
275 : 24180 : qsize = atomic_read(&__task_cred(p)->user->sigpending);
276 : : rcu_read_unlock();
277 : : qlim = task_rlimit(p, RLIMIT_SIGPENDING);
278 : 24180 : unlock_task_sighand(p, &flags);
279 : : }
280 : :
281 : 24180 : seq_printf(m, "Threads:\t%d\n", num_threads);
282 : 24180 : seq_printf(m, "SigQ:\t%lu/%lu\n", qsize, qlim);
283 : :
284 : : /* render them all */
285 : 24180 : render_sigset_t(m, "SigPnd:\t", &pending);
286 : 24180 : render_sigset_t(m, "ShdPnd:\t", &shpending);
287 : 24180 : render_sigset_t(m, "SigBlk:\t", &blocked);
288 : 24180 : render_sigset_t(m, "SigIgn:\t", &ignored);
289 : 24180 : render_sigset_t(m, "SigCgt:\t", &caught);
290 : : }
291 : :
292 : 0 : static void render_cap_t(struct seq_file *m, const char *header,
293 : : kernel_cap_t *a)
294 : : {
295 : : unsigned __capi;
296 : :
297 : 96720 : seq_puts(m, header);
298 [ + + ]: 386880 : CAP_FOR_EACH_U32(__capi) {
299 : 193440 : seq_printf(m, "%08x",
300 : 193440 : a->cap[(_KERNEL_CAPABILITY_U32S-1) - __capi]);
301 : : }
302 : 96720 : seq_putc(m, '\n');
303 : 96720 : }
304 : :
305 : : /* Remove non-existent capabilities */
306 : : #define NORM_CAPS(v) (v.cap[CAP_TO_INDEX(CAP_LAST_CAP)] &= \
307 : : CAP_TO_MASK(CAP_LAST_CAP + 1) - 1)
308 : :
309 : : static inline void task_cap(struct seq_file *m, struct task_struct *p)
310 : : {
311 : : const struct cred *cred;
312 : : kernel_cap_t cap_inheritable, cap_permitted, cap_effective, cap_bset;
313 : :
314 : : rcu_read_lock();
315 : 24180 : cred = __task_cred(p);
316 : 24180 : cap_inheritable = cred->cap_inheritable;
317 : 24180 : cap_permitted = cred->cap_permitted;
318 : 24180 : cap_effective = cred->cap_effective;
319 : 24180 : cap_bset = cred->cap_bset;
320 : : rcu_read_unlock();
321 : :
322 : 24180 : NORM_CAPS(cap_inheritable);
323 : 24180 : NORM_CAPS(cap_permitted);
324 : 24180 : NORM_CAPS(cap_effective);
325 : 24180 : NORM_CAPS(cap_bset);
326 : :
327 : 24180 : render_cap_t(m, "CapInh:\t", &cap_inheritable);
328 : 24180 : render_cap_t(m, "CapPrm:\t", &cap_permitted);
329 : 24180 : render_cap_t(m, "CapEff:\t", &cap_effective);
330 : 24180 : render_cap_t(m, "CapBnd:\t", &cap_bset);
331 : : }
332 : :
333 : : static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
334 : : {
335 : : #ifdef CONFIG_SECCOMP
336 : 24180 : seq_printf(m, "Seccomp:\t%d\n", p->seccomp.mode);
337 : : #endif
338 : : }
339 : :
340 : : static inline void task_context_switch_counts(struct seq_file *m,
341 : : struct task_struct *p)
342 : : {
343 : 24180 : seq_printf(m, "voluntary_ctxt_switches:\t%lu\n"
344 : : "nonvoluntary_ctxt_switches:\t%lu\n",
345 : : p->nvcsw,
346 : : p->nivcsw);
347 : : }
348 : :
349 : 0 : static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
350 : : {
351 : 24180 : seq_puts(m, "Cpus_allowed:\t");
352 : : seq_cpumask(m, &task->cpus_allowed);
353 : 24180 : seq_putc(m, '\n');
354 : 24180 : seq_puts(m, "Cpus_allowed_list:\t");
355 : : seq_cpumask_list(m, &task->cpus_allowed);
356 : 24180 : seq_putc(m, '\n');
357 : 24180 : }
358 : :
359 : 0 : int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
360 : : struct pid *pid, struct task_struct *task)
361 : : {
362 : 24180 : struct mm_struct *mm = get_task_mm(task);
363 : :
364 : : task_name(m, task);
365 : : task_state(m, ns, pid, task);
366 : :
367 [ + + ]: 24180 : if (mm) {
368 : 7869 : task_mem(m, mm);
369 : 7869 : mmput(mm);
370 : : }
371 : : task_sig(m, task);
372 : : task_cap(m, task);
373 : : task_seccomp(m, task);
374 : 24180 : task_cpus_allowed(m, task);
375 : : cpuset_task_status_allowed(m, task);
376 : : task_context_switch_counts(m, task);
377 : 24180 : return 0;
378 : : }
379 : :
380 : 0 : static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
381 : : struct pid *pid, struct task_struct *task, int whole)
382 : : {
383 : : unsigned long vsize, eip, esp, wchan = ~0UL;
384 : : int priority, nice;
385 : : int tty_pgrp = -1, tty_nr = 0;
386 : : sigset_t sigign, sigcatch;
387 : : char state;
388 : : pid_t ppid = 0, pgid = -1, sid = -1;
389 : : int num_threads = 0;
390 : : int permitted;
391 : : struct mm_struct *mm;
392 : : unsigned long long start_time;
393 : : unsigned long cmin_flt = 0, cmaj_flt = 0;
394 : : unsigned long min_flt = 0, maj_flt = 0;
395 : : cputime_t cutime, cstime, utime, stime;
396 : : cputime_t cgtime, gtime;
397 : : unsigned long rsslim = 0;
398 : : char tcomm[sizeof(task->comm)];
399 : : unsigned long flags;
400 : :
401 : 24982 : state = *get_task_state(task);
402 : : vsize = eip = esp = 0;
403 : 24982 : permitted = ptrace_may_access(task, PTRACE_MODE_READ | PTRACE_MODE_NOAUDIT);
404 : 24982 : mm = get_task_mm(task);
405 [ + + ]: 24982 : if (mm) {
406 : 8841 : vsize = task_vsize(mm);
407 [ + - ]: 8841 : if (permitted) {
408 : 8841 : eip = KSTK_EIP(task);
409 : 8841 : esp = KSTK_ESP(task);
410 : : }
411 : : }
412 : :
413 : 24982 : get_task_comm(tcomm, task);
414 : :
415 : : sigemptyset(&sigign);
416 : : sigemptyset(&sigcatch);
417 : 24982 : cutime = cstime = utime = stime = 0;
418 : : cgtime = gtime = 0;
419 : :
420 [ + - ]: 24982 : if (lock_task_sighand(task, &flags)) {
421 : 24982 : struct signal_struct *sig = task->signal;
422 : :
423 [ + + ]: 24982 : if (sig->tty) {
424 : 5597 : struct pid *pgrp = tty_get_pgrp(sig->tty);
425 : 5597 : tty_pgrp = pid_nr_ns(pgrp, ns);
426 : 5597 : put_pid(pgrp);
427 : 5597 : tty_nr = new_encode_dev(tty_devnum(sig->tty));
428 : : }
429 : :
430 : : num_threads = get_nr_threads(task);
431 : 24982 : collect_sigign_sigcatch(task, &sigign, &sigcatch);
432 : :
433 : 24982 : cmin_flt = sig->cmin_flt;
434 : 24982 : cmaj_flt = sig->cmaj_flt;
435 : 24982 : cutime = sig->cutime;
436 : 24982 : cstime = sig->cstime;
437 : 24982 : cgtime = sig->cgtime;
438 : 24982 : rsslim = ACCESS_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
439 : :
440 : : /* add up live thread stats at the group level */
441 [ + + ]: 24982 : if (whole) {
442 : : struct task_struct *t = task;
443 : : do {
444 : 26351 : min_flt += t->min_flt;
445 : 26351 : maj_flt += t->maj_flt;
446 : 26351 : gtime += task_gtime(t);
447 [ + + ]: 26351 : } while_each_thread(task, t);
448 : :
449 : 24965 : min_flt += sig->min_flt;
450 : 24965 : maj_flt += sig->maj_flt;
451 : 24965 : thread_group_cputime_adjusted(task, &utime, &stime);
452 : 24965 : gtime += sig->gtime;
453 : : }
454 : :
455 : : sid = task_session_nr_ns(task, ns);
456 : 24982 : ppid = task_tgid_nr_ns(task->real_parent, ns);
457 : : pgid = task_pgrp_nr_ns(task, ns);
458 : :
459 : 24982 : unlock_task_sighand(task, &flags);
460 : : }
461 : :
462 [ + - ][ + + ]: 24982 : if (permitted && (!whole || num_threads < 2))
463 : 24513 : wchan = get_wchan(task);
464 [ + + ]: 24982 : if (!whole) {
465 : 17 : min_flt = task->min_flt;
466 : 17 : maj_flt = task->maj_flt;
467 : 17 : task_cputime_adjusted(task, &utime, &stime);
468 : : gtime = task_gtime(task);
469 : : }
470 : :
471 : : /* scale priority and nice values from timeslices to -20..20 */
472 : : /* to make it look like a "normal" Unix priority/nice value */
473 : 24982 : priority = task_prio(task);
474 : 24982 : nice = task_nice(task);
475 : :
476 : : /* Temporary variable needed for gcc-2.96 */
477 : : /* convert timespec -> nsec*/
478 : 24982 : start_time =
479 : 24982 : (unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
480 : 24982 : + task->real_start_time.tv_nsec;
481 : : /* convert nsec -> ticks */
482 : 24982 : start_time = nsec_to_clock_t(start_time);
483 : :
484 : 24982 : seq_printf(m, "%d (%s) %c", pid_nr_ns(pid, ns), tcomm, state);
485 : 24982 : seq_put_decimal_ll(m, ' ', ppid);
486 : 24981 : seq_put_decimal_ll(m, ' ', pgid);
487 : 24982 : seq_put_decimal_ll(m, ' ', sid);
488 : 24982 : seq_put_decimal_ll(m, ' ', tty_nr);
489 : 24982 : seq_put_decimal_ll(m, ' ', tty_pgrp);
490 : 24982 : seq_put_decimal_ull(m, ' ', task->flags);
491 : 24982 : seq_put_decimal_ull(m, ' ', min_flt);
492 : 24982 : seq_put_decimal_ull(m, ' ', cmin_flt);
493 : 24982 : seq_put_decimal_ull(m, ' ', maj_flt);
494 : 24982 : seq_put_decimal_ull(m, ' ', cmaj_flt);
495 : 24982 : seq_put_decimal_ull(m, ' ', cputime_to_clock_t(utime));
496 : 24982 : seq_put_decimal_ull(m, ' ', cputime_to_clock_t(stime));
497 : 24982 : seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cutime));
498 : 24982 : seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cstime));
499 : 24982 : seq_put_decimal_ll(m, ' ', priority);
500 : 24982 : seq_put_decimal_ll(m, ' ', nice);
501 : 24982 : seq_put_decimal_ll(m, ' ', num_threads);
502 : 24982 : seq_put_decimal_ull(m, ' ', 0);
503 : 24982 : seq_put_decimal_ull(m, ' ', start_time);
504 : 24982 : seq_put_decimal_ull(m, ' ', vsize);
505 [ + + ]: 33821 : seq_put_decimal_ull(m, ' ', mm ? get_mm_rss(mm) : 0);
506 : 24982 : seq_put_decimal_ull(m, ' ', rsslim);
507 [ + + ][ + - ]: 24982 : seq_put_decimal_ull(m, ' ', mm ? (permitted ? mm->start_code : 1) : 0);
508 [ + + ][ + - ]: 24982 : seq_put_decimal_ull(m, ' ', mm ? (permitted ? mm->end_code : 1) : 0);
509 [ + + ]: 24982 : seq_put_decimal_ull(m, ' ', (permitted && mm) ? mm->start_stack : 0);
510 : 24982 : seq_put_decimal_ull(m, ' ', esp);
511 : 24982 : seq_put_decimal_ull(m, ' ', eip);
512 : : /* The signal information here is obsolete.
513 : : * It must be decimal for Linux 2.0 compatibility.
514 : : * Use /proc/#/status for real-time signals.
515 : : */
516 : 24982 : seq_put_decimal_ull(m, ' ', task->pending.signal.sig[0] & 0x7fffffffUL);
517 : 24982 : seq_put_decimal_ull(m, ' ', task->blocked.sig[0] & 0x7fffffffUL);
518 : 24982 : seq_put_decimal_ull(m, ' ', sigign.sig[0] & 0x7fffffffUL);
519 : 24982 : seq_put_decimal_ull(m, ' ', sigcatch.sig[0] & 0x7fffffffUL);
520 : 24982 : seq_put_decimal_ull(m, ' ', wchan);
521 : 24982 : seq_put_decimal_ull(m, ' ', 0);
522 : 24982 : seq_put_decimal_ull(m, ' ', 0);
523 : 24982 : seq_put_decimal_ll(m, ' ', task->exit_signal);
524 : 24982 : seq_put_decimal_ll(m, ' ', task_cpu(task));
525 : 24982 : seq_put_decimal_ull(m, ' ', task->rt_priority);
526 : 24982 : seq_put_decimal_ull(m, ' ', task->policy);
527 : 24982 : seq_put_decimal_ull(m, ' ', delayacct_blkio_ticks(task));
528 : 24982 : seq_put_decimal_ull(m, ' ', cputime_to_clock_t(gtime));
529 : 24982 : seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cgtime));
530 : :
531 [ + + ]: 24982 : if (mm && permitted) {
532 : 8841 : seq_put_decimal_ull(m, ' ', mm->start_data);
533 : 8841 : seq_put_decimal_ull(m, ' ', mm->end_data);
534 : 8841 : seq_put_decimal_ull(m, ' ', mm->start_brk);
535 : 8841 : seq_put_decimal_ull(m, ' ', mm->arg_start);
536 : 8841 : seq_put_decimal_ull(m, ' ', mm->arg_end);
537 : 8841 : seq_put_decimal_ull(m, ' ', mm->env_start);
538 : 8841 : seq_put_decimal_ull(m, ' ', mm->env_end);
539 : : } else
540 : 16141 : seq_printf(m, " 0 0 0 0 0 0 0");
541 : :
542 [ + - ]: 24982 : if (permitted)
543 : 24982 : seq_put_decimal_ll(m, ' ', task->exit_code);
544 : : else
545 : 0 : seq_put_decimal_ll(m, ' ', 0);
546 : :
547 : 24982 : seq_putc(m, '\n');
548 [ + + ]: 24982 : if (mm)
549 : 8841 : mmput(mm);
550 : 24982 : return 0;
551 : : }
552 : :
553 : 0 : int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
554 : : struct pid *pid, struct task_struct *task)
555 : : {
556 : 17 : return do_task_stat(m, ns, pid, task, 0);
557 : : }
558 : :
559 : 0 : int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
560 : : struct pid *pid, struct task_struct *task)
561 : : {
562 : 24965 : return do_task_stat(m, ns, pid, task, 1);
563 : : }
564 : :
565 : 0 : int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
566 : : struct pid *pid, struct task_struct *task)
567 : : {
568 : 2 : unsigned long size = 0, resident = 0, shared = 0, text = 0, data = 0;
569 : 2 : struct mm_struct *mm = get_task_mm(task);
570 : :
571 [ + - ]: 2 : if (mm) {
572 : 2 : size = task_statm(mm, &shared, &text, &data, &resident);
573 : 2 : mmput(mm);
574 : : }
575 : : /*
576 : : * For quick read, open code by putting numbers directly
577 : : * expected format is
578 : : * seq_printf(m, "%lu %lu %lu %lu 0 %lu 0\n",
579 : : * size, resident, shared, text, data);
580 : : */
581 : 2 : seq_put_decimal_ull(m, 0, size);
582 : 2 : seq_put_decimal_ull(m, ' ', resident);
583 : 2 : seq_put_decimal_ull(m, ' ', shared);
584 : 2 : seq_put_decimal_ull(m, ' ', text);
585 : 2 : seq_put_decimal_ull(m, ' ', 0);
586 : 2 : seq_put_decimal_ull(m, ' ', data);
587 : 2 : seq_put_decimal_ull(m, ' ', 0);
588 : 2 : seq_putc(m, '\n');
589 : :
590 : 2 : return 0;
591 : : }
592 : :
593 : : #ifdef CONFIG_CHECKPOINT_RESTORE
594 : : static struct pid *
595 : : get_children_pid(struct inode *inode, struct pid *pid_prev, loff_t pos)
596 : : {
597 : : struct task_struct *start, *task;
598 : : struct pid *pid = NULL;
599 : :
600 : : read_lock(&tasklist_lock);
601 : :
602 : : start = pid_task(proc_pid(inode), PIDTYPE_PID);
603 : : if (!start)
604 : : goto out;
605 : :
606 : : /*
607 : : * Lets try to continue searching first, this gives
608 : : * us significant speedup on children-rich processes.
609 : : */
610 : : if (pid_prev) {
611 : : task = pid_task(pid_prev, PIDTYPE_PID);
612 : : if (task && task->real_parent == start &&
613 : : !(list_empty(&task->sibling))) {
614 : : if (list_is_last(&task->sibling, &start->children))
615 : : goto out;
616 : : task = list_first_entry(&task->sibling,
617 : : struct task_struct, sibling);
618 : : pid = get_pid(task_pid(task));
619 : : goto out;
620 : : }
621 : : }
622 : :
623 : : /*
624 : : * Slow search case.
625 : : *
626 : : * We might miss some children here if children
627 : : * are exited while we were not holding the lock,
628 : : * but it was never promised to be accurate that
629 : : * much.
630 : : *
631 : : * "Just suppose that the parent sleeps, but N children
632 : : * exit after we printed their tids. Now the slow paths
633 : : * skips N extra children, we miss N tasks." (c)
634 : : *
635 : : * So one need to stop or freeze the leader and all
636 : : * its children to get a precise result.
637 : : */
638 : : list_for_each_entry(task, &start->children, sibling) {
639 : : if (pos-- == 0) {
640 : : pid = get_pid(task_pid(task));
641 : : break;
642 : : }
643 : : }
644 : :
645 : : out:
646 : : read_unlock(&tasklist_lock);
647 : : return pid;
648 : : }
649 : :
650 : : static int children_seq_show(struct seq_file *seq, void *v)
651 : : {
652 : : struct inode *inode = seq->private;
653 : : pid_t pid;
654 : :
655 : : pid = pid_nr_ns(v, inode->i_sb->s_fs_info);
656 : : return seq_printf(seq, "%d ", pid);
657 : : }
658 : :
659 : : static void *children_seq_start(struct seq_file *seq, loff_t *pos)
660 : : {
661 : : return get_children_pid(seq->private, NULL, *pos);
662 : : }
663 : :
664 : : static void *children_seq_next(struct seq_file *seq, void *v, loff_t *pos)
665 : : {
666 : : struct pid *pid;
667 : :
668 : : pid = get_children_pid(seq->private, v, *pos + 1);
669 : : put_pid(v);
670 : :
671 : : ++*pos;
672 : : return pid;
673 : : }
674 : :
675 : : static void children_seq_stop(struct seq_file *seq, void *v)
676 : : {
677 : : put_pid(v);
678 : : }
679 : :
680 : : static const struct seq_operations children_seq_ops = {
681 : : .start = children_seq_start,
682 : : .next = children_seq_next,
683 : : .stop = children_seq_stop,
684 : : .show = children_seq_show,
685 : : };
686 : :
687 : : static int children_seq_open(struct inode *inode, struct file *file)
688 : : {
689 : : struct seq_file *m;
690 : : int ret;
691 : :
692 : : ret = seq_open(file, &children_seq_ops);
693 : : if (ret)
694 : : return ret;
695 : :
696 : : m = file->private_data;
697 : : m->private = inode;
698 : :
699 : : return ret;
700 : : }
701 : :
702 : : int children_seq_release(struct inode *inode, struct file *file)
703 : : {
704 : : seq_release(inode, file);
705 : : return 0;
706 : : }
707 : :
708 : : const struct file_operations proc_tid_children_operations = {
709 : : .open = children_seq_open,
710 : : .read = seq_read,
711 : : .llseek = seq_lseek,
712 : : .release = children_seq_release,
713 : : };
714 : : #endif /* CONFIG_CHECKPOINT_RESTORE */
|