array.c 15.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
/*
 *  linux/fs/proc/array.c
 *
 *  Copyright (C) 1992  by Linus Torvalds
 *  based on ideas by Darren Senn
 *
 * Fixes:
 * Michael. K. Johnson: stat,statm extensions.
 *                      <johnsonm@stolaf.edu>
 *
 * Pauline Middelink :  Made cmdline,envline only break at '\0's, to
 *                      make sure SET_PROCTITLE works. Also removed
 *                      bad '!' which forced address recalculation for
 *                      EVERY character on the current page.
 *                      <middelin@polyware.iaf.nl>
 *
 * Danny ter Haar    :	added cpuinfo
 *			<dth@cistron.nl>
 *
 * Alessandro Rubini :  profile extension.
 *                      <rubini@ipvvis.unipv.it>
 *
 * Jeff Tranter      :  added BogoMips field to cpuinfo
 *                      <Jeff_Tranter@Mitel.COM>
 *
 * Bruno Haible      :  remove 4K limit for the maps file
 *			<haible@ma2s2.mathematik.uni-karlsruhe.de>
 *
 * Yves Arrouye      :  remove removal of trailing spaces in get_array.
 *			<Yves.Arrouye@marin.fdn.fr>
 *
 * Jerome Forissier  :  added per-CPU time information to /proc/stat
 *                      and /proc/<pid>/cpu extension
 *                      <forissier@isia.cma.fr>
 *			- Incorporation and non-SMP safe operation
 *			of forissier patch in 2.1.78 by
 *			Hans Marcus <crowbar@concepts.nl>
 *
 * aeb@cwi.nl        :  /proc/partitions
 *
 *
 * Alan Cox	     :  security fixes.
A
Alan Cox 已提交
43
 *			<alan@lxorguk.ukuu.org.uk>
L
Linus Torvalds 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
 *
 * Al Viro           :  safe handling of mm_struct
 *
 * Gerhard Wichert   :  added BIGMEM support
 * Siemens AG           <Gerhard.Wichert@pdb.siemens.de>
 *
 * Al Viro & Jeff Garzik :  moved most of the thing into base.c and
 *			 :  proc_misc.c. The rest may eventually go into
 *			 :  base.c too.
 */

#include <linux/types.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/kernel.h>
#include <linux/kernel_stat.h>
#include <linux/tty.h>
#include <linux/string.h>
#include <linux/mman.h>
#include <linux/proc_fs.h>
#include <linux/ioport.h>
65 66
#include <linux/uaccess.h>
#include <linux/io.h>
L
Linus Torvalds 已提交
67 68 69 70 71 72 73 74 75
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/signal.h>
#include <linux/highmem.h>
#include <linux/file.h>
A
Al Viro 已提交
76
#include <linux/fdtable.h>
L
Linus Torvalds 已提交
77 78
#include <linux/times.h>
#include <linux/cpuset.h>
79
#include <linux/rcupdate.h>
80
#include <linux/delayacct.h>
81
#include <linux/seq_file.h>
82
#include <linux/pid_namespace.h>
83
#include <linux/ptrace.h>
84
#include <linux/tracehook.h>
85
#include <linux/swapops.h>
L
Linus Torvalds 已提交
86 87 88 89 90

#include <asm/pgtable.h>
#include <asm/processor.h>
#include "internal.h"

91
static inline void task_name(struct seq_file *m, struct task_struct *p)
L
Linus Torvalds 已提交
92 93
{
	int i;
94
	char *buf, *end;
95
	char *name;
L
Linus Torvalds 已提交
96 97 98 99
	char tcomm[sizeof(p->comm)];

	get_task_comm(tcomm, p);

100 101 102
	seq_printf(m, "Name:\t");
	end = m->buf + m->size;
	buf = m->buf + m->count;
L
Linus Torvalds 已提交
103 104
	name = tcomm;
	i = sizeof(tcomm);
105
	while (i && (buf < end)) {
L
Linus Torvalds 已提交
106 107 108 109 110 111 112
		unsigned char c = *name;
		name++;
		i--;
		*buf = c;
		if (!c)
			break;
		if (c == '\\') {
113 114 115
			buf++;
			if (buf < end)
				*buf++ = c;
L
Linus Torvalds 已提交
116 117 118
			continue;
		}
		if (c == '\n') {
119 120 121
			*buf++ = '\\';
			if (buf < end)
				*buf++ = 'n';
L
Linus Torvalds 已提交
122 123 124
			continue;
		}
		buf++;
125 126 127
	}
	m->count = buf - m->buf;
	seq_printf(m, "\n");
L
Linus Torvalds 已提交
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
}

/*
 * The task state array is a strange "bitmap" of
 * reasons to sleep. Thus "running" is zero, and
 * you can test for combinations of others with
 * simple bit tests.
 */
static const char *task_state_array[] = {
	"R (running)",		/*  0 */
	"S (sleeping)",		/*  1 */
	"D (disk sleep)",	/*  2 */
	"T (stopped)",		/*  4 */
	"T (tracing stop)",	/*  8 */
	"Z (zombie)",		/* 16 */
	"X (dead)"		/* 32 */
};

146
static inline const char *get_task_state(struct task_struct *tsk)
L
Linus Torvalds 已提交
147
{
M
Matthew Wilcox 已提交
148
	unsigned int state = (tsk->state & TASK_REPORT) | tsk->exit_state;
L
Linus Torvalds 已提交
149 150 151 152 153 154 155 156 157
	const char **p = &task_state_array[0];

	while (state) {
		p++;
		state >>= 1;
	}
	return *p;
}

158 159
static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
				struct pid *pid, struct task_struct *p)
L
Linus Torvalds 已提交
160 161 162
{
	struct group_info *group_info;
	int g;
163
	struct fdtable *fdt = NULL;
164
	const struct cred *cred;
165
	pid_t ppid, tpid;
L
Linus Torvalds 已提交
166

167
	rcu_read_lock();
168 169
	ppid = pid_alive(p) ?
		task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
170 171 172 173 174 175
	tpid = 0;
	if (pid_alive(p)) {
		struct task_struct *tracer = tracehook_tracer_task(p);
		if (tracer)
			tpid = task_pid_nr_ns(tracer, ns);
	}
176
	cred = get_cred((struct cred *) __task_cred(p));
177
	seq_printf(m,
L
Linus Torvalds 已提交
178 179 180 181 182 183 184 185
		"State:\t%s\n"
		"Tgid:\t%d\n"
		"Pid:\t%d\n"
		"PPid:\t%d\n"
		"TracerPid:\t%d\n"
		"Uid:\t%d\t%d\t%d\t%d\n"
		"Gid:\t%d\t%d\t%d\t%d\n",
		get_task_state(p),
186
		task_tgid_nr_ns(p, ns),
187
		pid_nr_ns(pid, ns),
188
		ppid, tpid,
189 190
		cred->uid, cred->euid, cred->suid, cred->fsuid,
		cred->gid, cred->egid, cred->sgid, cred->fsgid);
191

L
Linus Torvalds 已提交
192
	task_lock(p);
193 194
	if (p->files)
		fdt = files_fdtable(p->files);
195
	seq_printf(m,
L
Linus Torvalds 已提交
196 197
		"FDSize:\t%d\n"
		"Groups:\t",
198
		fdt ? fdt->max_fds : 0);
199
	rcu_read_unlock();
L
Linus Torvalds 已提交
200

201
	group_info = cred->group_info;
L
Linus Torvalds 已提交
202 203
	task_unlock(p);

204
	for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
205
		seq_printf(m, "%d ", GROUP_AT(group_info, g));
206
	put_cred(cred);
L
Linus Torvalds 已提交
207

208
	seq_printf(m, "\n");
L
Linus Torvalds 已提交
209 210
}

211 212
static void render_sigset_t(struct seq_file *m, const char *header,
				sigset_t *set)
L
Linus Torvalds 已提交
213
{
214
	int i;
L
Linus Torvalds 已提交
215

216
	seq_printf(m, "%s", header);
L
Linus Torvalds 已提交
217 218 219 220 221 222 223 224 225 226

	i = _NSIG;
	do {
		int x = 0;

		i -= 4;
		if (sigismember(set, i+1)) x |= 1;
		if (sigismember(set, i+2)) x |= 2;
		if (sigismember(set, i+3)) x |= 4;
		if (sigismember(set, i+4)) x |= 8;
227
		seq_printf(m, "%x", x);
L
Linus Torvalds 已提交
228 229
	} while (i >= 4);

230
	seq_printf(m, "\n");
L
Linus Torvalds 已提交
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
}

static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
				    sigset_t *catch)
{
	struct k_sigaction *k;
	int i;

	k = p->sighand->action;
	for (i = 1; i <= _NSIG; ++i, ++k) {
		if (k->sa.sa_handler == SIG_IGN)
			sigaddset(ign, i);
		else if (k->sa.sa_handler != SIG_DFL)
			sigaddset(catch, i);
	}
}

248
static inline void task_sig(struct seq_file *m, struct task_struct *p)
L
Linus Torvalds 已提交
249
{
250
	unsigned long flags;
L
Linus Torvalds 已提交
251 252 253 254 255 256 257 258 259 260 261
	sigset_t pending, shpending, blocked, ignored, caught;
	int num_threads = 0;
	unsigned long qsize = 0;
	unsigned long qlim = 0;

	sigemptyset(&pending);
	sigemptyset(&shpending);
	sigemptyset(&blocked);
	sigemptyset(&ignored);
	sigemptyset(&caught);

262
	if (lock_task_sighand(p, &flags)) {
L
Linus Torvalds 已提交
263 264 265 266 267
		pending = p->pending.signal;
		shpending = p->signal->shared_pending.signal;
		blocked = p->blocked;
		collect_sigign_sigcatch(p, &ignored, &caught);
		num_threads = atomic_read(&p->signal->count);
268
		qsize = atomic_read(&__task_cred(p)->user->sigpending);
L
Linus Torvalds 已提交
269
		qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
270
		unlock_task_sighand(p, &flags);
L
Linus Torvalds 已提交
271 272
	}

273 274
	seq_printf(m, "Threads:\t%d\n", num_threads);
	seq_printf(m, "SigQ:\t%lu/%lu\n", qsize, qlim);
L
Linus Torvalds 已提交
275 276

	/* render them all */
277 278 279 280 281
	render_sigset_t(m, "SigPnd:\t", &pending);
	render_sigset_t(m, "ShdPnd:\t", &shpending);
	render_sigset_t(m, "SigBlk:\t", &blocked);
	render_sigset_t(m, "SigIgn:\t", &ignored);
	render_sigset_t(m, "SigCgt:\t", &caught);
L
Linus Torvalds 已提交
282 283
}

284 285
static void render_cap_t(struct seq_file *m, const char *header,
			kernel_cap_t *a)
286 287 288
{
	unsigned __capi;

289
	seq_printf(m, "%s", header);
290
	CAP_FOR_EACH_U32(__capi) {
291
		seq_printf(m, "%08x",
292
			   a->cap[(_KERNEL_CAPABILITY_U32S-1) - __capi]);
293
	}
294
	seq_printf(m, "\n");
295 296
}

297
static inline void task_cap(struct seq_file *m, struct task_struct *p)
L
Linus Torvalds 已提交
298
{
299 300
	const struct cred *cred;
	kernel_cap_t cap_inheritable, cap_permitted, cap_effective, cap_bset;
301

302 303 304 305 306 307 308 309 310 311 312 313
	rcu_read_lock();
	cred = __task_cred(p);
	cap_inheritable	= cred->cap_inheritable;
	cap_permitted	= cred->cap_permitted;
	cap_effective	= cred->cap_effective;
	cap_bset	= cred->cap_bset;
	rcu_read_unlock();

	render_cap_t(m, "CapInh:\t", &cap_inheritable);
	render_cap_t(m, "CapPrm:\t", &cap_permitted);
	render_cap_t(m, "CapEff:\t", &cap_effective);
	render_cap_t(m, "CapBnd:\t", &cap_bset);
L
Linus Torvalds 已提交
314 315
}

316 317
static inline void task_context_switch_counts(struct seq_file *m,
						struct task_struct *p)
318
{
319 320 321 322
	seq_printf(m,	"voluntary_ctxt_switches:\t%lu\n"
			"nonvoluntary_ctxt_switches:\t%lu\n",
			p->nvcsw,
			p->nivcsw);
323 324
}

325 326
#ifdef CONFIG_MMU

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
struct stack_stats {
	struct vm_area_struct *vma;
	unsigned long	startpage;
	unsigned long	usage;
};

static int stack_usage_pte_range(pmd_t *pmd, unsigned long addr,
				unsigned long end, struct mm_walk *walk)
{
	struct stack_stats *ss = walk->private;
	struct vm_area_struct *vma = ss->vma;
	pte_t *pte, ptent;
	spinlock_t *ptl;
	int ret = 0;

	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
	for (; addr != end; pte++, addr += PAGE_SIZE) {
		ptent = *pte;

#ifdef CONFIG_STACK_GROWSUP
		if (pte_present(ptent) || is_swap_pte(ptent))
			ss->usage = addr - ss->startpage + PAGE_SIZE;
#else
		if (pte_present(ptent) || is_swap_pte(ptent)) {
			ss->usage = ss->startpage - addr + PAGE_SIZE;
			pte++;
			ret = 1;
			break;
		}
#endif
	}
	pte_unmap_unlock(pte - 1, ptl);
	cond_resched();
	return ret;
}

static inline unsigned long get_stack_usage_in_bytes(struct vm_area_struct *vma,
				struct task_struct *task)
{
	struct stack_stats ss;
	struct mm_walk stack_walk = {
		.pmd_entry = stack_usage_pte_range,
		.mm = vma->vm_mm,
		.private = &ss,
	};

	if (!vma->vm_mm || is_vm_hugetlb_page(vma))
		return 0;

	ss.vma = vma;
	ss.startpage = task->stack_start & PAGE_MASK;
	ss.usage = 0;

#ifdef CONFIG_STACK_GROWSUP
	walk_page_range(KSTK_ESP(task) & PAGE_MASK, vma->vm_end,
		&stack_walk);
#else
	walk_page_range(vma->vm_start, (KSTK_ESP(task) & PAGE_MASK) + PAGE_SIZE,
		&stack_walk);
#endif
	return ss.usage;
}

static inline void task_show_stack_usage(struct seq_file *m,
						struct task_struct *task)
{
	struct vm_area_struct	*vma;
	struct mm_struct	*mm = get_task_mm(task);

	if (mm) {
		down_read(&mm->mmap_sem);
		vma = find_vma(mm, task->stack_start);
		if (vma)
			seq_printf(m, "Stack usage:\t%lu kB\n",
				get_stack_usage_in_bytes(vma, task) >> 10);

		up_read(&mm->mmap_sem);
		mmput(mm);
	}
}
407 408 409 410 411
#else
static void task_show_stack_usage(struct seq_file *m, struct task_struct *task)
{
}
#endif		/* CONFIG_MMU */
412

413 414 415 416 417 418 419 420 421 422
static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
{
	seq_printf(m, "Cpus_allowed:\t");
	seq_cpumask(m, &task->cpus_allowed);
	seq_printf(m, "\n");
	seq_printf(m, "Cpus_allowed_list:\t");
	seq_cpumask_list(m, &task->cpus_allowed);
	seq_printf(m, "\n");
}

423 424
int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
			struct pid *pid, struct task_struct *task)
L
Linus Torvalds 已提交
425 426 427
{
	struct mm_struct *mm = get_task_mm(task);

428 429
	task_name(m, task);
	task_state(m, ns, pid, task);
430

L
Linus Torvalds 已提交
431
	if (mm) {
432
		task_mem(m, mm);
L
Linus Torvalds 已提交
433 434
		mmput(mm);
	}
435 436
	task_sig(m, task);
	task_cap(m, task);
437
	task_cpus_allowed(m, task);
438
	cpuset_task_status_allowed(m, task);
439
#if defined(CONFIG_S390)
440
	task_show_regs(m, task);
L
Linus Torvalds 已提交
441
#endif
442
	task_context_switch_counts(m, task);
443
	task_show_stack_usage(m, task);
444
	return 0;
L
Linus Torvalds 已提交
445 446
}

447 448
static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
			struct pid *pid, struct task_struct *task, int whole)
L
Linus Torvalds 已提交
449 450 451 452 453 454
{
	unsigned long vsize, eip, esp, wchan = ~0UL;
	long priority, nice;
	int tty_pgrp = -1, tty_nr = 0;
	sigset_t sigign, sigcatch;
	char state;
455
	pid_t ppid = 0, pgid = -1, sid = -1;
L
Linus Torvalds 已提交
456
	int num_threads = 0;
457
	int permitted;
L
Linus Torvalds 已提交
458 459 460 461
	struct mm_struct *mm;
	unsigned long long start_time;
	unsigned long cmin_flt = 0, cmaj_flt = 0;
	unsigned long  min_flt = 0,  maj_flt = 0;
462
	cputime_t cutime, cstime, utime, stime;
463
	cputime_t cgtime, gtime;
L
Linus Torvalds 已提交
464 465
	unsigned long rsslim = 0;
	char tcomm[sizeof(task->comm)];
466
	unsigned long flags;
L
Linus Torvalds 已提交
467 468 469

	state = *get_task_state(task);
	vsize = eip = esp = 0;
470
	permitted = ptrace_may_access(task, PTRACE_MODE_READ);
L
Linus Torvalds 已提交
471 472 473
	mm = get_task_mm(task);
	if (mm) {
		vsize = task_vsize(mm);
474 475 476 477
		if (permitted) {
			eip = KSTK_EIP(task);
			esp = KSTK_ESP(task);
		}
L
Linus Torvalds 已提交
478 479 480 481 482 483
	}

	get_task_comm(tcomm, task);

	sigemptyset(&sigign);
	sigemptyset(&sigcatch);
484
	cutime = cstime = utime = stime = cputime_zero;
485
	cgtime = gtime = cputime_zero;
486

487 488
	if (lock_task_sighand(task, &flags)) {
		struct signal_struct *sig = task->signal;
489 490

		if (sig->tty) {
491 492 493
			struct pid *pgrp = tty_get_pgrp(sig->tty);
			tty_pgrp = pid_nr_ns(pgrp, ns);
			put_pid(pgrp);
494
			tty_nr = new_encode_dev(tty_devnum(sig->tty));
495 496 497
		}

		num_threads = atomic_read(&sig->count);
L
Linus Torvalds 已提交
498 499
		collect_sigign_sigcatch(task, &sigign, &sigcatch);

500 501 502 503
		cmin_flt = sig->cmin_flt;
		cmaj_flt = sig->cmaj_flt;
		cutime = sig->cutime;
		cstime = sig->cstime;
504
		cgtime = sig->cgtime;
505 506
		rsslim = sig->rlim[RLIMIT_RSS].rlim_cur;

L
Linus Torvalds 已提交
507 508
		/* add up live thread stats at the group level */
		if (whole) {
509
			struct task_cputime cputime;
510
			struct task_struct *t = task;
L
Linus Torvalds 已提交
511 512 513
			do {
				min_flt += t->min_flt;
				maj_flt += t->maj_flt;
514
				gtime = cputime_add(gtime, task_gtime(t));
L
Linus Torvalds 已提交
515 516 517
				t = next_thread(t);
			} while (t != task);

518 519
			min_flt += sig->min_flt;
			maj_flt += sig->maj_flt;
520 521 522
			thread_group_cputime(task, &cputime);
			utime = cputime.utime;
			stime = cputime.stime;
523
			gtime = cputime_add(gtime, sig->gtime);
L
Linus Torvalds 已提交
524
		}
525

526
		sid = task_session_nr_ns(task, ns);
527
		ppid = task_tgid_nr_ns(task->real_parent, ns);
528
		pgid = task_pgrp_nr_ns(task, ns);
529 530

		unlock_task_sighand(task, &flags);
L
Linus Torvalds 已提交
531 532
	}

533
	if (permitted && (!whole || num_threads < 2))
L
Linus Torvalds 已提交
534 535 536 537
		wchan = get_wchan(task);
	if (!whole) {
		min_flt = task->min_flt;
		maj_flt = task->maj_flt;
538
		task_times(task, &utime, &stime);
539
		gtime = task_gtime(task);
L
Linus Torvalds 已提交
540 541 542 543 544 545 546 547 548
	}

	/* scale priority and nice values from timeslices to -20..20 */
	/* to make it look like a "normal" Unix priority/nice value  */
	priority = task_prio(task);
	nice = task_nice(task);

	/* Temporary variable needed for gcc-2.96 */
	/* convert timespec -> nsec*/
549 550 551
	start_time =
		(unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
				+ task->real_start_time.tv_nsec;
L
Linus Torvalds 已提交
552 553 554
	/* convert nsec -> ticks */
	start_time = nsec_to_clock_t(start_time);

555
	seq_printf(m, "%d (%s) %c %d %d %d %d %d %u %lu \
556
%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
557
%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n",
558
		pid_nr_ns(pid, ns),
L
Linus Torvalds 已提交
559 560 561 562 563 564 565 566 567 568 569 570
		tcomm,
		state,
		ppid,
		pgid,
		sid,
		tty_nr,
		tty_pgrp,
		task->flags,
		min_flt,
		cmin_flt,
		maj_flt,
		cmaj_flt,
571 572
		cputime_to_clock_t(utime),
		cputime_to_clock_t(stime),
L
Linus Torvalds 已提交
573 574 575 576 577 578 579
		cputime_to_clock_t(cutime),
		cputime_to_clock_t(cstime),
		priority,
		nice,
		num_threads,
		start_time,
		vsize,
580
		mm ? get_mm_rss(mm) : 0,
581
		rsslim,
L
Linus Torvalds 已提交
582 583
		mm ? mm->start_code : 0,
		mm ? mm->end_code : 0,
584
		(permitted) ? task->stack_start : 0,
L
Linus Torvalds 已提交
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
		esp,
		eip,
		/* The signal information here is obsolete.
		 * It must be decimal for Linux 2.0 compatibility.
		 * Use /proc/#/status for real-time signals.
		 */
		task->pending.signal.sig[0] & 0x7fffffffUL,
		task->blocked.sig[0] & 0x7fffffffUL,
		sigign      .sig[0] & 0x7fffffffUL,
		sigcatch    .sig[0] & 0x7fffffffUL,
		wchan,
		0UL,
		0UL,
		task->exit_signal,
		task_cpu(task),
		task->rt_priority,
601
		task->policy,
602 603 604
		(unsigned long long)delayacct_blkio_ticks(task),
		cputime_to_clock_t(gtime),
		cputime_to_clock_t(cgtime));
605
	if (mm)
L
Linus Torvalds 已提交
606
		mmput(mm);
607
	return 0;
L
Linus Torvalds 已提交
608 609
}

610 611
int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
			struct pid *pid, struct task_struct *task)
L
Linus Torvalds 已提交
612
{
613
	return do_task_stat(m, ns, pid, task, 0);
L
Linus Torvalds 已提交
614 615
}

616 617
int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
			struct pid *pid, struct task_struct *task)
L
Linus Torvalds 已提交
618
{
619
	return do_task_stat(m, ns, pid, task, 1);
L
Linus Torvalds 已提交
620 621
}

622 623
int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
			struct pid *pid, struct task_struct *task)
L
Linus Torvalds 已提交
624 625 626
{
	int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0;
	struct mm_struct *mm = get_task_mm(task);
627

L
Linus Torvalds 已提交
628 629 630 631
	if (mm) {
		size = task_statm(mm, &shared, &text, &data, &resident);
		mmput(mm);
	}
632 633
	seq_printf(m, "%d %d %d %d %d %d %d\n",
			size, resident, shared, text, lib, data, 0);
L
Linus Torvalds 已提交
634

635
	return 0;
L
Linus Torvalds 已提交
636
}