[PATCH -mm 1/3] proc: simplify locking in remove_proc_entry()

From: Alexey Dobriyan
Date: Sat Mar 29 2008 - 17:03:48 EST


proc_subdir_lock protects only modifying and walking through PDE lists, so
after we've found PDE to remove and actually removed it from lists, there
is no need to hold proc_subdir_lock for the rest of operation.

Signed-off-by: Alexey Dobriyan <adobriyan@xxxxxxxxx>
---

fs/proc/generic.c | 82 ++++++++++++++++++++++++++----------------------------
1 file changed, 40 insertions(+), 42 deletions(-)

--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -734,60 +734,58 @@ void free_proc_entry(struct proc_dir_entry *de)
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
{
struct proc_dir_entry **p;
- struct proc_dir_entry *de;
+ struct proc_dir_entry *de = NULL;
const char *fn = name;
int len;

if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
- goto out;
+ return;
len = strlen(fn);

spin_lock(&proc_subdir_lock);
for (p = &parent->subdir; *p; p=&(*p)->next ) {
- if (!proc_match(len, fn, *p))
- continue;
- de = *p;
- *p = de->next;
- de->next = NULL;
-
- spin_lock(&de->pde_unload_lock);
- /*
- * Stop accepting new callers into module. If you're
- * dynamically allocating ->proc_fops, save a pointer somewhere.
- */
- de->proc_fops = NULL;
- /* Wait until all existing callers into module are done. */
- if (de->pde_users > 0) {
- DECLARE_COMPLETION_ONSTACK(c);
-
- if (!de->pde_unload_completion)
- de->pde_unload_completion = &c;
-
- spin_unlock(&de->pde_unload_lock);
- spin_unlock(&proc_subdir_lock);
+ if (proc_match(len, fn, *p)) {
+ de = *p;
+ *p = de->next;
+ de->next = NULL;
+ break;
+ }
+ }
+ spin_unlock(&proc_subdir_lock);
+ if (!de)
+ return;

- wait_for_completion(de->pde_unload_completion);
+ spin_lock(&de->pde_unload_lock);
+ /*
+ * Stop accepting new callers into module. If you're
+ * dynamically allocating ->proc_fops, save a pointer somewhere.
+ */
+ de->proc_fops = NULL;
+ /* Wait until all existing callers into module are done. */
+ if (de->pde_users > 0) {
+ DECLARE_COMPLETION_ONSTACK(c);
+
+ if (!de->pde_unload_completion)
+ de->pde_unload_completion = &c;

- spin_lock(&proc_subdir_lock);
- goto continue_removing;
- }
spin_unlock(&de->pde_unload_lock);

+ wait_for_completion(de->pde_unload_completion);
+
+ goto continue_removing;
+ }
+ spin_unlock(&de->pde_unload_lock);
+
continue_removing:
- if (S_ISDIR(de->mode))
- parent->nlink--;
- de->nlink = 0;
- if (de->subdir) {
- printk(KERN_WARNING "%s: removing non-empty directory "
- "'%s/%s', leaking at least '%s'\n", __func__,
- de->parent->name, de->name, de->subdir->name);
- WARN_ON(1);
- }
- if (atomic_dec_and_test(&de->count))
- free_proc_entry(de);
- break;
+ if (S_ISDIR(de->mode))
+ parent->nlink--;
+ de->nlink = 0;
+ if (de->subdir) {
+ printk(KERN_WARNING "%s: removing non-empty directory "
+ "'%s/%s', leaking at least '%s'\n", __func__,
+ de->parent->name, de->name, de->subdir->name);
+ WARN_ON(1);
}
- spin_unlock(&proc_subdir_lock);
-out:
- return;
+ if (atomic_dec_and_test(&de->count))
+ free_proc_entry(de);
}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/