aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-04-09 15:22:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-09 15:22:49 -0400
commite8f2b548de7ae65e17ee911e54712a3f26f69c60 (patch)
tree0b332c254088effc61d832f9e95d65861251214e /fs/proc
parent43ecdb0d31cf63d99d060af0585bf59be7fafcb2 (diff)
parente9c5d8a562f01b211926d70443378eb14b29a676 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro: "A nasty bug in fs/namespace.c caught by Andrey + a couple of less serious unpleasantness - ecryptfs misc device playing hopeless games with try_module_get() and palinfo procfs support being... not quite correctly done, to be polite." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: mnt: release locks on error path in do_loopback palinfo fixes procfs: add proc_remove_subtree() ecryptfs: close rmmod race
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/generic.c119
1 files changed, 89 insertions, 30 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 4b3b3ffb52f1..21e1a8f1659d 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -755,37 +755,8 @@ void pde_put(struct proc_dir_entry *pde)
755 free_proc_entry(pde); 755 free_proc_entry(pde);
756} 756}
757 757
758/* 758static void entry_rundown(struct proc_dir_entry *de)
759 * Remove a /proc entry and free it if it's not currently in use.
760 */
761void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
762{ 759{
763 struct proc_dir_entry **p;
764 struct proc_dir_entry *de = NULL;
765 const char *fn = name;
766 unsigned int len;
767
768 spin_lock(&proc_subdir_lock);
769 if (__xlate_proc_name(name, &parent, &fn) != 0) {
770 spin_unlock(&proc_subdir_lock);
771 return;
772 }
773 len = strlen(fn);
774
775 for (p = &parent->subdir; *p; p=&(*p)->next ) {
776 if (proc_match(len, fn, *p)) {
777 de = *p;
778 *p = de->next;
779 de->next = NULL;
780 break;
781 }
782 }
783 spin_unlock(&proc_subdir_lock);
784 if (!de) {
785 WARN(1, "name '%s'\n", name);
786 return;
787 }
788
789 spin_lock(&de->pde_unload_lock); 760 spin_lock(&de->pde_unload_lock);
790 /* 761 /*
791 * Stop accepting new callers into module. If you're 762 * Stop accepting new callers into module. If you're
@@ -817,6 +788,40 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
817 spin_lock(&de->pde_unload_lock); 788 spin_lock(&de->pde_unload_lock);
818 } 789 }
819 spin_unlock(&de->pde_unload_lock); 790 spin_unlock(&de->pde_unload_lock);
791}
792
793/*
794 * Remove a /proc entry and free it if it's not currently in use.
795 */
796void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
797{
798 struct proc_dir_entry **p;
799 struct proc_dir_entry *de = NULL;
800 const char *fn = name;
801 unsigned int len;
802
803 spin_lock(&proc_subdir_lock);
804 if (__xlate_proc_name(name, &parent, &fn) != 0) {
805 spin_unlock(&proc_subdir_lock);
806 return;
807 }
808 len = strlen(fn);
809
810 for (p = &parent->subdir; *p; p=&(*p)->next ) {
811 if (proc_match(len, fn, *p)) {
812 de = *p;
813 *p = de->next;
814 de->next = NULL;
815 break;
816 }
817 }
818 spin_unlock(&proc_subdir_lock);
819 if (!de) {
820 WARN(1, "name '%s'\n", name);
821 return;
822 }
823
824 entry_rundown(de);
820 825
821 if (S_ISDIR(de->mode)) 826 if (S_ISDIR(de->mode))
822 parent->nlink--; 827 parent->nlink--;
@@ -827,3 +832,57 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
827 pde_put(de); 832 pde_put(de);
828} 833}
829EXPORT_SYMBOL(remove_proc_entry); 834EXPORT_SYMBOL(remove_proc_entry);
835
836int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
837{
838 struct proc_dir_entry **p;
839 struct proc_dir_entry *root = NULL, *de, *next;
840 const char *fn = name;
841 unsigned int len;
842
843 spin_lock(&proc_subdir_lock);
844 if (__xlate_proc_name(name, &parent, &fn) != 0) {
845 spin_unlock(&proc_subdir_lock);
846 return -ENOENT;
847 }
848 len = strlen(fn);
849
850 for (p = &parent->subdir; *p; p=&(*p)->next ) {
851 if (proc_match(len, fn, *p)) {
852 root = *p;
853 *p = root->next;
854 root->next = NULL;
855 break;
856 }
857 }
858 if (!root) {
859 spin_unlock(&proc_subdir_lock);
860 return -ENOENT;
861 }
862 de = root;
863 while (1) {
864 next = de->subdir;
865 if (next) {
866 de->subdir = next->next;
867 next->next = NULL;
868 de = next;
869 continue;
870 }
871 spin_unlock(&proc_subdir_lock);
872
873 entry_rundown(de);
874 next = de->parent;
875 if (S_ISDIR(de->mode))
876 next->nlink--;
877 de->nlink = 0;
878 if (de == root)
879 break;
880 pde_put(de);
881
882 spin_lock(&proc_subdir_lock);
883 de = next;
884 }
885 pde_put(root);
886 return 0;
887}
888EXPORT_SYMBOL(remove_proc_subtree);