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.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 8a40e15f5ecb..4f8e53568b22 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -20,6 +20,7 @@
20#include <linux/namei.h> 20#include <linux/namei.h>
21#include <linux/bitops.h> 21#include <linux/bitops.h>
22#include <linux/spinlock.h> 22#include <linux/spinlock.h>
23#include <linux/completion.h>
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24 25
25#include "internal.h" 26#include "internal.h"
@@ -613,6 +614,9 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent,
613 ent->namelen = len; 614 ent->namelen = len;
614 ent->mode = mode; 615 ent->mode = mode;
615 ent->nlink = nlink; 616 ent->nlink = nlink;
617 ent->pde_users = 0;
618 spin_lock_init(&ent->pde_unload_lock);
619 ent->pde_unload_completion = NULL;
616 out: 620 out:
617 return ent; 621 return ent;
618} 622}
@@ -734,9 +738,35 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
734 de = *p; 738 de = *p;
735 *p = de->next; 739 *p = de->next;
736 de->next = NULL; 740 de->next = NULL;
741
742 spin_lock(&de->pde_unload_lock);
743 /*
744 * Stop accepting new callers into module. If you're
745 * dynamically allocating ->proc_fops, save a pointer somewhere.
746 */
747 de->proc_fops = NULL;
748 /* Wait until all existing callers into module are done. */
749 if (de->pde_users > 0) {
750 DECLARE_COMPLETION_ONSTACK(c);
751
752 if (!de->pde_unload_completion)
753 de->pde_unload_completion = &c;
754
755 spin_unlock(&de->pde_unload_lock);
756 spin_unlock(&proc_subdir_lock);
757
758 wait_for_completion(de->pde_unload_completion);
759
760 spin_lock(&proc_subdir_lock);
761 goto continue_removing;
762 }
763 spin_unlock(&de->pde_unload_lock);
764
765continue_removing:
737 if (S_ISDIR(de->mode)) 766 if (S_ISDIR(de->mode))
738 parent->nlink--; 767 parent->nlink--;
739 proc_kill_inodes(de); 768 if (!S_ISREG(de->mode))
769 proc_kill_inodes(de);
740 de->nlink = 0; 770 de->nlink = 0;
741 WARN_ON(de->subdir); 771 WARN_ON(de->subdir);
742 if (!atomic_read(&de->count)) 772 if (!atomic_read(&de->count))