aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/array.c5
-rw-r--r--fs/proc/base.c39
-rw-r--r--fs/proc/generic.c34
-rw-r--r--fs/proc/inode.c3
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/kcore.c2
-rw-r--r--fs/proc/kmsg.c2
-rw-r--r--fs/proc/proc_devtree.c101
-rw-r--r--fs/proc/proc_misc.c43
-rw-r--r--fs/proc/vmcore.c2
10 files changed, 196 insertions, 37 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 7eb1bd7f800c..7a76ad570230 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -330,7 +330,6 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
330 unsigned long min_flt = 0, maj_flt = 0; 330 unsigned long min_flt = 0, maj_flt = 0;
331 cputime_t cutime, cstime, utime, stime; 331 cputime_t cutime, cstime, utime, stime;
332 unsigned long rsslim = 0; 332 unsigned long rsslim = 0;
333 DEFINE_KTIME(it_real_value);
334 struct task_struct *t; 333 struct task_struct *t;
335 char tcomm[sizeof(task->comm)]; 334 char tcomm[sizeof(task->comm)];
336 335
@@ -386,7 +385,6 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
386 utime = cputime_add(utime, task->signal->utime); 385 utime = cputime_add(utime, task->signal->utime);
387 stime = cputime_add(stime, task->signal->stime); 386 stime = cputime_add(stime, task->signal->stime);
388 } 387 }
389 it_real_value = task->signal->real_timer.expires;
390 } 388 }
391 ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0; 389 ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
392 read_unlock(&tasklist_lock); 390 read_unlock(&tasklist_lock);
@@ -413,7 +411,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
413 start_time = nsec_to_clock_t(start_time); 411 start_time = nsec_to_clock_t(start_time);
414 412
415 res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ 413 res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
416%lu %lu %lu %lu %lu %ld %ld %ld %ld %d %ld %llu %lu %ld %lu %lu %lu %lu %lu \ 414%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
417%lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu\n", 415%lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu\n",
418 task->pid, 416 task->pid,
419 tcomm, 417 tcomm,
@@ -435,7 +433,6 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
435 priority, 433 priority,
436 nice, 434 nice,
437 num_threads, 435 num_threads,
438 (long) ktime_to_clock_t(it_real_value),
439 start_time, 436 start_time,
440 vsize, 437 vsize,
441 mm ? get_mm_rss(mm) : 0, 438 mm ? get_mm_rss(mm) : 0,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 20feb7568deb..8f1f49ceebec 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -104,6 +104,7 @@ enum pid_directory_inos {
104 PROC_TGID_MAPS, 104 PROC_TGID_MAPS,
105 PROC_TGID_NUMA_MAPS, 105 PROC_TGID_NUMA_MAPS,
106 PROC_TGID_MOUNTS, 106 PROC_TGID_MOUNTS,
107 PROC_TGID_MOUNTSTATS,
107 PROC_TGID_WCHAN, 108 PROC_TGID_WCHAN,
108#ifdef CONFIG_MMU 109#ifdef CONFIG_MMU
109 PROC_TGID_SMAPS, 110 PROC_TGID_SMAPS,
@@ -144,6 +145,7 @@ enum pid_directory_inos {
144 PROC_TID_MAPS, 145 PROC_TID_MAPS,
145 PROC_TID_NUMA_MAPS, 146 PROC_TID_NUMA_MAPS,
146 PROC_TID_MOUNTS, 147 PROC_TID_MOUNTS,
148 PROC_TID_MOUNTSTATS,
147 PROC_TID_WCHAN, 149 PROC_TID_WCHAN,
148#ifdef CONFIG_MMU 150#ifdef CONFIG_MMU
149 PROC_TID_SMAPS, 151 PROC_TID_SMAPS,
@@ -201,6 +203,7 @@ static struct pid_entry tgid_base_stuff[] = {
201 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), 203 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
202 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), 204 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
203 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), 205 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
206 E(PROC_TGID_MOUNTSTATS, "mountstats", S_IFREG|S_IRUSR),
204#ifdef CONFIG_MMU 207#ifdef CONFIG_MMU
205 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO), 208 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
206#endif 209#endif
@@ -732,6 +735,38 @@ static struct file_operations proc_mounts_operations = {
732 .poll = mounts_poll, 735 .poll = mounts_poll,
733}; 736};
734 737
738extern struct seq_operations mountstats_op;
739static int mountstats_open(struct inode *inode, struct file *file)
740{
741 struct task_struct *task = proc_task(inode);
742 int ret = seq_open(file, &mountstats_op);
743
744 if (!ret) {
745 struct seq_file *m = file->private_data;
746 struct namespace *namespace;
747 task_lock(task);
748 namespace = task->namespace;
749 if (namespace)
750 get_namespace(namespace);
751 task_unlock(task);
752
753 if (namespace)
754 m->private = namespace;
755 else {
756 seq_release(inode, file);
757 ret = -EINVAL;
758 }
759 }
760 return ret;
761}
762
763static struct file_operations proc_mountstats_operations = {
764 .open = mountstats_open,
765 .read = seq_read,
766 .llseek = seq_lseek,
767 .release = mounts_release,
768};
769
735#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ 770#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */
736 771
737static ssize_t proc_info_read(struct file * file, char __user * buf, 772static ssize_t proc_info_read(struct file * file, char __user * buf,
@@ -1730,6 +1765,10 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
1730 inode->i_fop = &proc_smaps_operations; 1765 inode->i_fop = &proc_smaps_operations;
1731 break; 1766 break;
1732#endif 1767#endif
1768 case PROC_TID_MOUNTSTATS:
1769 case PROC_TGID_MOUNTSTATS:
1770 inode->i_fop = &proc_mountstats_operations;
1771 break;
1733#ifdef CONFIG_SECURITY 1772#ifdef CONFIG_SECURITY
1734 case PROC_TID_ATTR: 1773 case PROC_TID_ATTR:
1735 inode->i_nlink = 2; 1774 inode->i_nlink = 2;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 20e5c4509a43..4ba03009cf72 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -19,6 +19,7 @@
19#include <linux/idr.h> 19#include <linux/idr.h>
20#include <linux/namei.h> 20#include <linux/namei.h>
21#include <linux/bitops.h> 21#include <linux/bitops.h>
22#include <linux/spinlock.h>
22#include <asm/uaccess.h> 23#include <asm/uaccess.h>
23 24
24#include "internal.h" 25#include "internal.h"
@@ -29,6 +30,8 @@ static ssize_t proc_file_write(struct file *file, const char __user *buffer,
29 size_t count, loff_t *ppos); 30 size_t count, loff_t *ppos);
30static loff_t proc_file_lseek(struct file *, loff_t, int); 31static loff_t proc_file_lseek(struct file *, loff_t, int);
31 32
33DEFINE_SPINLOCK(proc_subdir_lock);
34
32int proc_match(int len, const char *name, struct proc_dir_entry *de) 35int proc_match(int len, const char *name, struct proc_dir_entry *de)
33{ 36{
34 if (de->namelen != len) 37 if (de->namelen != len)
@@ -277,7 +280,9 @@ static int xlate_proc_name(const char *name,
277 const char *cp = name, *next; 280 const char *cp = name, *next;
278 struct proc_dir_entry *de; 281 struct proc_dir_entry *de;
279 int len; 282 int len;
283 int rtn = 0;
280 284
285 spin_lock(&proc_subdir_lock);
281 de = &proc_root; 286 de = &proc_root;
282 while (1) { 287 while (1) {
283 next = strchr(cp, '/'); 288 next = strchr(cp, '/');
@@ -289,13 +294,17 @@ static int xlate_proc_name(const char *name,
289 if (proc_match(len, cp, de)) 294 if (proc_match(len, cp, de))
290 break; 295 break;
291 } 296 }
292 if (!de) 297 if (!de) {
293 return -ENOENT; 298 rtn = -ENOENT;
299 goto out;
300 }
294 cp += len + 1; 301 cp += len + 1;
295 } 302 }
296 *residual = cp; 303 *residual = cp;
297 *ret = de; 304 *ret = de;
298 return 0; 305out:
306 spin_unlock(&proc_subdir_lock);
307 return rtn;
299} 308}
300 309
301static DEFINE_IDR(proc_inum_idr); 310static DEFINE_IDR(proc_inum_idr);
@@ -380,6 +389,7 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam
380 int error = -ENOENT; 389 int error = -ENOENT;
381 390
382 lock_kernel(); 391 lock_kernel();
392 spin_lock(&proc_subdir_lock);
383 de = PDE(dir); 393 de = PDE(dir);
384 if (de) { 394 if (de) {
385 for (de = de->subdir; de ; de = de->next) { 395 for (de = de->subdir; de ; de = de->next) {
@@ -388,12 +398,15 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam
388 if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { 398 if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
389 unsigned int ino = de->low_ino; 399 unsigned int ino = de->low_ino;
390 400
401 spin_unlock(&proc_subdir_lock);
391 error = -EINVAL; 402 error = -EINVAL;
392 inode = proc_get_inode(dir->i_sb, ino, de); 403 inode = proc_get_inode(dir->i_sb, ino, de);
404 spin_lock(&proc_subdir_lock);
393 break; 405 break;
394 } 406 }
395 } 407 }
396 } 408 }
409 spin_unlock(&proc_subdir_lock);
397 unlock_kernel(); 410 unlock_kernel();
398 411
399 if (inode) { 412 if (inode) {
@@ -447,11 +460,13 @@ int proc_readdir(struct file * filp,
447 filp->f_pos++; 460 filp->f_pos++;
448 /* fall through */ 461 /* fall through */
449 default: 462 default:
463 spin_lock(&proc_subdir_lock);
450 de = de->subdir; 464 de = de->subdir;
451 i -= 2; 465 i -= 2;
452 for (;;) { 466 for (;;) {
453 if (!de) { 467 if (!de) {
454 ret = 1; 468 ret = 1;
469 spin_unlock(&proc_subdir_lock);
455 goto out; 470 goto out;
456 } 471 }
457 if (!i) 472 if (!i)
@@ -461,12 +476,16 @@ int proc_readdir(struct file * filp,
461 } 476 }
462 477
463 do { 478 do {
479 /* filldir passes info to user space */
480 spin_unlock(&proc_subdir_lock);
464 if (filldir(dirent, de->name, de->namelen, filp->f_pos, 481 if (filldir(dirent, de->name, de->namelen, filp->f_pos,
465 de->low_ino, de->mode >> 12) < 0) 482 de->low_ino, de->mode >> 12) < 0)
466 goto out; 483 goto out;
484 spin_lock(&proc_subdir_lock);
467 filp->f_pos++; 485 filp->f_pos++;
468 de = de->next; 486 de = de->next;
469 } while (de); 487 } while (de);
488 spin_unlock(&proc_subdir_lock);
470 } 489 }
471 ret = 1; 490 ret = 1;
472out: unlock_kernel(); 491out: unlock_kernel();
@@ -500,9 +519,13 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
500 if (i == 0) 519 if (i == 0)
501 return -EAGAIN; 520 return -EAGAIN;
502 dp->low_ino = i; 521 dp->low_ino = i;
522
523 spin_lock(&proc_subdir_lock);
503 dp->next = dir->subdir; 524 dp->next = dir->subdir;
504 dp->parent = dir; 525 dp->parent = dir;
505 dir->subdir = dp; 526 dir->subdir = dp;
527 spin_unlock(&proc_subdir_lock);
528
506 if (S_ISDIR(dp->mode)) { 529 if (S_ISDIR(dp->mode)) {
507 if (dp->proc_iops == NULL) { 530 if (dp->proc_iops == NULL) {
508 dp->proc_fops = &proc_dir_operations; 531 dp->proc_fops = &proc_dir_operations;
@@ -537,7 +560,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de)
537 struct file * filp = list_entry(p, struct file, f_u.fu_list); 560 struct file * filp = list_entry(p, struct file, f_u.fu_list);
538 struct dentry * dentry = filp->f_dentry; 561 struct dentry * dentry = filp->f_dentry;
539 struct inode * inode; 562 struct inode * inode;
540 struct file_operations *fops; 563 const struct file_operations *fops;
541 564
542 if (dentry->d_op != &proc_dentry_operations) 565 if (dentry->d_op != &proc_dentry_operations)
543 continue; 566 continue;
@@ -694,6 +717,8 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
694 if (!parent && xlate_proc_name(name, &parent, &fn) != 0) 717 if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
695 goto out; 718 goto out;
696 len = strlen(fn); 719 len = strlen(fn);
720
721 spin_lock(&proc_subdir_lock);
697 for (p = &parent->subdir; *p; p=&(*p)->next ) { 722 for (p = &parent->subdir; *p; p=&(*p)->next ) {
698 if (!proc_match(len, fn, *p)) 723 if (!proc_match(len, fn, *p))
699 continue; 724 continue;
@@ -714,6 +739,7 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
714 } 739 }
715 break; 740 break;
716 } 741 }
742 spin_unlock(&proc_subdir_lock);
717out: 743out:
718 return; 744 return;
719} 745}
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 075d3e945602..722b9c463111 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -121,7 +121,8 @@ int __init proc_init_inodecache(void)
121{ 121{
122 proc_inode_cachep = kmem_cache_create("proc_inode_cache", 122 proc_inode_cachep = kmem_cache_create("proc_inode_cache",
123 sizeof(struct proc_inode), 123 sizeof(struct proc_inode),
124 0, SLAB_RECLAIM_ACCOUNT, 124 0, (SLAB_RECLAIM_ACCOUNT|
125 SLAB_MEM_SPREAD),
125 init_once, NULL); 126 init_once, NULL);
126 if (proc_inode_cachep == NULL) 127 if (proc_inode_cachep == NULL)
127 return -ENOMEM; 128 return -ENOMEM;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 95a1cf32b838..0502f17b860d 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -30,7 +30,7 @@ do { \
30 30
31#endif 31#endif
32 32
33extern void create_seq_entry(char *name, mode_t mode, struct file_operations *f); 33extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f);
34extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); 34extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **);
35extern int proc_tid_stat(struct task_struct *, char *); 35extern int proc_tid_stat(struct task_struct *, char *);
36extern int proc_tgid_stat(struct task_struct *, char *); 36extern int proc_tgid_stat(struct task_struct *, char *);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index adc2cd95169a..17f6e8fa1397 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -31,7 +31,7 @@ static int open_kcore(struct inode * inode, struct file * filp)
31 31
32static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *); 32static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *);
33 33
34struct file_operations proc_kcore_operations = { 34const struct file_operations proc_kcore_operations = {
35 .read = read_kcore, 35 .read = read_kcore,
36 .open = open_kcore, 36 .open = open_kcore,
37}; 37};
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 10d37bf25206..ff3b90b56e9d 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -47,7 +47,7 @@ static unsigned int kmsg_poll(struct file *file, poll_table *wait)
47} 47}
48 48
49 49
50struct file_operations proc_kmsg_operations = { 50const struct file_operations proc_kmsg_operations = {
51 .read = kmsg_read, 51 .read = kmsg_read,
52 .poll = kmsg_poll, 52 .poll = kmsg_poll,
53 .open = kmsg_open, 53 .open = kmsg_open,
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 9bdd077d6f55..abdf068bc27f 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -52,7 +52,8 @@ static int property_read_proc(char *page, char **start, off_t off,
52 * Add a property to a node 52 * Add a property to a node
53 */ 53 */
54static struct proc_dir_entry * 54static struct proc_dir_entry *
55__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp) 55__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp,
56 const char *name)
56{ 57{
57 struct proc_dir_entry *ent; 58 struct proc_dir_entry *ent;
58 59
@@ -60,14 +61,14 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
60 * Unfortunately proc_register puts each new entry 61 * Unfortunately proc_register puts each new entry
61 * at the beginning of the list. So we rearrange them. 62 * at the beginning of the list. So we rearrange them.
62 */ 63 */
63 ent = create_proc_read_entry(pp->name, 64 ent = create_proc_read_entry(name,
64 strncmp(pp->name, "security-", 9) 65 strncmp(name, "security-", 9)
65 ? S_IRUGO : S_IRUSR, de, 66 ? S_IRUGO : S_IRUSR, de,
66 property_read_proc, pp); 67 property_read_proc, pp);
67 if (ent == NULL) 68 if (ent == NULL)
68 return NULL; 69 return NULL;
69 70
70 if (!strncmp(pp->name, "security-", 9)) 71 if (!strncmp(name, "security-", 9))
71 ent->size = 0; /* don't leak number of password chars */ 72 ent->size = 0; /* don't leak number of password chars */
72 else 73 else
73 ent->size = pp->length; 74 ent->size = pp->length;
@@ -78,7 +79,7 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
78 79
79void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop) 80void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop)
80{ 81{
81 __proc_device_tree_add_prop(pde, prop); 82 __proc_device_tree_add_prop(pde, prop, prop->name);
82} 83}
83 84
84void proc_device_tree_remove_prop(struct proc_dir_entry *pde, 85void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
@@ -106,6 +107,69 @@ void proc_device_tree_update_prop(struct proc_dir_entry *pde,
106} 107}
107 108
108/* 109/*
110 * Various dodgy firmware might give us nodes and/or properties with
111 * conflicting names. That's generally ok, except for exporting via /proc,
112 * so munge names here to ensure they're unique.
113 */
114
115static int duplicate_name(struct proc_dir_entry *de, const char *name)
116{
117 struct proc_dir_entry *ent;
118 int found = 0;
119
120 spin_lock(&proc_subdir_lock);
121
122 for (ent = de->subdir; ent != NULL; ent = ent->next) {
123 if (strcmp(ent->name, name) == 0) {
124 found = 1;
125 break;
126 }
127 }
128
129 spin_unlock(&proc_subdir_lock);
130
131 return found;
132}
133
134static const char *fixup_name(struct device_node *np, struct proc_dir_entry *de,
135 const char *name)
136{
137 char *fixed_name;
138 int fixup_len = strlen(name) + 2 + 1; /* name + #x + \0 */
139 int i = 1, size;
140
141realloc:
142 fixed_name = kmalloc(fixup_len, GFP_KERNEL);
143 if (fixed_name == NULL) {
144 printk(KERN_ERR "device-tree: Out of memory trying to fixup "
145 "name \"%s\"\n", name);
146 return name;
147 }
148
149retry:
150 size = snprintf(fixed_name, fixup_len, "%s#%d", name, i);
151 size++; /* account for NULL */
152
153 if (size > fixup_len) {
154 /* We ran out of space, free and reallocate. */
155 kfree(fixed_name);
156 fixup_len = size;
157 goto realloc;
158 }
159
160 if (duplicate_name(de, fixed_name)) {
161 /* Multiple duplicates. Retry with a different offset. */
162 i++;
163 goto retry;
164 }
165
166 printk(KERN_WARNING "device-tree: Duplicate name in %s, "
167 "renamed to \"%s\"\n", np->full_name, fixed_name);
168
169 return fixed_name;
170}
171
172/*
109 * Process a node, adding entries for its children and its properties. 173 * Process a node, adding entries for its children and its properties.
110 */ 174 */
111void proc_device_tree_add_node(struct device_node *np, 175void proc_device_tree_add_node(struct device_node *np,
@@ -118,35 +182,30 @@ void proc_device_tree_add_node(struct device_node *np,
118 182
119 set_node_proc_entry(np, de); 183 set_node_proc_entry(np, de);
120 for (child = NULL; (child = of_get_next_child(np, child));) { 184 for (child = NULL; (child = of_get_next_child(np, child));) {
185 /* Use everything after the last slash, or the full name */
121 p = strrchr(child->full_name, '/'); 186 p = strrchr(child->full_name, '/');
122 if (!p) 187 if (!p)
123 p = child->full_name; 188 p = child->full_name;
124 else 189 else
125 ++p; 190 ++p;
191
192 if (duplicate_name(de, p))
193 p = fixup_name(np, de, p);
194
126 ent = proc_mkdir(p, de); 195 ent = proc_mkdir(p, de);
127 if (ent == 0) 196 if (ent == 0)
128 break; 197 break;
129 proc_device_tree_add_node(child, ent); 198 proc_device_tree_add_node(child, ent);
130 } 199 }
131 of_node_put(child); 200 of_node_put(child);
201
132 for (pp = np->properties; pp != 0; pp = pp->next) { 202 for (pp = np->properties; pp != 0; pp = pp->next) {
133 /* 203 p = pp->name;
134 * Yet another Apple device-tree bogosity: on some machines, 204
135 * they have properties & nodes with the same name. Those 205 if (duplicate_name(de, p))
136 * properties are quite unimportant for us though, thus we 206 p = fixup_name(np, de, p);
137 * simply "skip" them here, but we do have to check.
138 */
139 for (ent = de->subdir; ent != NULL; ent = ent->next)
140 if (!strcmp(ent->name, pp->name))
141 break;
142 if (ent != NULL) {
143 printk(KERN_WARNING "device-tree: property \"%s\" name"
144 " conflicts with node in %s\n", pp->name,
145 np->full_name);
146 continue;
147 }
148 207
149 ent = __proc_device_tree_add_prop(de, pp); 208 ent = __proc_device_tree_add_prop(de, pp, p);
150 if (ent == 0) 209 if (ent == 0)
151 break; 210 break;
152 } 211 }
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 1d24fead51a6..ef5a3323f4b5 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -312,7 +312,7 @@ static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
312 case BLK_HDR: 312 case BLK_HDR:
313 info->state = BLK_LIST; 313 info->state = BLK_LIST;
314 (*pos)++; 314 (*pos)++;
315 break; 315 /*fallthrough*/
316 case BLK_LIST: 316 case BLK_LIST:
317 if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) { 317 if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) {
318 /* 318 /*
@@ -485,6 +485,40 @@ static struct file_operations proc_slabinfo_operations = {
485 .llseek = seq_lseek, 485 .llseek = seq_lseek,
486 .release = seq_release, 486 .release = seq_release,
487}; 487};
488
489#ifdef CONFIG_DEBUG_SLAB_LEAK
490extern struct seq_operations slabstats_op;
491static int slabstats_open(struct inode *inode, struct file *file)
492{
493 unsigned long *n = kzalloc(PAGE_SIZE, GFP_KERNEL);
494 int ret = -ENOMEM;
495 if (n) {
496 ret = seq_open(file, &slabstats_op);
497 if (!ret) {
498 struct seq_file *m = file->private_data;
499 *n = PAGE_SIZE / (2 * sizeof(unsigned long));
500 m->private = n;
501 n = NULL;
502 }
503 kfree(n);
504 }
505 return ret;
506}
507
508static int slabstats_release(struct inode *inode, struct file *file)
509{
510 struct seq_file *m = file->private_data;
511 kfree(m->private);
512 return seq_release(inode, file);
513}
514
515static struct file_operations proc_slabstats_operations = {
516 .open = slabstats_open,
517 .read = seq_read,
518 .llseek = seq_lseek,
519 .release = slabstats_release,
520};
521#endif
488#endif 522#endif
489 523
490static int show_stat(struct seq_file *p, void *v) 524static int show_stat(struct seq_file *p, void *v)
@@ -500,7 +534,7 @@ static int show_stat(struct seq_file *p, void *v)
500 if (wall_to_monotonic.tv_nsec) 534 if (wall_to_monotonic.tv_nsec)
501 --jif; 535 --jif;
502 536
503 for_each_cpu(i) { 537 for_each_possible_cpu(i) {
504 int j; 538 int j;
505 539
506 user = cputime64_add(user, kstat_cpu(i).cpustat.user); 540 user = cputime64_add(user, kstat_cpu(i).cpustat.user);
@@ -697,7 +731,7 @@ static struct file_operations proc_sysrq_trigger_operations = {
697 731
698struct proc_dir_entry *proc_root_kcore; 732struct proc_dir_entry *proc_root_kcore;
699 733
700void create_seq_entry(char *name, mode_t mode, struct file_operations *f) 734void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
701{ 735{
702 struct proc_dir_entry *entry; 736 struct proc_dir_entry *entry;
703 entry = create_proc_entry(name, mode, NULL); 737 entry = create_proc_entry(name, mode, NULL);
@@ -744,6 +778,9 @@ void __init proc_misc_init(void)
744 create_seq_entry("interrupts", 0, &proc_interrupts_operations); 778 create_seq_entry("interrupts", 0, &proc_interrupts_operations);
745#ifdef CONFIG_SLAB 779#ifdef CONFIG_SLAB
746 create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations); 780 create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
781#ifdef CONFIG_DEBUG_SLAB_LEAK
782 create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations);
783#endif
747#endif 784#endif
748 create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); 785 create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
749 create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations); 786 create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 4063fb32f78c..7efa73d44c9a 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -172,7 +172,7 @@ static int open_vmcore(struct inode *inode, struct file *filp)
172 return 0; 172 return 0;
173} 173}
174 174
175struct file_operations proc_vmcore_operations = { 175const struct file_operations proc_vmcore_operations = {
176 .read = read_vmcore, 176 .read = read_vmcore,
177 .open = open_vmcore, 177 .open = open_vmcore,
178}; 178};