aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/generic.c32
-rw-r--r--fs/proc/proc_devtree.c2
-rw-r--r--include/linux/proc_fs.h3
3 files changed, 34 insertions, 3 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 20e5c4509a43..47b7a20d45eb 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;
@@ -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/proc_devtree.c b/fs/proc/proc_devtree.c
index 9bdd077d6f55..596b4b4f1cc8 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -136,9 +136,11 @@ void proc_device_tree_add_node(struct device_node *np,
136 * properties are quite unimportant for us though, thus we 136 * properties are quite unimportant for us though, thus we
137 * simply "skip" them here, but we do have to check. 137 * simply "skip" them here, but we do have to check.
138 */ 138 */
139 spin_lock(&proc_subdir_lock);
139 for (ent = de->subdir; ent != NULL; ent = ent->next) 140 for (ent = de->subdir; ent != NULL; ent = ent->next)
140 if (!strcmp(ent->name, pp->name)) 141 if (!strcmp(ent->name, pp->name))
141 break; 142 break;
143 spin_unlock(&proc_subdir_lock);
142 if (ent != NULL) { 144 if (ent != NULL) {
143 printk(KERN_WARNING "device-tree: property \"%s\" name" 145 printk(KERN_WARNING "device-tree: property \"%s\" name"
144 " conflicts with node in %s\n", pp->name, 146 " conflicts with node in %s\n", pp->name,
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index aa6322d45198..6b12b0f661b4 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -4,6 +4,7 @@
4#include <linux/config.h> 4#include <linux/config.h>
5#include <linux/slab.h> 5#include <linux/slab.h>
6#include <linux/fs.h> 6#include <linux/fs.h>
7#include <linux/spinlock.h>
7#include <asm/atomic.h> 8#include <asm/atomic.h>
8 9
9/* 10/*
@@ -92,6 +93,8 @@ extern struct proc_dir_entry *proc_bus;
92extern struct proc_dir_entry *proc_root_driver; 93extern struct proc_dir_entry *proc_root_driver;
93extern struct proc_dir_entry *proc_root_kcore; 94extern struct proc_dir_entry *proc_root_kcore;
94 95
96extern spinlock_t proc_subdir_lock;
97
95extern void proc_root_init(void); 98extern void proc_root_init(void);
96extern void proc_misc_init(void); 99extern void proc_misc_init(void);
97 100