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
}

/*
 * 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 */
141
	"t (tracing stop)",	/*  8 */
L
Linus Torvalds 已提交
142
	"Z (zombie)",		/* 16 */
143 144 145 146
	"X (dead)",		/* 32 */
	"x (dead)",		/* 64 */
	"K (wakekill)",		/* 128 */
	"W (waking)",		/* 256 */
L
Linus Torvalds 已提交
147 148
};

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

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

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

170
	rcu_read_lock();
171 172
	ppid = pid_alive(p) ?
		task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
173 174 175 176 177 178
	tpid = 0;
	if (pid_alive(p)) {
		struct task_struct *tracer = tracehook_tracer_task(p);
		if (tracer)
			tpid = task_pid_nr_ns(tracer, ns);
	}
179
	cred = get_cred((struct cred *) __task_cred(p));
180
	seq_printf(m,
L
Linus Torvalds 已提交
181 182 183 184 185 186 187 188
		"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),
189
		task_tgid_nr_ns(p, ns),
190
		pid_nr_ns(pid, ns),
191
		ppid, tpid,
192 193
		cred->uid, cred->euid, cred->suid, cred->fsuid,
		cred->gid, cred->egid, cred->sgid, cred->fsgid);
194

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

204
	group_info = cred->group_info;
L
Linus Torvalds 已提交
205 206
	task_unlock(p);

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

211
	seq_printf(m, "\n");
L
Linus Torvalds 已提交
212 213
}

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

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

	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;
230
		seq_printf(m, "%x", x);
L
Linus Torvalds 已提交
231 232
	} while (i >= 4);

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

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);
	}
}

251
static inline void task_sig(struct seq_file *m, struct task_struct *p)
L
Linus Torvalds 已提交
252
{
253
	unsigned long flags;
L
Linus Torvalds 已提交
254 255 256 257 258 259 260 261 262 263 264
	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);

265
	if (lock_task_sighand(p, &flags)) {
L
Linus Torvalds 已提交
266 267 268 269 270
		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);
271
		qsize = atomic_read(&__task_cred(p)->user->sigpending);
L
Linus Torvalds 已提交
272
		qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
273
		unlock_task_sighand(p, &flags);
L
Linus Torvalds 已提交
274 275
	}

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

	/* render them all */
280 281 282 283 284
	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 已提交
285 286
}

287 288
static void render_cap_t(struct seq_file *m, const char *header,
			kernel_cap_t *a)
289 290 291
{
	unsigned __capi;

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

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

305 306 307 308 309 310 311 312 313 314 315 316
	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 已提交
317 318
}

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

328 329
#ifdef CONFIG_MMU

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 407 408 409
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);
	}
}
410 411 412 413 414
#else
static void task_show_stack_usage(struct seq_file *m, struct task_struct *task)
{
}
#endif		/* CONFIG_MMU */
415

416 417 418 419 420 421 422 423 424 425
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");
}

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

431 432
	task_name(m, task);
	task_state(m, ns, pid, task);
433

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

450 451
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 已提交
452 453 454 455 456 457
{
	unsigned long vsize, eip, esp, wchan = ~0UL;
	long priority, nice;
	int tty_pgrp = -1, tty_nr = 0;
	sigset_t sigign, sigcatch;
	char state;
458
	pid_t ppid = 0, pgid = -1, sid = -1;
L
Linus Torvalds 已提交
459
	int num_threads = 0;
460
	int permitted;
L
Linus Torvalds 已提交
461 462 463 464
	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;
465
	cputime_t cutime, cstime, utime, stime;
466
	cputime_t cgtime, gtime;
L
Linus Torvalds 已提交
467 468
	unsigned long rsslim = 0;
	char tcomm[sizeof(task->comm)];
469
	unsigned long flags;
L
Linus Torvalds 已提交
470 471 472

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

	get_task_comm(tcomm, task);

	sigemptyset(&sigign);
	sigemptyset(&sigcatch);
487
	cutime = cstime = utime = stime = cputime_zero;
488
	cgtime = gtime = cputime_zero;
489

490 491
	if (lock_task_sighand(task, &flags)) {
		struct signal_struct *sig = task->signal;
492 493

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

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

503 504 505 506
		cmin_flt = sig->cmin_flt;
		cmaj_flt = sig->cmaj_flt;
		cutime = sig->cutime;
		cstime = sig->cstime;
507
		cgtime = sig->cgtime;
508 509
		rsslim = sig->rlim[RLIMIT_RSS].rlim_cur;

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

520 521
			min_flt += sig->min_flt;
			maj_flt += sig->maj_flt;
522
			thread_group_times(task, &utime, &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);
H
Hidetoshi Seto 已提交
539
		gtime = task->gtime;
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 && mm) ? 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
}