aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/generic.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-04-29 19:53:17 -0400
committerH. Peter Anvin <hpa@zytor.com>2010-04-29 19:53:17 -0400
commitd9c5841e22231e4e49fd0a1004164e6fce59b7a6 (patch)
treee1f589c46b3ff79bbe7b1b2469f6362f94576da6 /fs/proc/generic.c
parentb701a47ba48b698976fb2fe05fb285b0edc1d26a (diff)
parent5967ed87ade85a421ef814296c3c7f182b08c225 (diff)
Merge branch 'x86/asm' into x86/atomic
Merge reason: Conflict between LOCK_PREFIX_HERE and relative alternatives pointers Resolved Conflicts: arch/x86/include/asm/alternative.h arch/x86/kernel/alternative.c Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'fs/proc/generic.c')
-rw-r--r--fs/proc/generic.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 480cb1065eec..43c127490606 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -13,6 +13,7 @@
13#include <linux/proc_fs.h> 13#include <linux/proc_fs.h>
14#include <linux/stat.h> 14#include <linux/stat.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/slab.h>
16#include <linux/mount.h> 17#include <linux/mount.h>
17#include <linux/init.h> 18#include <linux/init.h>
18#include <linux/idr.h> 19#include <linux/idr.h>
@@ -291,19 +292,17 @@ static const struct inode_operations proc_file_inode_operations = {
291 * returns the struct proc_dir_entry for "/proc/tty/driver", and 292 * returns the struct proc_dir_entry for "/proc/tty/driver", and
292 * returns "serial" in residual. 293 * returns "serial" in residual.
293 */ 294 */
294static int xlate_proc_name(const char *name, 295static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
295 struct proc_dir_entry **ret, const char **residual) 296 const char **residual)
296{ 297{
297 const char *cp = name, *next; 298 const char *cp = name, *next;
298 struct proc_dir_entry *de; 299 struct proc_dir_entry *de;
299 int len; 300 int len;
300 int rtn = 0;
301 301
302 de = *ret; 302 de = *ret;
303 if (!de) 303 if (!de)
304 de = &proc_root; 304 de = &proc_root;
305 305
306 spin_lock(&proc_subdir_lock);
307 while (1) { 306 while (1) {
308 next = strchr(cp, '/'); 307 next = strchr(cp, '/');
309 if (!next) 308 if (!next)
@@ -315,16 +314,25 @@ static int xlate_proc_name(const char *name,
315 break; 314 break;
316 } 315 }
317 if (!de) { 316 if (!de) {
318 rtn = -ENOENT; 317 WARN(1, "name '%s'\n", name);
319 goto out; 318 return -ENOENT;
320 } 319 }
321 cp += len + 1; 320 cp += len + 1;
322 } 321 }
323 *residual = cp; 322 *residual = cp;
324 *ret = de; 323 *ret = de;
325out: 324 return 0;
325}
326
327static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
328 const char **residual)
329{
330 int rv;
331
332 spin_lock(&proc_subdir_lock);
333 rv = __xlate_proc_name(name, ret, residual);
326 spin_unlock(&proc_subdir_lock); 334 spin_unlock(&proc_subdir_lock);
327 return rtn; 335 return rv;
328} 336}
329 337
330static DEFINE_IDA(proc_inum_ida); 338static DEFINE_IDA(proc_inum_ida);
@@ -662,6 +670,7 @@ struct proc_dir_entry *proc_symlink(const char *name,
662 } 670 }
663 return ent; 671 return ent;
664} 672}
673EXPORT_SYMBOL(proc_symlink);
665 674
666struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, 675struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
667 struct proc_dir_entry *parent) 676 struct proc_dir_entry *parent)
@@ -700,6 +709,7 @@ struct proc_dir_entry *proc_mkdir(const char *name,
700{ 709{
701 return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent); 710 return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
702} 711}
712EXPORT_SYMBOL(proc_mkdir);
703 713
704struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, 714struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
705 struct proc_dir_entry *parent) 715 struct proc_dir_entry *parent)
@@ -728,6 +738,7 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
728 } 738 }
729 return ent; 739 return ent;
730} 740}
741EXPORT_SYMBOL(create_proc_entry);
731 742
732struct proc_dir_entry *proc_create_data(const char *name, mode_t mode, 743struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
733 struct proc_dir_entry *parent, 744 struct proc_dir_entry *parent,
@@ -762,6 +773,7 @@ out_free:
762out: 773out:
763 return NULL; 774 return NULL;
764} 775}
776EXPORT_SYMBOL(proc_create_data);
765 777
766static void free_proc_entry(struct proc_dir_entry *de) 778static void free_proc_entry(struct proc_dir_entry *de)
767{ 779{
@@ -793,11 +805,13 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
793 const char *fn = name; 805 const char *fn = name;
794 int len; 806 int len;
795 807
796 if (xlate_proc_name(name, &parent, &fn) != 0) 808 spin_lock(&proc_subdir_lock);
809 if (__xlate_proc_name(name, &parent, &fn) != 0) {
810 spin_unlock(&proc_subdir_lock);
797 return; 811 return;
812 }
798 len = strlen(fn); 813 len = strlen(fn);
799 814
800 spin_lock(&proc_subdir_lock);
801 for (p = &parent->subdir; *p; p=&(*p)->next ) { 815 for (p = &parent->subdir; *p; p=&(*p)->next ) {
802 if (proc_match(len, fn, *p)) { 816 if (proc_match(len, fn, *p)) {
803 de = *p; 817 de = *p;
@@ -807,8 +821,10 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
807 } 821 }
808 } 822 }
809 spin_unlock(&proc_subdir_lock); 823 spin_unlock(&proc_subdir_lock);
810 if (!de) 824 if (!de) {
825 WARN(1, "name '%s'\n", name);
811 return; 826 return;
827 }
812 828
813 spin_lock(&de->pde_unload_lock); 829 spin_lock(&de->pde_unload_lock);
814 /* 830 /*
@@ -853,3 +869,4 @@ continue_removing:
853 de->parent->name, de->name, de->subdir->name); 869 de->parent->name, de->name, de->subdir->name);
854 pde_put(de); 870 pde_put(de);
855} 871}
872EXPORT_SYMBOL(remove_proc_entry);