diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-07-26 11:48:49 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-26 11:48:49 -0400 |
commit | c3cc99ff5d24e2eeaf7ec2032e720681916990e3 (patch) | |
tree | c3e74171bbbd2adde9d60b9db1c440415c8d2831 /fs/proc | |
parent | 38ffbe66d59051fd9cfcfc8545f164700e2fa3bc (diff) | |
parent | 024e8ac04453b3525448c31ef39848cf675ba6db (diff) |
Merge branch 'linus' into x86/xen
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/Kconfig | 59 | ||||
-rw-r--r-- | fs/proc/base.c | 86 | ||||
-rw-r--r-- | fs/proc/generic.c | 14 | ||||
-rw-r--r-- | fs/proc/inode.c | 81 | ||||
-rw-r--r-- | fs/proc/internal.h | 8 | ||||
-rw-r--r-- | fs/proc/kcore.c | 10 | ||||
-rw-r--r-- | fs/proc/kmsg.c | 2 | ||||
-rw-r--r-- | fs/proc/proc_misc.c | 19 |
8 files changed, 242 insertions, 37 deletions
diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig new file mode 100644 index 000000000000..73cd7a418f06 --- /dev/null +++ b/fs/proc/Kconfig | |||
@@ -0,0 +1,59 @@ | |||
1 | config PROC_FS | ||
2 | bool "/proc file system support" if EMBEDDED | ||
3 | default y | ||
4 | help | ||
5 | This is a virtual file system providing information about the status | ||
6 | of the system. "Virtual" means that it doesn't take up any space on | ||
7 | your hard disk: the files are created on the fly by the kernel when | ||
8 | you try to access them. Also, you cannot read the files with older | ||
9 | version of the program less: you need to use more or cat. | ||
10 | |||
11 | It's totally cool; for example, "cat /proc/interrupts" gives | ||
12 | information about what the different IRQs are used for at the moment | ||
13 | (there is a small number of Interrupt ReQuest lines in your computer | ||
14 | that are used by the attached devices to gain the CPU's attention -- | ||
15 | often a source of trouble if two devices are mistakenly configured | ||
16 | to use the same IRQ). The program procinfo to display some | ||
17 | information about your system gathered from the /proc file system. | ||
18 | |||
19 | Before you can use the /proc file system, it has to be mounted, | ||
20 | meaning it has to be given a location in the directory hierarchy. | ||
21 | That location should be /proc. A command such as "mount -t proc proc | ||
22 | /proc" or the equivalent line in /etc/fstab does the job. | ||
23 | |||
24 | The /proc file system is explained in the file | ||
25 | <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage | ||
26 | ("man 5 proc"). | ||
27 | |||
28 | This option will enlarge your kernel by about 67 KB. Several | ||
29 | programs depend on this, so everyone should say Y here. | ||
30 | |||
31 | config PROC_KCORE | ||
32 | bool "/proc/kcore support" if !ARM | ||
33 | depends on PROC_FS && MMU | ||
34 | |||
35 | config PROC_VMCORE | ||
36 | bool "/proc/vmcore support (EXPERIMENTAL)" | ||
37 | depends on PROC_FS && CRASH_DUMP | ||
38 | default y | ||
39 | help | ||
40 | Exports the dump image of crashed kernel in ELF format. | ||
41 | |||
42 | config PROC_SYSCTL | ||
43 | bool "Sysctl support (/proc/sys)" if EMBEDDED | ||
44 | depends on PROC_FS | ||
45 | select SYSCTL | ||
46 | default y | ||
47 | ---help--- | ||
48 | The sysctl interface provides a means of dynamically changing | ||
49 | certain kernel parameters and variables on the fly without requiring | ||
50 | a recompile of the kernel or reboot of the system. The primary | ||
51 | interface is through /proc/sys. If you say Y here a tree of | ||
52 | modifiable sysctl entries will be generated beneath the | ||
53 | /proc/sys directory. They are explained in the files | ||
54 | in <file:Documentation/sysctl/>. Note that enabling this | ||
55 | option will enlarge the kernel by at least 8 KB. | ||
56 | |||
57 | As it is generally a good thing, you should say Y here unless | ||
58 | building a kernel for install/rescue disks or your system is very | ||
59 | limited in memory. | ||
diff --git a/fs/proc/base.c b/fs/proc/base.c index 58c3e6a8e15e..a891fe4cb43b 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -2376,29 +2376,82 @@ static int proc_base_fill_cache(struct file *filp, void *dirent, | |||
2376 | } | 2376 | } |
2377 | 2377 | ||
2378 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2378 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
2379 | static int proc_pid_io_accounting(struct task_struct *task, char *buffer) | 2379 | static int do_io_accounting(struct task_struct *task, char *buffer, int whole) |
2380 | { | 2380 | { |
2381 | u64 rchar, wchar, syscr, syscw; | ||
2382 | struct task_io_accounting ioac; | ||
2383 | |||
2384 | if (!whole) { | ||
2385 | rchar = task->rchar; | ||
2386 | wchar = task->wchar; | ||
2387 | syscr = task->syscr; | ||
2388 | syscw = task->syscw; | ||
2389 | memcpy(&ioac, &task->ioac, sizeof(ioac)); | ||
2390 | } else { | ||
2391 | unsigned long flags; | ||
2392 | struct task_struct *t = task; | ||
2393 | rchar = wchar = syscr = syscw = 0; | ||
2394 | memset(&ioac, 0, sizeof(ioac)); | ||
2395 | |||
2396 | rcu_read_lock(); | ||
2397 | do { | ||
2398 | rchar += t->rchar; | ||
2399 | wchar += t->wchar; | ||
2400 | syscr += t->syscr; | ||
2401 | syscw += t->syscw; | ||
2402 | |||
2403 | ioac.read_bytes += t->ioac.read_bytes; | ||
2404 | ioac.write_bytes += t->ioac.write_bytes; | ||
2405 | ioac.cancelled_write_bytes += | ||
2406 | t->ioac.cancelled_write_bytes; | ||
2407 | t = next_thread(t); | ||
2408 | } while (t != task); | ||
2409 | rcu_read_unlock(); | ||
2410 | |||
2411 | if (lock_task_sighand(task, &flags)) { | ||
2412 | struct signal_struct *sig = task->signal; | ||
2413 | |||
2414 | rchar += sig->rchar; | ||
2415 | wchar += sig->wchar; | ||
2416 | syscr += sig->syscr; | ||
2417 | syscw += sig->syscw; | ||
2418 | |||
2419 | ioac.read_bytes += sig->ioac.read_bytes; | ||
2420 | ioac.write_bytes += sig->ioac.write_bytes; | ||
2421 | ioac.cancelled_write_bytes += | ||
2422 | sig->ioac.cancelled_write_bytes; | ||
2423 | |||
2424 | unlock_task_sighand(task, &flags); | ||
2425 | } | ||
2426 | } | ||
2427 | |||
2381 | return sprintf(buffer, | 2428 | return sprintf(buffer, |
2382 | #ifdef CONFIG_TASK_XACCT | ||
2383 | "rchar: %llu\n" | 2429 | "rchar: %llu\n" |
2384 | "wchar: %llu\n" | 2430 | "wchar: %llu\n" |
2385 | "syscr: %llu\n" | 2431 | "syscr: %llu\n" |
2386 | "syscw: %llu\n" | 2432 | "syscw: %llu\n" |
2387 | #endif | ||
2388 | "read_bytes: %llu\n" | 2433 | "read_bytes: %llu\n" |
2389 | "write_bytes: %llu\n" | 2434 | "write_bytes: %llu\n" |
2390 | "cancelled_write_bytes: %llu\n", | 2435 | "cancelled_write_bytes: %llu\n", |
2391 | #ifdef CONFIG_TASK_XACCT | 2436 | (unsigned long long)rchar, |
2392 | (unsigned long long)task->rchar, | 2437 | (unsigned long long)wchar, |
2393 | (unsigned long long)task->wchar, | 2438 | (unsigned long long)syscr, |
2394 | (unsigned long long)task->syscr, | 2439 | (unsigned long long)syscw, |
2395 | (unsigned long long)task->syscw, | 2440 | (unsigned long long)ioac.read_bytes, |
2396 | #endif | 2441 | (unsigned long long)ioac.write_bytes, |
2397 | (unsigned long long)task->ioac.read_bytes, | 2442 | (unsigned long long)ioac.cancelled_write_bytes); |
2398 | (unsigned long long)task->ioac.write_bytes, | 2443 | } |
2399 | (unsigned long long)task->ioac.cancelled_write_bytes); | 2444 | |
2445 | static int proc_tid_io_accounting(struct task_struct *task, char *buffer) | ||
2446 | { | ||
2447 | return do_io_accounting(task, buffer, 0); | ||
2400 | } | 2448 | } |
2401 | #endif | 2449 | |
2450 | static int proc_tgid_io_accounting(struct task_struct *task, char *buffer) | ||
2451 | { | ||
2452 | return do_io_accounting(task, buffer, 1); | ||
2453 | } | ||
2454 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | ||
2402 | 2455 | ||
2403 | /* | 2456 | /* |
2404 | * Thread groups | 2457 | * Thread groups |
@@ -2470,7 +2523,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2470 | REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter), | 2523 | REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter), |
2471 | #endif | 2524 | #endif |
2472 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2525 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
2473 | INF("io", S_IRUGO, pid_io_accounting), | 2526 | INF("io", S_IRUGO, tgid_io_accounting), |
2474 | #endif | 2527 | #endif |
2475 | }; | 2528 | }; |
2476 | 2529 | ||
@@ -2797,6 +2850,9 @@ static const struct pid_entry tid_base_stuff[] = { | |||
2797 | #ifdef CONFIG_FAULT_INJECTION | 2850 | #ifdef CONFIG_FAULT_INJECTION |
2798 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), | 2851 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), |
2799 | #endif | 2852 | #endif |
2853 | #ifdef CONFIG_TASK_IO_ACCOUNTING | ||
2854 | INF("io", S_IRUGO, tid_io_accounting), | ||
2855 | #endif | ||
2800 | }; | 2856 | }; |
2801 | 2857 | ||
2802 | static int proc_tid_base_readdir(struct file * filp, | 2858 | static int proc_tid_base_readdir(struct file * filp, |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 43e54e86cefd..bc0a0dd2d844 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -597,6 +597,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent, | |||
597 | ent->pde_users = 0; | 597 | ent->pde_users = 0; |
598 | spin_lock_init(&ent->pde_unload_lock); | 598 | spin_lock_init(&ent->pde_unload_lock); |
599 | ent->pde_unload_completion = NULL; | 599 | ent->pde_unload_completion = NULL; |
600 | INIT_LIST_HEAD(&ent->pde_openers); | ||
600 | out: | 601 | out: |
601 | return ent; | 602 | return ent; |
602 | } | 603 | } |
@@ -789,6 +790,19 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
789 | spin_unlock(&de->pde_unload_lock); | 790 | spin_unlock(&de->pde_unload_lock); |
790 | 791 | ||
791 | continue_removing: | 792 | continue_removing: |
793 | spin_lock(&de->pde_unload_lock); | ||
794 | while (!list_empty(&de->pde_openers)) { | ||
795 | struct pde_opener *pdeo; | ||
796 | |||
797 | pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh); | ||
798 | list_del(&pdeo->lh); | ||
799 | spin_unlock(&de->pde_unload_lock); | ||
800 | pdeo->release(pdeo->inode, pdeo->file); | ||
801 | kfree(pdeo); | ||
802 | spin_lock(&de->pde_unload_lock); | ||
803 | } | ||
804 | spin_unlock(&de->pde_unload_lock); | ||
805 | |||
792 | if (S_ISDIR(de->mode)) | 806 | if (S_ISDIR(de->mode)) |
793 | parent->nlink--; | 807 | parent->nlink--; |
794 | de->nlink = 0; | 808 | de->nlink = 0; |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index b08d10017911..02eca2ed9dd7 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -111,27 +111,25 @@ int __init proc_init_inodecache(void) | |||
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
113 | 113 | ||
114 | static int proc_remount(struct super_block *sb, int *flags, char *data) | ||
115 | { | ||
116 | *flags |= MS_NODIRATIME; | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static const struct super_operations proc_sops = { | 114 | static const struct super_operations proc_sops = { |
121 | .alloc_inode = proc_alloc_inode, | 115 | .alloc_inode = proc_alloc_inode, |
122 | .destroy_inode = proc_destroy_inode, | 116 | .destroy_inode = proc_destroy_inode, |
123 | .drop_inode = generic_delete_inode, | 117 | .drop_inode = generic_delete_inode, |
124 | .delete_inode = proc_delete_inode, | 118 | .delete_inode = proc_delete_inode, |
125 | .statfs = simple_statfs, | 119 | .statfs = simple_statfs, |
126 | .remount_fs = proc_remount, | ||
127 | }; | 120 | }; |
128 | 121 | ||
129 | static void pde_users_dec(struct proc_dir_entry *pde) | 122 | static void __pde_users_dec(struct proc_dir_entry *pde) |
130 | { | 123 | { |
131 | spin_lock(&pde->pde_unload_lock); | ||
132 | pde->pde_users--; | 124 | pde->pde_users--; |
133 | if (pde->pde_unload_completion && pde->pde_users == 0) | 125 | if (pde->pde_unload_completion && pde->pde_users == 0) |
134 | complete(pde->pde_unload_completion); | 126 | complete(pde->pde_unload_completion); |
127 | } | ||
128 | |||
129 | static void pde_users_dec(struct proc_dir_entry *pde) | ||
130 | { | ||
131 | spin_lock(&pde->pde_unload_lock); | ||
132 | __pde_users_dec(pde); | ||
135 | spin_unlock(&pde->pde_unload_lock); | 133 | spin_unlock(&pde->pde_unload_lock); |
136 | } | 134 | } |
137 | 135 | ||
@@ -318,36 +316,97 @@ static int proc_reg_open(struct inode *inode, struct file *file) | |||
318 | struct proc_dir_entry *pde = PDE(inode); | 316 | struct proc_dir_entry *pde = PDE(inode); |
319 | int rv = 0; | 317 | int rv = 0; |
320 | int (*open)(struct inode *, struct file *); | 318 | int (*open)(struct inode *, struct file *); |
319 | int (*release)(struct inode *, struct file *); | ||
320 | struct pde_opener *pdeo; | ||
321 | |||
322 | /* | ||
323 | * What for, you ask? Well, we can have open, rmmod, remove_proc_entry | ||
324 | * sequence. ->release won't be called because ->proc_fops will be | ||
325 | * cleared. Depending on complexity of ->release, consequences vary. | ||
326 | * | ||
327 | * We can't wait for mercy when close will be done for real, it's | ||
328 | * deadlockable: rmmod foo </proc/foo . So, we're going to do ->release | ||
329 | * by hand in remove_proc_entry(). For this, save opener's credentials | ||
330 | * for later. | ||
331 | */ | ||
332 | pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL); | ||
333 | if (!pdeo) | ||
334 | return -ENOMEM; | ||
321 | 335 | ||
322 | spin_lock(&pde->pde_unload_lock); | 336 | spin_lock(&pde->pde_unload_lock); |
323 | if (!pde->proc_fops) { | 337 | if (!pde->proc_fops) { |
324 | spin_unlock(&pde->pde_unload_lock); | 338 | spin_unlock(&pde->pde_unload_lock); |
339 | kfree(pdeo); | ||
325 | return rv; | 340 | return rv; |
326 | } | 341 | } |
327 | pde->pde_users++; | 342 | pde->pde_users++; |
328 | open = pde->proc_fops->open; | 343 | open = pde->proc_fops->open; |
344 | release = pde->proc_fops->release; | ||
329 | spin_unlock(&pde->pde_unload_lock); | 345 | spin_unlock(&pde->pde_unload_lock); |
330 | 346 | ||
331 | if (open) | 347 | if (open) |
332 | rv = open(inode, file); | 348 | rv = open(inode, file); |
333 | 349 | ||
334 | pde_users_dec(pde); | 350 | spin_lock(&pde->pde_unload_lock); |
351 | if (rv == 0 && release) { | ||
352 | /* To know what to release. */ | ||
353 | pdeo->inode = inode; | ||
354 | pdeo->file = file; | ||
355 | /* Strictly for "too late" ->release in proc_reg_release(). */ | ||
356 | pdeo->release = release; | ||
357 | list_add(&pdeo->lh, &pde->pde_openers); | ||
358 | } else | ||
359 | kfree(pdeo); | ||
360 | __pde_users_dec(pde); | ||
361 | spin_unlock(&pde->pde_unload_lock); | ||
335 | return rv; | 362 | return rv; |
336 | } | 363 | } |
337 | 364 | ||
365 | static struct pde_opener *find_pde_opener(struct proc_dir_entry *pde, | ||
366 | struct inode *inode, struct file *file) | ||
367 | { | ||
368 | struct pde_opener *pdeo; | ||
369 | |||
370 | list_for_each_entry(pdeo, &pde->pde_openers, lh) { | ||
371 | if (pdeo->inode == inode && pdeo->file == file) | ||
372 | return pdeo; | ||
373 | } | ||
374 | return NULL; | ||
375 | } | ||
376 | |||
338 | static int proc_reg_release(struct inode *inode, struct file *file) | 377 | static int proc_reg_release(struct inode *inode, struct file *file) |
339 | { | 378 | { |
340 | struct proc_dir_entry *pde = PDE(inode); | 379 | struct proc_dir_entry *pde = PDE(inode); |
341 | int rv = 0; | 380 | int rv = 0; |
342 | int (*release)(struct inode *, struct file *); | 381 | int (*release)(struct inode *, struct file *); |
382 | struct pde_opener *pdeo; | ||
343 | 383 | ||
344 | spin_lock(&pde->pde_unload_lock); | 384 | spin_lock(&pde->pde_unload_lock); |
385 | pdeo = find_pde_opener(pde, inode, file); | ||
345 | if (!pde->proc_fops) { | 386 | if (!pde->proc_fops) { |
346 | spin_unlock(&pde->pde_unload_lock); | 387 | /* |
388 | * Can't simply exit, __fput() will think that everything is OK, | ||
389 | * and move on to freeing struct file. remove_proc_entry() will | ||
390 | * find slacker in opener's list and will try to do non-trivial | ||
391 | * things with struct file. Therefore, remove opener from list. | ||
392 | * | ||
393 | * But if opener is removed from list, who will ->release it? | ||
394 | */ | ||
395 | if (pdeo) { | ||
396 | list_del(&pdeo->lh); | ||
397 | spin_unlock(&pde->pde_unload_lock); | ||
398 | rv = pdeo->release(inode, file); | ||
399 | kfree(pdeo); | ||
400 | } else | ||
401 | spin_unlock(&pde->pde_unload_lock); | ||
347 | return rv; | 402 | return rv; |
348 | } | 403 | } |
349 | pde->pde_users++; | 404 | pde->pde_users++; |
350 | release = pde->proc_fops->release; | 405 | release = pde->proc_fops->release; |
406 | if (pdeo) { | ||
407 | list_del(&pdeo->lh); | ||
408 | kfree(pdeo); | ||
409 | } | ||
351 | spin_unlock(&pde->pde_unload_lock); | 410 | spin_unlock(&pde->pde_unload_lock); |
352 | 411 | ||
353 | if (release) | 412 | if (release) |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 28cbca805905..442202314d53 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -63,6 +63,7 @@ extern const struct file_operations proc_smaps_operations; | |||
63 | extern const struct file_operations proc_clear_refs_operations; | 63 | extern const struct file_operations proc_clear_refs_operations; |
64 | extern const struct file_operations proc_pagemap_operations; | 64 | extern const struct file_operations proc_pagemap_operations; |
65 | extern const struct file_operations proc_net_operations; | 65 | extern const struct file_operations proc_net_operations; |
66 | extern const struct file_operations proc_kmsg_operations; | ||
66 | extern const struct inode_operations proc_net_inode_operations; | 67 | extern const struct inode_operations proc_net_inode_operations; |
67 | 68 | ||
68 | void free_proc_entry(struct proc_dir_entry *de); | 69 | void free_proc_entry(struct proc_dir_entry *de); |
@@ -88,3 +89,10 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *ino, | |||
88 | struct dentry *dentry); | 89 | struct dentry *dentry); |
89 | int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, | 90 | int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, |
90 | filldir_t filldir); | 91 | filldir_t filldir); |
92 | |||
93 | struct pde_opener { | ||
94 | struct inode *inode; | ||
95 | struct file *file; | ||
96 | int (*release)(struct inode *, struct file *); | ||
97 | struct list_head lh; | ||
98 | }; | ||
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index e78c81fcf547..c2370c76fb71 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
@@ -23,6 +23,10 @@ | |||
23 | 23 | ||
24 | #define CORE_STR "CORE" | 24 | #define CORE_STR "CORE" |
25 | 25 | ||
26 | #ifndef ELF_CORE_EFLAGS | ||
27 | #define ELF_CORE_EFLAGS 0 | ||
28 | #endif | ||
29 | |||
26 | static int open_kcore(struct inode * inode, struct file * filp) | 30 | static int open_kcore(struct inode * inode, struct file * filp) |
27 | { | 31 | { |
28 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; | 32 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; |
@@ -164,11 +168,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff) | |||
164 | elf->e_entry = 0; | 168 | elf->e_entry = 0; |
165 | elf->e_phoff = sizeof(struct elfhdr); | 169 | elf->e_phoff = sizeof(struct elfhdr); |
166 | elf->e_shoff = 0; | 170 | elf->e_shoff = 0; |
167 | #if defined(CONFIG_H8300) | 171 | elf->e_flags = ELF_CORE_EFLAGS; |
168 | elf->e_flags = ELF_FLAGS; | ||
169 | #else | ||
170 | elf->e_flags = 0; | ||
171 | #endif | ||
172 | elf->e_ehsize = sizeof(struct elfhdr); | 172 | elf->e_ehsize = sizeof(struct elfhdr); |
173 | elf->e_phentsize= sizeof(struct elf_phdr); | 173 | elf->e_phentsize= sizeof(struct elf_phdr); |
174 | elf->e_phnum = nphdr; | 174 | elf->e_phnum = nphdr; |
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index ff3b90b56e9d..9fd5df3f40ce 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | 17 | ||
18 | #include "internal.h" | ||
19 | |||
18 | extern wait_queue_head_t log_wait; | 20 | extern wait_queue_head_t log_wait; |
19 | 21 | ||
20 | extern int do_syslog(int type, char __user *bug, int count); | 22 | extern int do_syslog(int type, char __user *bug, int count); |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index c652d469dc08..ded969862960 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -232,7 +232,6 @@ static int meminfo_read_proc(char *page, char **start, off_t off, | |||
232 | #undef K | 232 | #undef K |
233 | } | 233 | } |
234 | 234 | ||
235 | extern const struct seq_operations fragmentation_op; | ||
236 | static int fragmentation_open(struct inode *inode, struct file *file) | 235 | static int fragmentation_open(struct inode *inode, struct file *file) |
237 | { | 236 | { |
238 | (void)inode; | 237 | (void)inode; |
@@ -246,7 +245,6 @@ static const struct file_operations fragmentation_file_operations = { | |||
246 | .release = seq_release, | 245 | .release = seq_release, |
247 | }; | 246 | }; |
248 | 247 | ||
249 | extern const struct seq_operations pagetypeinfo_op; | ||
250 | static int pagetypeinfo_open(struct inode *inode, struct file *file) | 248 | static int pagetypeinfo_open(struct inode *inode, struct file *file) |
251 | { | 249 | { |
252 | return seq_open(file, &pagetypeinfo_op); | 250 | return seq_open(file, &pagetypeinfo_op); |
@@ -259,7 +257,6 @@ static const struct file_operations pagetypeinfo_file_ops = { | |||
259 | .release = seq_release, | 257 | .release = seq_release, |
260 | }; | 258 | }; |
261 | 259 | ||
262 | extern const struct seq_operations zoneinfo_op; | ||
263 | static int zoneinfo_open(struct inode *inode, struct file *file) | 260 | static int zoneinfo_open(struct inode *inode, struct file *file) |
264 | { | 261 | { |
265 | return seq_open(file, &zoneinfo_op); | 262 | return seq_open(file, &zoneinfo_op); |
@@ -356,7 +353,6 @@ static const struct file_operations proc_devinfo_operations = { | |||
356 | .release = seq_release, | 353 | .release = seq_release, |
357 | }; | 354 | }; |
358 | 355 | ||
359 | extern const struct seq_operations vmstat_op; | ||
360 | static int vmstat_open(struct inode *inode, struct file *file) | 356 | static int vmstat_open(struct inode *inode, struct file *file) |
361 | { | 357 | { |
362 | return seq_open(file, &vmstat_op); | 358 | return seq_open(file, &vmstat_op); |
@@ -468,14 +464,25 @@ static const struct file_operations proc_slabstats_operations = { | |||
468 | #ifdef CONFIG_MMU | 464 | #ifdef CONFIG_MMU |
469 | static int vmalloc_open(struct inode *inode, struct file *file) | 465 | static int vmalloc_open(struct inode *inode, struct file *file) |
470 | { | 466 | { |
471 | return seq_open(file, &vmalloc_op); | 467 | unsigned int *ptr = NULL; |
468 | int ret; | ||
469 | |||
470 | if (NUMA_BUILD) | ||
471 | ptr = kmalloc(nr_node_ids * sizeof(unsigned int), GFP_KERNEL); | ||
472 | ret = seq_open(file, &vmalloc_op); | ||
473 | if (!ret) { | ||
474 | struct seq_file *m = file->private_data; | ||
475 | m->private = ptr; | ||
476 | } else | ||
477 | kfree(ptr); | ||
478 | return ret; | ||
472 | } | 479 | } |
473 | 480 | ||
474 | static const struct file_operations proc_vmalloc_operations = { | 481 | static const struct file_operations proc_vmalloc_operations = { |
475 | .open = vmalloc_open, | 482 | .open = vmalloc_open, |
476 | .read = seq_read, | 483 | .read = seq_read, |
477 | .llseek = seq_lseek, | 484 | .llseek = seq_lseek, |
478 | .release = seq_release, | 485 | .release = seq_release_private, |
479 | }; | 486 | }; |
480 | #endif | 487 | #endif |
481 | 488 | ||