aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-12-31 02:31:57 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-31 02:31:57 -0500
commita9de18eb761f7c1c860964b2e5addc1a35c7e861 (patch)
tree886e75fdfd09690cd262ca69cb7f5d1d42b48602 /fs/proc
parentb2aaf8f74cdc84a9182f6cabf198b7763bcb9d40 (diff)
parent6a94cb73064c952255336cc57731904174b2c58f (diff)
Merge branch 'linus' into stackprotector
Conflicts: arch/x86/include/asm/pda.h kernel/fork.c
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/Makefile13
-rw-r--r--fs/proc/array.c42
-rw-r--r--fs/proc/base.c42
-rw-r--r--fs/proc/cmdline.c29
-rw-r--r--fs/proc/cpuinfo.c24
-rw-r--r--fs/proc/devices.c70
-rw-r--r--fs/proc/generic.c3
-rw-r--r--fs/proc/inode.c3
-rw-r--r--fs/proc/internal.h3
-rw-r--r--fs/proc/interrupts.c53
-rw-r--r--fs/proc/kcore.c14
-rw-r--r--fs/proc/kmsg.c12
-rw-r--r--fs/proc/loadavg.c51
-rw-r--r--fs/proc/meminfo.c168
-rw-r--r--fs/proc/page.c147
-rw-r--r--fs/proc/proc_devtree.c6
-rw-r--r--fs/proc/proc_misc.c940
-rw-r--r--fs/proc/proc_sysctl.c16
-rw-r--r--fs/proc/root.c8
-rw-r--r--fs/proc/stat.c161
-rw-r--r--fs/proc/task_mmu.c29
-rw-r--r--fs/proc/uptime.c45
-rw-r--r--fs/proc/version.c34
-rw-r--r--fs/proc/vmcore.c11
24 files changed, 915 insertions, 1009 deletions
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index ebaba0213546..63d965193b22 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -8,11 +8,20 @@ proc-y := nommu.o task_nommu.o
8proc-$(CONFIG_MMU) := mmu.o task_mmu.o 8proc-$(CONFIG_MMU) := mmu.o task_mmu.o
9 9
10proc-y += inode.o root.o base.o generic.o array.o \ 10proc-y += inode.o root.o base.o generic.o array.o \
11 proc_tty.o proc_misc.o 11 proc_tty.o
12 12proc-y += cmdline.o
13proc-y += cpuinfo.o
14proc-y += devices.o
15proc-y += interrupts.o
16proc-y += loadavg.o
17proc-y += meminfo.o
18proc-y += stat.o
19proc-y += uptime.o
20proc-y += version.o
13proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o 21proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o
14proc-$(CONFIG_NET) += proc_net.o 22proc-$(CONFIG_NET) += proc_net.o
15proc-$(CONFIG_PROC_KCORE) += kcore.o 23proc-$(CONFIG_PROC_KCORE) += kcore.o
16proc-$(CONFIG_PROC_VMCORE) += vmcore.o 24proc-$(CONFIG_PROC_VMCORE) += vmcore.o
17proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o 25proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o
18proc-$(CONFIG_PRINTK) += kmsg.o 26proc-$(CONFIG_PRINTK) += kmsg.o
27proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o
diff --git a/fs/proc/array.c b/fs/proc/array.c
index f4bc0e789539..7e4877d9dcb5 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -40,7 +40,7 @@
40 * 40 *
41 * 41 *
42 * Alan Cox : security fixes. 42 * Alan Cox : security fixes.
43 * <Alan.Cox@linux.org> 43 * <alan@lxorguk.ukuu.org.uk>
44 * 44 *
45 * Al Viro : safe handling of mm_struct 45 * Al Viro : safe handling of mm_struct
46 * 46 *
@@ -159,6 +159,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
159 struct group_info *group_info; 159 struct group_info *group_info;
160 int g; 160 int g;
161 struct fdtable *fdt = NULL; 161 struct fdtable *fdt = NULL;
162 const struct cred *cred;
162 pid_t ppid, tpid; 163 pid_t ppid, tpid;
163 164
164 rcu_read_lock(); 165 rcu_read_lock();
@@ -170,6 +171,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
170 if (tracer) 171 if (tracer)
171 tpid = task_pid_nr_ns(tracer, ns); 172 tpid = task_pid_nr_ns(tracer, ns);
172 } 173 }
174 cred = get_cred((struct cred *) __task_cred(p));
173 seq_printf(m, 175 seq_printf(m,
174 "State:\t%s\n" 176 "State:\t%s\n"
175 "Tgid:\t%d\n" 177 "Tgid:\t%d\n"
@@ -182,8 +184,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
182 task_tgid_nr_ns(p, ns), 184 task_tgid_nr_ns(p, ns),
183 pid_nr_ns(pid, ns), 185 pid_nr_ns(pid, ns),
184 ppid, tpid, 186 ppid, tpid,
185 p->uid, p->euid, p->suid, p->fsuid, 187 cred->uid, cred->euid, cred->suid, cred->fsuid,
186 p->gid, p->egid, p->sgid, p->fsgid); 188 cred->gid, cred->egid, cred->sgid, cred->fsgid);
187 189
188 task_lock(p); 190 task_lock(p);
189 if (p->files) 191 if (p->files)
@@ -194,13 +196,12 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
194 fdt ? fdt->max_fds : 0); 196 fdt ? fdt->max_fds : 0);
195 rcu_read_unlock(); 197 rcu_read_unlock();
196 198
197 group_info = p->group_info; 199 group_info = cred->group_info;
198 get_group_info(group_info);
199 task_unlock(p); 200 task_unlock(p);
200 201
201 for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) 202 for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
202 seq_printf(m, "%d ", GROUP_AT(group_info, g)); 203 seq_printf(m, "%d ", GROUP_AT(group_info, g));
203 put_group_info(group_info); 204 put_cred(cred);
204 205
205 seq_printf(m, "\n"); 206 seq_printf(m, "\n");
206} 207}
@@ -262,7 +263,7 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p)
262 blocked = p->blocked; 263 blocked = p->blocked;
263 collect_sigign_sigcatch(p, &ignored, &caught); 264 collect_sigign_sigcatch(p, &ignored, &caught);
264 num_threads = atomic_read(&p->signal->count); 265 num_threads = atomic_read(&p->signal->count);
265 qsize = atomic_read(&p->user->sigpending); 266 qsize = atomic_read(&__task_cred(p)->user->sigpending);
266 qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur; 267 qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
267 unlock_task_sighand(p, &flags); 268 unlock_task_sighand(p, &flags);
268 } 269 }
@@ -293,10 +294,21 @@ static void render_cap_t(struct seq_file *m, const char *header,
293 294
294static inline void task_cap(struct seq_file *m, struct task_struct *p) 295static inline void task_cap(struct seq_file *m, struct task_struct *p)
295{ 296{
296 render_cap_t(m, "CapInh:\t", &p->cap_inheritable); 297 const struct cred *cred;
297 render_cap_t(m, "CapPrm:\t", &p->cap_permitted); 298 kernel_cap_t cap_inheritable, cap_permitted, cap_effective, cap_bset;
298 render_cap_t(m, "CapEff:\t", &p->cap_effective); 299
299 render_cap_t(m, "CapBnd:\t", &p->cap_bset); 300 rcu_read_lock();
301 cred = __task_cred(p);
302 cap_inheritable = cred->cap_inheritable;
303 cap_permitted = cred->cap_permitted;
304 cap_effective = cred->cap_effective;
305 cap_bset = cred->cap_bset;
306 rcu_read_unlock();
307
308 render_cap_t(m, "CapInh:\t", &cap_inheritable);
309 render_cap_t(m, "CapPrm:\t", &cap_permitted);
310 render_cap_t(m, "CapEff:\t", &cap_effective);
311 render_cap_t(m, "CapBnd:\t", &cap_bset);
300} 312}
301 313
302static inline void task_context_switch_counts(struct seq_file *m, 314static inline void task_context_switch_counts(struct seq_file *m,
@@ -388,20 +400,20 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
388 400
389 /* add up live thread stats at the group level */ 401 /* add up live thread stats at the group level */
390 if (whole) { 402 if (whole) {
403 struct task_cputime cputime;
391 struct task_struct *t = task; 404 struct task_struct *t = task;
392 do { 405 do {
393 min_flt += t->min_flt; 406 min_flt += t->min_flt;
394 maj_flt += t->maj_flt; 407 maj_flt += t->maj_flt;
395 utime = cputime_add(utime, task_utime(t));
396 stime = cputime_add(stime, task_stime(t));
397 gtime = cputime_add(gtime, task_gtime(t)); 408 gtime = cputime_add(gtime, task_gtime(t));
398 t = next_thread(t); 409 t = next_thread(t);
399 } while (t != task); 410 } while (t != task);
400 411
401 min_flt += sig->min_flt; 412 min_flt += sig->min_flt;
402 maj_flt += sig->maj_flt; 413 maj_flt += sig->maj_flt;
403 utime = cputime_add(utime, sig->utime); 414 thread_group_cputime(task, &cputime);
404 stime = cputime_add(stime, sig->stime); 415 utime = cputime.utime;
416 stime = cputime.stime;
405 gtime = cputime_add(gtime, sig->gtime); 417 gtime = cputime_add(gtime, sig->gtime);
406 } 418 }
407 419
diff --git a/fs/proc/base.c b/fs/proc/base.c
index b5918ae8ca79..cad92c1ac2b3 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -347,8 +347,8 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
347static int proc_pid_schedstat(struct task_struct *task, char *buffer) 347static int proc_pid_schedstat(struct task_struct *task, char *buffer)
348{ 348{
349 return sprintf(buffer, "%llu %llu %lu\n", 349 return sprintf(buffer, "%llu %llu %lu\n",
350 task->sched_info.cpu_time, 350 (unsigned long long)task->se.sum_exec_runtime,
351 task->sched_info.run_delay, 351 (unsigned long long)task->sched_info.run_delay,
352 task->sched_info.pcount); 352 task->sched_info.pcount);
353} 353}
354#endif 354#endif
@@ -371,7 +371,7 @@ static int lstats_show_proc(struct seq_file *m, void *v)
371 task->latency_record[i].time, 371 task->latency_record[i].time,
372 task->latency_record[i].max); 372 task->latency_record[i].max);
373 for (q = 0; q < LT_BACKTRACEDEPTH; q++) { 373 for (q = 0; q < LT_BACKTRACEDEPTH; q++) {
374 char sym[KSYM_NAME_LEN]; 374 char sym[KSYM_SYMBOL_LEN];
375 char *c; 375 char *c;
376 if (!task->latency_record[i].backtrace[q]) 376 if (!task->latency_record[i].backtrace[q])
377 break; 377 break;
@@ -1406,6 +1406,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
1406{ 1406{
1407 struct inode * inode; 1407 struct inode * inode;
1408 struct proc_inode *ei; 1408 struct proc_inode *ei;
1409 const struct cred *cred;
1409 1410
1410 /* We need a new inode */ 1411 /* We need a new inode */
1411 1412
@@ -1428,8 +1429,11 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
1428 inode->i_uid = 0; 1429 inode->i_uid = 0;
1429 inode->i_gid = 0; 1430 inode->i_gid = 0;
1430 if (task_dumpable(task)) { 1431 if (task_dumpable(task)) {
1431 inode->i_uid = task->euid; 1432 rcu_read_lock();
1432 inode->i_gid = task->egid; 1433 cred = __task_cred(task);
1434 inode->i_uid = cred->euid;
1435 inode->i_gid = cred->egid;
1436 rcu_read_unlock();
1433 } 1437 }
1434 security_task_to_inode(task, inode); 1438 security_task_to_inode(task, inode);
1435 1439
@@ -1445,6 +1449,8 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
1445{ 1449{
1446 struct inode *inode = dentry->d_inode; 1450 struct inode *inode = dentry->d_inode;
1447 struct task_struct *task; 1451 struct task_struct *task;
1452 const struct cred *cred;
1453
1448 generic_fillattr(inode, stat); 1454 generic_fillattr(inode, stat);
1449 1455
1450 rcu_read_lock(); 1456 rcu_read_lock();
@@ -1454,8 +1460,9 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
1454 if (task) { 1460 if (task) {
1455 if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || 1461 if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
1456 task_dumpable(task)) { 1462 task_dumpable(task)) {
1457 stat->uid = task->euid; 1463 cred = __task_cred(task);
1458 stat->gid = task->egid; 1464 stat->uid = cred->euid;
1465 stat->gid = cred->egid;
1459 } 1466 }
1460 } 1467 }
1461 rcu_read_unlock(); 1468 rcu_read_unlock();
@@ -1483,11 +1490,16 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
1483{ 1490{
1484 struct inode *inode = dentry->d_inode; 1491 struct inode *inode = dentry->d_inode;
1485 struct task_struct *task = get_proc_task(inode); 1492 struct task_struct *task = get_proc_task(inode);
1493 const struct cred *cred;
1494
1486 if (task) { 1495 if (task) {
1487 if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || 1496 if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
1488 task_dumpable(task)) { 1497 task_dumpable(task)) {
1489 inode->i_uid = task->euid; 1498 rcu_read_lock();
1490 inode->i_gid = task->egid; 1499 cred = __task_cred(task);
1500 inode->i_uid = cred->euid;
1501 inode->i_gid = cred->egid;
1502 rcu_read_unlock();
1491 } else { 1503 } else {
1492 inode->i_uid = 0; 1504 inode->i_uid = 0;
1493 inode->i_gid = 0; 1505 inode->i_gid = 0;
@@ -1649,6 +1661,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1649 struct task_struct *task = get_proc_task(inode); 1661 struct task_struct *task = get_proc_task(inode);
1650 int fd = proc_fd(inode); 1662 int fd = proc_fd(inode);
1651 struct files_struct *files; 1663 struct files_struct *files;
1664 const struct cred *cred;
1652 1665
1653 if (task) { 1666 if (task) {
1654 files = get_files_struct(task); 1667 files = get_files_struct(task);
@@ -1658,8 +1671,11 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1658 rcu_read_unlock(); 1671 rcu_read_unlock();
1659 put_files_struct(files); 1672 put_files_struct(files);
1660 if (task_dumpable(task)) { 1673 if (task_dumpable(task)) {
1661 inode->i_uid = task->euid; 1674 rcu_read_lock();
1662 inode->i_gid = task->egid; 1675 cred = __task_cred(task);
1676 inode->i_uid = cred->euid;
1677 inode->i_gid = cred->egid;
1678 rcu_read_unlock();
1663 } else { 1679 } else {
1664 inode->i_uid = 0; 1680 inode->i_uid = 0;
1665 inode->i_gid = 0; 1681 inode->i_gid = 0;
@@ -1712,9 +1728,9 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
1712 file = fcheck_files(files, fd); 1728 file = fcheck_files(files, fd);
1713 if (!file) 1729 if (!file)
1714 goto out_unlock; 1730 goto out_unlock;
1715 if (file->f_mode & 1) 1731 if (file->f_mode & FMODE_READ)
1716 inode->i_mode |= S_IRUSR | S_IXUSR; 1732 inode->i_mode |= S_IRUSR | S_IXUSR;
1717 if (file->f_mode & 2) 1733 if (file->f_mode & FMODE_WRITE)
1718 inode->i_mode |= S_IWUSR | S_IXUSR; 1734 inode->i_mode |= S_IWUSR | S_IXUSR;
1719 spin_unlock(&files->file_lock); 1735 spin_unlock(&files->file_lock);
1720 put_files_struct(files); 1736 put_files_struct(files);
diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c
new file mode 100644
index 000000000000..82676e3fcd1d
--- /dev/null
+++ b/fs/proc/cmdline.c
@@ -0,0 +1,29 @@
1#include <linux/fs.h>
2#include <linux/init.h>
3#include <linux/proc_fs.h>
4#include <linux/seq_file.h>
5
6static int cmdline_proc_show(struct seq_file *m, void *v)
7{
8 seq_printf(m, "%s\n", saved_command_line);
9 return 0;
10}
11
12static int cmdline_proc_open(struct inode *inode, struct file *file)
13{
14 return single_open(file, cmdline_proc_show, NULL);
15}
16
17static const struct file_operations cmdline_proc_fops = {
18 .open = cmdline_proc_open,
19 .read = seq_read,
20 .llseek = seq_lseek,
21 .release = single_release,
22};
23
24static int __init proc_cmdline_init(void)
25{
26 proc_create("cmdline", 0, NULL, &cmdline_proc_fops);
27 return 0;
28}
29module_init(proc_cmdline_init);
diff --git a/fs/proc/cpuinfo.c b/fs/proc/cpuinfo.c
new file mode 100644
index 000000000000..5a1e539a234b
--- /dev/null
+++ b/fs/proc/cpuinfo.c
@@ -0,0 +1,24 @@
1#include <linux/fs.h>
2#include <linux/init.h>
3#include <linux/proc_fs.h>
4#include <linux/seq_file.h>
5
6extern const struct seq_operations cpuinfo_op;
7static int cpuinfo_open(struct inode *inode, struct file *file)
8{
9 return seq_open(file, &cpuinfo_op);
10}
11
12static const struct file_operations proc_cpuinfo_operations = {
13 .open = cpuinfo_open,
14 .read = seq_read,
15 .llseek = seq_lseek,
16 .release = seq_release,
17};
18
19static int __init proc_cpuinfo_init(void)
20{
21 proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations);
22 return 0;
23}
24module_init(proc_cpuinfo_init);
diff --git a/fs/proc/devices.c b/fs/proc/devices.c
new file mode 100644
index 000000000000..59ee7da959c9
--- /dev/null
+++ b/fs/proc/devices.c
@@ -0,0 +1,70 @@
1#include <linux/fs.h>
2#include <linux/init.h>
3#include <linux/proc_fs.h>
4#include <linux/seq_file.h>
5
6static int devinfo_show(struct seq_file *f, void *v)
7{
8 int i = *(loff_t *) v;
9
10 if (i < CHRDEV_MAJOR_HASH_SIZE) {
11 if (i == 0)
12 seq_printf(f, "Character devices:\n");
13 chrdev_show(f, i);
14 }
15#ifdef CONFIG_BLOCK
16 else {
17 i -= CHRDEV_MAJOR_HASH_SIZE;
18 if (i == 0)
19 seq_printf(f, "\nBlock devices:\n");
20 blkdev_show(f, i);
21 }
22#endif
23 return 0;
24}
25
26static void *devinfo_start(struct seq_file *f, loff_t *pos)
27{
28 if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
29 return pos;
30 return NULL;
31}
32
33static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
34{
35 (*pos)++;
36 if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
37 return NULL;
38 return pos;
39}
40
41static void devinfo_stop(struct seq_file *f, void *v)
42{
43 /* Nothing to do */
44}
45
46static const struct seq_operations devinfo_ops = {
47 .start = devinfo_start,
48 .next = devinfo_next,
49 .stop = devinfo_stop,
50 .show = devinfo_show
51};
52
53static int devinfo_open(struct inode *inode, struct file *filp)
54{
55 return seq_open(filp, &devinfo_ops);
56}
57
58static const struct file_operations proc_devinfo_operations = {
59 .open = devinfo_open,
60 .read = seq_read,
61 .llseek = seq_lseek,
62 .release = seq_release,
63};
64
65static int __init proc_devices_init(void)
66{
67 proc_create("devices", 0, NULL, &proc_devinfo_operations);
68 return 0;
69}
70module_init(proc_devices_init);
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 7821589a17d5..60a359b35582 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -547,9 +547,8 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
547 547
548 for (tmp = dir->subdir; tmp; tmp = tmp->next) 548 for (tmp = dir->subdir; tmp; tmp = tmp->next)
549 if (strcmp(tmp->name, dp->name) == 0) { 549 if (strcmp(tmp->name, dp->name) == 0) {
550 printk(KERN_WARNING "proc_dir_entry '%s/%s' already registered\n", 550 WARN(1, KERN_WARNING "proc_dir_entry '%s/%s' already registered\n",
551 dir->name, dp->name); 551 dir->name, dp->name);
552 dump_stack();
553 break; 552 break;
554 } 553 }
555 554
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index c6b4fa7e3b49..2543fd00c658 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -106,14 +106,13 @@ static void init_once(void *foo)
106 inode_init_once(&ei->vfs_inode); 106 inode_init_once(&ei->vfs_inode);
107} 107}
108 108
109int __init proc_init_inodecache(void) 109void __init proc_init_inodecache(void)
110{ 110{
111 proc_inode_cachep = kmem_cache_create("proc_inode_cache", 111 proc_inode_cachep = kmem_cache_create("proc_inode_cache",
112 sizeof(struct proc_inode), 112 sizeof(struct proc_inode),
113 0, (SLAB_RECLAIM_ACCOUNT| 113 0, (SLAB_RECLAIM_ACCOUNT|
114 SLAB_MEM_SPREAD|SLAB_PANIC), 114 SLAB_MEM_SPREAD|SLAB_PANIC),
115 init_once); 115 init_once);
116 return 0;
117} 116}
118 117
119static const struct super_operations proc_sops = { 118static const struct super_operations proc_sops = {
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 3bfb7b8747b3..3e8aeb8b61ce 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -61,12 +61,11 @@ extern const struct file_operations proc_smaps_operations;
61extern const struct file_operations proc_clear_refs_operations; 61extern const struct file_operations proc_clear_refs_operations;
62extern const struct file_operations proc_pagemap_operations; 62extern const struct file_operations proc_pagemap_operations;
63extern const struct file_operations proc_net_operations; 63extern const struct file_operations proc_net_operations;
64extern const struct file_operations proc_kmsg_operations;
65extern const struct inode_operations proc_net_inode_operations; 64extern const struct inode_operations proc_net_inode_operations;
66 65
67void free_proc_entry(struct proc_dir_entry *de); 66void free_proc_entry(struct proc_dir_entry *de);
68 67
69int proc_init_inodecache(void); 68void proc_init_inodecache(void);
70 69
71static inline struct pid *proc_pid(struct inode *inode) 70static inline struct pid *proc_pid(struct inode *inode)
72{ 71{
diff --git a/fs/proc/interrupts.c b/fs/proc/interrupts.c
new file mode 100644
index 000000000000..05029c0e2f24
--- /dev/null
+++ b/fs/proc/interrupts.c
@@ -0,0 +1,53 @@
1#include <linux/fs.h>
2#include <linux/init.h>
3#include <linux/interrupt.h>
4#include <linux/irqnr.h>
5#include <linux/proc_fs.h>
6#include <linux/seq_file.h>
7
8/*
9 * /proc/interrupts
10 */
11static void *int_seq_start(struct seq_file *f, loff_t *pos)
12{
13 return (*pos <= nr_irqs) ? pos : NULL;
14}
15
16static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
17{
18 (*pos)++;
19 if (*pos > nr_irqs)
20 return NULL;
21 return pos;
22}
23
24static void int_seq_stop(struct seq_file *f, void *v)
25{
26 /* Nothing to do */
27}
28
29static const struct seq_operations int_seq_ops = {
30 .start = int_seq_start,
31 .next = int_seq_next,
32 .stop = int_seq_stop,
33 .show = show_interrupts
34};
35
36static int interrupts_open(struct inode *inode, struct file *filp)
37{
38 return seq_open(filp, &int_seq_ops);
39}
40
41static const struct file_operations proc_interrupts_operations = {
42 .open = interrupts_open,
43 .read = seq_read,
44 .llseek = seq_lseek,
45 .release = seq_release,
46};
47
48static int __init proc_interrupts_init(void)
49{
50 proc_create("interrupts", 0, NULL, &proc_interrupts_operations);
51 return 0;
52}
53module_init(proc_interrupts_init);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index c2370c76fb71..59b43a068872 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -27,6 +27,8 @@
27#define ELF_CORE_EFLAGS 0 27#define ELF_CORE_EFLAGS 0
28#endif 28#endif
29 29
30static struct proc_dir_entry *proc_root_kcore;
31
30static int open_kcore(struct inode * inode, struct file * filp) 32static int open_kcore(struct inode * inode, struct file * filp)
31{ 33{
32 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; 34 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
@@ -34,7 +36,7 @@ static int open_kcore(struct inode * inode, struct file * filp)
34 36
35static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *); 37static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *);
36 38
37const struct file_operations proc_kcore_operations = { 39static const struct file_operations proc_kcore_operations = {
38 .read = read_kcore, 40 .read = read_kcore,
39 .open = open_kcore, 41 .open = open_kcore,
40}; 42};
@@ -399,3 +401,13 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
399 401
400 return acc; 402 return acc;
401} 403}
404
405static int __init proc_kcore_init(void)
406{
407 proc_root_kcore = proc_create("kcore", S_IRUSR, NULL, &proc_kcore_operations);
408 if (proc_root_kcore)
409 proc_root_kcore->size =
410 (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
411 return 0;
412}
413module_init(proc_kcore_init);
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 9fd5df3f40ce..7ca78346d3f0 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -10,13 +10,12 @@
10#include <linux/time.h> 10#include <linux/time.h>
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/poll.h> 12#include <linux/poll.h>
13#include <linux/proc_fs.h>
13#include <linux/fs.h> 14#include <linux/fs.h>
14 15
15#include <asm/uaccess.h> 16#include <asm/uaccess.h>
16#include <asm/io.h> 17#include <asm/io.h>
17 18
18#include "internal.h"
19
20extern wait_queue_head_t log_wait; 19extern wait_queue_head_t log_wait;
21 20
22extern int do_syslog(int type, char __user *bug, int count); 21extern int do_syslog(int type, char __user *bug, int count);
@@ -49,9 +48,16 @@ static unsigned int kmsg_poll(struct file *file, poll_table *wait)
49} 48}
50 49
51 50
52const struct file_operations proc_kmsg_operations = { 51static const struct file_operations proc_kmsg_operations = {
53 .read = kmsg_read, 52 .read = kmsg_read,
54 .poll = kmsg_poll, 53 .poll = kmsg_poll,
55 .open = kmsg_open, 54 .open = kmsg_open,
56 .release = kmsg_release, 55 .release = kmsg_release,
57}; 56};
57
58static int __init proc_kmsg_init(void)
59{
60 proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations);
61 return 0;
62}
63module_init(proc_kmsg_init);
diff --git a/fs/proc/loadavg.c b/fs/proc/loadavg.c
new file mode 100644
index 000000000000..9bca39cf99ee
--- /dev/null
+++ b/fs/proc/loadavg.c
@@ -0,0 +1,51 @@
1#include <linux/fs.h>
2#include <linux/init.h>
3#include <linux/pid_namespace.h>
4#include <linux/proc_fs.h>
5#include <linux/sched.h>
6#include <linux/seq_file.h>
7#include <linux/seqlock.h>
8#include <linux/time.h>
9
10#define LOAD_INT(x) ((x) >> FSHIFT)
11#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
12
13static int loadavg_proc_show(struct seq_file *m, void *v)
14{
15 int a, b, c;
16 unsigned long seq;
17
18 do {
19 seq = read_seqbegin(&xtime_lock);
20 a = avenrun[0] + (FIXED_1/200);
21 b = avenrun[1] + (FIXED_1/200);
22 c = avenrun[2] + (FIXED_1/200);
23 } while (read_seqretry(&xtime_lock, seq));
24
25 seq_printf(m, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
26 LOAD_INT(a), LOAD_FRAC(a),
27 LOAD_INT(b), LOAD_FRAC(b),
28 LOAD_INT(c), LOAD_FRAC(c),
29 nr_running(), nr_threads,
30 task_active_pid_ns(current)->last_pid);
31 return 0;
32}
33
34static int loadavg_proc_open(struct inode *inode, struct file *file)
35{
36 return single_open(file, loadavg_proc_show, NULL);
37}
38
39static const struct file_operations loadavg_proc_fops = {
40 .open = loadavg_proc_open,
41 .read = seq_read,
42 .llseek = seq_lseek,
43 .release = single_release,
44};
45
46static int __init proc_loadavg_init(void)
47{
48 proc_create("loadavg", 0, NULL, &loadavg_proc_fops);
49 return 0;
50}
51module_init(proc_loadavg_init);
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
new file mode 100644
index 000000000000..b1675c4e66da
--- /dev/null
+++ b/fs/proc/meminfo.c
@@ -0,0 +1,168 @@
1#include <linux/fs.h>
2#include <linux/hugetlb.h>
3#include <linux/init.h>
4#include <linux/kernel.h>
5#include <linux/mm.h>
6#include <linux/mman.h>
7#include <linux/mmzone.h>
8#include <linux/proc_fs.h>
9#include <linux/quicklist.h>
10#include <linux/seq_file.h>
11#include <linux/swap.h>
12#include <linux/vmstat.h>
13#include <asm/atomic.h>
14#include <asm/page.h>
15#include <asm/pgtable.h>
16#include "internal.h"
17
18void __attribute__((weak)) arch_report_meminfo(struct seq_file *m)
19{
20}
21
22static int meminfo_proc_show(struct seq_file *m, void *v)
23{
24 struct sysinfo i;
25 unsigned long committed;
26 unsigned long allowed;
27 struct vmalloc_info vmi;
28 long cached;
29 unsigned long pages[NR_LRU_LISTS];
30 int lru;
31
32/*
33 * display in kilobytes.
34 */
35#define K(x) ((x) << (PAGE_SHIFT - 10))
36 si_meminfo(&i);
37 si_swapinfo(&i);
38 committed = atomic_long_read(&vm_committed_space);
39 allowed = ((totalram_pages - hugetlb_total_pages())
40 * sysctl_overcommit_ratio / 100) + total_swap_pages;
41
42 cached = global_page_state(NR_FILE_PAGES) -
43 total_swapcache_pages - i.bufferram;
44 if (cached < 0)
45 cached = 0;
46
47 get_vmalloc_info(&vmi);
48
49 for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++)
50 pages[lru] = global_page_state(NR_LRU_BASE + lru);
51
52 /*
53 * Tagged format, for easy grepping and expansion.
54 */
55 seq_printf(m,
56 "MemTotal: %8lu kB\n"
57 "MemFree: %8lu kB\n"
58 "Buffers: %8lu kB\n"
59 "Cached: %8lu kB\n"
60 "SwapCached: %8lu kB\n"
61 "Active: %8lu kB\n"
62 "Inactive: %8lu kB\n"
63 "Active(anon): %8lu kB\n"
64 "Inactive(anon): %8lu kB\n"
65 "Active(file): %8lu kB\n"
66 "Inactive(file): %8lu kB\n"
67#ifdef CONFIG_UNEVICTABLE_LRU
68 "Unevictable: %8lu kB\n"
69 "Mlocked: %8lu kB\n"
70#endif
71#ifdef CONFIG_HIGHMEM
72 "HighTotal: %8lu kB\n"
73 "HighFree: %8lu kB\n"
74 "LowTotal: %8lu kB\n"
75 "LowFree: %8lu kB\n"
76#endif
77 "SwapTotal: %8lu kB\n"
78 "SwapFree: %8lu kB\n"
79 "Dirty: %8lu kB\n"
80 "Writeback: %8lu kB\n"
81 "AnonPages: %8lu kB\n"
82 "Mapped: %8lu kB\n"
83 "Slab: %8lu kB\n"
84 "SReclaimable: %8lu kB\n"
85 "SUnreclaim: %8lu kB\n"
86 "PageTables: %8lu kB\n"
87#ifdef CONFIG_QUICKLIST
88 "Quicklists: %8lu kB\n"
89#endif
90 "NFS_Unstable: %8lu kB\n"
91 "Bounce: %8lu kB\n"
92 "WritebackTmp: %8lu kB\n"
93 "CommitLimit: %8lu kB\n"
94 "Committed_AS: %8lu kB\n"
95 "VmallocTotal: %8lu kB\n"
96 "VmallocUsed: %8lu kB\n"
97 "VmallocChunk: %8lu kB\n",
98 K(i.totalram),
99 K(i.freeram),
100 K(i.bufferram),
101 K(cached),
102 K(total_swapcache_pages),
103 K(pages[LRU_ACTIVE_ANON] + pages[LRU_ACTIVE_FILE]),
104 K(pages[LRU_INACTIVE_ANON] + pages[LRU_INACTIVE_FILE]),
105 K(pages[LRU_ACTIVE_ANON]),
106 K(pages[LRU_INACTIVE_ANON]),
107 K(pages[LRU_ACTIVE_FILE]),
108 K(pages[LRU_INACTIVE_FILE]),
109#ifdef CONFIG_UNEVICTABLE_LRU
110 K(pages[LRU_UNEVICTABLE]),
111 K(global_page_state(NR_MLOCK)),
112#endif
113#ifdef CONFIG_HIGHMEM
114 K(i.totalhigh),
115 K(i.freehigh),
116 K(i.totalram-i.totalhigh),
117 K(i.freeram-i.freehigh),
118#endif
119 K(i.totalswap),
120 K(i.freeswap),
121 K(global_page_state(NR_FILE_DIRTY)),
122 K(global_page_state(NR_WRITEBACK)),
123 K(global_page_state(NR_ANON_PAGES)),
124 K(global_page_state(NR_FILE_MAPPED)),
125 K(global_page_state(NR_SLAB_RECLAIMABLE) +
126 global_page_state(NR_SLAB_UNRECLAIMABLE)),
127 K(global_page_state(NR_SLAB_RECLAIMABLE)),
128 K(global_page_state(NR_SLAB_UNRECLAIMABLE)),
129 K(global_page_state(NR_PAGETABLE)),
130#ifdef CONFIG_QUICKLIST
131 K(quicklist_total_size()),
132#endif
133 K(global_page_state(NR_UNSTABLE_NFS)),
134 K(global_page_state(NR_BOUNCE)),
135 K(global_page_state(NR_WRITEBACK_TEMP)),
136 K(allowed),
137 K(committed),
138 (unsigned long)VMALLOC_TOTAL >> 10,
139 vmi.used >> 10,
140 vmi.largest_chunk >> 10
141 );
142
143 hugetlb_report_meminfo(m);
144
145 arch_report_meminfo(m);
146
147 return 0;
148#undef K
149}
150
151static int meminfo_proc_open(struct inode *inode, struct file *file)
152{
153 return single_open(file, meminfo_proc_show, NULL);
154}
155
156static const struct file_operations meminfo_proc_fops = {
157 .open = meminfo_proc_open,
158 .read = seq_read,
159 .llseek = seq_lseek,
160 .release = single_release,
161};
162
163static int __init proc_meminfo_init(void)
164{
165 proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
166 return 0;
167}
168module_init(proc_meminfo_init);
diff --git a/fs/proc/page.c b/fs/proc/page.c
new file mode 100644
index 000000000000..767d95a6d1b1
--- /dev/null
+++ b/fs/proc/page.c
@@ -0,0 +1,147 @@
1#include <linux/bootmem.h>
2#include <linux/compiler.h>
3#include <linux/fs.h>
4#include <linux/init.h>
5#include <linux/mm.h>
6#include <linux/mmzone.h>
7#include <linux/proc_fs.h>
8#include <linux/seq_file.h>
9#include <asm/uaccess.h>
10#include "internal.h"
11
12#define KPMSIZE sizeof(u64)
13#define KPMMASK (KPMSIZE - 1)
14/* /proc/kpagecount - an array exposing page counts
15 *
16 * Each entry is a u64 representing the corresponding
17 * physical page count.
18 */
19static ssize_t kpagecount_read(struct file *file, char __user *buf,
20 size_t count, loff_t *ppos)
21{
22 u64 __user *out = (u64 __user *)buf;
23 struct page *ppage;
24 unsigned long src = *ppos;
25 unsigned long pfn;
26 ssize_t ret = 0;
27 u64 pcount;
28
29 pfn = src / KPMSIZE;
30 count = min_t(size_t, count, (max_pfn * KPMSIZE) - src);
31 if (src & KPMMASK || count & KPMMASK)
32 return -EINVAL;
33
34 while (count > 0) {
35 ppage = NULL;
36 if (pfn_valid(pfn))
37 ppage = pfn_to_page(pfn);
38 pfn++;
39 if (!ppage)
40 pcount = 0;
41 else
42 pcount = page_mapcount(ppage);
43
44 if (put_user(pcount, out++)) {
45 ret = -EFAULT;
46 break;
47 }
48
49 count -= KPMSIZE;
50 }
51
52 *ppos += (char __user *)out - buf;
53 if (!ret)
54 ret = (char __user *)out - buf;
55 return ret;
56}
57
58static const struct file_operations proc_kpagecount_operations = {
59 .llseek = mem_lseek,
60 .read = kpagecount_read,
61};
62
63/* /proc/kpageflags - an array exposing page flags
64 *
65 * Each entry is a u64 representing the corresponding
66 * physical page flags.
67 */
68
69/* These macros are used to decouple internal flags from exported ones */
70
71#define KPF_LOCKED 0
72#define KPF_ERROR 1
73#define KPF_REFERENCED 2
74#define KPF_UPTODATE 3
75#define KPF_DIRTY 4
76#define KPF_LRU 5
77#define KPF_ACTIVE 6
78#define KPF_SLAB 7
79#define KPF_WRITEBACK 8
80#define KPF_RECLAIM 9
81#define KPF_BUDDY 10
82
83#define kpf_copy_bit(flags, srcpos, dstpos) (((flags >> srcpos) & 1) << dstpos)
84
85static ssize_t kpageflags_read(struct file *file, char __user *buf,
86 size_t count, loff_t *ppos)
87{
88 u64 __user *out = (u64 __user *)buf;
89 struct page *ppage;
90 unsigned long src = *ppos;
91 unsigned long pfn;
92 ssize_t ret = 0;
93 u64 kflags, uflags;
94
95 pfn = src / KPMSIZE;
96 count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
97 if (src & KPMMASK || count & KPMMASK)
98 return -EINVAL;
99
100 while (count > 0) {
101 ppage = NULL;
102 if (pfn_valid(pfn))
103 ppage = pfn_to_page(pfn);
104 pfn++;
105 if (!ppage)
106 kflags = 0;
107 else
108 kflags = ppage->flags;
109
110 uflags = kpf_copy_bit(KPF_LOCKED, PG_locked, kflags) |
111 kpf_copy_bit(kflags, KPF_ERROR, PG_error) |
112 kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) |
113 kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) |
114 kpf_copy_bit(kflags, KPF_DIRTY, PG_dirty) |
115 kpf_copy_bit(kflags, KPF_LRU, PG_lru) |
116 kpf_copy_bit(kflags, KPF_ACTIVE, PG_active) |
117 kpf_copy_bit(kflags, KPF_SLAB, PG_slab) |
118 kpf_copy_bit(kflags, KPF_WRITEBACK, PG_writeback) |
119 kpf_copy_bit(kflags, KPF_RECLAIM, PG_reclaim) |
120 kpf_copy_bit(kflags, KPF_BUDDY, PG_buddy);
121
122 if (put_user(uflags, out++)) {
123 ret = -EFAULT;
124 break;
125 }
126
127 count -= KPMSIZE;
128 }
129
130 *ppos += (char __user *)out - buf;
131 if (!ret)
132 ret = (char __user *)out - buf;
133 return ret;
134}
135
136static const struct file_operations proc_kpageflags_operations = {
137 .llseek = mem_lseek,
138 .read = kpageflags_read,
139};
140
141static int __init proc_page_init(void)
142{
143 proc_create("kpagecount", S_IRUSR, NULL, &proc_kpagecount_operations);
144 proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations);
145 return 0;
146}
147module_init(proc_page_init);
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index eca471bc8512..de2bba5a3440 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -4,6 +4,7 @@
4 * Copyright 1997 Paul Mackerras 4 * Copyright 1997 Paul Mackerras
5 */ 5 */
6#include <linux/errno.h> 6#include <linux/errno.h>
7#include <linux/init.h>
7#include <linux/time.h> 8#include <linux/time.h>
8#include <linux/proc_fs.h> 9#include <linux/proc_fs.h>
9#include <linux/stat.h> 10#include <linux/stat.h>
@@ -214,11 +215,10 @@ void proc_device_tree_add_node(struct device_node *np,
214/* 215/*
215 * Called on initialization to set up the /proc/device-tree subtree 216 * Called on initialization to set up the /proc/device-tree subtree
216 */ 217 */
217void proc_device_tree_init(void) 218void __init proc_device_tree_init(void)
218{ 219{
219 struct device_node *root; 220 struct device_node *root;
220 if ( !have_of ) 221
221 return;
222 proc_device_tree = proc_mkdir("device-tree", NULL); 222 proc_device_tree = proc_mkdir("device-tree", NULL);
223 if (proc_device_tree == 0) 223 if (proc_device_tree == 0)
224 return; 224 return;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
deleted file mode 100644
index b675a49c1823..000000000000
--- a/fs/proc/proc_misc.c
+++ /dev/null
@@ -1,940 +0,0 @@
1/*
2 * linux/fs/proc/proc_misc.c
3 *
4 * linux/fs/proc/array.c
5 * Copyright (C) 1992 by Linus Torvalds
6 * based on ideas by Darren Senn
7 *
8 * This used to be the part of array.c. See the rest of history and credits
9 * there. I took this into a separate file and switched the thing to generic
10 * proc_file_inode_operations, leaving in array.c only per-process stuff.
11 * Inumbers allocation made dynamic (via create_proc_entry()). AV, May 1999.
12 *
13 * Changes:
14 * Fulton Green : Encapsulated position metric calculations.
15 * <kernel@FultonGreen.com>
16 */
17
18#include <linux/types.h>
19#include <linux/errno.h>
20#include <linux/time.h>
21#include <linux/kernel.h>
22#include <linux/kernel_stat.h>
23#include <linux/fs.h>
24#include <linux/tty.h>
25#include <linux/string.h>
26#include <linux/mman.h>
27#include <linux/quicklist.h>
28#include <linux/proc_fs.h>
29#include <linux/ioport.h>
30#include <linux/mm.h>
31#include <linux/mmzone.h>
32#include <linux/pagemap.h>
33#include <linux/interrupt.h>
34#include <linux/swap.h>
35#include <linux/slab.h>
36#include <linux/genhd.h>
37#include <linux/smp.h>
38#include <linux/signal.h>
39#include <linux/module.h>
40#include <linux/init.h>
41#include <linux/seq_file.h>
42#include <linux/times.h>
43#include <linux/profile.h>
44#include <linux/utsname.h>
45#include <linux/blkdev.h>
46#include <linux/hugetlb.h>
47#include <linux/jiffies.h>
48#include <linux/sysrq.h>
49#include <linux/vmalloc.h>
50#include <linux/crash_dump.h>
51#include <linux/pid_namespace.h>
52#include <linux/bootmem.h>
53#include <asm/uaccess.h>
54#include <asm/pgtable.h>
55#include <asm/io.h>
56#include <asm/tlb.h>
57#include <asm/div64.h>
58#include "internal.h"
59
60#define LOAD_INT(x) ((x) >> FSHIFT)
61#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
62/*
63 * Warning: stuff below (imported functions) assumes that its output will fit
64 * into one page. For some of those functions it may be wrong. Moreover, we
65 * have a way to deal with that gracefully. Right now I used straightforward
66 * wrappers, but this needs further analysis wrt potential overflows.
67 */
68extern int get_hardware_list(char *);
69extern int get_stram_list(char *);
70extern int get_exec_domain_list(char *);
71
72static int proc_calc_metrics(char *page, char **start, off_t off,
73 int count, int *eof, int len)
74{
75 if (len <= off+count) *eof = 1;
76 *start = page + off;
77 len -= off;
78 if (len>count) len = count;
79 if (len<0) len = 0;
80 return len;
81}
82
83static int loadavg_read_proc(char *page, char **start, off_t off,
84 int count, int *eof, void *data)
85{
86 int a, b, c;
87 int len;
88 unsigned long seq;
89
90 do {
91 seq = read_seqbegin(&xtime_lock);
92 a = avenrun[0] + (FIXED_1/200);
93 b = avenrun[1] + (FIXED_1/200);
94 c = avenrun[2] + (FIXED_1/200);
95 } while (read_seqretry(&xtime_lock, seq));
96
97 len = sprintf(page,"%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
98 LOAD_INT(a), LOAD_FRAC(a),
99 LOAD_INT(b), LOAD_FRAC(b),
100 LOAD_INT(c), LOAD_FRAC(c),
101 nr_running(), nr_threads,
102 task_active_pid_ns(current)->last_pid);
103 return proc_calc_metrics(page, start, off, count, eof, len);
104}
105
106static int uptime_read_proc(char *page, char **start, off_t off,
107 int count, int *eof, void *data)
108{
109 struct timespec uptime;
110 struct timespec idle;
111 int len;
112 cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
113
114 do_posix_clock_monotonic_gettime(&uptime);
115 monotonic_to_bootbased(&uptime);
116 cputime_to_timespec(idletime, &idle);
117 len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
118 (unsigned long) uptime.tv_sec,
119 (uptime.tv_nsec / (NSEC_PER_SEC / 100)),
120 (unsigned long) idle.tv_sec,
121 (idle.tv_nsec / (NSEC_PER_SEC / 100)));
122
123 return proc_calc_metrics(page, start, off, count, eof, len);
124}
125
126int __attribute__((weak)) arch_report_meminfo(char *page)
127{
128 return 0;
129}
130
131static int meminfo_read_proc(char *page, char **start, off_t off,
132 int count, int *eof, void *data)
133{
134 struct sysinfo i;
135 int len;
136 unsigned long committed;
137 unsigned long allowed;
138 struct vmalloc_info vmi;
139 long cached;
140
141/*
142 * display in kilobytes.
143 */
144#define K(x) ((x) << (PAGE_SHIFT - 10))
145 si_meminfo(&i);
146 si_swapinfo(&i);
147 committed = atomic_long_read(&vm_committed_space);
148 allowed = ((totalram_pages - hugetlb_total_pages())
149 * sysctl_overcommit_ratio / 100) + total_swap_pages;
150
151 cached = global_page_state(NR_FILE_PAGES) -
152 total_swapcache_pages - i.bufferram;
153 if (cached < 0)
154 cached = 0;
155
156 get_vmalloc_info(&vmi);
157
158 /*
159 * Tagged format, for easy grepping and expansion.
160 */
161 len = sprintf(page,
162 "MemTotal: %8lu kB\n"
163 "MemFree: %8lu kB\n"
164 "Buffers: %8lu kB\n"
165 "Cached: %8lu kB\n"
166 "SwapCached: %8lu kB\n"
167 "Active: %8lu kB\n"
168 "Inactive: %8lu kB\n"
169#ifdef CONFIG_HIGHMEM
170 "HighTotal: %8lu kB\n"
171 "HighFree: %8lu kB\n"
172 "LowTotal: %8lu kB\n"
173 "LowFree: %8lu kB\n"
174#endif
175 "SwapTotal: %8lu kB\n"
176 "SwapFree: %8lu kB\n"
177 "Dirty: %8lu kB\n"
178 "Writeback: %8lu kB\n"
179 "AnonPages: %8lu kB\n"
180 "Mapped: %8lu kB\n"
181 "Slab: %8lu kB\n"
182 "SReclaimable: %8lu kB\n"
183 "SUnreclaim: %8lu kB\n"
184 "PageTables: %8lu kB\n"
185#ifdef CONFIG_QUICKLIST
186 "Quicklists: %8lu kB\n"
187#endif
188 "NFS_Unstable: %8lu kB\n"
189 "Bounce: %8lu kB\n"
190 "WritebackTmp: %8lu kB\n"
191 "CommitLimit: %8lu kB\n"
192 "Committed_AS: %8lu kB\n"
193 "VmallocTotal: %8lu kB\n"
194 "VmallocUsed: %8lu kB\n"
195 "VmallocChunk: %8lu kB\n",
196 K(i.totalram),
197 K(i.freeram),
198 K(i.bufferram),
199 K(cached),
200 K(total_swapcache_pages),
201 K(global_page_state(NR_ACTIVE)),
202 K(global_page_state(NR_INACTIVE)),
203#ifdef CONFIG_HIGHMEM
204 K(i.totalhigh),
205 K(i.freehigh),
206 K(i.totalram-i.totalhigh),
207 K(i.freeram-i.freehigh),
208#endif
209 K(i.totalswap),
210 K(i.freeswap),
211 K(global_page_state(NR_FILE_DIRTY)),
212 K(global_page_state(NR_WRITEBACK)),
213 K(global_page_state(NR_ANON_PAGES)),
214 K(global_page_state(NR_FILE_MAPPED)),
215 K(global_page_state(NR_SLAB_RECLAIMABLE) +
216 global_page_state(NR_SLAB_UNRECLAIMABLE)),
217 K(global_page_state(NR_SLAB_RECLAIMABLE)),
218 K(global_page_state(NR_SLAB_UNRECLAIMABLE)),
219 K(global_page_state(NR_PAGETABLE)),
220#ifdef CONFIG_QUICKLIST
221 K(quicklist_total_size()),
222#endif
223 K(global_page_state(NR_UNSTABLE_NFS)),
224 K(global_page_state(NR_BOUNCE)),
225 K(global_page_state(NR_WRITEBACK_TEMP)),
226 K(allowed),
227 K(committed),
228 (unsigned long)VMALLOC_TOTAL >> 10,
229 vmi.used >> 10,
230 vmi.largest_chunk >> 10
231 );
232
233 len += hugetlb_report_meminfo(page + len);
234
235 len += arch_report_meminfo(page + len);
236
237 return proc_calc_metrics(page, start, off, count, eof, len);
238#undef K
239}
240
241static int fragmentation_open(struct inode *inode, struct file *file)
242{
243 (void)inode;
244 return seq_open(file, &fragmentation_op);
245}
246
247static const struct file_operations fragmentation_file_operations = {
248 .open = fragmentation_open,
249 .read = seq_read,
250 .llseek = seq_lseek,
251 .release = seq_release,
252};
253
254static int pagetypeinfo_open(struct inode *inode, struct file *file)
255{
256 return seq_open(file, &pagetypeinfo_op);
257}
258
259static const struct file_operations pagetypeinfo_file_ops = {
260 .open = pagetypeinfo_open,
261 .read = seq_read,
262 .llseek = seq_lseek,
263 .release = seq_release,
264};
265
266static int zoneinfo_open(struct inode *inode, struct file *file)
267{
268 return seq_open(file, &zoneinfo_op);
269}
270
271static const struct file_operations proc_zoneinfo_file_operations = {
272 .open = zoneinfo_open,
273 .read = seq_read,
274 .llseek = seq_lseek,
275 .release = seq_release,
276};
277
278static int version_read_proc(char *page, char **start, off_t off,
279 int count, int *eof, void *data)
280{
281 int len;
282
283 len = snprintf(page, PAGE_SIZE, linux_proc_banner,
284 utsname()->sysname,
285 utsname()->release,
286 utsname()->version);
287 return proc_calc_metrics(page, start, off, count, eof, len);
288}
289
290extern const struct seq_operations cpuinfo_op;
291static int cpuinfo_open(struct inode *inode, struct file *file)
292{
293 return seq_open(file, &cpuinfo_op);
294}
295
296static const struct file_operations proc_cpuinfo_operations = {
297 .open = cpuinfo_open,
298 .read = seq_read,
299 .llseek = seq_lseek,
300 .release = seq_release,
301};
302
303static int devinfo_show(struct seq_file *f, void *v)
304{
305 int i = *(loff_t *) v;
306
307 if (i < CHRDEV_MAJOR_HASH_SIZE) {
308 if (i == 0)
309 seq_printf(f, "Character devices:\n");
310 chrdev_show(f, i);
311 }
312#ifdef CONFIG_BLOCK
313 else {
314 i -= CHRDEV_MAJOR_HASH_SIZE;
315 if (i == 0)
316 seq_printf(f, "\nBlock devices:\n");
317 blkdev_show(f, i);
318 }
319#endif
320 return 0;
321}
322
323static void *devinfo_start(struct seq_file *f, loff_t *pos)
324{
325 if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
326 return pos;
327 return NULL;
328}
329
330static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
331{
332 (*pos)++;
333 if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
334 return NULL;
335 return pos;
336}
337
338static void devinfo_stop(struct seq_file *f, void *v)
339{
340 /* Nothing to do */
341}
342
343static const struct seq_operations devinfo_ops = {
344 .start = devinfo_start,
345 .next = devinfo_next,
346 .stop = devinfo_stop,
347 .show = devinfo_show
348};
349
350static int devinfo_open(struct inode *inode, struct file *filp)
351{
352 return seq_open(filp, &devinfo_ops);
353}
354
355static const struct file_operations proc_devinfo_operations = {
356 .open = devinfo_open,
357 .read = seq_read,
358 .llseek = seq_lseek,
359 .release = seq_release,
360};
361
362static int vmstat_open(struct inode *inode, struct file *file)
363{
364 return seq_open(file, &vmstat_op);
365}
366static const struct file_operations proc_vmstat_file_operations = {
367 .open = vmstat_open,
368 .read = seq_read,
369 .llseek = seq_lseek,
370 .release = seq_release,
371};
372
373#ifdef CONFIG_PROC_HARDWARE
374static int hardware_read_proc(char *page, char **start, off_t off,
375 int count, int *eof, void *data)
376{
377 int len = get_hardware_list(page);
378 return proc_calc_metrics(page, start, off, count, eof, len);
379}
380#endif
381
382#ifdef CONFIG_STRAM_PROC
383static int stram_read_proc(char *page, char **start, off_t off,
384 int count, int *eof, void *data)
385{
386 int len = get_stram_list(page);
387 return proc_calc_metrics(page, start, off, count, eof, len);
388}
389#endif
390
391#ifdef CONFIG_BLOCK
392static int partitions_open(struct inode *inode, struct file *file)
393{
394 return seq_open(file, &partitions_op);
395}
396static const struct file_operations proc_partitions_operations = {
397 .open = partitions_open,
398 .read = seq_read,
399 .llseek = seq_lseek,
400 .release = seq_release,
401};
402
403static int diskstats_open(struct inode *inode, struct file *file)
404{
405 return seq_open(file, &diskstats_op);
406}
407static const struct file_operations proc_diskstats_operations = {
408 .open = diskstats_open,
409 .read = seq_read,
410 .llseek = seq_lseek,
411 .release = seq_release,
412};
413#endif
414
415#ifdef CONFIG_MODULES
416extern const struct seq_operations modules_op;
417static int modules_open(struct inode *inode, struct file *file)
418{
419 return seq_open(file, &modules_op);
420}
421static const struct file_operations proc_modules_operations = {
422 .open = modules_open,
423 .read = seq_read,
424 .llseek = seq_lseek,
425 .release = seq_release,
426};
427#endif
428
429#ifdef CONFIG_SLABINFO
430static int slabinfo_open(struct inode *inode, struct file *file)
431{
432 return seq_open(file, &slabinfo_op);
433}
434static const struct file_operations proc_slabinfo_operations = {
435 .open = slabinfo_open,
436 .read = seq_read,
437 .write = slabinfo_write,
438 .llseek = seq_lseek,
439 .release = seq_release,
440};
441
442#ifdef CONFIG_DEBUG_SLAB_LEAK
443extern const struct seq_operations slabstats_op;
444static int slabstats_open(struct inode *inode, struct file *file)
445{
446 unsigned long *n = kzalloc(PAGE_SIZE, GFP_KERNEL);
447 int ret = -ENOMEM;
448 if (n) {
449 ret = seq_open(file, &slabstats_op);
450 if (!ret) {
451 struct seq_file *m = file->private_data;
452 *n = PAGE_SIZE / (2 * sizeof(unsigned long));
453 m->private = n;
454 n = NULL;
455 }
456 kfree(n);
457 }
458 return ret;
459}
460
461static const struct file_operations proc_slabstats_operations = {
462 .open = slabstats_open,
463 .read = seq_read,
464 .llseek = seq_lseek,
465 .release = seq_release_private,
466};
467#endif
468#endif
469
470#ifdef CONFIG_MMU
471static int vmalloc_open(struct inode *inode, struct file *file)
472{
473 unsigned int *ptr = NULL;
474 int ret;
475
476 if (NUMA_BUILD)
477 ptr = kmalloc(nr_node_ids * sizeof(unsigned int), GFP_KERNEL);
478 ret = seq_open(file, &vmalloc_op);
479 if (!ret) {
480 struct seq_file *m = file->private_data;
481 m->private = ptr;
482 } else
483 kfree(ptr);
484 return ret;
485}
486
487static const struct file_operations proc_vmalloc_operations = {
488 .open = vmalloc_open,
489 .read = seq_read,
490 .llseek = seq_lseek,
491 .release = seq_release_private,
492};
493#endif
494
495#ifndef arch_irq_stat_cpu
496#define arch_irq_stat_cpu(cpu) 0
497#endif
498#ifndef arch_irq_stat
499#define arch_irq_stat() 0
500#endif
501
502static int show_stat(struct seq_file *p, void *v)
503{
504 int i;
505 unsigned long jif;
506 cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
507 cputime64_t guest;
508 u64 sum = 0;
509 struct timespec boottime;
510 unsigned int *per_irq_sum;
511
512 per_irq_sum = kzalloc(sizeof(unsigned int)*NR_IRQS, GFP_KERNEL);
513 if (!per_irq_sum)
514 return -ENOMEM;
515
516 user = nice = system = idle = iowait =
517 irq = softirq = steal = cputime64_zero;
518 guest = cputime64_zero;
519 getboottime(&boottime);
520 jif = boottime.tv_sec;
521
522 for_each_possible_cpu(i) {
523 int j;
524
525 user = cputime64_add(user, kstat_cpu(i).cpustat.user);
526 nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice);
527 system = cputime64_add(system, kstat_cpu(i).cpustat.system);
528 idle = cputime64_add(idle, kstat_cpu(i).cpustat.idle);
529 iowait = cputime64_add(iowait, kstat_cpu(i).cpustat.iowait);
530 irq = cputime64_add(irq, kstat_cpu(i).cpustat.irq);
531 softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
532 steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
533 guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
534 for (j = 0; j < NR_IRQS; j++) {
535 unsigned int temp = kstat_cpu(i).irqs[j];
536 sum += temp;
537 per_irq_sum[j] += temp;
538 }
539 sum += arch_irq_stat_cpu(i);
540 }
541 sum += arch_irq_stat();
542
543 seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
544 (unsigned long long)cputime64_to_clock_t(user),
545 (unsigned long long)cputime64_to_clock_t(nice),
546 (unsigned long long)cputime64_to_clock_t(system),
547 (unsigned long long)cputime64_to_clock_t(idle),
548 (unsigned long long)cputime64_to_clock_t(iowait),
549 (unsigned long long)cputime64_to_clock_t(irq),
550 (unsigned long long)cputime64_to_clock_t(softirq),
551 (unsigned long long)cputime64_to_clock_t(steal),
552 (unsigned long long)cputime64_to_clock_t(guest));
553 for_each_online_cpu(i) {
554
555 /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
556 user = kstat_cpu(i).cpustat.user;
557 nice = kstat_cpu(i).cpustat.nice;
558 system = kstat_cpu(i).cpustat.system;
559 idle = kstat_cpu(i).cpustat.idle;
560 iowait = kstat_cpu(i).cpustat.iowait;
561 irq = kstat_cpu(i).cpustat.irq;
562 softirq = kstat_cpu(i).cpustat.softirq;
563 steal = kstat_cpu(i).cpustat.steal;
564 guest = kstat_cpu(i).cpustat.guest;
565 seq_printf(p,
566 "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
567 i,
568 (unsigned long long)cputime64_to_clock_t(user),
569 (unsigned long long)cputime64_to_clock_t(nice),
570 (unsigned long long)cputime64_to_clock_t(system),
571 (unsigned long long)cputime64_to_clock_t(idle),
572 (unsigned long long)cputime64_to_clock_t(iowait),
573 (unsigned long long)cputime64_to_clock_t(irq),
574 (unsigned long long)cputime64_to_clock_t(softirq),
575 (unsigned long long)cputime64_to_clock_t(steal),
576 (unsigned long long)cputime64_to_clock_t(guest));
577 }
578 seq_printf(p, "intr %llu", (unsigned long long)sum);
579
580 for (i = 0; i < NR_IRQS; i++)
581 seq_printf(p, " %u", per_irq_sum[i]);
582
583 seq_printf(p,
584 "\nctxt %llu\n"
585 "btime %lu\n"
586 "processes %lu\n"
587 "procs_running %lu\n"
588 "procs_blocked %lu\n",
589 nr_context_switches(),
590 (unsigned long)jif,
591 total_forks,
592 nr_running(),
593 nr_iowait());
594
595 kfree(per_irq_sum);
596 return 0;
597}
598
599static int stat_open(struct inode *inode, struct file *file)
600{
601 unsigned size = 4096 * (1 + num_possible_cpus() / 32);
602 char *buf;
603 struct seq_file *m;
604 int res;
605
606 /* don't ask for more than the kmalloc() max size, currently 128 KB */
607 if (size > 128 * 1024)
608 size = 128 * 1024;
609 buf = kmalloc(size, GFP_KERNEL);
610 if (!buf)
611 return -ENOMEM;
612
613 res = single_open(file, show_stat, NULL);
614 if (!res) {
615 m = file->private_data;
616 m->buf = buf;
617 m->size = size;
618 } else
619 kfree(buf);
620 return res;
621}
622static const struct file_operations proc_stat_operations = {
623 .open = stat_open,
624 .read = seq_read,
625 .llseek = seq_lseek,
626 .release = single_release,
627};
628
629/*
630 * /proc/interrupts
631 */
632static void *int_seq_start(struct seq_file *f, loff_t *pos)
633{
634 return (*pos <= NR_IRQS) ? pos : NULL;
635}
636
637static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
638{
639 (*pos)++;
640 if (*pos > NR_IRQS)
641 return NULL;
642 return pos;
643}
644
645static void int_seq_stop(struct seq_file *f, void *v)
646{
647 /* Nothing to do */
648}
649
650
651static const struct seq_operations int_seq_ops = {
652 .start = int_seq_start,
653 .next = int_seq_next,
654 .stop = int_seq_stop,
655 .show = show_interrupts
656};
657
658static int interrupts_open(struct inode *inode, struct file *filp)
659{
660 return seq_open(filp, &int_seq_ops);
661}
662
663static const struct file_operations proc_interrupts_operations = {
664 .open = interrupts_open,
665 .read = seq_read,
666 .llseek = seq_lseek,
667 .release = seq_release,
668};
669
670static int filesystems_read_proc(char *page, char **start, off_t off,
671 int count, int *eof, void *data)
672{
673 int len = get_filesystem_list(page);
674 return proc_calc_metrics(page, start, off, count, eof, len);
675}
676
677static int cmdline_read_proc(char *page, char **start, off_t off,
678 int count, int *eof, void *data)
679{
680 int len;
681
682 len = sprintf(page, "%s\n", saved_command_line);
683 return proc_calc_metrics(page, start, off, count, eof, len);
684}
685
686#ifdef CONFIG_FILE_LOCKING
687static int locks_open(struct inode *inode, struct file *filp)
688{
689 return seq_open(filp, &locks_seq_operations);
690}
691
692static const struct file_operations proc_locks_operations = {
693 .open = locks_open,
694 .read = seq_read,
695 .llseek = seq_lseek,
696 .release = seq_release,
697};
698#endif /* CONFIG_FILE_LOCKING */
699
700static int execdomains_read_proc(char *page, char **start, off_t off,
701 int count, int *eof, void *data)
702{
703 int len = get_exec_domain_list(page);
704 return proc_calc_metrics(page, start, off, count, eof, len);
705}
706
707#ifdef CONFIG_MAGIC_SYSRQ
708/*
709 * writing 'C' to /proc/sysrq-trigger is like sysrq-C
710 */
711static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
712 size_t count, loff_t *ppos)
713{
714 if (count) {
715 char c;
716
717 if (get_user(c, buf))
718 return -EFAULT;
719 __handle_sysrq(c, NULL, 0);
720 }
721 return count;
722}
723
724static const struct file_operations proc_sysrq_trigger_operations = {
725 .write = write_sysrq_trigger,
726};
727#endif
728
729#ifdef CONFIG_PROC_PAGE_MONITOR
730#define KPMSIZE sizeof(u64)
731#define KPMMASK (KPMSIZE - 1)
732/* /proc/kpagecount - an array exposing page counts
733 *
734 * Each entry is a u64 representing the corresponding
735 * physical page count.
736 */
737static ssize_t kpagecount_read(struct file *file, char __user *buf,
738 size_t count, loff_t *ppos)
739{
740 u64 __user *out = (u64 __user *)buf;
741 struct page *ppage;
742 unsigned long src = *ppos;
743 unsigned long pfn;
744 ssize_t ret = 0;
745 u64 pcount;
746
747 pfn = src / KPMSIZE;
748 count = min_t(size_t, count, (max_pfn * KPMSIZE) - src);
749 if (src & KPMMASK || count & KPMMASK)
750 return -EINVAL;
751
752 while (count > 0) {
753 ppage = NULL;
754 if (pfn_valid(pfn))
755 ppage = pfn_to_page(pfn);
756 pfn++;
757 if (!ppage)
758 pcount = 0;
759 else
760 pcount = page_mapcount(ppage);
761
762 if (put_user(pcount, out++)) {
763 ret = -EFAULT;
764 break;
765 }
766
767 count -= KPMSIZE;
768 }
769
770 *ppos += (char __user *)out - buf;
771 if (!ret)
772 ret = (char __user *)out - buf;
773 return ret;
774}
775
776static struct file_operations proc_kpagecount_operations = {
777 .llseek = mem_lseek,
778 .read = kpagecount_read,
779};
780
781/* /proc/kpageflags - an array exposing page flags
782 *
783 * Each entry is a u64 representing the corresponding
784 * physical page flags.
785 */
786
787/* These macros are used to decouple internal flags from exported ones */
788
789#define KPF_LOCKED 0
790#define KPF_ERROR 1
791#define KPF_REFERENCED 2
792#define KPF_UPTODATE 3
793#define KPF_DIRTY 4
794#define KPF_LRU 5
795#define KPF_ACTIVE 6
796#define KPF_SLAB 7
797#define KPF_WRITEBACK 8
798#define KPF_RECLAIM 9
799#define KPF_BUDDY 10
800
801#define kpf_copy_bit(flags, srcpos, dstpos) (((flags >> srcpos) & 1) << dstpos)
802
803static ssize_t kpageflags_read(struct file *file, char __user *buf,
804 size_t count, loff_t *ppos)
805{
806 u64 __user *out = (u64 __user *)buf;
807 struct page *ppage;
808 unsigned long src = *ppos;
809 unsigned long pfn;
810 ssize_t ret = 0;
811 u64 kflags, uflags;
812
813 pfn = src / KPMSIZE;
814 count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
815 if (src & KPMMASK || count & KPMMASK)
816 return -EINVAL;
817
818 while (count > 0) {
819 ppage = NULL;
820 if (pfn_valid(pfn))
821 ppage = pfn_to_page(pfn);
822 pfn++;
823 if (!ppage)
824 kflags = 0;
825 else
826 kflags = ppage->flags;
827
828 uflags = kpf_copy_bit(KPF_LOCKED, PG_locked, kflags) |
829 kpf_copy_bit(kflags, KPF_ERROR, PG_error) |
830 kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) |
831 kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) |
832 kpf_copy_bit(kflags, KPF_DIRTY, PG_dirty) |
833 kpf_copy_bit(kflags, KPF_LRU, PG_lru) |
834 kpf_copy_bit(kflags, KPF_ACTIVE, PG_active) |
835 kpf_copy_bit(kflags, KPF_SLAB, PG_slab) |
836 kpf_copy_bit(kflags, KPF_WRITEBACK, PG_writeback) |
837 kpf_copy_bit(kflags, KPF_RECLAIM, PG_reclaim) |
838 kpf_copy_bit(kflags, KPF_BUDDY, PG_buddy);
839
840 if (put_user(uflags, out++)) {
841 ret = -EFAULT;
842 break;
843 }
844
845 count -= KPMSIZE;
846 }
847
848 *ppos += (char __user *)out - buf;
849 if (!ret)
850 ret = (char __user *)out - buf;
851 return ret;
852}
853
854static struct file_operations proc_kpageflags_operations = {
855 .llseek = mem_lseek,
856 .read = kpageflags_read,
857};
858#endif /* CONFIG_PROC_PAGE_MONITOR */
859
860struct proc_dir_entry *proc_root_kcore;
861
862void __init proc_misc_init(void)
863{
864 static struct {
865 char *name;
866 int (*read_proc)(char*,char**,off_t,int,int*,void*);
867 } *p, simple_ones[] = {
868 {"loadavg", loadavg_read_proc},
869 {"uptime", uptime_read_proc},
870 {"meminfo", meminfo_read_proc},
871 {"version", version_read_proc},
872#ifdef CONFIG_PROC_HARDWARE
873 {"hardware", hardware_read_proc},
874#endif
875#ifdef CONFIG_STRAM_PROC
876 {"stram", stram_read_proc},
877#endif
878 {"filesystems", filesystems_read_proc},
879 {"cmdline", cmdline_read_proc},
880 {"execdomains", execdomains_read_proc},
881 {NULL,}
882 };
883 for (p = simple_ones; p->name; p++)
884 create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
885
886 proc_symlink("mounts", NULL, "self/mounts");
887
888 /* And now for trickier ones */
889#ifdef CONFIG_PRINTK
890 proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations);
891#endif
892#ifdef CONFIG_FILE_LOCKING
893 proc_create("locks", 0, NULL, &proc_locks_operations);
894#endif
895 proc_create("devices", 0, NULL, &proc_devinfo_operations);
896 proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations);
897#ifdef CONFIG_BLOCK
898 proc_create("partitions", 0, NULL, &proc_partitions_operations);
899#endif
900 proc_create("stat", 0, NULL, &proc_stat_operations);
901 proc_create("interrupts", 0, NULL, &proc_interrupts_operations);
902#ifdef CONFIG_SLABINFO
903 proc_create("slabinfo",S_IWUSR|S_IRUGO,NULL,&proc_slabinfo_operations);
904#ifdef CONFIG_DEBUG_SLAB_LEAK
905 proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
906#endif
907#endif
908#ifdef CONFIG_MMU
909 proc_create("vmallocinfo", S_IRUSR, NULL, &proc_vmalloc_operations);
910#endif
911 proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
912 proc_create("pagetypeinfo", S_IRUGO, NULL, &pagetypeinfo_file_ops);
913 proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
914 proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
915#ifdef CONFIG_BLOCK
916 proc_create("diskstats", 0, NULL, &proc_diskstats_operations);
917#endif
918#ifdef CONFIG_MODULES
919 proc_create("modules", 0, NULL, &proc_modules_operations);
920#endif
921#ifdef CONFIG_SCHEDSTATS
922 proc_create("schedstat", 0, NULL, &proc_schedstat_operations);
923#endif
924#ifdef CONFIG_PROC_KCORE
925 proc_root_kcore = proc_create("kcore", S_IRUSR, NULL, &proc_kcore_operations);
926 if (proc_root_kcore)
927 proc_root_kcore->size =
928 (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
929#endif
930#ifdef CONFIG_PROC_PAGE_MONITOR
931 proc_create("kpagecount", S_IRUSR, NULL, &proc_kpagecount_operations);
932 proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations);
933#endif
934#ifdef CONFIG_PROC_VMCORE
935 proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
936#endif
937#ifdef CONFIG_MAGIC_SYSRQ
938 proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations);
939#endif
940}
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 945a81043ba2..06ed10b7da9e 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * /proc/sys support 2 * /proc/sys support
3 */ 3 */
4 4#include <linux/init.h>
5#include <linux/sysctl.h> 5#include <linux/sysctl.h>
6#include <linux/proc_fs.h> 6#include <linux/proc_fs.h>
7#include <linux/security.h> 7#include <linux/security.h>
@@ -31,6 +31,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
31 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 31 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
32 inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */ 32 inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */
33 inode->i_mode = table->mode; 33 inode->i_mode = table->mode;
34 inode->i_uid = inode->i_gid = 0;
34 if (!table->child) { 35 if (!table->child) {
35 inode->i_mode |= S_IFREG; 36 inode->i_mode |= S_IFREG;
36 inode->i_op = &proc_sys_inode_operations; 37 inode->i_op = &proc_sys_inode_operations;
@@ -298,13 +299,19 @@ static int proc_sys_permission(struct inode *inode, int mask)
298 * sysctl entries that are not writeable, 299 * sysctl entries that are not writeable,
299 * are _NOT_ writeable, capabilities or not. 300 * are _NOT_ writeable, capabilities or not.
300 */ 301 */
301 struct ctl_table_header *head = grab_header(inode); 302 struct ctl_table_header *head;
302 struct ctl_table *table = PROC_I(inode)->sysctl_entry; 303 struct ctl_table *table;
303 int error; 304 int error;
304 305
306 /* Executable files are not allowed under /proc/sys/ */
307 if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))
308 return -EACCES;
309
310 head = grab_header(inode);
305 if (IS_ERR(head)) 311 if (IS_ERR(head))
306 return PTR_ERR(head); 312 return PTR_ERR(head);
307 313
314 table = PROC_I(inode)->sysctl_entry;
308 if (!table) /* global root - r-xr-xr-x */ 315 if (!table) /* global root - r-xr-xr-x */
309 error = mask & MAY_WRITE ? -EACCES : 0; 316 error = mask & MAY_WRITE ? -EACCES : 0;
310 else /* Use the permissions on the sysctl table entry */ 317 else /* Use the permissions on the sysctl table entry */
@@ -353,6 +360,7 @@ static const struct file_operations proc_sys_file_operations = {
353 360
354static const struct file_operations proc_sys_dir_file_operations = { 361static const struct file_operations proc_sys_dir_file_operations = {
355 .readdir = proc_sys_readdir, 362 .readdir = proc_sys_readdir,
363 .llseek = generic_file_llseek,
356}; 364};
357 365
358static const struct inode_operations proc_sys_inode_operations = { 366static const struct inode_operations proc_sys_inode_operations = {
@@ -395,7 +403,7 @@ static struct dentry_operations proc_sys_dentry_operations = {
395 .d_compare = proc_sys_compare, 403 .d_compare = proc_sys_compare,
396}; 404};
397 405
398int proc_sys_init(void) 406int __init proc_sys_init(void)
399{ 407{
400 struct proc_dir_entry *proc_sys_root; 408 struct proc_dir_entry *proc_sys_root;
401 409
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 95117538a4f6..7761602af9de 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -104,9 +104,9 @@ static struct file_system_type proc_fs_type = {
104 104
105void __init proc_root_init(void) 105void __init proc_root_init(void)
106{ 106{
107 int err = proc_init_inodecache(); 107 int err;
108 if (err) 108
109 return; 109 proc_init_inodecache();
110 err = register_filesystem(&proc_fs_type); 110 err = register_filesystem(&proc_fs_type);
111 if (err) 111 if (err)
112 return; 112 return;
@@ -117,7 +117,7 @@ void __init proc_root_init(void)
117 return; 117 return;
118 } 118 }
119 119
120 proc_misc_init(); 120 proc_symlink("mounts", NULL, "self/mounts");
121 121
122 proc_net_init(); 122 proc_net_init();
123 123
diff --git a/fs/proc/stat.c b/fs/proc/stat.c
new file mode 100644
index 000000000000..3bb1cf1e7425
--- /dev/null
+++ b/fs/proc/stat.c
@@ -0,0 +1,161 @@
1#include <linux/cpumask.h>
2#include <linux/fs.h>
3#include <linux/gfp.h>
4#include <linux/init.h>
5#include <linux/interrupt.h>
6#include <linux/kernel_stat.h>
7#include <linux/proc_fs.h>
8#include <linux/sched.h>
9#include <linux/seq_file.h>
10#include <linux/slab.h>
11#include <linux/time.h>
12#include <asm/cputime.h>
13
14#ifndef arch_irq_stat_cpu
15#define arch_irq_stat_cpu(cpu) 0
16#endif
17#ifndef arch_irq_stat
18#define arch_irq_stat() 0
19#endif
20
21static int show_stat(struct seq_file *p, void *v)
22{
23 int i, j;
24 unsigned long jif;
25 cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
26 cputime64_t guest;
27 u64 sum = 0;
28 struct timespec boottime;
29 unsigned int per_irq_sum;
30
31 user = nice = system = idle = iowait =
32 irq = softirq = steal = cputime64_zero;
33 guest = cputime64_zero;
34 getboottime(&boottime);
35 jif = boottime.tv_sec;
36
37 for_each_possible_cpu(i) {
38 user = cputime64_add(user, kstat_cpu(i).cpustat.user);
39 nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice);
40 system = cputime64_add(system, kstat_cpu(i).cpustat.system);
41 idle = cputime64_add(idle, kstat_cpu(i).cpustat.idle);
42 iowait = cputime64_add(iowait, kstat_cpu(i).cpustat.iowait);
43 irq = cputime64_add(irq, kstat_cpu(i).cpustat.irq);
44 softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
45 steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
46 guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
47 for_each_irq_nr(j) {
48#ifdef CONFIG_SPARSE_IRQ
49 if (!irq_to_desc(j))
50 continue;
51#endif
52 sum += kstat_irqs_cpu(j, i);
53 }
54 sum += arch_irq_stat_cpu(i);
55 }
56 sum += arch_irq_stat();
57
58 seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
59 (unsigned long long)cputime64_to_clock_t(user),
60 (unsigned long long)cputime64_to_clock_t(nice),
61 (unsigned long long)cputime64_to_clock_t(system),
62 (unsigned long long)cputime64_to_clock_t(idle),
63 (unsigned long long)cputime64_to_clock_t(iowait),
64 (unsigned long long)cputime64_to_clock_t(irq),
65 (unsigned long long)cputime64_to_clock_t(softirq),
66 (unsigned long long)cputime64_to_clock_t(steal),
67 (unsigned long long)cputime64_to_clock_t(guest));
68 for_each_online_cpu(i) {
69
70 /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
71 user = kstat_cpu(i).cpustat.user;
72 nice = kstat_cpu(i).cpustat.nice;
73 system = kstat_cpu(i).cpustat.system;
74 idle = kstat_cpu(i).cpustat.idle;
75 iowait = kstat_cpu(i).cpustat.iowait;
76 irq = kstat_cpu(i).cpustat.irq;
77 softirq = kstat_cpu(i).cpustat.softirq;
78 steal = kstat_cpu(i).cpustat.steal;
79 guest = kstat_cpu(i).cpustat.guest;
80 seq_printf(p,
81 "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
82 i,
83 (unsigned long long)cputime64_to_clock_t(user),
84 (unsigned long long)cputime64_to_clock_t(nice),
85 (unsigned long long)cputime64_to_clock_t(system),
86 (unsigned long long)cputime64_to_clock_t(idle),
87 (unsigned long long)cputime64_to_clock_t(iowait),
88 (unsigned long long)cputime64_to_clock_t(irq),
89 (unsigned long long)cputime64_to_clock_t(softirq),
90 (unsigned long long)cputime64_to_clock_t(steal),
91 (unsigned long long)cputime64_to_clock_t(guest));
92 }
93 seq_printf(p, "intr %llu", (unsigned long long)sum);
94
95 /* sum again ? it could be updated? */
96 for_each_irq_nr(j) {
97 per_irq_sum = 0;
98#ifdef CONFIG_SPARSE_IRQ
99 if (!irq_to_desc(j)) {
100 seq_printf(p, " %u", per_irq_sum);
101 continue;
102 }
103#endif
104 for_each_possible_cpu(i)
105 per_irq_sum += kstat_irqs_cpu(j, i);
106
107 seq_printf(p, " %u", per_irq_sum);
108 }
109
110 seq_printf(p,
111 "\nctxt %llu\n"
112 "btime %lu\n"
113 "processes %lu\n"
114 "procs_running %lu\n"
115 "procs_blocked %lu\n",
116 nr_context_switches(),
117 (unsigned long)jif,
118 total_forks,
119 nr_running(),
120 nr_iowait());
121
122 return 0;
123}
124
125static int stat_open(struct inode *inode, struct file *file)
126{
127 unsigned size = 4096 * (1 + num_possible_cpus() / 32);
128 char *buf;
129 struct seq_file *m;
130 int res;
131
132 /* don't ask for more than the kmalloc() max size, currently 128 KB */
133 if (size > 128 * 1024)
134 size = 128 * 1024;
135 buf = kmalloc(size, GFP_KERNEL);
136 if (!buf)
137 return -ENOMEM;
138
139 res = single_open(file, show_stat, NULL);
140 if (!res) {
141 m = file->private_data;
142 m->buf = buf;
143 m->size = size;
144 } else
145 kfree(buf);
146 return res;
147}
148
149static const struct file_operations proc_stat_operations = {
150 .open = stat_open,
151 .read = seq_read,
152 .llseek = seq_lseek,
153 .release = single_release,
154};
155
156static int __init proc_stat_init(void)
157{
158 proc_create("stat", 0, NULL, &proc_stat_operations);
159 return 0;
160}
161module_init(proc_stat_init);
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 4806830ea2a1..3a8bdd7f5756 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -198,11 +198,8 @@ static int do_maps_open(struct inode *inode, struct file *file,
198 return ret; 198 return ret;
199} 199}
200 200
201static int show_map(struct seq_file *m, void *v) 201static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
202{ 202{
203 struct proc_maps_private *priv = m->private;
204 struct task_struct *task = priv->task;
205 struct vm_area_struct *vma = v;
206 struct mm_struct *mm = vma->vm_mm; 203 struct mm_struct *mm = vma->vm_mm;
207 struct file *file = vma->vm_file; 204 struct file *file = vma->vm_file;
208 int flags = vma->vm_flags; 205 int flags = vma->vm_flags;
@@ -254,6 +251,15 @@ static int show_map(struct seq_file *m, void *v)
254 } 251 }
255 } 252 }
256 seq_putc(m, '\n'); 253 seq_putc(m, '\n');
254}
255
256static int show_map(struct seq_file *m, void *v)
257{
258 struct vm_area_struct *vma = v;
259 struct proc_maps_private *priv = m->private;
260 struct task_struct *task = priv->task;
261
262 show_map_vma(m, vma);
257 263
258 if (m->count < m->size) /* vma is copied successfully */ 264 if (m->count < m->size) /* vma is copied successfully */
259 m->version = (vma != get_gate_vma(task))? vma->vm_start: 0; 265 m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
@@ -364,9 +370,10 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
364 370
365static int show_smap(struct seq_file *m, void *v) 371static int show_smap(struct seq_file *m, void *v)
366{ 372{
373 struct proc_maps_private *priv = m->private;
374 struct task_struct *task = priv->task;
367 struct vm_area_struct *vma = v; 375 struct vm_area_struct *vma = v;
368 struct mem_size_stats mss; 376 struct mem_size_stats mss;
369 int ret;
370 struct mm_walk smaps_walk = { 377 struct mm_walk smaps_walk = {
371 .pmd_entry = smaps_pte_range, 378 .pmd_entry = smaps_pte_range,
372 .mm = vma->vm_mm, 379 .mm = vma->vm_mm,
@@ -378,9 +385,7 @@ static int show_smap(struct seq_file *m, void *v)
378 if (vma->vm_mm && !is_vm_hugetlb_page(vma)) 385 if (vma->vm_mm && !is_vm_hugetlb_page(vma))
379 walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); 386 walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk);
380 387
381 ret = show_map(m, v); 388 show_map_vma(m, vma);
382 if (ret)
383 return ret;
384 389
385 seq_printf(m, 390 seq_printf(m,
386 "Size: %8lu kB\n" 391 "Size: %8lu kB\n"
@@ -402,7 +407,9 @@ static int show_smap(struct seq_file *m, void *v)
402 mss.referenced >> 10, 407 mss.referenced >> 10,
403 mss.swap >> 10); 408 mss.swap >> 10);
404 409
405 return ret; 410 if (m->count < m->size) /* vma is copied successfully */
411 m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0;
412 return 0;
406} 413}
407 414
408static const struct seq_operations proc_pid_smaps_op = { 415static const struct seq_operations proc_pid_smaps_op = {
@@ -550,9 +557,9 @@ static u64 swap_pte_to_pagemap_entry(pte_t pte)
550 return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); 557 return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT);
551} 558}
552 559
553static unsigned long pte_to_pagemap_entry(pte_t pte) 560static u64 pte_to_pagemap_entry(pte_t pte)
554{ 561{
555 unsigned long pme = 0; 562 u64 pme = 0;
556 if (is_swap_pte(pte)) 563 if (is_swap_pte(pte))
557 pme = PM_PFRAME(swap_pte_to_pagemap_entry(pte)) 564 pme = PM_PFRAME(swap_pte_to_pagemap_entry(pte))
558 | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP; 565 | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP;
diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c
new file mode 100644
index 000000000000..df26aa88fa47
--- /dev/null
+++ b/fs/proc/uptime.c
@@ -0,0 +1,45 @@
1#include <linux/init.h>
2#include <linux/proc_fs.h>
3#include <linux/sched.h>
4#include <linux/time.h>
5#include <asm/cputime.h>
6
7static int proc_calc_metrics(char *page, char **start, off_t off,
8 int count, int *eof, int len)
9{
10 if (len <= off + count)
11 *eof = 1;
12 *start = page + off;
13 len -= off;
14 if (len > count)
15 len = count;
16 if (len < 0)
17 len = 0;
18 return len;
19}
20
21static int uptime_read_proc(char *page, char **start, off_t off, int count,
22 int *eof, void *data)
23{
24 struct timespec uptime;
25 struct timespec idle;
26 int len;
27 cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
28
29 do_posix_clock_monotonic_gettime(&uptime);
30 monotonic_to_bootbased(&uptime);
31 cputime_to_timespec(idletime, &idle);
32 len = sprintf(page, "%lu.%02lu %lu.%02lu\n",
33 (unsigned long) uptime.tv_sec,
34 (uptime.tv_nsec / (NSEC_PER_SEC / 100)),
35 (unsigned long) idle.tv_sec,
36 (idle.tv_nsec / (NSEC_PER_SEC / 100)));
37 return proc_calc_metrics(page, start, off, count, eof, len);
38}
39
40static int __init proc_uptime_init(void)
41{
42 create_proc_read_entry("uptime", 0, NULL, uptime_read_proc, NULL);
43 return 0;
44}
45module_init(proc_uptime_init);
diff --git a/fs/proc/version.c b/fs/proc/version.c
new file mode 100644
index 000000000000..76817a60678c
--- /dev/null
+++ b/fs/proc/version.c
@@ -0,0 +1,34 @@
1#include <linux/fs.h>
2#include <linux/init.h>
3#include <linux/kernel.h>
4#include <linux/proc_fs.h>
5#include <linux/seq_file.h>
6#include <linux/utsname.h>
7
8static int version_proc_show(struct seq_file *m, void *v)
9{
10 seq_printf(m, linux_proc_banner,
11 utsname()->sysname,
12 utsname()->release,
13 utsname()->version);
14 return 0;
15}
16
17static int version_proc_open(struct inode *inode, struct file *file)
18{
19 return single_open(file, version_proc_show, NULL);
20}
21
22static const struct file_operations version_proc_fops = {
23 .open = version_proc_open,
24 .read = seq_read,
25 .llseek = seq_lseek,
26 .release = single_release,
27};
28
29static int __init proc_version_init(void)
30{
31 proc_create("version", 0, NULL, &version_proc_fops);
32 return 0;
33}
34module_init(proc_version_init);
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 841368b87a29..03ec59504906 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -32,10 +32,7 @@ static size_t elfcorebuf_sz;
32/* Total size of vmcore file. */ 32/* Total size of vmcore file. */
33static u64 vmcore_size; 33static u64 vmcore_size;
34 34
35/* Stores the physical address of elf header of crash image. */ 35static struct proc_dir_entry *proc_vmcore = NULL;
36unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
37
38struct proc_dir_entry *proc_vmcore = NULL;
39 36
40/* Reads a page from the oldmem device from given offset. */ 37/* Reads a page from the oldmem device from given offset. */
41static ssize_t read_from_oldmem(char *buf, size_t count, 38static ssize_t read_from_oldmem(char *buf, size_t count,
@@ -165,7 +162,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
165 return acc; 162 return acc;
166} 163}
167 164
168const struct file_operations proc_vmcore_operations = { 165static const struct file_operations proc_vmcore_operations = {
169 .read = read_vmcore, 166 .read = read_vmcore,
170}; 167};
171 168
@@ -647,7 +644,7 @@ static int __init vmcore_init(void)
647 int rc = 0; 644 int rc = 0;
648 645
649 /* If elfcorehdr= has been passed in cmdline, then capture the dump.*/ 646 /* If elfcorehdr= has been passed in cmdline, then capture the dump.*/
650 if (!(elfcorehdr_addr < ELFCORE_ADDR_MAX)) 647 if (!(is_vmcore_usable()))
651 return rc; 648 return rc;
652 rc = parse_crash_elf_headers(); 649 rc = parse_crash_elf_headers();
653 if (rc) { 650 if (rc) {
@@ -655,7 +652,7 @@ static int __init vmcore_init(void)
655 return rc; 652 return rc;
656 } 653 }
657 654
658 /* Initialize /proc/vmcore size if proc is already up. */ 655 proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
659 if (proc_vmcore) 656 if (proc_vmcore)
660 proc_vmcore->size = vmcore_size; 657 proc_vmcore->size = vmcore_size;
661 return 0; 658 return 0;