diff options
Diffstat (limited to 'fs/proc/generic.c')
-rw-r--r-- | fs/proc/generic.c | 38 |
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 | */ |
294 | static int xlate_proc_name(const char *name, | 294 | static 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; |
325 | out: | 323 | return 0; |
324 | } | ||
325 | |||
326 | static 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 | ||
330 | static DEFINE_IDA(proc_inum_ida); | 337 | static 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 | } |
672 | EXPORT_SYMBOL(proc_symlink); | ||
665 | 673 | ||
666 | struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, | 674 | struct 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 | } |
711 | EXPORT_SYMBOL(proc_mkdir); | ||
703 | 712 | ||
704 | struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, | 713 | struct 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 | } |
740 | EXPORT_SYMBOL(create_proc_entry); | ||
731 | 741 | ||
732 | struct proc_dir_entry *proc_create_data(const char *name, mode_t mode, | 742 | struct 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: | |||
762 | out: | 772 | out: |
763 | return NULL; | 773 | return NULL; |
764 | } | 774 | } |
775 | EXPORT_SYMBOL(proc_create_data); | ||
765 | 776 | ||
766 | static void free_proc_entry(struct proc_dir_entry *de) | 777 | static 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 | } |
871 | EXPORT_SYMBOL(remove_proc_entry); | ||