array.c 14.7 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
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
#include <linux/smp.h>
#include <linux/signal.h>
#include <linux/highmem.h>
#include <linux/file.h>
A
Al Viro 已提交
75
#include <linux/fdtable.h>
L
Linus Torvalds 已提交
76 77
#include <linux/times.h>
#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>
L
Linus Torvalds 已提交
84 85 86 87 88

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

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

	get_task_comm(tcomm, p);

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

/*
 * 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.
 */
M
Mike Frysinger 已提交
134
static const char * const task_state_array[] = {
135 136 137 138 139 140 141 142
	"R (running)",		/*   0 */
	"S (sleeping)",		/*   1 */
	"D (disk sleep)",	/*   2 */
	"T (stopped)",		/*   4 */
	"t (tracing stop)",	/*   8 */
	"Z (zombie)",		/*  16 */
	"X (dead)",		/*  32 */
	"x (dead)",		/*  64 */
143 144
	"K (wakekill)",		/* 128 */
	"W (waking)",		/* 256 */
L
Linus Torvalds 已提交
145 146
};

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

152 153
	BUILD_BUG_ON(1 + ilog2(TASK_STATE_MAX) != ARRAY_SIZE(task_state_array));

L
Linus Torvalds 已提交
154 155 156 157 158 159 160
	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
	tpid = 0;
	if (pid_alive(p)) {
175
		struct task_struct *tracer = ptrace_parent(p);
176 177 178
		if (tracer)
			tpid = task_pid_nr_ns(tracer, ns);
	}
179
	cred = get_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_putc(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_puts(m, 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_putc(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
		pending = p->pending.signal;
		shpending = p->signal->shared_pending.signal;
		blocked = p->blocked;
		collect_sigign_sigcatch(p, &ignored, &caught);
270
		num_threads = get_nr_threads(p);
271
		rcu_read_lock();  /* FIXME: is this correct? */
272
		qsize = atomic_read(&__task_cred(p)->user->sigpending);
273
		rcu_read_unlock();
J
Jiri Slaby 已提交
274
		qlim = task_rlimit(p, RLIMIT_SIGPENDING);
275
		unlock_task_sighand(p, &flags);
L
Linus Torvalds 已提交
276 277
	}

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

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

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

294
	seq_puts(m, header);
295
	CAP_FOR_EACH_U32(__capi) {
296
		seq_printf(m, "%08x",
297
			   a->cap[(_KERNEL_CAPABILITY_U32S-1) - __capi]);
298
	}
299
	seq_putc(m, '\n');
300 301
}

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

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

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

330 331
static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
{
332
	seq_puts(m, "Cpus_allowed:\t");
333
	seq_cpumask(m, &task->cpus_allowed);
334 335
	seq_putc(m, '\n');
	seq_puts(m, "Cpus_allowed_list:\t");
336
	seq_cpumask_list(m, &task->cpus_allowed);
337
	seq_putc(m, '\n');
338 339
}

340 341
int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
			struct pid *pid, struct task_struct *task)
L
Linus Torvalds 已提交
342 343 344
{
	struct mm_struct *mm = get_task_mm(task);

345 346
	task_name(m, task);
	task_state(m, ns, pid, task);
347

L
Linus Torvalds 已提交
348
	if (mm) {
349
		task_mem(m, mm);
L
Linus Torvalds 已提交
350 351
		mmput(mm);
	}
352 353
	task_sig(m, task);
	task_cap(m, task);
354
	task_cpus_allowed(m, task);
355 356 357
	cpuset_task_status_allowed(m, task);
	task_context_switch_counts(m, task);
	return 0;
L
Linus Torvalds 已提交
358 359
}

360 361
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 已提交
362 363 364 365 366 367
{
	unsigned long vsize, eip, esp, wchan = ~0UL;
	long priority, nice;
	int tty_pgrp = -1, tty_nr = 0;
	sigset_t sigign, sigcatch;
	char state;
368
	pid_t ppid = 0, pgid = -1, sid = -1;
L
Linus Torvalds 已提交
369
	int num_threads = 0;
370
	int permitted;
L
Linus Torvalds 已提交
371 372 373 374
	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;
375
	cputime_t cutime, cstime, utime, stime;
376
	cputime_t cgtime, gtime;
L
Linus Torvalds 已提交
377 378
	unsigned long rsslim = 0;
	char tcomm[sizeof(task->comm)];
379
	unsigned long flags;
L
Linus Torvalds 已提交
380 381 382

	state = *get_task_state(task);
	vsize = eip = esp = 0;
383
	permitted = ptrace_may_access(task, PTRACE_MODE_READ | PTRACE_MODE_NOAUDIT);
L
Linus Torvalds 已提交
384 385 386
	mm = get_task_mm(task);
	if (mm) {
		vsize = task_vsize(mm);
387 388 389 390
		if (permitted) {
			eip = KSTK_EIP(task);
			esp = KSTK_ESP(task);
		}
L
Linus Torvalds 已提交
391 392 393 394 395 396
	}

	get_task_comm(tcomm, task);

	sigemptyset(&sigign);
	sigemptyset(&sigcatch);
397 398
	cutime = cstime = utime = stime = 0;
	cgtime = gtime = 0;
399

400 401
	if (lock_task_sighand(task, &flags)) {
		struct signal_struct *sig = task->signal;
402 403

		if (sig->tty) {
404 405 406
			struct pid *pgrp = tty_get_pgrp(sig->tty);
			tty_pgrp = pid_nr_ns(pgrp, ns);
			put_pid(pgrp);
407
			tty_nr = new_encode_dev(tty_devnum(sig->tty));
408 409
		}

410
		num_threads = get_nr_threads(task);
L
Linus Torvalds 已提交
411 412
		collect_sigign_sigcatch(task, &sigign, &sigcatch);

413 414 415 416
		cmin_flt = sig->cmin_flt;
		cmaj_flt = sig->cmaj_flt;
		cutime = sig->cutime;
		cstime = sig->cstime;
417
		cgtime = sig->cgtime;
J
Jiri Slaby 已提交
418
		rsslim = ACCESS_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
419

L
Linus Torvalds 已提交
420 421
		/* add up live thread stats at the group level */
		if (whole) {
422
			struct task_struct *t = task;
L
Linus Torvalds 已提交
423 424 425
			do {
				min_flt += t->min_flt;
				maj_flt += t->maj_flt;
426
				gtime += t->gtime;
L
Linus Torvalds 已提交
427 428 429
				t = next_thread(t);
			} while (t != task);

430 431
			min_flt += sig->min_flt;
			maj_flt += sig->maj_flt;
432
			thread_group_times(task, &utime, &stime);
433
			gtime += sig->gtime;
L
Linus Torvalds 已提交
434
		}
435

436
		sid = task_session_nr_ns(task, ns);
437
		ppid = task_tgid_nr_ns(task->real_parent, ns);
438
		pgid = task_pgrp_nr_ns(task, ns);
439 440

		unlock_task_sighand(task, &flags);
L
Linus Torvalds 已提交
441 442
	}

443
	if (permitted && (!whole || num_threads < 2))
L
Linus Torvalds 已提交
444 445 446 447
		wchan = get_wchan(task);
	if (!whole) {
		min_flt = task->min_flt;
		maj_flt = task->maj_flt;
448
		task_times(task, &utime, &stime);
H
Hidetoshi Seto 已提交
449
		gtime = task->gtime;
L
Linus Torvalds 已提交
450 451 452 453 454 455 456 457 458
	}

	/* 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*/
459 460 461
	start_time =
		(unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
				+ task->real_start_time.tv_nsec;
L
Linus Torvalds 已提交
462 463 464
	/* convert nsec -> ticks */
	start_time = nsec_to_clock_t(start_time);

465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
	seq_printf(m, "%d (%s) %c", pid_nr_ns(pid, ns), tcomm, state);
	seq_put_decimal_ll(m, ' ', ppid);
	seq_put_decimal_ll(m, ' ', pgid);
	seq_put_decimal_ll(m, ' ', sid);
	seq_put_decimal_ll(m, ' ', tty_nr);
	seq_put_decimal_ll(m, ' ', tty_pgrp);
	seq_put_decimal_ull(m, ' ', task->flags);
	seq_put_decimal_ull(m, ' ', min_flt);
	seq_put_decimal_ull(m, ' ', cmin_flt);
	seq_put_decimal_ull(m, ' ', maj_flt);
	seq_put_decimal_ull(m, ' ', cmaj_flt);
	seq_put_decimal_ull(m, ' ', cputime_to_clock_t(utime));
	seq_put_decimal_ull(m, ' ', cputime_to_clock_t(stime));
	seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cutime));
	seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cstime));
	seq_put_decimal_ll(m, ' ', priority);
	seq_put_decimal_ll(m, ' ', nice);
	seq_put_decimal_ll(m, ' ', num_threads);
	seq_put_decimal_ull(m, ' ', 0);
	seq_put_decimal_ull(m, ' ', start_time);
	seq_put_decimal_ull(m, ' ', vsize);
	seq_put_decimal_ll(m, ' ', mm ? get_mm_rss(mm) : 0);
	seq_put_decimal_ull(m, ' ', rsslim);
	seq_put_decimal_ull(m, ' ', mm ? (permitted ? mm->start_code : 1) : 0);
	seq_put_decimal_ull(m, ' ', mm ? (permitted ? mm->end_code : 1) : 0);
	seq_put_decimal_ull(m, ' ', (permitted && mm) ? mm->start_stack : 0);
	seq_put_decimal_ull(m, ' ', esp);
	seq_put_decimal_ull(m, ' ', eip);
	/* The signal information here is obsolete.
	 * It must be decimal for Linux 2.0 compatibility.
	 * Use /proc/#/status for real-time signals.
	 */
	seq_put_decimal_ull(m, ' ', task->pending.signal.sig[0] & 0x7fffffffUL);
	seq_put_decimal_ull(m, ' ', task->blocked.sig[0] & 0x7fffffffUL);
	seq_put_decimal_ull(m, ' ', sigign.sig[0] & 0x7fffffffUL);
	seq_put_decimal_ull(m, ' ', sigcatch.sig[0] & 0x7fffffffUL);
	seq_put_decimal_ull(m, ' ', wchan);
	seq_put_decimal_ull(m, ' ', 0);
	seq_put_decimal_ull(m, ' ', 0);
	seq_put_decimal_ll(m, ' ', task->exit_signal);
	seq_put_decimal_ll(m, ' ', task_cpu(task));
	seq_put_decimal_ull(m, ' ', task->rt_priority);
	seq_put_decimal_ull(m, ' ', task->policy);
	seq_put_decimal_ull(m, ' ', delayacct_blkio_ticks(task));
	seq_put_decimal_ull(m, ' ', cputime_to_clock_t(gtime));
	seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cgtime));
	seq_put_decimal_ull(m, ' ', (mm && permitted) ? mm->start_data : 0);
	seq_put_decimal_ull(m, ' ', (mm && permitted) ? mm->end_data : 0);
	seq_put_decimal_ull(m, ' ', (mm && permitted) ? mm->start_brk : 0);
	seq_putc(m, '\n');
515
	if (mm)
L
Linus Torvalds 已提交
516
		mmput(mm);
517
	return 0;
L
Linus Torvalds 已提交
518 519
}

520 521
int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
			struct pid *pid, struct task_struct *task)
L
Linus Torvalds 已提交
522
{
523
	return do_task_stat(m, ns, pid, task, 0);
L
Linus Torvalds 已提交
524 525
}

526 527
int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
			struct pid *pid, struct task_struct *task)
L
Linus Torvalds 已提交
528
{
529
	return do_task_stat(m, ns, pid, task, 1);
L
Linus Torvalds 已提交
530 531
}

532 533
int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
			struct pid *pid, struct task_struct *task)
L
Linus Torvalds 已提交
534
{
535
	unsigned long size = 0, resident = 0, shared = 0, text = 0, data = 0;
L
Linus Torvalds 已提交
536
	struct mm_struct *mm = get_task_mm(task);
537

L
Linus Torvalds 已提交
538 539 540 541
	if (mm) {
		size = task_statm(mm, &shared, &text, &data, &resident);
		mmput(mm);
	}
542 543 544 545 546 547 548 549 550 551 552
	/*
	 * For quick read, open code by putting numbers directly
	 * expected format is
	 * seq_printf(m, "%lu %lu %lu %lu 0 %lu 0\n",
	 *               size, resident, shared, text, data);
	 */
	seq_put_decimal_ull(m, 0, size);
	seq_put_decimal_ull(m, ' ', resident);
	seq_put_decimal_ull(m, ' ', shared);
	seq_put_decimal_ull(m, ' ', text);
	seq_put_decimal_ull(m, ' ', 0);
K
KAMEZAWA Hiroyuki 已提交
553
	seq_put_decimal_ull(m, ' ', data);
554 555
	seq_put_decimal_ull(m, ' ', 0);
	seq_putc(m, '\n');
L
Linus Torvalds 已提交
556

557
	return 0;
L
Linus Torvalds 已提交
558
}