aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/array.c')
-rw-r--r--fs/proc/array.c163
1 files changed, 86 insertions, 77 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index b380313092bd..07d6c4853fe8 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -77,6 +77,7 @@
77#include <linux/cpuset.h> 77#include <linux/cpuset.h>
78#include <linux/rcupdate.h> 78#include <linux/rcupdate.h>
79#include <linux/delayacct.h> 79#include <linux/delayacct.h>
80#include <linux/seq_file.h>
80#include <linux/pid_namespace.h> 81#include <linux/pid_namespace.h>
81 82
82#include <asm/pgtable.h> 83#include <asm/pgtable.h>
@@ -88,18 +89,21 @@
88do { memcpy(buffer, string, strlen(string)); \ 89do { memcpy(buffer, string, strlen(string)); \
89 buffer += strlen(string); } while (0) 90 buffer += strlen(string); } while (0)
90 91
91static inline char *task_name(struct task_struct *p, char *buf) 92static inline void task_name(struct seq_file *m, struct task_struct *p)
92{ 93{
93 int i; 94 int i;
95 char *buf, *end;
94 char *name; 96 char *name;
95 char tcomm[sizeof(p->comm)]; 97 char tcomm[sizeof(p->comm)];
96 98
97 get_task_comm(tcomm, p); 99 get_task_comm(tcomm, p);
98 100
99 ADDBUF(buf, "Name:\t"); 101 seq_printf(m, "Name:\t");
102 end = m->buf + m->size;
103 buf = m->buf + m->count;
100 name = tcomm; 104 name = tcomm;
101 i = sizeof(tcomm); 105 i = sizeof(tcomm);
102 do { 106 while (i && (buf < end)) {
103 unsigned char c = *name; 107 unsigned char c = *name;
104 name++; 108 name++;
105 i--; 109 i--;
@@ -107,20 +111,21 @@ static inline char *task_name(struct task_struct *p, char *buf)
107 if (!c) 111 if (!c)
108 break; 112 break;
109 if (c == '\\') { 113 if (c == '\\') {
110 buf[1] = c; 114 buf++;
111 buf += 2; 115 if (buf < end)
116 *buf++ = c;
112 continue; 117 continue;
113 } 118 }
114 if (c == '\n') { 119 if (c == '\n') {
115 buf[0] = '\\'; 120 *buf++ = '\\';
116 buf[1] = 'n'; 121 if (buf < end)
117 buf += 2; 122 *buf++ = 'n';
118 continue; 123 continue;
119 } 124 }
120 buf++; 125 buf++;
121 } while (i); 126 }
122 *buf = '\n'; 127 m->count = buf - m->buf;
123 return buf+1; 128 seq_printf(m, "\n");
124} 129}
125 130
126/* 131/*
@@ -151,21 +156,20 @@ static inline const char *get_task_state(struct task_struct *tsk)
151 return *p; 156 return *p;
152} 157}
153 158
154static inline char *task_state(struct task_struct *p, char *buffer) 159static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
160 struct pid *pid, struct task_struct *p)
155{ 161{
156 struct group_info *group_info; 162 struct group_info *group_info;
157 int g; 163 int g;
158 struct fdtable *fdt = NULL; 164 struct fdtable *fdt = NULL;
159 struct pid_namespace *ns;
160 pid_t ppid, tpid; 165 pid_t ppid, tpid;
161 166
162 ns = current->nsproxy->pid_ns;
163 rcu_read_lock(); 167 rcu_read_lock();
164 ppid = pid_alive(p) ? 168 ppid = pid_alive(p) ?
165 task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; 169 task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
166 tpid = pid_alive(p) && p->ptrace ? 170 tpid = pid_alive(p) && p->ptrace ?
167 task_pid_nr_ns(rcu_dereference(p->parent), ns) : 0; 171 task_pid_nr_ns(rcu_dereference(p->parent), ns) : 0;
168 buffer += sprintf(buffer, 172 seq_printf(m,
169 "State:\t%s\n" 173 "State:\t%s\n"
170 "Tgid:\t%d\n" 174 "Tgid:\t%d\n"
171 "Pid:\t%d\n" 175 "Pid:\t%d\n"
@@ -175,7 +179,7 @@ static inline char *task_state(struct task_struct *p, char *buffer)
175 "Gid:\t%d\t%d\t%d\t%d\n", 179 "Gid:\t%d\t%d\t%d\t%d\n",
176 get_task_state(p), 180 get_task_state(p),
177 task_tgid_nr_ns(p, ns), 181 task_tgid_nr_ns(p, ns),
178 task_pid_nr_ns(p, ns), 182 pid_nr_ns(pid, ns),
179 ppid, tpid, 183 ppid, tpid,
180 p->uid, p->euid, p->suid, p->fsuid, 184 p->uid, p->euid, p->suid, p->fsuid,
181 p->gid, p->egid, p->sgid, p->fsgid); 185 p->gid, p->egid, p->sgid, p->fsgid);
@@ -183,7 +187,7 @@ static inline char *task_state(struct task_struct *p, char *buffer)
183 task_lock(p); 187 task_lock(p);
184 if (p->files) 188 if (p->files)
185 fdt = files_fdtable(p->files); 189 fdt = files_fdtable(p->files);
186 buffer += sprintf(buffer, 190 seq_printf(m,
187 "FDSize:\t%d\n" 191 "FDSize:\t%d\n"
188 "Groups:\t", 192 "Groups:\t",
189 fdt ? fdt->max_fds : 0); 193 fdt ? fdt->max_fds : 0);
@@ -194,20 +198,18 @@ static inline char *task_state(struct task_struct *p, char *buffer)
194 task_unlock(p); 198 task_unlock(p);
195 199
196 for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) 200 for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
197 buffer += sprintf(buffer, "%d ", GROUP_AT(group_info, g)); 201 seq_printf(m, "%d ", GROUP_AT(group_info, g));
198 put_group_info(group_info); 202 put_group_info(group_info);
199 203
200 buffer += sprintf(buffer, "\n"); 204 seq_printf(m, "\n");
201 return buffer;
202} 205}
203 206
204static char *render_sigset_t(const char *header, sigset_t *set, char *buffer) 207static void render_sigset_t(struct seq_file *m, const char *header,
208 sigset_t *set)
205{ 209{
206 int i, len; 210 int i;
207 211
208 len = strlen(header); 212 seq_printf(m, "%s", header);
209 memcpy(buffer, header, len);
210 buffer += len;
211 213
212 i = _NSIG; 214 i = _NSIG;
213 do { 215 do {
@@ -218,12 +220,10 @@ static char *render_sigset_t(const char *header, sigset_t *set, char *buffer)
218 if (sigismember(set, i+2)) x |= 2; 220 if (sigismember(set, i+2)) x |= 2;
219 if (sigismember(set, i+3)) x |= 4; 221 if (sigismember(set, i+3)) x |= 4;
220 if (sigismember(set, i+4)) x |= 8; 222 if (sigismember(set, i+4)) x |= 8;
221 *buffer++ = (x < 10 ? '0' : 'a' - 10) + x; 223 seq_printf(m, "%x", x);
222 } while (i >= 4); 224 } while (i >= 4);
223 225
224 *buffer++ = '\n'; 226 seq_printf(m, "\n");
225 *buffer = 0;
226 return buffer;
227} 227}
228 228
229static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign, 229static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
@@ -241,7 +241,7 @@ static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
241 } 241 }
242} 242}
243 243
244static inline char *task_sig(struct task_struct *p, char *buffer) 244static inline void task_sig(struct seq_file *m, struct task_struct *p)
245{ 245{
246 unsigned long flags; 246 unsigned long flags;
247 sigset_t pending, shpending, blocked, ignored, caught; 247 sigset_t pending, shpending, blocked, ignored, caught;
@@ -268,58 +268,66 @@ static inline char *task_sig(struct task_struct *p, char *buffer)
268 } 268 }
269 rcu_read_unlock(); 269 rcu_read_unlock();
270 270
271 buffer += sprintf(buffer, "Threads:\t%d\n", num_threads); 271 seq_printf(m, "Threads:\t%d\n", num_threads);
272 buffer += sprintf(buffer, "SigQ:\t%lu/%lu\n", qsize, qlim); 272 seq_printf(m, "SigQ:\t%lu/%lu\n", qsize, qlim);
273 273
274 /* render them all */ 274 /* render them all */
275 buffer = render_sigset_t("SigPnd:\t", &pending, buffer); 275 render_sigset_t(m, "SigPnd:\t", &pending);
276 buffer = render_sigset_t("ShdPnd:\t", &shpending, buffer); 276 render_sigset_t(m, "ShdPnd:\t", &shpending);
277 buffer = render_sigset_t("SigBlk:\t", &blocked, buffer); 277 render_sigset_t(m, "SigBlk:\t", &blocked);
278 buffer = render_sigset_t("SigIgn:\t", &ignored, buffer); 278 render_sigset_t(m, "SigIgn:\t", &ignored);
279 buffer = render_sigset_t("SigCgt:\t", &caught, buffer); 279 render_sigset_t(m, "SigCgt:\t", &caught);
280}
280 281
281 return buffer; 282static void render_cap_t(struct seq_file *m, const char *header,
283 kernel_cap_t *a)
284{
285 unsigned __capi;
286
287 seq_printf(m, "%s", header);
288 CAP_FOR_EACH_U32(__capi) {
289 seq_printf(m, "%08x",
290 a->cap[(_LINUX_CAPABILITY_U32S-1) - __capi]);
291 }
292 seq_printf(m, "\n");
282} 293}
283 294
284static inline char *task_cap(struct task_struct *p, char *buffer) 295static inline void task_cap(struct seq_file *m, struct task_struct *p)
285{ 296{
286 return buffer + sprintf(buffer, "CapInh:\t%016x\n" 297 render_cap_t(m, "CapInh:\t", &p->cap_inheritable);
287 "CapPrm:\t%016x\n" 298 render_cap_t(m, "CapPrm:\t", &p->cap_permitted);
288 "CapEff:\t%016x\n", 299 render_cap_t(m, "CapEff:\t", &p->cap_effective);
289 cap_t(p->cap_inheritable),
290 cap_t(p->cap_permitted),
291 cap_t(p->cap_effective));
292} 300}
293 301
294static inline char *task_context_switch_counts(struct task_struct *p, 302static inline void task_context_switch_counts(struct seq_file *m,
295 char *buffer) 303 struct task_struct *p)
296{ 304{
297 return buffer + sprintf(buffer, "voluntary_ctxt_switches:\t%lu\n" 305 seq_printf(m, "voluntary_ctxt_switches:\t%lu\n"
298 "nonvoluntary_ctxt_switches:\t%lu\n", 306 "nonvoluntary_ctxt_switches:\t%lu\n",
299 p->nvcsw, 307 p->nvcsw,
300 p->nivcsw); 308 p->nivcsw);
301} 309}
302 310
303int proc_pid_status(struct task_struct *task, char *buffer) 311int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
312 struct pid *pid, struct task_struct *task)
304{ 313{
305 char *orig = buffer;
306 struct mm_struct *mm = get_task_mm(task); 314 struct mm_struct *mm = get_task_mm(task);
307 315
308 buffer = task_name(task, buffer); 316 task_name(m, task);
309 buffer = task_state(task, buffer); 317 task_state(m, ns, pid, task);
310 318
311 if (mm) { 319 if (mm) {
312 buffer = task_mem(mm, buffer); 320 task_mem(m, mm);
313 mmput(mm); 321 mmput(mm);
314 } 322 }
315 buffer = task_sig(task, buffer); 323 task_sig(m, task);
316 buffer = task_cap(task, buffer); 324 task_cap(m, task);
317 buffer = cpuset_task_status_allowed(task, buffer); 325 cpuset_task_status_allowed(m, task);
318#if defined(CONFIG_S390) 326#if defined(CONFIG_S390)
319 buffer = task_show_regs(task, buffer); 327 task_show_regs(m, task);
320#endif 328#endif
321 buffer = task_context_switch_counts(task, buffer); 329 task_context_switch_counts(m, task);
322 return buffer - orig; 330 return 0;
323} 331}
324 332
325/* 333/*
@@ -381,14 +389,14 @@ static cputime_t task_gtime(struct task_struct *p)
381 return p->gtime; 389 return p->gtime;
382} 390}
383 391
384static int do_task_stat(struct task_struct *task, char *buffer, int whole) 392static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
393 struct pid *pid, struct task_struct *task, int whole)
385{ 394{
386 unsigned long vsize, eip, esp, wchan = ~0UL; 395 unsigned long vsize, eip, esp, wchan = ~0UL;
387 long priority, nice; 396 long priority, nice;
388 int tty_pgrp = -1, tty_nr = 0; 397 int tty_pgrp = -1, tty_nr = 0;
389 sigset_t sigign, sigcatch; 398 sigset_t sigign, sigcatch;
390 char state; 399 char state;
391 int res;
392 pid_t ppid = 0, pgid = -1, sid = -1; 400 pid_t ppid = 0, pgid = -1, sid = -1;
393 int num_threads = 0; 401 int num_threads = 0;
394 struct mm_struct *mm; 402 struct mm_struct *mm;
@@ -400,9 +408,6 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole)
400 unsigned long rsslim = 0; 408 unsigned long rsslim = 0;
401 char tcomm[sizeof(task->comm)]; 409 char tcomm[sizeof(task->comm)];
402 unsigned long flags; 410 unsigned long flags;
403 struct pid_namespace *ns;
404
405 ns = current->nsproxy->pid_ns;
406 411
407 state = *get_task_state(task); 412 state = *get_task_state(task);
408 vsize = eip = esp = 0; 413 vsize = eip = esp = 0;
@@ -489,10 +494,10 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole)
489 /* convert nsec -> ticks */ 494 /* convert nsec -> ticks */
490 start_time = nsec_to_clock_t(start_time); 495 start_time = nsec_to_clock_t(start_time);
491 496
492 res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \ 497 seq_printf(m, "%d (%s) %c %d %d %d %d %d %u %lu \
493%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ 498%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
494%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n", 499%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n",
495 task_pid_nr_ns(task, ns), 500 pid_nr_ns(pid, ns),
496 tcomm, 501 tcomm,
497 state, 502 state,
498 ppid, 503 ppid,
@@ -541,20 +546,23 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole)
541 cputime_to_clock_t(cgtime)); 546 cputime_to_clock_t(cgtime));
542 if (mm) 547 if (mm)
543 mmput(mm); 548 mmput(mm);
544 return res; 549 return 0;
545} 550}
546 551
547int proc_tid_stat(struct task_struct *task, char *buffer) 552int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
553 struct pid *pid, struct task_struct *task)
548{ 554{
549 return do_task_stat(task, buffer, 0); 555 return do_task_stat(m, ns, pid, task, 0);
550} 556}
551 557
552int proc_tgid_stat(struct task_struct *task, char *buffer) 558int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
559 struct pid *pid, struct task_struct *task)
553{ 560{
554 return do_task_stat(task, buffer, 1); 561 return do_task_stat(m, ns, pid, task, 1);
555} 562}
556 563
557int proc_pid_statm(struct task_struct *task, char *buffer) 564int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
565 struct pid *pid, struct task_struct *task)
558{ 566{
559 int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0; 567 int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0;
560 struct mm_struct *mm = get_task_mm(task); 568 struct mm_struct *mm = get_task_mm(task);
@@ -563,7 +571,8 @@ int proc_pid_statm(struct task_struct *task, char *buffer)
563 size = task_statm(mm, &shared, &text, &data, &resident); 571 size = task_statm(mm, &shared, &text, &data, &resident);
564 mmput(mm); 572 mmput(mm);
565 } 573 }
574 seq_printf(m, "%d %d %d %d %d %d %d\n",
575 size, resident, shared, text, lib, data, 0);
566 576
567 return sprintf(buffer, "%d %d %d %d %d %d %d\n", 577 return 0;
568 size, resident, shared, text, lib, data, 0);
569} 578}