diff options
-rw-r--r-- | Documentation/filesystems/proc.txt | 1 | ||||
-rw-r--r-- | arch/mips/kernel/stacktrace.c | 24 | ||||
-rw-r--r-- | fs/proc/base.c | 231 | ||||
-rw-r--r-- | fs/proc/generic.c | 8 | ||||
-rw-r--r-- | fs/proc/inode.c | 3 | ||||
-rw-r--r-- | fs/proc/proc_net.c | 2 | ||||
-rw-r--r-- | fs/proc/root.c | 8 |
7 files changed, 153 insertions, 124 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 32e94635484f..d105eb45282a 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt | |||
@@ -140,6 +140,7 @@ Table 1-1: Process specific entries in /proc | |||
140 | statm Process memory status information | 140 | statm Process memory status information |
141 | status Process status in human readable form | 141 | status Process status in human readable form |
142 | wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan | 142 | wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan |
143 | stack Report full stack trace, enable via CONFIG_STACKTRACE | ||
143 | smaps Extension based on maps, the rss size for each mapped file | 144 | smaps Extension based on maps, the rss size for each mapped file |
144 | .............................................................................. | 145 | .............................................................................. |
145 | 146 | ||
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c index 0632e2a849c0..58f5cd76c8c3 100644 --- a/arch/mips/kernel/stacktrace.c +++ b/arch/mips/kernel/stacktrace.c | |||
@@ -32,7 +32,8 @@ static void save_raw_context_stack(struct stack_trace *trace, | |||
32 | } | 32 | } |
33 | } | 33 | } |
34 | 34 | ||
35 | static void save_context_stack(struct stack_trace *trace, struct pt_regs *regs) | 35 | static void save_context_stack(struct stack_trace *trace, |
36 | struct task_struct *tsk, struct pt_regs *regs) | ||
36 | { | 37 | { |
37 | unsigned long sp = regs->regs[29]; | 38 | unsigned long sp = regs->regs[29]; |
38 | #ifdef CONFIG_KALLSYMS | 39 | #ifdef CONFIG_KALLSYMS |
@@ -41,7 +42,7 @@ static void save_context_stack(struct stack_trace *trace, struct pt_regs *regs) | |||
41 | 42 | ||
42 | if (raw_show_trace || !__kernel_text_address(pc)) { | 43 | if (raw_show_trace || !__kernel_text_address(pc)) { |
43 | unsigned long stack_page = | 44 | unsigned long stack_page = |
44 | (unsigned long)task_stack_page(current); | 45 | (unsigned long)task_stack_page(tsk); |
45 | if (stack_page && sp >= stack_page && | 46 | if (stack_page && sp >= stack_page && |
46 | sp <= stack_page + THREAD_SIZE - 32) | 47 | sp <= stack_page + THREAD_SIZE - 32) |
47 | save_raw_context_stack(trace, sp); | 48 | save_raw_context_stack(trace, sp); |
@@ -54,7 +55,7 @@ static void save_context_stack(struct stack_trace *trace, struct pt_regs *regs) | |||
54 | trace->entries[trace->nr_entries++] = pc; | 55 | trace->entries[trace->nr_entries++] = pc; |
55 | if (trace->nr_entries >= trace->max_entries) | 56 | if (trace->nr_entries >= trace->max_entries) |
56 | break; | 57 | break; |
57 | pc = unwind_stack(current, &sp, pc, &ra); | 58 | pc = unwind_stack(tsk, &sp, pc, &ra); |
58 | } while (pc); | 59 | } while (pc); |
59 | #else | 60 | #else |
60 | save_raw_context_stack(trace, sp); | 61 | save_raw_context_stack(trace, sp); |
@@ -66,12 +67,23 @@ static void save_context_stack(struct stack_trace *trace, struct pt_regs *regs) | |||
66 | */ | 67 | */ |
67 | void save_stack_trace(struct stack_trace *trace) | 68 | void save_stack_trace(struct stack_trace *trace) |
68 | { | 69 | { |
70 | save_stack_trace_tsk(current, trace); | ||
71 | } | ||
72 | EXPORT_SYMBOL_GPL(save_stack_trace); | ||
73 | |||
74 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) | ||
75 | { | ||
69 | struct pt_regs dummyregs; | 76 | struct pt_regs dummyregs; |
70 | struct pt_regs *regs = &dummyregs; | 77 | struct pt_regs *regs = &dummyregs; |
71 | 78 | ||
72 | WARN_ON(trace->nr_entries || !trace->max_entries); | 79 | WARN_ON(trace->nr_entries || !trace->max_entries); |
73 | 80 | ||
74 | prepare_frametrace(regs); | 81 | if (tsk != current) { |
75 | save_context_stack(trace, regs); | 82 | regs->regs[29] = tsk->thread.reg29; |
83 | regs->regs[31] = 0; | ||
84 | regs->cp0_epc = tsk->thread.reg31; | ||
85 | } else | ||
86 | prepare_frametrace(regs); | ||
87 | save_context_stack(trace, tsk, regs); | ||
76 | } | 88 | } |
77 | EXPORT_SYMBOL_GPL(save_stack_trace); | 89 | EXPORT_SYMBOL_GPL(save_stack_trace_tsk); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 10fd5223d600..0c9de19a1633 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -65,6 +65,7 @@ | |||
65 | #include <linux/mm.h> | 65 | #include <linux/mm.h> |
66 | #include <linux/rcupdate.h> | 66 | #include <linux/rcupdate.h> |
67 | #include <linux/kallsyms.h> | 67 | #include <linux/kallsyms.h> |
68 | #include <linux/stacktrace.h> | ||
68 | #include <linux/resource.h> | 69 | #include <linux/resource.h> |
69 | #include <linux/module.h> | 70 | #include <linux/module.h> |
70 | #include <linux/mount.h> | 71 | #include <linux/mount.h> |
@@ -109,25 +110,22 @@ struct pid_entry { | |||
109 | .op = OP, \ | 110 | .op = OP, \ |
110 | } | 111 | } |
111 | 112 | ||
112 | #define DIR(NAME, MODE, OTYPE) \ | 113 | #define DIR(NAME, MODE, iops, fops) \ |
113 | NOD(NAME, (S_IFDIR|(MODE)), \ | 114 | NOD(NAME, (S_IFDIR|(MODE)), &iops, &fops, {} ) |
114 | &proc_##OTYPE##_inode_operations, &proc_##OTYPE##_operations, \ | 115 | #define LNK(NAME, get_link) \ |
115 | {} ) | ||
116 | #define LNK(NAME, OTYPE) \ | ||
117 | NOD(NAME, (S_IFLNK|S_IRWXUGO), \ | 116 | NOD(NAME, (S_IFLNK|S_IRWXUGO), \ |
118 | &proc_pid_link_inode_operations, NULL, \ | 117 | &proc_pid_link_inode_operations, NULL, \ |
119 | { .proc_get_link = &proc_##OTYPE##_link } ) | 118 | { .proc_get_link = get_link } ) |
120 | #define REG(NAME, MODE, OTYPE) \ | 119 | #define REG(NAME, MODE, fops) \ |
121 | NOD(NAME, (S_IFREG|(MODE)), NULL, \ | 120 | NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {}) |
122 | &proc_##OTYPE##_operations, {}) | 121 | #define INF(NAME, MODE, read) \ |
123 | #define INF(NAME, MODE, OTYPE) \ | ||
124 | NOD(NAME, (S_IFREG|(MODE)), \ | 122 | NOD(NAME, (S_IFREG|(MODE)), \ |
125 | NULL, &proc_info_file_operations, \ | 123 | NULL, &proc_info_file_operations, \ |
126 | { .proc_read = &proc_##OTYPE } ) | 124 | { .proc_read = read } ) |
127 | #define ONE(NAME, MODE, OTYPE) \ | 125 | #define ONE(NAME, MODE, show) \ |
128 | NOD(NAME, (S_IFREG|(MODE)), \ | 126 | NOD(NAME, (S_IFREG|(MODE)), \ |
129 | NULL, &proc_single_file_operations, \ | 127 | NULL, &proc_single_file_operations, \ |
130 | { .proc_show = &proc_##OTYPE } ) | 128 | { .proc_show = show } ) |
131 | 129 | ||
132 | /* | 130 | /* |
133 | * Count the number of hardlinks for the pid_entry table, excluding the . | 131 | * Count the number of hardlinks for the pid_entry table, excluding the . |
@@ -308,9 +306,9 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer) | |||
308 | struct mm_struct *mm = get_task_mm(task); | 306 | struct mm_struct *mm = get_task_mm(task); |
309 | if (mm) { | 307 | if (mm) { |
310 | unsigned int nwords = 0; | 308 | unsigned int nwords = 0; |
311 | do | 309 | do { |
312 | nwords += 2; | 310 | nwords += 2; |
313 | while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */ | 311 | } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */ |
314 | res = nwords * sizeof(mm->saved_auxv[0]); | 312 | res = nwords * sizeof(mm->saved_auxv[0]); |
315 | if (res > PAGE_SIZE) | 313 | if (res > PAGE_SIZE) |
316 | res = PAGE_SIZE; | 314 | res = PAGE_SIZE; |
@@ -340,6 +338,37 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer) | |||
340 | } | 338 | } |
341 | #endif /* CONFIG_KALLSYMS */ | 339 | #endif /* CONFIG_KALLSYMS */ |
342 | 340 | ||
341 | #ifdef CONFIG_STACKTRACE | ||
342 | |||
343 | #define MAX_STACK_TRACE_DEPTH 64 | ||
344 | |||
345 | static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns, | ||
346 | struct pid *pid, struct task_struct *task) | ||
347 | { | ||
348 | struct stack_trace trace; | ||
349 | unsigned long *entries; | ||
350 | int i; | ||
351 | |||
352 | entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL); | ||
353 | if (!entries) | ||
354 | return -ENOMEM; | ||
355 | |||
356 | trace.nr_entries = 0; | ||
357 | trace.max_entries = MAX_STACK_TRACE_DEPTH; | ||
358 | trace.entries = entries; | ||
359 | trace.skip = 0; | ||
360 | save_stack_trace_tsk(task, &trace); | ||
361 | |||
362 | for (i = 0; i < trace.nr_entries; i++) { | ||
363 | seq_printf(m, "[<%p>] %pS\n", | ||
364 | (void *)entries[i], (void *)entries[i]); | ||
365 | } | ||
366 | kfree(entries); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | #endif | ||
371 | |||
343 | #ifdef CONFIG_SCHEDSTATS | 372 | #ifdef CONFIG_SCHEDSTATS |
344 | /* | 373 | /* |
345 | * Provides /proc/PID/schedstat | 374 | * Provides /proc/PID/schedstat |
@@ -1186,8 +1215,6 @@ static int sched_show(struct seq_file *m, void *v) | |||
1186 | struct inode *inode = m->private; | 1215 | struct inode *inode = m->private; |
1187 | struct task_struct *p; | 1216 | struct task_struct *p; |
1188 | 1217 | ||
1189 | WARN_ON(!inode); | ||
1190 | |||
1191 | p = get_proc_task(inode); | 1218 | p = get_proc_task(inode); |
1192 | if (!p) | 1219 | if (!p) |
1193 | return -ESRCH; | 1220 | return -ESRCH; |
@@ -1205,8 +1232,6 @@ sched_write(struct file *file, const char __user *buf, | |||
1205 | struct inode *inode = file->f_path.dentry->d_inode; | 1232 | struct inode *inode = file->f_path.dentry->d_inode; |
1206 | struct task_struct *p; | 1233 | struct task_struct *p; |
1207 | 1234 | ||
1208 | WARN_ON(!inode); | ||
1209 | |||
1210 | p = get_proc_task(inode); | 1235 | p = get_proc_task(inode); |
1211 | if (!p) | 1236 | if (!p) |
1212 | return -ESRCH; | 1237 | return -ESRCH; |
@@ -1974,13 +1999,11 @@ static struct dentry *proc_pident_lookup(struct inode *dir, | |||
1974 | const struct pid_entry *ents, | 1999 | const struct pid_entry *ents, |
1975 | unsigned int nents) | 2000 | unsigned int nents) |
1976 | { | 2001 | { |
1977 | struct inode *inode; | ||
1978 | struct dentry *error; | 2002 | struct dentry *error; |
1979 | struct task_struct *task = get_proc_task(dir); | 2003 | struct task_struct *task = get_proc_task(dir); |
1980 | const struct pid_entry *p, *last; | 2004 | const struct pid_entry *p, *last; |
1981 | 2005 | ||
1982 | error = ERR_PTR(-ENOENT); | 2006 | error = ERR_PTR(-ENOENT); |
1983 | inode = NULL; | ||
1984 | 2007 | ||
1985 | if (!task) | 2008 | if (!task) |
1986 | goto out_no_task; | 2009 | goto out_no_task; |
@@ -2136,12 +2159,12 @@ static const struct file_operations proc_pid_attr_operations = { | |||
2136 | }; | 2159 | }; |
2137 | 2160 | ||
2138 | static const struct pid_entry attr_dir_stuff[] = { | 2161 | static const struct pid_entry attr_dir_stuff[] = { |
2139 | REG("current", S_IRUGO|S_IWUGO, pid_attr), | 2162 | REG("current", S_IRUGO|S_IWUGO, proc_pid_attr_operations), |
2140 | REG("prev", S_IRUGO, pid_attr), | 2163 | REG("prev", S_IRUGO, proc_pid_attr_operations), |
2141 | REG("exec", S_IRUGO|S_IWUGO, pid_attr), | 2164 | REG("exec", S_IRUGO|S_IWUGO, proc_pid_attr_operations), |
2142 | REG("fscreate", S_IRUGO|S_IWUGO, pid_attr), | 2165 | REG("fscreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), |
2143 | REG("keycreate", S_IRUGO|S_IWUGO, pid_attr), | 2166 | REG("keycreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), |
2144 | REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr), | 2167 | REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), |
2145 | }; | 2168 | }; |
2146 | 2169 | ||
2147 | static int proc_attr_dir_readdir(struct file * filp, | 2170 | static int proc_attr_dir_readdir(struct file * filp, |
@@ -2461,74 +2484,77 @@ static const struct file_operations proc_task_operations; | |||
2461 | static const struct inode_operations proc_task_inode_operations; | 2484 | static const struct inode_operations proc_task_inode_operations; |
2462 | 2485 | ||
2463 | static const struct pid_entry tgid_base_stuff[] = { | 2486 | static const struct pid_entry tgid_base_stuff[] = { |
2464 | DIR("task", S_IRUGO|S_IXUGO, task), | 2487 | DIR("task", S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations), |
2465 | DIR("fd", S_IRUSR|S_IXUSR, fd), | 2488 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), |
2466 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), | 2489 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), |
2467 | #ifdef CONFIG_NET | 2490 | #ifdef CONFIG_NET |
2468 | DIR("net", S_IRUGO|S_IXUGO, net), | 2491 | DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations), |
2469 | #endif | 2492 | #endif |
2470 | REG("environ", S_IRUSR, environ), | 2493 | REG("environ", S_IRUSR, proc_environ_operations), |
2471 | INF("auxv", S_IRUSR, pid_auxv), | 2494 | INF("auxv", S_IRUSR, proc_pid_auxv), |
2472 | ONE("status", S_IRUGO, pid_status), | 2495 | ONE("status", S_IRUGO, proc_pid_status), |
2473 | ONE("personality", S_IRUSR, pid_personality), | 2496 | ONE("personality", S_IRUSR, proc_pid_personality), |
2474 | INF("limits", S_IRUSR, pid_limits), | 2497 | INF("limits", S_IRUSR, proc_pid_limits), |
2475 | #ifdef CONFIG_SCHED_DEBUG | 2498 | #ifdef CONFIG_SCHED_DEBUG |
2476 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), | 2499 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), |
2477 | #endif | 2500 | #endif |
2478 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | 2501 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
2479 | INF("syscall", S_IRUSR, pid_syscall), | 2502 | INF("syscall", S_IRUSR, proc_pid_syscall), |
2480 | #endif | 2503 | #endif |
2481 | INF("cmdline", S_IRUGO, pid_cmdline), | 2504 | INF("cmdline", S_IRUGO, proc_pid_cmdline), |
2482 | ONE("stat", S_IRUGO, tgid_stat), | 2505 | ONE("stat", S_IRUGO, proc_tgid_stat), |
2483 | ONE("statm", S_IRUGO, pid_statm), | 2506 | ONE("statm", S_IRUGO, proc_pid_statm), |
2484 | REG("maps", S_IRUGO, maps), | 2507 | REG("maps", S_IRUGO, proc_maps_operations), |
2485 | #ifdef CONFIG_NUMA | 2508 | #ifdef CONFIG_NUMA |
2486 | REG("numa_maps", S_IRUGO, numa_maps), | 2509 | REG("numa_maps", S_IRUGO, proc_numa_maps_operations), |
2487 | #endif | 2510 | #endif |
2488 | REG("mem", S_IRUSR|S_IWUSR, mem), | 2511 | REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations), |
2489 | LNK("cwd", cwd), | 2512 | LNK("cwd", proc_cwd_link), |
2490 | LNK("root", root), | 2513 | LNK("root", proc_root_link), |
2491 | LNK("exe", exe), | 2514 | LNK("exe", proc_exe_link), |
2492 | REG("mounts", S_IRUGO, mounts), | 2515 | REG("mounts", S_IRUGO, proc_mounts_operations), |
2493 | REG("mountinfo", S_IRUGO, mountinfo), | 2516 | REG("mountinfo", S_IRUGO, proc_mountinfo_operations), |
2494 | REG("mountstats", S_IRUSR, mountstats), | 2517 | REG("mountstats", S_IRUSR, proc_mountstats_operations), |
2495 | #ifdef CONFIG_PROC_PAGE_MONITOR | 2518 | #ifdef CONFIG_PROC_PAGE_MONITOR |
2496 | REG("clear_refs", S_IWUSR, clear_refs), | 2519 | REG("clear_refs", S_IWUSR, proc_clear_refs_operations), |
2497 | REG("smaps", S_IRUGO, smaps), | 2520 | REG("smaps", S_IRUGO, proc_smaps_operations), |
2498 | REG("pagemap", S_IRUSR, pagemap), | 2521 | REG("pagemap", S_IRUSR, proc_pagemap_operations), |
2499 | #endif | 2522 | #endif |
2500 | #ifdef CONFIG_SECURITY | 2523 | #ifdef CONFIG_SECURITY |
2501 | DIR("attr", S_IRUGO|S_IXUGO, attr_dir), | 2524 | DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), |
2502 | #endif | 2525 | #endif |
2503 | #ifdef CONFIG_KALLSYMS | 2526 | #ifdef CONFIG_KALLSYMS |
2504 | INF("wchan", S_IRUGO, pid_wchan), | 2527 | INF("wchan", S_IRUGO, proc_pid_wchan), |
2528 | #endif | ||
2529 | #ifdef CONFIG_STACKTRACE | ||
2530 | ONE("stack", S_IRUSR, proc_pid_stack), | ||
2505 | #endif | 2531 | #endif |
2506 | #ifdef CONFIG_SCHEDSTATS | 2532 | #ifdef CONFIG_SCHEDSTATS |
2507 | INF("schedstat", S_IRUGO, pid_schedstat), | 2533 | INF("schedstat", S_IRUGO, proc_pid_schedstat), |
2508 | #endif | 2534 | #endif |
2509 | #ifdef CONFIG_LATENCYTOP | 2535 | #ifdef CONFIG_LATENCYTOP |
2510 | REG("latency", S_IRUGO, lstats), | 2536 | REG("latency", S_IRUGO, proc_lstats_operations), |
2511 | #endif | 2537 | #endif |
2512 | #ifdef CONFIG_PROC_PID_CPUSET | 2538 | #ifdef CONFIG_PROC_PID_CPUSET |
2513 | REG("cpuset", S_IRUGO, cpuset), | 2539 | REG("cpuset", S_IRUGO, proc_cpuset_operations), |
2514 | #endif | 2540 | #endif |
2515 | #ifdef CONFIG_CGROUPS | 2541 | #ifdef CONFIG_CGROUPS |
2516 | REG("cgroup", S_IRUGO, cgroup), | 2542 | REG("cgroup", S_IRUGO, proc_cgroup_operations), |
2517 | #endif | 2543 | #endif |
2518 | INF("oom_score", S_IRUGO, oom_score), | 2544 | INF("oom_score", S_IRUGO, proc_oom_score), |
2519 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2545 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adjust_operations), |
2520 | #ifdef CONFIG_AUDITSYSCALL | 2546 | #ifdef CONFIG_AUDITSYSCALL |
2521 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), | 2547 | REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), |
2522 | REG("sessionid", S_IRUGO, sessionid), | 2548 | REG("sessionid", S_IRUGO, proc_sessionid_operations), |
2523 | #endif | 2549 | #endif |
2524 | #ifdef CONFIG_FAULT_INJECTION | 2550 | #ifdef CONFIG_FAULT_INJECTION |
2525 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), | 2551 | REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), |
2526 | #endif | 2552 | #endif |
2527 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) | 2553 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) |
2528 | REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter), | 2554 | REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), |
2529 | #endif | 2555 | #endif |
2530 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2556 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
2531 | INF("io", S_IRUGO, tgid_io_accounting), | 2557 | INF("io", S_IRUGO, proc_tgid_io_accounting), |
2532 | #endif | 2558 | #endif |
2533 | }; | 2559 | }; |
2534 | 2560 | ||
@@ -2801,66 +2827,69 @@ out_no_task: | |||
2801 | * Tasks | 2827 | * Tasks |
2802 | */ | 2828 | */ |
2803 | static const struct pid_entry tid_base_stuff[] = { | 2829 | static const struct pid_entry tid_base_stuff[] = { |
2804 | DIR("fd", S_IRUSR|S_IXUSR, fd), | 2830 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), |
2805 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), | 2831 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fd_operations), |
2806 | REG("environ", S_IRUSR, environ), | 2832 | REG("environ", S_IRUSR, proc_environ_operations), |
2807 | INF("auxv", S_IRUSR, pid_auxv), | 2833 | INF("auxv", S_IRUSR, proc_pid_auxv), |
2808 | ONE("status", S_IRUGO, pid_status), | 2834 | ONE("status", S_IRUGO, proc_pid_status), |
2809 | ONE("personality", S_IRUSR, pid_personality), | 2835 | ONE("personality", S_IRUSR, proc_pid_personality), |
2810 | INF("limits", S_IRUSR, pid_limits), | 2836 | INF("limits", S_IRUSR, proc_pid_limits), |
2811 | #ifdef CONFIG_SCHED_DEBUG | 2837 | #ifdef CONFIG_SCHED_DEBUG |
2812 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), | 2838 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), |
2813 | #endif | 2839 | #endif |
2814 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | 2840 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
2815 | INF("syscall", S_IRUSR, pid_syscall), | 2841 | INF("syscall", S_IRUSR, proc_pid_syscall), |
2816 | #endif | 2842 | #endif |
2817 | INF("cmdline", S_IRUGO, pid_cmdline), | 2843 | INF("cmdline", S_IRUGO, proc_pid_cmdline), |
2818 | ONE("stat", S_IRUGO, tid_stat), | 2844 | ONE("stat", S_IRUGO, proc_tid_stat), |
2819 | ONE("statm", S_IRUGO, pid_statm), | 2845 | ONE("statm", S_IRUGO, proc_pid_statm), |
2820 | REG("maps", S_IRUGO, maps), | 2846 | REG("maps", S_IRUGO, proc_maps_operations), |
2821 | #ifdef CONFIG_NUMA | 2847 | #ifdef CONFIG_NUMA |
2822 | REG("numa_maps", S_IRUGO, numa_maps), | 2848 | REG("numa_maps", S_IRUGO, proc_numa_maps_operations), |
2823 | #endif | 2849 | #endif |
2824 | REG("mem", S_IRUSR|S_IWUSR, mem), | 2850 | REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations), |
2825 | LNK("cwd", cwd), | 2851 | LNK("cwd", proc_cwd_link), |
2826 | LNK("root", root), | 2852 | LNK("root", proc_root_link), |
2827 | LNK("exe", exe), | 2853 | LNK("exe", proc_exe_link), |
2828 | REG("mounts", S_IRUGO, mounts), | 2854 | REG("mounts", S_IRUGO, proc_mounts_operations), |
2829 | REG("mountinfo", S_IRUGO, mountinfo), | 2855 | REG("mountinfo", S_IRUGO, proc_mountinfo_operations), |
2830 | #ifdef CONFIG_PROC_PAGE_MONITOR | 2856 | #ifdef CONFIG_PROC_PAGE_MONITOR |
2831 | REG("clear_refs", S_IWUSR, clear_refs), | 2857 | REG("clear_refs", S_IWUSR, proc_clear_refs_operations), |
2832 | REG("smaps", S_IRUGO, smaps), | 2858 | REG("smaps", S_IRUGO, proc_smaps_operations), |
2833 | REG("pagemap", S_IRUSR, pagemap), | 2859 | REG("pagemap", S_IRUSR, proc_pagemap_operations), |
2834 | #endif | 2860 | #endif |
2835 | #ifdef CONFIG_SECURITY | 2861 | #ifdef CONFIG_SECURITY |
2836 | DIR("attr", S_IRUGO|S_IXUGO, attr_dir), | 2862 | DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), |
2837 | #endif | 2863 | #endif |
2838 | #ifdef CONFIG_KALLSYMS | 2864 | #ifdef CONFIG_KALLSYMS |
2839 | INF("wchan", S_IRUGO, pid_wchan), | 2865 | INF("wchan", S_IRUGO, proc_pid_wchan), |
2866 | #endif | ||
2867 | #ifdef CONFIG_STACKTRACE | ||
2868 | ONE("stack", S_IRUSR, proc_pid_stack), | ||
2840 | #endif | 2869 | #endif |
2841 | #ifdef CONFIG_SCHEDSTATS | 2870 | #ifdef CONFIG_SCHEDSTATS |
2842 | INF("schedstat", S_IRUGO, pid_schedstat), | 2871 | INF("schedstat", S_IRUGO, proc_pid_schedstat), |
2843 | #endif | 2872 | #endif |
2844 | #ifdef CONFIG_LATENCYTOP | 2873 | #ifdef CONFIG_LATENCYTOP |
2845 | REG("latency", S_IRUGO, lstats), | 2874 | REG("latency", S_IRUGO, proc_lstats_operations), |
2846 | #endif | 2875 | #endif |
2847 | #ifdef CONFIG_PROC_PID_CPUSET | 2876 | #ifdef CONFIG_PROC_PID_CPUSET |
2848 | REG("cpuset", S_IRUGO, cpuset), | 2877 | REG("cpuset", S_IRUGO, proc_cpuset_operations), |
2849 | #endif | 2878 | #endif |
2850 | #ifdef CONFIG_CGROUPS | 2879 | #ifdef CONFIG_CGROUPS |
2851 | REG("cgroup", S_IRUGO, cgroup), | 2880 | REG("cgroup", S_IRUGO, proc_cgroup_operations), |
2852 | #endif | 2881 | #endif |
2853 | INF("oom_score", S_IRUGO, oom_score), | 2882 | INF("oom_score", S_IRUGO, proc_oom_score), |
2854 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2883 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adjust_operations), |
2855 | #ifdef CONFIG_AUDITSYSCALL | 2884 | #ifdef CONFIG_AUDITSYSCALL |
2856 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), | 2885 | REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), |
2857 | REG("sessionid", S_IRUSR, sessionid), | 2886 | REG("sessionid", S_IRUSR, proc_sessionid_operations), |
2858 | #endif | 2887 | #endif |
2859 | #ifdef CONFIG_FAULT_INJECTION | 2888 | #ifdef CONFIG_FAULT_INJECTION |
2860 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), | 2889 | REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), |
2861 | #endif | 2890 | #endif |
2862 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2891 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
2863 | INF("io", S_IRUGO, tid_io_accounting), | 2892 | INF("io", S_IRUGO, proc_tid_io_accounting), |
2864 | #endif | 2893 | #endif |
2865 | }; | 2894 | }; |
2866 | 2895 | ||
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 60a359b35582..db7fa5cab988 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/stat.h> | 14 | #include <linux/stat.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/mount.h> | 16 | #include <linux/mount.h> |
17 | #include <linux/smp_lock.h> | ||
18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
19 | #include <linux/idr.h> | 18 | #include <linux/idr.h> |
20 | #include <linux/namei.h> | 19 | #include <linux/namei.h> |
@@ -379,7 +378,6 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir, | |||
379 | struct inode *inode = NULL; | 378 | struct inode *inode = NULL; |
380 | int error = -ENOENT; | 379 | int error = -ENOENT; |
381 | 380 | ||
382 | lock_kernel(); | ||
383 | spin_lock(&proc_subdir_lock); | 381 | spin_lock(&proc_subdir_lock); |
384 | for (de = de->subdir; de ; de = de->next) { | 382 | for (de = de->subdir; de ; de = de->next) { |
385 | if (de->namelen != dentry->d_name.len) | 383 | if (de->namelen != dentry->d_name.len) |
@@ -397,7 +395,6 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir, | |||
397 | } | 395 | } |
398 | spin_unlock(&proc_subdir_lock); | 396 | spin_unlock(&proc_subdir_lock); |
399 | out_unlock: | 397 | out_unlock: |
400 | unlock_kernel(); | ||
401 | 398 | ||
402 | if (inode) { | 399 | if (inode) { |
403 | dentry->d_op = &proc_dentry_operations; | 400 | dentry->d_op = &proc_dentry_operations; |
@@ -432,8 +429,6 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, | |||
432 | struct inode *inode = filp->f_path.dentry->d_inode; | 429 | struct inode *inode = filp->f_path.dentry->d_inode; |
433 | int ret = 0; | 430 | int ret = 0; |
434 | 431 | ||
435 | lock_kernel(); | ||
436 | |||
437 | ino = inode->i_ino; | 432 | ino = inode->i_ino; |
438 | i = filp->f_pos; | 433 | i = filp->f_pos; |
439 | switch (i) { | 434 | switch (i) { |
@@ -487,7 +482,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, | |||
487 | spin_unlock(&proc_subdir_lock); | 482 | spin_unlock(&proc_subdir_lock); |
488 | } | 483 | } |
489 | ret = 1; | 484 | ret = 1; |
490 | out: unlock_kernel(); | 485 | out: |
491 | return ret; | 486 | return ret; |
492 | } | 487 | } |
493 | 488 | ||
@@ -504,6 +499,7 @@ int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
504 | * the /proc directory. | 499 | * the /proc directory. |
505 | */ | 500 | */ |
506 | static const struct file_operations proc_dir_operations = { | 501 | static const struct file_operations proc_dir_operations = { |
502 | .llseek = generic_file_llseek, | ||
507 | .read = generic_read_dir, | 503 | .read = generic_read_dir, |
508 | .readdir = proc_readdir, | 504 | .readdir = proc_readdir, |
509 | }; | 505 | }; |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 2543fd00c658..3e76bb9b3ad6 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -35,16 +35,13 @@ struct proc_dir_entry *de_get(struct proc_dir_entry *de) | |||
35 | */ | 35 | */ |
36 | void de_put(struct proc_dir_entry *de) | 36 | void de_put(struct proc_dir_entry *de) |
37 | { | 37 | { |
38 | lock_kernel(); | ||
39 | if (!atomic_read(&de->count)) { | 38 | if (!atomic_read(&de->count)) { |
40 | printk("de_put: entry %s already free!\n", de->name); | 39 | printk("de_put: entry %s already free!\n", de->name); |
41 | unlock_kernel(); | ||
42 | return; | 40 | return; |
43 | } | 41 | } |
44 | 42 | ||
45 | if (atomic_dec_and_test(&de->count)) | 43 | if (atomic_dec_and_test(&de->count)) |
46 | free_proc_entry(de); | 44 | free_proc_entry(de); |
47 | unlock_kernel(); | ||
48 | } | 45 | } |
49 | 46 | ||
50 | /* | 47 | /* |
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 7bc296f424ae..04d1270f1c38 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/bitops.h> | 20 | #include <linux/bitops.h> |
21 | #include <linux/smp_lock.h> | ||
22 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
23 | #include <linux/nsproxy.h> | 22 | #include <linux/nsproxy.h> |
24 | #include <net/net_namespace.h> | 23 | #include <net/net_namespace.h> |
@@ -172,6 +171,7 @@ static int proc_tgid_net_readdir(struct file *filp, void *dirent, | |||
172 | } | 171 | } |
173 | 172 | ||
174 | const struct file_operations proc_net_operations = { | 173 | const struct file_operations proc_net_operations = { |
174 | .llseek = generic_file_llseek, | ||
175 | .read = generic_read_dir, | 175 | .read = generic_read_dir, |
176 | .readdir = proc_tgid_net_readdir, | 176 | .readdir = proc_tgid_net_readdir, |
177 | }; | 177 | }; |
diff --git a/fs/proc/root.c b/fs/proc/root.c index 7761602af9de..f6299a25594e 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
19 | #include <linux/smp_lock.h> | ||
20 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
21 | #include <linux/pid_namespace.h> | 20 | #include <linux/pid_namespace.h> |
22 | 21 | ||
@@ -162,17 +161,12 @@ static int proc_root_readdir(struct file * filp, | |||
162 | unsigned int nr = filp->f_pos; | 161 | unsigned int nr = filp->f_pos; |
163 | int ret; | 162 | int ret; |
164 | 163 | ||
165 | lock_kernel(); | ||
166 | |||
167 | if (nr < FIRST_PROCESS_ENTRY) { | 164 | if (nr < FIRST_PROCESS_ENTRY) { |
168 | int error = proc_readdir(filp, dirent, filldir); | 165 | int error = proc_readdir(filp, dirent, filldir); |
169 | if (error <= 0) { | 166 | if (error <= 0) |
170 | unlock_kernel(); | ||
171 | return error; | 167 | return error; |
172 | } | ||
173 | filp->f_pos = FIRST_PROCESS_ENTRY; | 168 | filp->f_pos = FIRST_PROCESS_ENTRY; |
174 | } | 169 | } |
175 | unlock_kernel(); | ||
176 | 170 | ||
177 | ret = proc_pid_readdir(filp, dirent, filldir); | 171 | ret = proc_pid_readdir(filp, dirent, filldir); |
178 | return ret; | 172 | return ret; |