diff options
author | H. Peter Anvin <hpa@zytor.com> | 2010-04-29 19:53:17 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-04-29 19:53:17 -0400 |
commit | d9c5841e22231e4e49fd0a1004164e6fce59b7a6 (patch) | |
tree | e1f589c46b3ff79bbe7b1b2469f6362f94576da6 /fs/proc/generic.c | |
parent | b701a47ba48b698976fb2fe05fb285b0edc1d26a (diff) | |
parent | 5967ed87ade85a421ef814296c3c7f182b08c225 (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.c | 39 |
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 | */ |
294 | static int xlate_proc_name(const char *name, | 295 | static 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; |
325 | out: | 324 | return 0; |
325 | } | ||
326 | |||
327 | static 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 | ||
330 | static DEFINE_IDA(proc_inum_ida); | 338 | static 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 | } |
673 | EXPORT_SYMBOL(proc_symlink); | ||
665 | 674 | ||
666 | struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, | 675 | struct 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 | } |
712 | EXPORT_SYMBOL(proc_mkdir); | ||
703 | 713 | ||
704 | struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, | 714 | struct 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 | } |
741 | EXPORT_SYMBOL(create_proc_entry); | ||
731 | 742 | ||
732 | struct proc_dir_entry *proc_create_data(const char *name, mode_t mode, | 743 | struct 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: | |||
762 | out: | 773 | out: |
763 | return NULL; | 774 | return NULL; |
764 | } | 775 | } |
776 | EXPORT_SYMBOL(proc_create_data); | ||
765 | 777 | ||
766 | static void free_proc_entry(struct proc_dir_entry *de) | 778 | static 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 | } |
872 | EXPORT_SYMBOL(remove_proc_entry); | ||