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.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);