aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/array.c123
-rw-r--r--fs/proc/base.c156
-rw-r--r--fs/proc/generic.c52
-rw-r--r--fs/proc/inode.c254
-rw-r--r--fs/proc/proc_misc.c7
-rw-r--r--fs/proc/proc_tty.c15
6 files changed, 460 insertions, 147 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 74f30e0c0381..965625a0977d 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -62,6 +62,8 @@
62#include <linux/mman.h> 62#include <linux/mman.h>
63#include <linux/proc_fs.h> 63#include <linux/proc_fs.h>
64#include <linux/ioport.h> 64#include <linux/ioport.h>
65#include <linux/uaccess.h>
66#include <linux/io.h>
65#include <linux/mm.h> 67#include <linux/mm.h>
66#include <linux/hugetlb.h> 68#include <linux/hugetlb.h>
67#include <linux/pagemap.h> 69#include <linux/pagemap.h>
@@ -76,9 +78,7 @@
76#include <linux/rcupdate.h> 78#include <linux/rcupdate.h>
77#include <linux/delayacct.h> 79#include <linux/delayacct.h>
78 80
79#include <asm/uaccess.h>
80#include <asm/pgtable.h> 81#include <asm/pgtable.h>
81#include <asm/io.h>
82#include <asm/processor.h> 82#include <asm/processor.h>
83#include "internal.h" 83#include "internal.h"
84 84
@@ -87,10 +87,10 @@
87do { memcpy(buffer, string, strlen(string)); \ 87do { memcpy(buffer, string, strlen(string)); \
88 buffer += strlen(string); } while (0) 88 buffer += strlen(string); } while (0)
89 89
90static inline char * task_name(struct task_struct *p, char * buf) 90static inline char *task_name(struct task_struct *p, char *buf)
91{ 91{
92 int i; 92 int i;
93 char * name; 93 char *name;
94 char tcomm[sizeof(p->comm)]; 94 char tcomm[sizeof(p->comm)];
95 95
96 get_task_comm(tcomm, p); 96 get_task_comm(tcomm, p);
@@ -138,7 +138,7 @@ static const char *task_state_array[] = {
138 "X (dead)" /* 32 */ 138 "X (dead)" /* 32 */
139}; 139};
140 140
141static inline const char * get_task_state(struct task_struct *tsk) 141static inline const char *get_task_state(struct task_struct *tsk)
142{ 142{
143 unsigned int state = (tsk->state & (TASK_RUNNING | 143 unsigned int state = (tsk->state & (TASK_RUNNING |
144 TASK_INTERRUPTIBLE | 144 TASK_INTERRUPTIBLE |
@@ -156,7 +156,7 @@ static inline const char * get_task_state(struct task_struct *tsk)
156 return *p; 156 return *p;
157} 157}
158 158
159static inline char * task_state(struct task_struct *p, char *buffer) 159static inline char *task_state(struct task_struct *p, char *buffer)
160{ 160{
161 struct group_info *group_info; 161 struct group_info *group_info;
162 int g; 162 int g;
@@ -165,7 +165,6 @@ static inline char * task_state(struct task_struct *p, char *buffer)
165 rcu_read_lock(); 165 rcu_read_lock();
166 buffer += sprintf(buffer, 166 buffer += sprintf(buffer,
167 "State:\t%s\n" 167 "State:\t%s\n"
168 "SleepAVG:\t%lu%%\n"
169 "Tgid:\t%d\n" 168 "Tgid:\t%d\n"
170 "Pid:\t%d\n" 169 "Pid:\t%d\n"
171 "PPid:\t%d\n" 170 "PPid:\t%d\n"
@@ -173,9 +172,8 @@ static inline char * task_state(struct task_struct *p, char *buffer)
173 "Uid:\t%d\t%d\t%d\t%d\n" 172 "Uid:\t%d\t%d\t%d\t%d\n"
174 "Gid:\t%d\t%d\t%d\t%d\n", 173 "Gid:\t%d\t%d\t%d\t%d\n",
175 get_task_state(p), 174 get_task_state(p),
176 (p->sleep_avg/1024)*100/(1020000000/1024), 175 p->tgid, p->pid,
177 p->tgid, p->pid, 176 pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
178 pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
179 pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0, 177 pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
180 p->uid, p->euid, p->suid, p->fsuid, 178 p->uid, p->euid, p->suid, p->fsuid,
181 p->gid, p->egid, p->sgid, p->fsgid); 179 p->gid, p->egid, p->sgid, p->fsgid);
@@ -193,15 +191,15 @@ static inline char * task_state(struct task_struct *p, char *buffer)
193 get_group_info(group_info); 191 get_group_info(group_info);
194 task_unlock(p); 192 task_unlock(p);
195 193
196 for (g = 0; g < min(group_info->ngroups,NGROUPS_SMALL); g++) 194 for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
197 buffer += sprintf(buffer, "%d ", GROUP_AT(group_info,g)); 195 buffer += sprintf(buffer, "%d ", GROUP_AT(group_info, g));
198 put_group_info(group_info); 196 put_group_info(group_info);
199 197
200 buffer += sprintf(buffer, "\n"); 198 buffer += sprintf(buffer, "\n");
201 return buffer; 199 return buffer;
202} 200}
203 201
204static char * render_sigset_t(const char *header, sigset_t *set, char *buffer) 202static char *render_sigset_t(const char *header, sigset_t *set, char *buffer)
205{ 203{
206 int i, len; 204 int i, len;
207 205
@@ -241,7 +239,7 @@ static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
241 } 239 }
242} 240}
243 241
244static inline char * task_sig(struct task_struct *p, char *buffer) 242static inline char *task_sig(struct task_struct *p, char *buffer)
245{ 243{
246 unsigned long flags; 244 unsigned long flags;
247 sigset_t pending, shpending, blocked, ignored, caught; 245 sigset_t pending, shpending, blocked, ignored, caught;
@@ -291,14 +289,23 @@ static inline char *task_cap(struct task_struct *p, char *buffer)
291 cap_t(p->cap_effective)); 289 cap_t(p->cap_effective));
292} 290}
293 291
294int proc_pid_status(struct task_struct *task, char * buffer) 292static inline char *task_context_switch_counts(struct task_struct *p,
293 char *buffer)
295{ 294{
296 char * orig = buffer; 295 return buffer + sprintf(buffer, "voluntary_ctxt_switches:\t%lu\n"
296 "nonvoluntary_ctxt_switches:\t%lu\n",
297 p->nvcsw,
298 p->nivcsw);
299}
300
301int proc_pid_status(struct task_struct *task, char *buffer)
302{
303 char *orig = buffer;
297 struct mm_struct *mm = get_task_mm(task); 304 struct mm_struct *mm = get_task_mm(task);
298 305
299 buffer = task_name(task, buffer); 306 buffer = task_name(task, buffer);
300 buffer = task_state(task, buffer); 307 buffer = task_state(task, buffer);
301 308
302 if (mm) { 309 if (mm) {
303 buffer = task_mem(mm, buffer); 310 buffer = task_mem(mm, buffer);
304 mmput(mm); 311 mmput(mm);
@@ -309,10 +316,45 @@ int proc_pid_status(struct task_struct *task, char * buffer)
309#if defined(CONFIG_S390) 316#if defined(CONFIG_S390)
310 buffer = task_show_regs(task, buffer); 317 buffer = task_show_regs(task, buffer);
311#endif 318#endif
319 buffer = task_context_switch_counts(task, buffer);
312 return buffer - orig; 320 return buffer - orig;
313} 321}
314 322
315static int do_task_stat(struct task_struct *task, char * buffer, int whole) 323static clock_t task_utime(struct task_struct *p)
324{
325 clock_t utime = cputime_to_clock_t(p->utime),
326 total = utime + cputime_to_clock_t(p->stime);
327 u64 temp;
328
329 /*
330 * Use CFS's precise accounting:
331 */
332 temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime);
333
334 if (total) {
335 temp *= utime;
336 do_div(temp, total);
337 }
338 utime = (clock_t)temp;
339
340 return utime;
341}
342
343static clock_t task_stime(struct task_struct *p)
344{
345 clock_t stime;
346
347 /*
348 * Use CFS's precise accounting. (we subtract utime from
349 * the total, to make sure the total observed by userspace
350 * grows monotonically - apps rely on that):
351 */
352 stime = nsec_to_clock_t(p->se.sum_exec_runtime) - task_utime(p);
353
354 return stime;
355}
356
357static int do_task_stat(struct task_struct *task, char *buffer, int whole)
316{ 358{
317 unsigned long vsize, eip, esp, wchan = ~0UL; 359 unsigned long vsize, eip, esp, wchan = ~0UL;
318 long priority, nice; 360 long priority, nice;
@@ -320,13 +362,14 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
320 sigset_t sigign, sigcatch; 362 sigset_t sigign, sigcatch;
321 char state; 363 char state;
322 int res; 364 int res;
323 pid_t ppid = 0, pgid = -1, sid = -1; 365 pid_t ppid = 0, pgid = -1, sid = -1;
324 int num_threads = 0; 366 int num_threads = 0;
325 struct mm_struct *mm; 367 struct mm_struct *mm;
326 unsigned long long start_time; 368 unsigned long long start_time;
327 unsigned long cmin_flt = 0, cmaj_flt = 0; 369 unsigned long cmin_flt = 0, cmaj_flt = 0;
328 unsigned long min_flt = 0, maj_flt = 0; 370 unsigned long min_flt = 0, maj_flt = 0;
329 cputime_t cutime, cstime, utime, stime; 371 cputime_t cutime, cstime;
372 clock_t utime, stime;
330 unsigned long rsslim = 0; 373 unsigned long rsslim = 0;
331 char tcomm[sizeof(task->comm)]; 374 char tcomm[sizeof(task->comm)];
332 unsigned long flags; 375 unsigned long flags;
@@ -344,7 +387,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
344 387
345 sigemptyset(&sigign); 388 sigemptyset(&sigign);
346 sigemptyset(&sigcatch); 389 sigemptyset(&sigcatch);
347 cutime = cstime = utime = stime = cputime_zero; 390 cutime = cstime = cputime_zero;
391 utime = stime = 0;
348 392
349 rcu_read_lock(); 393 rcu_read_lock();
350 if (lock_task_sighand(task, &flags)) { 394 if (lock_task_sighand(task, &flags)) {
@@ -370,15 +414,15 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
370 do { 414 do {
371 min_flt += t->min_flt; 415 min_flt += t->min_flt;
372 maj_flt += t->maj_flt; 416 maj_flt += t->maj_flt;
373 utime = cputime_add(utime, t->utime); 417 utime += task_utime(t);
374 stime = cputime_add(stime, t->stime); 418 stime += task_stime(t);
375 t = next_thread(t); 419 t = next_thread(t);
376 } while (t != task); 420 } while (t != task);
377 421
378 min_flt += sig->min_flt; 422 min_flt += sig->min_flt;
379 maj_flt += sig->maj_flt; 423 maj_flt += sig->maj_flt;
380 utime = cputime_add(utime, sig->utime); 424 utime += cputime_to_clock_t(sig->utime);
381 stime = cputime_add(stime, sig->stime); 425 stime += cputime_to_clock_t(sig->stime);
382 } 426 }
383 427
384 sid = signal_session(sig); 428 sid = signal_session(sig);
@@ -389,13 +433,13 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
389 } 433 }
390 rcu_read_unlock(); 434 rcu_read_unlock();
391 435
392 if (!whole || num_threads<2) 436 if (!whole || num_threads < 2)
393 wchan = get_wchan(task); 437 wchan = get_wchan(task);
394 if (!whole) { 438 if (!whole) {
395 min_flt = task->min_flt; 439 min_flt = task->min_flt;
396 maj_flt = task->maj_flt; 440 maj_flt = task->maj_flt;
397 utime = task->utime; 441 utime = task_utime(task);
398 stime = task->stime; 442 stime = task_stime(task);
399 } 443 }
400 444
401 /* scale priority and nice values from timeslices to -20..20 */ 445 /* scale priority and nice values from timeslices to -20..20 */
@@ -405,12 +449,13 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
405 449
406 /* Temporary variable needed for gcc-2.96 */ 450 /* Temporary variable needed for gcc-2.96 */
407 /* convert timespec -> nsec*/ 451 /* convert timespec -> nsec*/
408 start_time = (unsigned long long)task->start_time.tv_sec * NSEC_PER_SEC 452 start_time =
409 + task->start_time.tv_nsec; 453 (unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
454 + task->real_start_time.tv_nsec;
410 /* convert nsec -> ticks */ 455 /* convert nsec -> ticks */
411 start_time = nsec_to_clock_t(start_time); 456 start_time = nsec_to_clock_t(start_time);
412 457
413 res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %lu \ 458 res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \
414%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ 459%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
415%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu\n", 460%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu\n",
416 task->pid, 461 task->pid,
@@ -426,8 +471,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
426 cmin_flt, 471 cmin_flt,
427 maj_flt, 472 maj_flt,
428 cmaj_flt, 473 cmaj_flt,
429 cputime_to_clock_t(utime), 474 utime,
430 cputime_to_clock_t(stime), 475 stime,
431 cputime_to_clock_t(cutime), 476 cputime_to_clock_t(cutime),
432 cputime_to_clock_t(cstime), 477 cputime_to_clock_t(cstime),
433 priority, 478 priority,
@@ -436,7 +481,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
436 start_time, 481 start_time,
437 vsize, 482 vsize,
438 mm ? get_mm_rss(mm) : 0, 483 mm ? get_mm_rss(mm) : 0,
439 rsslim, 484 rsslim,
440 mm ? mm->start_code : 0, 485 mm ? mm->start_code : 0,
441 mm ? mm->end_code : 0, 486 mm ? mm->end_code : 0,
442 mm ? mm->start_stack : 0, 487 mm ? mm->start_stack : 0,
@@ -458,17 +503,17 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
458 task->rt_priority, 503 task->rt_priority,
459 task->policy, 504 task->policy,
460 (unsigned long long)delayacct_blkio_ticks(task)); 505 (unsigned long long)delayacct_blkio_ticks(task));
461 if(mm) 506 if (mm)
462 mmput(mm); 507 mmput(mm);
463 return res; 508 return res;
464} 509}
465 510
466int proc_tid_stat(struct task_struct *task, char * buffer) 511int proc_tid_stat(struct task_struct *task, char *buffer)
467{ 512{
468 return do_task_stat(task, buffer, 0); 513 return do_task_stat(task, buffer, 0);
469} 514}
470 515
471int proc_tgid_stat(struct task_struct *task, char * buffer) 516int proc_tgid_stat(struct task_struct *task, char *buffer)
472{ 517{
473 return do_task_stat(task, buffer, 1); 518 return do_task_stat(task, buffer, 1);
474} 519}
@@ -477,12 +522,12 @@ int proc_pid_statm(struct task_struct *task, char *buffer)
477{ 522{
478 int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0; 523 int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0;
479 struct mm_struct *mm = get_task_mm(task); 524 struct mm_struct *mm = get_task_mm(task);
480 525
481 if (mm) { 526 if (mm) {
482 size = task_statm(mm, &shared, &text, &data, &resident); 527 size = task_statm(mm, &shared, &text, &data, &resident);
483 mmput(mm); 528 mmput(mm);
484 } 529 }
485 530
486 return sprintf(buffer,"%d %d %d %d %d %d %d\n", 531 return sprintf(buffer, "%d %d %d %d %d %d %d\n",
487 size, resident, shared, text, lib, data, 0); 532 size, resident, shared, text, lib, data, 0);
488} 533}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a5fa1fdafc4e..42cb4f5613b6 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -67,7 +67,6 @@
67#include <linux/mount.h> 67#include <linux/mount.h>
68#include <linux/security.h> 68#include <linux/security.h>
69#include <linux/ptrace.h> 69#include <linux/ptrace.h>
70#include <linux/seccomp.h>
71#include <linux/cpuset.h> 70#include <linux/cpuset.h>
72#include <linux/audit.h> 71#include <linux/audit.h>
73#include <linux/poll.h> 72#include <linux/poll.h>
@@ -204,12 +203,17 @@ static int proc_pid_environ(struct task_struct *task, char * buffer)
204 int res = 0; 203 int res = 0;
205 struct mm_struct *mm = get_task_mm(task); 204 struct mm_struct *mm = get_task_mm(task);
206 if (mm) { 205 if (mm) {
207 unsigned int len = mm->env_end - mm->env_start; 206 unsigned int len;
207
208 res = -ESRCH;
209 if (!ptrace_may_attach(task))
210 goto out;
211
212 len = mm->env_end - mm->env_start;
208 if (len > PAGE_SIZE) 213 if (len > PAGE_SIZE)
209 len = PAGE_SIZE; 214 len = PAGE_SIZE;
210 res = access_process_vm(task, mm->env_start, buffer, len, 0); 215 res = access_process_vm(task, mm->env_start, buffer, len, 0);
211 if (!ptrace_may_attach(task)) 216out:
212 res = -ESRCH;
213 mmput(mm); 217 mmput(mm);
214 } 218 }
215 return res; 219 return res;
@@ -279,7 +283,7 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer)
279static int proc_pid_wchan(struct task_struct *task, char *buffer) 283static int proc_pid_wchan(struct task_struct *task, char *buffer)
280{ 284{
281 unsigned long wchan; 285 unsigned long wchan;
282 char symname[KSYM_NAME_LEN+1]; 286 char symname[KSYM_NAME_LEN];
283 287
284 wchan = get_wchan(task); 288 wchan = get_wchan(task);
285 289
@@ -296,7 +300,7 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
296 */ 300 */
297static int proc_pid_schedstat(struct task_struct *task, char *buffer) 301static int proc_pid_schedstat(struct task_struct *task, char *buffer)
298{ 302{
299 return sprintf(buffer, "%lu %lu %lu\n", 303 return sprintf(buffer, "%llu %llu %lu\n",
300 task->sched_info.cpu_time, 304 task->sched_info.cpu_time,
301 task->sched_info.run_delay, 305 task->sched_info.run_delay,
302 task->sched_info.pcnt); 306 task->sched_info.pcnt);
@@ -812,71 +816,6 @@ static const struct file_operations proc_loginuid_operations = {
812}; 816};
813#endif 817#endif
814 818
815#ifdef CONFIG_SECCOMP
816static ssize_t seccomp_read(struct file *file, char __user *buf,
817 size_t count, loff_t *ppos)
818{
819 struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
820 char __buf[20];
821 size_t len;
822
823 if (!tsk)
824 return -ESRCH;
825 /* no need to print the trailing zero, so use only len */
826 len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
827 put_task_struct(tsk);
828
829 return simple_read_from_buffer(buf, count, ppos, __buf, len);
830}
831
832static ssize_t seccomp_write(struct file *file, const char __user *buf,
833 size_t count, loff_t *ppos)
834{
835 struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
836 char __buf[20], *end;
837 unsigned int seccomp_mode;
838 ssize_t result;
839
840 result = -ESRCH;
841 if (!tsk)
842 goto out_no_task;
843
844 /* can set it only once to be even more secure */
845 result = -EPERM;
846 if (unlikely(tsk->seccomp.mode))
847 goto out;
848
849 result = -EFAULT;
850 memset(__buf, 0, sizeof(__buf));
851 count = min(count, sizeof(__buf) - 1);
852 if (copy_from_user(__buf, buf, count))
853 goto out;
854
855 seccomp_mode = simple_strtoul(__buf, &end, 0);
856 if (*end == '\n')
857 end++;
858 result = -EINVAL;
859 if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
860 tsk->seccomp.mode = seccomp_mode;
861 set_tsk_thread_flag(tsk, TIF_SECCOMP);
862 } else
863 goto out;
864 result = -EIO;
865 if (unlikely(!(end - __buf)))
866 goto out;
867 result = end - __buf;
868out:
869 put_task_struct(tsk);
870out_no_task:
871 return result;
872}
873
874static const struct file_operations proc_seccomp_operations = {
875 .read = seccomp_read,
876 .write = seccomp_write,
877};
878#endif /* CONFIG_SECCOMP */
879
880#ifdef CONFIG_FAULT_INJECTION 819#ifdef CONFIG_FAULT_INJECTION
881static ssize_t proc_fault_inject_read(struct file * file, char __user * buf, 820static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
882 size_t count, loff_t *ppos) 821 size_t count, loff_t *ppos)
@@ -929,6 +868,69 @@ static const struct file_operations proc_fault_inject_operations = {
929}; 868};
930#endif 869#endif
931 870
871#ifdef CONFIG_SCHED_DEBUG
872/*
873 * Print out various scheduling related per-task fields:
874 */
875static int sched_show(struct seq_file *m, void *v)
876{
877 struct inode *inode = m->private;
878 struct task_struct *p;
879
880 WARN_ON(!inode);
881
882 p = get_proc_task(inode);
883 if (!p)
884 return -ESRCH;
885 proc_sched_show_task(p, m);
886
887 put_task_struct(p);
888
889 return 0;
890}
891
892static ssize_t
893sched_write(struct file *file, const char __user *buf,
894 size_t count, loff_t *offset)
895{
896 struct inode *inode = file->f_path.dentry->d_inode;
897 struct task_struct *p;
898
899 WARN_ON(!inode);
900
901 p = get_proc_task(inode);
902 if (!p)
903 return -ESRCH;
904 proc_sched_set_task(p);
905
906 put_task_struct(p);
907
908 return count;
909}
910
911static int sched_open(struct inode *inode, struct file *filp)
912{
913 int ret;
914
915 ret = single_open(filp, sched_show, NULL);
916 if (!ret) {
917 struct seq_file *m = filp->private_data;
918
919 m->private = inode;
920 }
921 return ret;
922}
923
924static const struct file_operations proc_pid_sched_operations = {
925 .open = sched_open,
926 .read = seq_read,
927 .write = sched_write,
928 .llseek = seq_lseek,
929 .release = seq_release,
930};
931
932#endif
933
932static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) 934static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
933{ 935{
934 struct inode *inode = dentry->d_inode; 936 struct inode *inode = dentry->d_inode;
@@ -1963,6 +1965,9 @@ static const struct pid_entry tgid_base_stuff[] = {
1963 INF("environ", S_IRUSR, pid_environ), 1965 INF("environ", S_IRUSR, pid_environ),
1964 INF("auxv", S_IRUSR, pid_auxv), 1966 INF("auxv", S_IRUSR, pid_auxv),
1965 INF("status", S_IRUGO, pid_status), 1967 INF("status", S_IRUGO, pid_status),
1968#ifdef CONFIG_SCHED_DEBUG
1969 REG("sched", S_IRUGO|S_IWUSR, pid_sched),
1970#endif
1966 INF("cmdline", S_IRUGO, pid_cmdline), 1971 INF("cmdline", S_IRUGO, pid_cmdline),
1967 INF("stat", S_IRUGO, tgid_stat), 1972 INF("stat", S_IRUGO, tgid_stat),
1968 INF("statm", S_IRUGO, pid_statm), 1973 INF("statm", S_IRUGO, pid_statm),
@@ -1971,9 +1976,6 @@ static const struct pid_entry tgid_base_stuff[] = {
1971 REG("numa_maps", S_IRUGO, numa_maps), 1976 REG("numa_maps", S_IRUGO, numa_maps),
1972#endif 1977#endif
1973 REG("mem", S_IRUSR|S_IWUSR, mem), 1978 REG("mem", S_IRUSR|S_IWUSR, mem),
1974#ifdef CONFIG_SECCOMP
1975 REG("seccomp", S_IRUSR|S_IWUSR, seccomp),
1976#endif
1977 LNK("cwd", cwd), 1979 LNK("cwd", cwd),
1978 LNK("root", root), 1980 LNK("root", root),
1979 LNK("exe", exe), 1981 LNK("exe", exe),
@@ -2247,6 +2249,9 @@ static const struct pid_entry tid_base_stuff[] = {
2247 INF("environ", S_IRUSR, pid_environ), 2249 INF("environ", S_IRUSR, pid_environ),
2248 INF("auxv", S_IRUSR, pid_auxv), 2250 INF("auxv", S_IRUSR, pid_auxv),
2249 INF("status", S_IRUGO, pid_status), 2251 INF("status", S_IRUGO, pid_status),
2252#ifdef CONFIG_SCHED_DEBUG
2253 REG("sched", S_IRUGO|S_IWUSR, pid_sched),
2254#endif
2250 INF("cmdline", S_IRUGO, pid_cmdline), 2255 INF("cmdline", S_IRUGO, pid_cmdline),
2251 INF("stat", S_IRUGO, tid_stat), 2256 INF("stat", S_IRUGO, tid_stat),
2252 INF("statm", S_IRUGO, pid_statm), 2257 INF("statm", S_IRUGO, pid_statm),
@@ -2255,9 +2260,6 @@ static const struct pid_entry tid_base_stuff[] = {
2255 REG("numa_maps", S_IRUGO, numa_maps), 2260 REG("numa_maps", S_IRUGO, numa_maps),
2256#endif 2261#endif
2257 REG("mem", S_IRUSR|S_IWUSR, mem), 2262 REG("mem", S_IRUSR|S_IWUSR, mem),
2258#ifdef CONFIG_SECCOMP
2259 REG("seccomp", S_IRUSR|S_IWUSR, seccomp),
2260#endif
2261 LNK("cwd", cwd), 2263 LNK("cwd", cwd),
2262 LNK("root", root), 2264 LNK("root", root),
2263 LNK("exe", exe), 2265 LNK("exe", exe),
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 8a40e15f5ecb..b5e7155d30d8 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -20,6 +20,7 @@
20#include <linux/namei.h> 20#include <linux/namei.h>
21#include <linux/bitops.h> 21#include <linux/bitops.h>
22#include <linux/spinlock.h> 22#include <linux/spinlock.h>
23#include <linux/completion.h>
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24 25
25#include "internal.h" 26#include "internal.h"
@@ -529,12 +530,6 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
529 return -EAGAIN; 530 return -EAGAIN;
530 dp->low_ino = i; 531 dp->low_ino = i;
531 532
532 spin_lock(&proc_subdir_lock);
533 dp->next = dir->subdir;
534 dp->parent = dir;
535 dir->subdir = dp;
536 spin_unlock(&proc_subdir_lock);
537
538 if (S_ISDIR(dp->mode)) { 533 if (S_ISDIR(dp->mode)) {
539 if (dp->proc_iops == NULL) { 534 if (dp->proc_iops == NULL) {
540 dp->proc_fops = &proc_dir_operations; 535 dp->proc_fops = &proc_dir_operations;
@@ -550,6 +545,13 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
550 if (dp->proc_iops == NULL) 545 if (dp->proc_iops == NULL)
551 dp->proc_iops = &proc_file_inode_operations; 546 dp->proc_iops = &proc_file_inode_operations;
552 } 547 }
548
549 spin_lock(&proc_subdir_lock);
550 dp->next = dir->subdir;
551 dp->parent = dir;
552 dir->subdir = dp;
553 spin_unlock(&proc_subdir_lock);
554
553 return 0; 555 return 0;
554} 556}
555 557
@@ -613,6 +615,9 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent,
613 ent->namelen = len; 615 ent->namelen = len;
614 ent->mode = mode; 616 ent->mode = mode;
615 ent->nlink = nlink; 617 ent->nlink = nlink;
618 ent->pde_users = 0;
619 spin_lock_init(&ent->pde_unload_lock);
620 ent->pde_unload_completion = NULL;
616 out: 621 out:
617 return ent; 622 return ent;
618} 623}
@@ -649,9 +654,6 @@ struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
649 654
650 ent = proc_create(&parent, name, S_IFDIR | mode, 2); 655 ent = proc_create(&parent, name, S_IFDIR | mode, 2);
651 if (ent) { 656 if (ent) {
652 ent->proc_fops = &proc_dir_operations;
653 ent->proc_iops = &proc_dir_inode_operations;
654
655 if (proc_register(parent, ent) < 0) { 657 if (proc_register(parent, ent) < 0) {
656 kfree(ent); 658 kfree(ent);
657 ent = NULL; 659 ent = NULL;
@@ -686,10 +688,6 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
686 688
687 ent = proc_create(&parent,name,mode,nlink); 689 ent = proc_create(&parent,name,mode,nlink);
688 if (ent) { 690 if (ent) {
689 if (S_ISDIR(mode)) {
690 ent->proc_fops = &proc_dir_operations;
691 ent->proc_iops = &proc_dir_inode_operations;
692 }
693 if (proc_register(parent, ent) < 0) { 691 if (proc_register(parent, ent) < 0) {
694 kfree(ent); 692 kfree(ent);
695 ent = NULL; 693 ent = NULL;
@@ -734,9 +732,35 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
734 de = *p; 732 de = *p;
735 *p = de->next; 733 *p = de->next;
736 de->next = NULL; 734 de->next = NULL;
735
736 spin_lock(&de->pde_unload_lock);
737 /*
738 * Stop accepting new callers into module. If you're
739 * dynamically allocating ->proc_fops, save a pointer somewhere.
740 */
741 de->proc_fops = NULL;
742 /* Wait until all existing callers into module are done. */
743 if (de->pde_users > 0) {
744 DECLARE_COMPLETION_ONSTACK(c);
745
746 if (!de->pde_unload_completion)
747 de->pde_unload_completion = &c;
748
749 spin_unlock(&de->pde_unload_lock);
750 spin_unlock(&proc_subdir_lock);
751
752 wait_for_completion(de->pde_unload_completion);
753
754 spin_lock(&proc_subdir_lock);
755 goto continue_removing;
756 }
757 spin_unlock(&de->pde_unload_lock);
758
759continue_removing:
737 if (S_ISDIR(de->mode)) 760 if (S_ISDIR(de->mode))
738 parent->nlink--; 761 parent->nlink--;
739 proc_kill_inodes(de); 762 if (!S_ISREG(de->mode))
763 proc_kill_inodes(de);
740 de->nlink = 0; 764 de->nlink = 0;
741 WARN_ON(de->subdir); 765 WARN_ON(de->subdir);
742 if (!atomic_read(&de->count)) 766 if (!atomic_read(&de->count))
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index d5ce65c68d7b..dd28e86ab422 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -10,6 +10,7 @@
10#include <linux/mm.h> 10#include <linux/mm.h>
11#include <linux/string.h> 11#include <linux/string.h>
12#include <linux/stat.h> 12#include <linux/stat.h>
13#include <linux/completion.h>
13#include <linux/file.h> 14#include <linux/file.h>
14#include <linux/limits.h> 15#include <linux/limits.h>
15#include <linux/init.h> 16#include <linux/init.h>
@@ -140,6 +141,251 @@ static const struct super_operations proc_sops = {
140 .remount_fs = proc_remount, 141 .remount_fs = proc_remount,
141}; 142};
142 143
144static void pde_users_dec(struct proc_dir_entry *pde)
145{
146 spin_lock(&pde->pde_unload_lock);
147 pde->pde_users--;
148 if (pde->pde_unload_completion && pde->pde_users == 0)
149 complete(pde->pde_unload_completion);
150 spin_unlock(&pde->pde_unload_lock);
151}
152
153static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
154{
155 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
156 loff_t rv = -EINVAL;
157 loff_t (*llseek)(struct file *, loff_t, int);
158
159 spin_lock(&pde->pde_unload_lock);
160 /*
161 * remove_proc_entry() is going to delete PDE (as part of module
162 * cleanup sequence). No new callers into module allowed.
163 */
164 if (!pde->proc_fops) {
165 spin_unlock(&pde->pde_unload_lock);
166 return rv;
167 }
168 /*
169 * Bump refcount so that remove_proc_entry will wail for ->llseek to
170 * complete.
171 */
172 pde->pde_users++;
173 /*
174 * Save function pointer under lock, to protect against ->proc_fops
175 * NULL'ifying right after ->pde_unload_lock is dropped.
176 */
177 llseek = pde->proc_fops->llseek;
178 spin_unlock(&pde->pde_unload_lock);
179
180 if (!llseek)
181 llseek = default_llseek;
182 rv = llseek(file, offset, whence);
183
184 pde_users_dec(pde);
185 return rv;
186}
187
188static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
189{
190 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
191 ssize_t rv = -EIO;
192 ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
193
194 spin_lock(&pde->pde_unload_lock);
195 if (!pde->proc_fops) {
196 spin_unlock(&pde->pde_unload_lock);
197 return rv;
198 }
199 pde->pde_users++;
200 read = pde->proc_fops->read;
201 spin_unlock(&pde->pde_unload_lock);
202
203 if (read)
204 rv = read(file, buf, count, ppos);
205
206 pde_users_dec(pde);
207 return rv;
208}
209
210static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
211{
212 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
213 ssize_t rv = -EIO;
214 ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
215
216 spin_lock(&pde->pde_unload_lock);
217 if (!pde->proc_fops) {
218 spin_unlock(&pde->pde_unload_lock);
219 return rv;
220 }
221 pde->pde_users++;
222 write = pde->proc_fops->write;
223 spin_unlock(&pde->pde_unload_lock);
224
225 if (write)
226 rv = write(file, buf, count, ppos);
227
228 pde_users_dec(pde);
229 return rv;
230}
231
232static unsigned int proc_reg_poll(struct file *file, struct poll_table_struct *pts)
233{
234 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
235 unsigned int rv = 0;
236 unsigned int (*poll)(struct file *, struct poll_table_struct *);
237
238 spin_lock(&pde->pde_unload_lock);
239 if (!pde->proc_fops) {
240 spin_unlock(&pde->pde_unload_lock);
241 return rv;
242 }
243 pde->pde_users++;
244 poll = pde->proc_fops->poll;
245 spin_unlock(&pde->pde_unload_lock);
246
247 if (poll)
248 rv = poll(file, pts);
249
250 pde_users_dec(pde);
251 return rv;
252}
253
254static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
255{
256 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
257 long rv = -ENOTTY;
258 long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
259 int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);
260
261 spin_lock(&pde->pde_unload_lock);
262 if (!pde->proc_fops) {
263 spin_unlock(&pde->pde_unload_lock);
264 return rv;
265 }
266 pde->pde_users++;
267 unlocked_ioctl = pde->proc_fops->unlocked_ioctl;
268 ioctl = pde->proc_fops->ioctl;
269 spin_unlock(&pde->pde_unload_lock);
270
271 if (unlocked_ioctl) {
272 rv = unlocked_ioctl(file, cmd, arg);
273 if (rv == -ENOIOCTLCMD)
274 rv = -EINVAL;
275 } else if (ioctl) {
276 lock_kernel();
277 rv = ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
278 unlock_kernel();
279 }
280
281 pde_users_dec(pde);
282 return rv;
283}
284
285#ifdef CONFIG_COMPAT
286static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
287{
288 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
289 long rv = -ENOTTY;
290 long (*compat_ioctl)(struct file *, unsigned int, unsigned long);
291
292 spin_lock(&pde->pde_unload_lock);
293 if (!pde->proc_fops) {
294 spin_unlock(&pde->pde_unload_lock);
295 return rv;
296 }
297 pde->pde_users++;
298 compat_ioctl = pde->proc_fops->compat_ioctl;
299 spin_unlock(&pde->pde_unload_lock);
300
301 if (compat_ioctl)
302 rv = compat_ioctl(file, cmd, arg);
303
304 pde_users_dec(pde);
305 return rv;
306}
307#endif
308
309static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
310{
311 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
312 int rv = -EIO;
313 int (*mmap)(struct file *, struct vm_area_struct *);
314
315 spin_lock(&pde->pde_unload_lock);
316 if (!pde->proc_fops) {
317 spin_unlock(&pde->pde_unload_lock);
318 return rv;
319 }
320 pde->pde_users++;
321 mmap = pde->proc_fops->mmap;
322 spin_unlock(&pde->pde_unload_lock);
323
324 if (mmap)
325 rv = mmap(file, vma);
326
327 pde_users_dec(pde);
328 return rv;
329}
330
331static int proc_reg_open(struct inode *inode, struct file *file)
332{
333 struct proc_dir_entry *pde = PDE(inode);
334 int rv = 0;
335 int (*open)(struct inode *, struct file *);
336
337 spin_lock(&pde->pde_unload_lock);
338 if (!pde->proc_fops) {
339 spin_unlock(&pde->pde_unload_lock);
340 return rv;
341 }
342 pde->pde_users++;
343 open = pde->proc_fops->open;
344 spin_unlock(&pde->pde_unload_lock);
345
346 if (open)
347 rv = open(inode, file);
348
349 pde_users_dec(pde);
350 return rv;
351}
352
353static int proc_reg_release(struct inode *inode, struct file *file)
354{
355 struct proc_dir_entry *pde = PDE(inode);
356 int rv = 0;
357 int (*release)(struct inode *, struct file *);
358
359 spin_lock(&pde->pde_unload_lock);
360 if (!pde->proc_fops) {
361 spin_unlock(&pde->pde_unload_lock);
362 return rv;
363 }
364 pde->pde_users++;
365 release = pde->proc_fops->release;
366 spin_unlock(&pde->pde_unload_lock);
367
368 if (release)
369 rv = release(inode, file);
370
371 pde_users_dec(pde);
372 return rv;
373}
374
375static const struct file_operations proc_reg_file_ops = {
376 .llseek = proc_reg_llseek,
377 .read = proc_reg_read,
378 .write = proc_reg_write,
379 .poll = proc_reg_poll,
380 .unlocked_ioctl = proc_reg_unlocked_ioctl,
381#ifdef CONFIG_COMPAT
382 .compat_ioctl = proc_reg_compat_ioctl,
383#endif
384 .mmap = proc_reg_mmap,
385 .open = proc_reg_open,
386 .release = proc_reg_release,
387};
388
143struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, 389struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
144 struct proc_dir_entry *de) 390 struct proc_dir_entry *de)
145{ 391{
@@ -166,8 +412,12 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
166 inode->i_nlink = de->nlink; 412 inode->i_nlink = de->nlink;
167 if (de->proc_iops) 413 if (de->proc_iops)
168 inode->i_op = de->proc_iops; 414 inode->i_op = de->proc_iops;
169 if (de->proc_fops) 415 if (de->proc_fops) {
170 inode->i_fop = de->proc_fops; 416 if (S_ISREG(inode->i_mode))
417 inode->i_fop = &proc_reg_file_ops;
418 else
419 inode->i_fop = de->proc_fops;
420 }
171 } 421 }
172 422
173 return inode; 423 return inode;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 5fd49e47f83a..d24b8d46059a 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -105,6 +105,7 @@ static int uptime_read_proc(char *page, char **start, off_t off,
105 cputime_t idletime = cputime_add(init_task.utime, init_task.stime); 105 cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
106 106
107 do_posix_clock_monotonic_gettime(&uptime); 107 do_posix_clock_monotonic_gettime(&uptime);
108 monotonic_to_bootbased(&uptime);
108 cputime_to_timespec(idletime, &idle); 109 cputime_to_timespec(idletime, &idle);
109 len = sprintf(page,"%lu.%02lu %lu.%02lu\n", 110 len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
110 (unsigned long) uptime.tv_sec, 111 (unsigned long) uptime.tv_sec,
@@ -443,12 +444,12 @@ static int show_stat(struct seq_file *p, void *v)
443 unsigned long jif; 444 unsigned long jif;
444 cputime64_t user, nice, system, idle, iowait, irq, softirq, steal; 445 cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
445 u64 sum = 0; 446 u64 sum = 0;
447 struct timespec boottime;
446 448
447 user = nice = system = idle = iowait = 449 user = nice = system = idle = iowait =
448 irq = softirq = steal = cputime64_zero; 450 irq = softirq = steal = cputime64_zero;
449 jif = - wall_to_monotonic.tv_sec; 451 getboottime(&boottime);
450 if (wall_to_monotonic.tv_nsec) 452 jif = boottime.tv_sec;
451 --jif;
452 453
453 for_each_possible_cpu(i) { 454 for_each_possible_cpu(i) {
454 int j; 455 int j;
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index b3a473b0a191..22846225acfa 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -69,7 +69,7 @@ static void show_tty_range(struct seq_file *m, struct tty_driver *p,
69 69
70static int show_tty_driver(struct seq_file *m, void *v) 70static int show_tty_driver(struct seq_file *m, void *v)
71{ 71{
72 struct tty_driver *p = v; 72 struct tty_driver *p = list_entry(v, struct tty_driver, tty_drivers);
73 dev_t from = MKDEV(p->major, p->minor_start); 73 dev_t from = MKDEV(p->major, p->minor_start);
74 dev_t to = from + p->num; 74 dev_t to = from + p->num;
75 75
@@ -106,22 +106,13 @@ static int show_tty_driver(struct seq_file *m, void *v)
106/* iterator */ 106/* iterator */
107static void *t_start(struct seq_file *m, loff_t *pos) 107static void *t_start(struct seq_file *m, loff_t *pos)
108{ 108{
109 struct list_head *p;
110 loff_t l = *pos;
111
112 mutex_lock(&tty_mutex); 109 mutex_lock(&tty_mutex);
113 list_for_each(p, &tty_drivers) 110 return seq_list_start(&tty_drivers, *pos);
114 if (!l--)
115 return list_entry(p, struct tty_driver, tty_drivers);
116 return NULL;
117} 111}
118 112
119static void *t_next(struct seq_file *m, void *v, loff_t *pos) 113static void *t_next(struct seq_file *m, void *v, loff_t *pos)
120{ 114{
121 struct list_head *p = ((struct tty_driver *)v)->tty_drivers.next; 115 return seq_list_next(v, &tty_drivers, pos);
122 (*pos)++;
123 return p==&tty_drivers ? NULL :
124 list_entry(p, struct tty_driver, tty_drivers);
125} 116}
126 117
127static void t_stop(struct seq_file *m, void *v) 118static void t_stop(struct seq_file *m, void *v)