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 : 13099 : get_task_comm(tcomm, p);
98 : :
99 : 13099 : seq_puts(m, "Name:\t");
100 : 13099 : end = m->buf + m->size;
101 : 13099 : buf = m->buf + m->count;
102 : : name = tcomm;
103 : : i = sizeof(tcomm);
104 [ + - ]: 130398 : while (i && (buf < end)) {
105 : 130398 : unsigned char c = *name;
106 : 130398 : name++;
107 : 130398 : i--;
108 : 130398 : *buf = c;
109 [ + + ]: 130398 : if (!c)
110 : : break;
111 [ - + ]: 117299 : if (c == '\\') {
112 : 0 : buf++;
113 [ # # ]: 0 : if (buf < end)
114 : 0 : *buf++ = c;
115 : 0 : continue;
116 : : }
117 [ - + ]: 117299 : if (c == '\n') {
118 : 0 : *buf++ = '\\';
119 [ # # ]: 0 : if (buf < end)
120 : 0 : *buf++ = 'n';
121 : 0 : continue;
122 : : }
123 : 117299 : buf++;
124 : : }
125 : 13099 : m->count = buf - m->buf;
126 : 13099 : 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 : : "x (dead)", /* 64 */
144 : : "K (wakekill)", /* 128 */
145 : : "W (waking)", /* 256 */
146 : : "P (parked)", /* 512 */
147 : : };
148 : :
149 : : static inline const char *get_task_state(struct task_struct *tsk)
150 : : {
151 : 26580 : unsigned int state = (tsk->state & TASK_REPORT) | tsk->exit_state;
152 : : const char * const *p = &task_state_array[0];
153 : :
154 : : BUILD_BUG_ON(1 + ilog2(TASK_STATE_MAX) != ARRAY_SIZE(task_state_array));
155 : :
156 [ + + ][ + + ]: 50270 : while (state) {
157 : 23690 : p++;
158 : 23690 : state >>= 1;
159 : : }
160 : 26580 : return *p;
161 : : }
162 : :
163 : : static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
164 : : struct pid *pid, struct task_struct *p)
165 : : {
166 : : struct user_namespace *user_ns = seq_user_ns(m);
167 : : struct group_info *group_info;
168 : : int g;
169 : : struct fdtable *fdt = NULL;
170 : : const struct cred *cred;
171 : : pid_t ppid, tpid;
172 : :
173 : : rcu_read_lock();
174 : : ppid = pid_alive(p) ?
175 [ + - ]: 13099 : task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
176 : : tpid = 0;
177 [ + - ]: 13099 : if (pid_alive(p)) {
178 : : struct task_struct *tracer = ptrace_parent(p);
179 [ - + ]: 13099 : if (tracer)
180 : : tpid = task_pid_nr_ns(tracer, ns);
181 : : }
182 : 13099 : cred = get_task_cred(p);
183 [ - + ][ - + ]: 26198 : seq_printf(m,
[ - - ][ # # ]
184 : : "State:\t%s\n"
185 : : "Tgid:\t%d\n"
186 : : "Ngid:\t%d\n"
187 : : "Pid:\t%d\n"
188 : : "PPid:\t%d\n"
189 : : "TracerPid:\t%d\n"
190 : : "Uid:\t%d\t%d\t%d\t%d\n"
191 : : "Gid:\t%d\t%d\t%d\t%d\n",
192 : : get_task_state(p),
193 : : task_tgid_nr_ns(p, ns),
194 : : task_numa_group_id(p),
195 : : pid_nr_ns(pid, ns),
196 : : ppid, tpid,
197 : : from_kuid_munged(user_ns, cred->uid),
198 : : from_kuid_munged(user_ns, cred->euid),
199 : : from_kuid_munged(user_ns, cred->suid),
200 : : from_kuid_munged(user_ns, cred->fsuid),
201 : : from_kgid_munged(user_ns, cred->gid),
202 : : from_kgid_munged(user_ns, cred->egid),
203 : : from_kgid_munged(user_ns, cred->sgid),
204 : : from_kgid_munged(user_ns, cred->fsgid));
205 : :
206 : : task_lock(p);
207 [ + - ]: 13099 : if (p->files)
208 : 13099 : fdt = files_fdtable(p->files);
209 [ + - ]: 13099 : seq_printf(m,
210 : : "FDSize:\t%d\n"
211 : : "Groups:\t",
212 : : fdt ? fdt->max_fds : 0);
213 : : rcu_read_unlock();
214 : :
215 : 13099 : group_info = cred->group_info;
216 : : task_unlock(p);
217 : :
218 [ + + ]: 16874 : for (g = 0; g < group_info->ngroups; g++)
219 : 3775 : seq_printf(m, "%d ",
220 : 3775 : from_kgid_munged(user_ns, GROUP_AT(group_info, g)));
221 : : put_cred(cred);
222 : :
223 : 13099 : seq_putc(m, '\n');
224 : : }
225 : :
226 : 0 : void render_sigset_t(struct seq_file *m, const char *header,
227 : : sigset_t *set)
228 : : {
229 : : int i;
230 : :
231 : 65495 : seq_puts(m, header);
232 : :
233 : : i = _NSIG;
234 : : do {
235 : : int x = 0;
236 : :
237 : 1113415 : i -= 4;
238 [ + + ]: 1113415 : if (sigismember(set, i+1)) x |= 1;
239 [ + + ]: 1113415 : if (sigismember(set, i+2)) x |= 2;
240 [ + + ]: 1047920 : if (sigismember(set, i+3)) x |= 4;
241 [ + + ]: 1047920 : if (sigismember(set, i+4)) x |= 8;
242 : 1047920 : seq_printf(m, "%x", x);
243 [ + + ]: 1047920 : } while (i >= 4);
244 : :
245 : 65495 : seq_putc(m, '\n');
246 : 65495 : }
247 : :
248 : 0 : static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
249 : : sigset_t *catch)
250 : : {
251 : : struct k_sigaction *k;
252 : : int i;
253 : :
254 : 26580 : k = p->sighand->action;
255 [ + + ]: 1727700 : for (i = 1; i <= _NSIG; ++i, ++k) {
256 [ + + ]: 1701120 : if (k->sa.sa_handler == SIG_IGN)
257 : : sigaddset(ign, i);
258 [ + + ]: 593306 : else if (k->sa.sa_handler != SIG_DFL)
259 : : sigaddset(catch, i);
260 : : }
261 : 26580 : }
262 : :
263 : : static inline void task_sig(struct seq_file *m, struct task_struct *p)
264 : : {
265 : : unsigned long flags;
266 : : sigset_t pending, shpending, blocked, ignored, caught;
267 : : int num_threads = 0;
268 : : unsigned long qsize = 0;
269 : : unsigned long qlim = 0;
270 : :
271 : : sigemptyset(&pending);
272 : : sigemptyset(&shpending);
273 : : sigemptyset(&blocked);
274 : : sigemptyset(&ignored);
275 : : sigemptyset(&caught);
276 : :
277 [ + - ]: 13099 : if (lock_task_sighand(p, &flags)) {
278 : 13099 : pending = p->pending.signal;
279 : 13099 : shpending = p->signal->shared_pending.signal;
280 : 13099 : blocked = p->blocked;
281 : 13099 : collect_sigign_sigcatch(p, &ignored, &caught);
282 : : num_threads = get_nr_threads(p);
283 : : rcu_read_lock(); /* FIXME: is this correct? */
284 : 13099 : qsize = atomic_read(&__task_cred(p)->user->sigpending);
285 : : rcu_read_unlock();
286 : : qlim = task_rlimit(p, RLIMIT_SIGPENDING);
287 : 13099 : unlock_task_sighand(p, &flags);
288 : : }
289 : :
290 : 13099 : seq_printf(m, "Threads:\t%d\n", num_threads);
291 : 13099 : seq_printf(m, "SigQ:\t%lu/%lu\n", qsize, qlim);
292 : :
293 : : /* render them all */
294 : 13099 : render_sigset_t(m, "SigPnd:\t", &pending);
295 : 13099 : render_sigset_t(m, "ShdPnd:\t", &shpending);
296 : 13099 : render_sigset_t(m, "SigBlk:\t", &blocked);
297 : 13099 : render_sigset_t(m, "SigIgn:\t", &ignored);
298 : 13099 : render_sigset_t(m, "SigCgt:\t", &caught);
299 : : }
300 : :
301 : 0 : static void render_cap_t(struct seq_file *m, const char *header,
302 : : kernel_cap_t *a)
303 : : {
304 : : unsigned __capi;
305 : :
306 : 52396 : seq_puts(m, header);
307 [ + + ]: 209584 : CAP_FOR_EACH_U32(__capi) {
308 : 104792 : seq_printf(m, "%08x",
309 : 104792 : a->cap[(_KERNEL_CAPABILITY_U32S-1) - __capi]);
310 : : }
311 : 52396 : seq_putc(m, '\n');
312 : 52396 : }
313 : :
314 : : /* Remove non-existent capabilities */
315 : : #define NORM_CAPS(v) (v.cap[CAP_TO_INDEX(CAP_LAST_CAP)] &= \
316 : : CAP_TO_MASK(CAP_LAST_CAP + 1) - 1)
317 : :
318 : : static inline void task_cap(struct seq_file *m, struct task_struct *p)
319 : : {
320 : : const struct cred *cred;
321 : : kernel_cap_t cap_inheritable, cap_permitted, cap_effective, cap_bset;
322 : :
323 : : rcu_read_lock();
324 : 13099 : cred = __task_cred(p);
325 : 13099 : cap_inheritable = cred->cap_inheritable;
326 : 13099 : cap_permitted = cred->cap_permitted;
327 : 13099 : cap_effective = cred->cap_effective;
328 : 13099 : cap_bset = cred->cap_bset;
329 : : rcu_read_unlock();
330 : :
331 : 13099 : NORM_CAPS(cap_inheritable);
332 : 13099 : NORM_CAPS(cap_permitted);
333 : 13099 : NORM_CAPS(cap_effective);
334 : 13099 : NORM_CAPS(cap_bset);
335 : :
336 : 13099 : render_cap_t(m, "CapInh:\t", &cap_inheritable);
337 : 13099 : render_cap_t(m, "CapPrm:\t", &cap_permitted);
338 : 13099 : render_cap_t(m, "CapEff:\t", &cap_effective);
339 : 13099 : render_cap_t(m, "CapBnd:\t", &cap_bset);
340 : : }
341 : :
342 : : static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
343 : : {
344 : : #ifdef CONFIG_SECCOMP
345 : 13099 : seq_printf(m, "Seccomp:\t%d\n", p->seccomp.mode);
346 : : #endif
347 : : }
348 : :
349 : : static inline void task_context_switch_counts(struct seq_file *m,
350 : : struct task_struct *p)
351 : : {
352 : 13099 : seq_printf(m, "voluntary_ctxt_switches:\t%lu\n"
353 : : "nonvoluntary_ctxt_switches:\t%lu\n",
354 : : p->nvcsw,
355 : : p->nivcsw);
356 : : }
357 : :
358 : 0 : static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
359 : : {
360 : 13099 : seq_puts(m, "Cpus_allowed:\t");
361 : : seq_cpumask(m, &task->cpus_allowed);
362 : 13099 : seq_putc(m, '\n');
363 : 13099 : seq_puts(m, "Cpus_allowed_list:\t");
364 : : seq_cpumask_list(m, &task->cpus_allowed);
365 : 13099 : seq_putc(m, '\n');
366 : 13099 : }
367 : :
368 : 0 : int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
369 : : struct pid *pid, struct task_struct *task)
370 : : {
371 : 13099 : struct mm_struct *mm = get_task_mm(task);
372 : :
373 : : task_name(m, task);
374 : : task_state(m, ns, pid, task);
375 : :
376 [ + + ]: 13099 : if (mm) {
377 : 4363 : task_mem(m, mm);
378 : 4363 : mmput(mm);
379 : : }
380 : : task_sig(m, task);
381 : : task_cap(m, task);
382 : : task_seccomp(m, task);
383 : 13099 : task_cpus_allowed(m, task);
384 : : cpuset_task_status_allowed(m, task);
385 : : task_context_switch_counts(m, task);
386 : 13099 : return 0;
387 : : }
388 : :
389 : 0 : static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
390 : : struct pid *pid, struct task_struct *task, int whole)
391 : : {
392 : : unsigned long vsize, eip, esp, wchan = ~0UL;
393 : : int priority, nice;
394 : : int tty_pgrp = -1, tty_nr = 0;
395 : : sigset_t sigign, sigcatch;
396 : : char state;
397 : : pid_t ppid = 0, pgid = -1, sid = -1;
398 : : int num_threads = 0;
399 : : int permitted;
400 : : struct mm_struct *mm;
401 : : unsigned long long start_time;
402 : : unsigned long cmin_flt = 0, cmaj_flt = 0;
403 : : unsigned long min_flt = 0, maj_flt = 0;
404 : : cputime_t cutime, cstime, utime, stime;
405 : : cputime_t cgtime, gtime;
406 : : unsigned long rsslim = 0;
407 : : char tcomm[sizeof(task->comm)];
408 : : unsigned long flags;
409 : :
410 : 13481 : state = *get_task_state(task);
411 : : vsize = eip = esp = 0;
412 : 13481 : permitted = ptrace_may_access(task, PTRACE_MODE_READ | PTRACE_MODE_NOAUDIT);
413 : 13481 : mm = get_task_mm(task);
414 [ + + ]: 13481 : if (mm) {
415 : 5091 : vsize = task_vsize(mm);
416 [ + - ]: 5091 : if (permitted) {
417 : 5091 : eip = KSTK_EIP(task);
418 : 5091 : esp = KSTK_ESP(task);
419 : : }
420 : : }
421 : :
422 : 13481 : get_task_comm(tcomm, task);
423 : :
424 : : sigemptyset(&sigign);
425 : : sigemptyset(&sigcatch);
426 : 13481 : cutime = cstime = utime = stime = 0;
427 : : cgtime = gtime = 0;
428 : :
429 [ + - ]: 13481 : if (lock_task_sighand(task, &flags)) {
430 : 13481 : struct signal_struct *sig = task->signal;
431 : :
432 [ + + ]: 13481 : if (sig->tty) {
433 : 3407 : struct pid *pgrp = tty_get_pgrp(sig->tty);
434 : 3407 : tty_pgrp = pid_nr_ns(pgrp, ns);
435 : 3407 : put_pid(pgrp);
436 : 3407 : tty_nr = new_encode_dev(tty_devnum(sig->tty));
437 : : }
438 : :
439 : : num_threads = get_nr_threads(task);
440 : 13481 : collect_sigign_sigcatch(task, &sigign, &sigcatch);
441 : :
442 : 13481 : cmin_flt = sig->cmin_flt;
443 : 13481 : cmaj_flt = sig->cmaj_flt;
444 : 13481 : cutime = sig->cutime;
445 : 13481 : cstime = sig->cstime;
446 : 13481 : cgtime = sig->cgtime;
447 : 13481 : rsslim = ACCESS_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
448 : :
449 : : /* add up live thread stats at the group level */
450 [ + + ]: 13481 : if (whole) {
451 : : struct task_struct *t = task;
452 : : do {
453 : 15829 : min_flt += t->min_flt;
454 : 15829 : maj_flt += t->maj_flt;
455 : 15829 : gtime += task_gtime(t);
456 : 15829 : t = next_thread(t);
457 [ + + ]: 15829 : } while (t != task);
458 : :
459 : 13476 : min_flt += sig->min_flt;
460 : 13476 : maj_flt += sig->maj_flt;
461 : 13476 : thread_group_cputime_adjusted(task, &utime, &stime);
462 : 13476 : gtime += sig->gtime;
463 : : }
464 : :
465 : : sid = task_session_nr_ns(task, ns);
466 : 13481 : ppid = task_tgid_nr_ns(task->real_parent, ns);
467 : : pgid = task_pgrp_nr_ns(task, ns);
468 : :
469 : 13481 : unlock_task_sighand(task, &flags);
470 : : }
471 : :
472 [ + - ][ + + ]: 13481 : if (permitted && (!whole || num_threads < 2))
473 : 13141 : wchan = get_wchan(task);
474 [ + + ]: 13481 : if (!whole) {
475 : 5 : min_flt = task->min_flt;
476 : 5 : maj_flt = task->maj_flt;
477 : 5 : task_cputime_adjusted(task, &utime, &stime);
478 : : gtime = task_gtime(task);
479 : : }
480 : :
481 : : /* scale priority and nice values from timeslices to -20..20 */
482 : : /* to make it look like a "normal" Unix priority/nice value */
483 : 13481 : priority = task_prio(task);
484 : 13481 : nice = task_nice(task);
485 : :
486 : : /* Temporary variable needed for gcc-2.96 */
487 : : /* convert timespec -> nsec*/
488 : 13481 : start_time =
489 : 13481 : (unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
490 : 13481 : + task->real_start_time.tv_nsec;
491 : : /* convert nsec -> ticks */
492 : 13481 : start_time = nsec_to_clock_t(start_time);
493 : :
494 : 13481 : seq_printf(m, "%d (%s) %c", pid_nr_ns(pid, ns), tcomm, state);
495 : 13481 : seq_put_decimal_ll(m, ' ', ppid);
496 : 13481 : seq_put_decimal_ll(m, ' ', pgid);
497 : 13481 : seq_put_decimal_ll(m, ' ', sid);
498 : 13481 : seq_put_decimal_ll(m, ' ', tty_nr);
499 : 13481 : seq_put_decimal_ll(m, ' ', tty_pgrp);
500 : 13481 : seq_put_decimal_ull(m, ' ', task->flags);
501 : 13481 : seq_put_decimal_ull(m, ' ', min_flt);
502 : 13481 : seq_put_decimal_ull(m, ' ', cmin_flt);
503 : 13481 : seq_put_decimal_ull(m, ' ', maj_flt);
504 : 13481 : seq_put_decimal_ull(m, ' ', cmaj_flt);
505 : 13481 : seq_put_decimal_ull(m, ' ', cputime_to_clock_t(utime));
506 : 13481 : seq_put_decimal_ull(m, ' ', cputime_to_clock_t(stime));
507 : 13481 : seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cutime));
508 : 13481 : seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cstime));
509 : 13481 : seq_put_decimal_ll(m, ' ', priority);
510 : 13481 : seq_put_decimal_ll(m, ' ', nice);
511 : 13481 : seq_put_decimal_ll(m, ' ', num_threads);
512 : 13481 : seq_put_decimal_ull(m, ' ', 0);
513 : 13481 : seq_put_decimal_ull(m, ' ', start_time);
514 : 13481 : seq_put_decimal_ull(m, ' ', vsize);
515 [ + + ]: 18572 : seq_put_decimal_ull(m, ' ', mm ? get_mm_rss(mm) : 0);
516 : 13481 : seq_put_decimal_ull(m, ' ', rsslim);
517 [ + + ][ + - ]: 13481 : seq_put_decimal_ull(m, ' ', mm ? (permitted ? mm->start_code : 1) : 0);
518 [ + + ][ + - ]: 13481 : seq_put_decimal_ull(m, ' ', mm ? (permitted ? mm->end_code : 1) : 0);
519 [ + + ]: 13481 : seq_put_decimal_ull(m, ' ', (permitted && mm) ? mm->start_stack : 0);
520 : 13481 : seq_put_decimal_ull(m, ' ', esp);
521 : 13481 : seq_put_decimal_ull(m, ' ', eip);
522 : : /* The signal information here is obsolete.
523 : : * It must be decimal for Linux 2.0 compatibility.
524 : : * Use /proc/#/status for real-time signals.
525 : : */
526 : 13481 : seq_put_decimal_ull(m, ' ', task->pending.signal.sig[0] & 0x7fffffffUL);
527 : 13481 : seq_put_decimal_ull(m, ' ', task->blocked.sig[0] & 0x7fffffffUL);
528 : 13481 : seq_put_decimal_ull(m, ' ', sigign.sig[0] & 0x7fffffffUL);
529 : 13481 : seq_put_decimal_ull(m, ' ', sigcatch.sig[0] & 0x7fffffffUL);
530 : 13481 : seq_put_decimal_ull(m, ' ', wchan);
531 : 13481 : seq_put_decimal_ull(m, ' ', 0);
532 : 13481 : seq_put_decimal_ull(m, ' ', 0);
533 : 13481 : seq_put_decimal_ll(m, ' ', task->exit_signal);
534 : 13481 : seq_put_decimal_ll(m, ' ', task_cpu(task));
535 : 13481 : seq_put_decimal_ull(m, ' ', task->rt_priority);
536 : 13481 : seq_put_decimal_ull(m, ' ', task->policy);
537 : 13481 : seq_put_decimal_ull(m, ' ', delayacct_blkio_ticks(task));
538 : 13481 : seq_put_decimal_ull(m, ' ', cputime_to_clock_t(gtime));
539 : 13481 : seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cgtime));
540 : :
541 [ + + ]: 13481 : if (mm && permitted) {
542 : 5091 : seq_put_decimal_ull(m, ' ', mm->start_data);
543 : 5091 : seq_put_decimal_ull(m, ' ', mm->end_data);
544 : 5091 : seq_put_decimal_ull(m, ' ', mm->start_brk);
545 : 5091 : seq_put_decimal_ull(m, ' ', mm->arg_start);
546 : 5091 : seq_put_decimal_ull(m, ' ', mm->arg_end);
547 : 5091 : seq_put_decimal_ull(m, ' ', mm->env_start);
548 : 5091 : seq_put_decimal_ull(m, ' ', mm->env_end);
549 : : } else
550 : 8390 : seq_printf(m, " 0 0 0 0 0 0 0");
551 : :
552 [ + - ]: 13481 : if (permitted)
553 : 13481 : seq_put_decimal_ll(m, ' ', task->exit_code);
554 : : else
555 : 0 : seq_put_decimal_ll(m, ' ', 0);
556 : :
557 : 13481 : seq_putc(m, '\n');
558 [ + + ]: 13481 : if (mm)
559 : 5091 : mmput(mm);
560 : 13481 : return 0;
561 : : }
562 : :
563 : 0 : int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
564 : : struct pid *pid, struct task_struct *task)
565 : : {
566 : 5 : return do_task_stat(m, ns, pid, task, 0);
567 : : }
568 : :
569 : 0 : int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
570 : : struct pid *pid, struct task_struct *task)
571 : : {
572 : 13476 : return do_task_stat(m, ns, pid, task, 1);
573 : : }
574 : :
575 : 0 : int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
576 : : struct pid *pid, struct task_struct *task)
577 : : {
578 : 2 : unsigned long size = 0, resident = 0, shared = 0, text = 0, data = 0;
579 : 2 : struct mm_struct *mm = get_task_mm(task);
580 : :
581 [ + - ]: 2 : if (mm) {
582 : 2 : size = task_statm(mm, &shared, &text, &data, &resident);
583 : 2 : mmput(mm);
584 : : }
585 : : /*
586 : : * For quick read, open code by putting numbers directly
587 : : * expected format is
588 : : * seq_printf(m, "%lu %lu %lu %lu 0 %lu 0\n",
589 : : * size, resident, shared, text, data);
590 : : */
591 : 2 : seq_put_decimal_ull(m, 0, size);
592 : 2 : seq_put_decimal_ull(m, ' ', resident);
593 : 2 : seq_put_decimal_ull(m, ' ', shared);
594 : 2 : seq_put_decimal_ull(m, ' ', text);
595 : 2 : seq_put_decimal_ull(m, ' ', 0);
596 : 2 : seq_put_decimal_ull(m, ' ', data);
597 : 2 : seq_put_decimal_ull(m, ' ', 0);
598 : 2 : seq_putc(m, '\n');
599 : :
600 : 2 : return 0;
601 : : }
602 : :
603 : : #ifdef CONFIG_CHECKPOINT_RESTORE
604 : : static struct pid *
605 : : get_children_pid(struct inode *inode, struct pid *pid_prev, loff_t pos)
606 : : {
607 : : struct task_struct *start, *task;
608 : : struct pid *pid = NULL;
609 : :
610 : : read_lock(&tasklist_lock);
611 : :
612 : : start = pid_task(proc_pid(inode), PIDTYPE_PID);
613 : : if (!start)
614 : : goto out;
615 : :
616 : : /*
617 : : * Lets try to continue searching first, this gives
618 : : * us significant speedup on children-rich processes.
619 : : */
620 : : if (pid_prev) {
621 : : task = pid_task(pid_prev, PIDTYPE_PID);
622 : : if (task && task->real_parent == start &&
623 : : !(list_empty(&task->sibling))) {
624 : : if (list_is_last(&task->sibling, &start->children))
625 : : goto out;
626 : : task = list_first_entry(&task->sibling,
627 : : struct task_struct, sibling);
628 : : pid = get_pid(task_pid(task));
629 : : goto out;
630 : : }
631 : : }
632 : :
633 : : /*
634 : : * Slow search case.
635 : : *
636 : : * We might miss some children here if children
637 : : * are exited while we were not holding the lock,
638 : : * but it was never promised to be accurate that
639 : : * much.
640 : : *
641 : : * "Just suppose that the parent sleeps, but N children
642 : : * exit after we printed their tids. Now the slow paths
643 : : * skips N extra children, we miss N tasks." (c)
644 : : *
645 : : * So one need to stop or freeze the leader and all
646 : : * its children to get a precise result.
647 : : */
648 : : list_for_each_entry(task, &start->children, sibling) {
649 : : if (pos-- == 0) {
650 : : pid = get_pid(task_pid(task));
651 : : break;
652 : : }
653 : : }
654 : :
655 : : out:
656 : : read_unlock(&tasklist_lock);
657 : : return pid;
658 : : }
659 : :
660 : : static int children_seq_show(struct seq_file *seq, void *v)
661 : : {
662 : : struct inode *inode = seq->private;
663 : : pid_t pid;
664 : :
665 : : pid = pid_nr_ns(v, inode->i_sb->s_fs_info);
666 : : return seq_printf(seq, "%d ", pid);
667 : : }
668 : :
669 : : static void *children_seq_start(struct seq_file *seq, loff_t *pos)
670 : : {
671 : : return get_children_pid(seq->private, NULL, *pos);
672 : : }
673 : :
674 : : static void *children_seq_next(struct seq_file *seq, void *v, loff_t *pos)
675 : : {
676 : : struct pid *pid;
677 : :
678 : : pid = get_children_pid(seq->private, v, *pos + 1);
679 : : put_pid(v);
680 : :
681 : : ++*pos;
682 : : return pid;
683 : : }
684 : :
685 : : static void children_seq_stop(struct seq_file *seq, void *v)
686 : : {
687 : : put_pid(v);
688 : : }
689 : :
690 : : static const struct seq_operations children_seq_ops = {
691 : : .start = children_seq_start,
692 : : .next = children_seq_next,
693 : : .stop = children_seq_stop,
694 : : .show = children_seq_show,
695 : : };
696 : :
697 : : static int children_seq_open(struct inode *inode, struct file *file)
698 : : {
699 : : struct seq_file *m;
700 : : int ret;
701 : :
702 : : ret = seq_open(file, &children_seq_ops);
703 : : if (ret)
704 : : return ret;
705 : :
706 : : m = file->private_data;
707 : : m->private = inode;
708 : :
709 : : return ret;
710 : : }
711 : :
712 : : int children_seq_release(struct inode *inode, struct file *file)
713 : : {
714 : : seq_release(inode, file);
715 : : return 0;
716 : : }
717 : :
718 : : const struct file_operations proc_tid_children_operations = {
719 : : .open = children_seq_open,
720 : : .read = seq_read,
721 : : .llseek = seq_lseek,
722 : : .release = children_seq_release,
723 : : };
724 : : #endif /* CONFIG_CHECKPOINT_RESTORE */
|