aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/generic.c')
-rw-r--r--fs/proc/generic.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 480cb1065eec..08f4d71dacd7 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -291,19 +291,17 @@ static const struct inode_operations proc_file_inode_operations = {
291 * returns the struct proc_dir_entry for "/proc/tty/driver", and 291 * returns the struct proc_dir_entry for "/proc/tty/driver", and
292 * returns "serial" in residual. 292 * returns "serial" in residual.
293 */ 293 */
294static int xlate_proc_name(const char *name, 294static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
295 struct proc_dir_entry **ret, const char **residual) 295 const char **residual)
296{ 296{
297 const char *cp = name, *next; 297 const char *cp = name, *next;
298 struct proc_dir_entry *de; 298 struct proc_dir_entry *de;
299 int len; 299 int len;
300 int rtn = 0;
301 300
302 de = *ret; 301 de = *ret;
303 if (!de) 302 if (!de)
304 de = &proc_root; 303 de = &proc_root;
305 304
306 spin_lock(&proc_subdir_lock);
307 while (1) { 305 while (1) {
308 next = strchr(cp, '/'); 306 next = strchr(cp, '/');
309 if (!next) 307 if (!next)
@@ -315,16 +313,25 @@ static int xlate_proc_name(const char *name,
315 break; 313 break;
316 } 314 }
317 if (!de) { 315 if (!de) {
318 rtn = -ENOENT; 316 WARN(1, "name '%s'\n", name);
319 goto out; 317 return -ENOENT;
320 } 318 }
321 cp += len + 1; 319 cp += len + 1;
322 } 320 }
323 *residual = cp; 321 *residual = cp;
324 *ret = de; 322 *ret = de;
325out: 323 return 0;
324}
325
326static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
327 const char **residual)
328{
329 int rv;
330
331 spin_lock(&proc_subdir_lock);
332 rv = __xlate_proc_name(name, ret, residual);
326 spin_unlock(&proc_subdir_lock); 333 spin_unlock(&proc_subdir_lock);
327 return rtn; 334 return rv;
328} 335}
329 336
330static DEFINE_IDA(proc_inum_ida); 337static DEFINE_IDA(proc_inum_ida);
@@ -662,6 +669,7 @@ struct proc_dir_entry *proc_symlink(const char *name,
662 } 669 }
663 return ent; 670 return ent;
664} 671}
672EXPORT_SYMBOL(proc_symlink);
665 673
666struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, 674struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
667 struct proc_dir_entry *parent) 675 struct proc_dir_entry *parent)
@@ -700,6 +708,7 @@ struct proc_dir_entry *proc_mkdir(const char *name,
700{ 708{
701 return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent); 709 return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
702} 710}
711EXPORT_SYMBOL(proc_mkdir);
703 712
704struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, 713struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
705 struct proc_dir_entry *parent) 714 struct proc_dir_entry *parent)
@@ -728,6 +737,7 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
728 } 737 }
729 return ent; 738 return ent;
730} 739}
740EXPORT_SYMBOL(create_proc_entry);
731 741
732struct proc_dir_entry *proc_create_data(const char *name, mode_t mode, 742struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
733 struct proc_dir_entry *parent, 743 struct proc_dir_entry *parent,
@@ -762,6 +772,7 @@ out_free:
762out: 772out:
763 return NULL; 773 return NULL;
764} 774}
775EXPORT_SYMBOL(proc_create_data);
765 776
766static void free_proc_entry(struct proc_dir_entry *de) 777static void free_proc_entry(struct proc_dir_entry *de)
767{ 778{
@@ -793,11 +804,13 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
793 const char *fn = name; 804 const char *fn = name;
794 int len; 805 int len;
795 806
796 if (xlate_proc_name(name, &parent, &fn) != 0) 807 spin_lock(&proc_subdir_lock);
808 if (__xlate_proc_name(name, &parent, &fn) != 0) {
809 spin_unlock(&proc_subdir_lock);
797 return; 810 return;
811 }
798 len = strlen(fn); 812 len = strlen(fn);
799 813
800 spin_lock(&proc_subdir_lock);
801 for (p = &parent->subdir; *p; p=&(*p)->next ) { 814 for (p = &parent->subdir; *p; p=&(*p)->next ) {
802 if (proc_match(len, fn, *p)) { 815 if (proc_match(len, fn, *p)) {
803 de = *p; 816 de = *p;
@@ -807,8 +820,10 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
807 } 820 }
808 } 821 }
809 spin_unlock(&proc_subdir_lock); 822 spin_unlock(&proc_subdir_lock);
810 if (!de) 823 if (!de) {
824 WARN(1, "name '%s'\n", name);
811 return; 825 return;
826 }
812 827
813 spin_lock(&de->pde_unload_lock); 828 spin_lock(&de->pde_unload_lock);
814 /* 829 /*
@@ -853,3 +868,4 @@ continue_removing:
853 de->parent->name, de->name, de->subdir->name); 868 de->parent->name, de->name, de->subdir->name);
854 pde_put(de); 869 pde_put(de);
855} 870}
871EXPORT_SYMBOL(remove_proc_entry);