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.c52
1 files changed, 38 insertions, 14 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 8a40e15f5ecb..b5e7155d30d8 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"
@@ -529,12 +530,6 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
529 return -EAGAIN; 530 return -EAGAIN;
530 dp->low_ino = i; 531 dp->low_ino = i;
531 532
532 spin_lock(&proc_subdir_lock);
533 dp->next = dir->subdir;
534 dp->parent = dir;
535 dir->subdir = dp;
536 spin_unlock(&proc_subdir_lock);
537
538 if (S_ISDIR(dp->mode)) { 533 if (S_ISDIR(dp->mode)) {
539 if (dp->proc_iops == NULL) { 534 if (dp->proc_iops == NULL) {
540 dp->proc_fops = &proc_dir_operations; 535 dp->proc_fops = &proc_dir_operations;
@@ -550,6 +545,13 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
550 if (dp->proc_iops == NULL) 545 if (dp->proc_iops == NULL)
551 dp->proc_iops = &proc_file_inode_operations; 546 dp->proc_iops = &proc_file_inode_operations;
552 } 547 }
548
549 spin_lock(&proc_subdir_lock);
550 dp->next = dir->subdir;
551 dp->parent = dir;
552 dir->subdir = dp;
553 spin_unlock(&proc_subdir_lock);
554
553 return 0; 555 return 0;
554} 556}
555 557
@@ -613,6 +615,9 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent,
613 ent->namelen = len; 615 ent->namelen = len;
614 ent->mode = mode; 616 ent->mode = mode;
615 ent->nlink = nlink; 617 ent->nlink = nlink;
618 ent->pde_users = 0;
619 spin_lock_init(&ent->pde_unload_lock);
620 ent->pde_unload_completion = NULL;
616 out: 621 out:
617 return ent; 622 return ent;
618} 623}
@@ -649,9 +654,6 @@ struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
649 654
650 ent = proc_create(&parent, name, S_IFDIR | mode, 2); 655 ent = proc_create(&parent, name, S_IFDIR | mode, 2);
651 if (ent) { 656 if (ent) {
652 ent->proc_fops = &proc_dir_operations;
653 ent->proc_iops = &proc_dir_inode_operations;
654
655 if (proc_register(parent, ent) < 0) { 657 if (proc_register(parent, ent) < 0) {
656 kfree(ent); 658 kfree(ent);
657 ent = NULL; 659 ent = NULL;
@@ -686,10 +688,6 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
686 688
687 ent = proc_create(&parent,name,mode,nlink); 689 ent = proc_create(&parent,name,mode,nlink);
688 if (ent) { 690 if (ent) {
689 if (S_ISDIR(mode)) {
690 ent->proc_fops = &proc_dir_operations;
691 ent->proc_iops = &proc_dir_inode_operations;
692 }
693 if (proc_register(parent, ent) < 0) { 691 if (proc_register(parent, ent) < 0) {
694 kfree(ent); 692 kfree(ent);
695 ent = NULL; 693 ent = NULL;
@@ -734,9 +732,35 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
734 de = *p; 732 de = *p;
735 *p = de->next; 733 *p = de->next;
736 de->next = NULL; 734 de->next = NULL;
735
736 spin_lock(&de->pde_unload_lock);
737 /*
738 * Stop accepting new callers into module. If you're
739 * dynamically allocating ->proc_fops, save a pointer somewhere.
740 */
741 de->proc_fops = NULL;
742 /* Wait until all existing callers into module are done. */
743 if (de->pde_users > 0) {
744 DECLARE_COMPLETION_ONSTACK(c);
745
746 if (!de->pde_unload_completion)
747 de->pde_unload_completion = &c;
748
749 spin_unlock(&de->pde_unload_lock);
750 spin_unlock(&proc_subdir_lock);
751
752 wait_for_completion(de->pde_unload_completion);
753
754 spin_lock(&proc_subdir_lock);
755 goto continue_removing;
756 }
757 spin_unlock(&de->pde_unload_lock);
758
759continue_removing:
737 if (S_ISDIR(de->mode)) 760 if (S_ISDIR(de->mode))
738 parent->nlink--; 761 parent->nlink--;
739 proc_kill_inodes(de); 762 if (!S_ISREG(de->mode))
763 proc_kill_inodes(de);
740 de->nlink = 0; 764 de->nlink = 0;
741 WARN_ON(de->subdir); 765 WARN_ON(de->subdir);
742 if (!atomic_read(&de->count)) 766 if (!atomic_read(&de->count))