aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-26 11:48:49 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-26 11:48:49 -0400
commitc3cc99ff5d24e2eeaf7ec2032e720681916990e3 (patch)
treec3e74171bbbd2adde9d60b9db1c440415c8d2831 /fs/proc
parent38ffbe66d59051fd9cfcfc8545f164700e2fa3bc (diff)
parent024e8ac04453b3525448c31ef39848cf675ba6db (diff)
Merge branch 'linus' into x86/xen
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/Kconfig59
-rw-r--r--fs/proc/base.c86
-rw-r--r--fs/proc/generic.c14
-rw-r--r--fs/proc/inode.c81
-rw-r--r--fs/proc/internal.h8
-rw-r--r--fs/proc/kcore.c10
-rw-r--r--fs/proc/kmsg.c2
-rw-r--r--fs/proc/proc_misc.c19
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 @@
1config 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
31config PROC_KCORE
32 bool "/proc/kcore support" if !ARM
33 depends on PROC_FS && MMU
34
35config 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
42config 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
2379static int proc_pid_io_accounting(struct task_struct *task, char *buffer) 2379static 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
2445static 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
2450static 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
2802static int proc_tid_base_readdir(struct file * filp, 2858static 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
791continue_removing: 792continue_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
114static int proc_remount(struct super_block *sb, int *flags, char *data)
115{
116 *flags |= MS_NODIRATIME;
117 return 0;
118}
119
120static const struct super_operations proc_sops = { 114static 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
129static void pde_users_dec(struct proc_dir_entry *pde) 122static 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
129static 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
365static 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
338static int proc_reg_release(struct inode *inode, struct file *file) 377static 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;
63extern const struct file_operations proc_clear_refs_operations; 63extern const struct file_operations proc_clear_refs_operations;
64extern const struct file_operations proc_pagemap_operations; 64extern const struct file_operations proc_pagemap_operations;
65extern const struct file_operations proc_net_operations; 65extern const struct file_operations proc_net_operations;
66extern const struct file_operations proc_kmsg_operations;
66extern const struct inode_operations proc_net_inode_operations; 67extern const struct inode_operations proc_net_inode_operations;
67 68
68void free_proc_entry(struct proc_dir_entry *de); 69void 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);
89int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, 90int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
90 filldir_t filldir); 91 filldir_t filldir);
92
93struct 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
26static int open_kcore(struct inode * inode, struct file * filp) 30static 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
18extern wait_queue_head_t log_wait; 20extern wait_queue_head_t log_wait;
19 21
20extern int do_syslog(int type, char __user *bug, int count); 22extern 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
235extern const struct seq_operations fragmentation_op;
236static int fragmentation_open(struct inode *inode, struct file *file) 235static 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
249extern const struct seq_operations pagetypeinfo_op;
250static int pagetypeinfo_open(struct inode *inode, struct file *file) 248static 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
262extern const struct seq_operations zoneinfo_op;
263static int zoneinfo_open(struct inode *inode, struct file *file) 260static 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
359extern const struct seq_operations vmstat_op;
360static int vmstat_open(struct inode *inode, struct file *file) 356static 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
469static int vmalloc_open(struct inode *inode, struct file *file) 465static 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
474static const struct file_operations proc_vmalloc_operations = { 481static 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