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.c149
1 files changed, 82 insertions, 67 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index a36ad3c75cf4..43e54e86cefd 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -69,12 +69,7 @@ proc_file_read(struct file *file, char __user *buf, size_t nbytes,
69 count = min_t(size_t, PROC_BLOCK_SIZE, nbytes); 69 count = min_t(size_t, PROC_BLOCK_SIZE, nbytes);
70 70
71 start = NULL; 71 start = NULL;
72 if (dp->get_info) { 72 if (dp->read_proc) {
73 /* Handle old net routines */
74 n = dp->get_info(page, &start, *ppos, count);
75 if (n < count)
76 eof = 1;
77 } else if (dp->read_proc) {
78 /* 73 /*
79 * How to be a proc read function 74 * How to be a proc read function
80 * ------------------------------ 75 * ------------------------------
@@ -277,8 +272,11 @@ static int xlate_proc_name(const char *name,
277 int len; 272 int len;
278 int rtn = 0; 273 int rtn = 0;
279 274
275 de = *ret;
276 if (!de)
277 de = &proc_root;
278
280 spin_lock(&proc_subdir_lock); 279 spin_lock(&proc_subdir_lock);
281 de = &proc_root;
282 while (1) { 280 while (1) {
283 next = strchr(cp, '/'); 281 next = strchr(cp, '/');
284 if (!next) 282 if (!next)
@@ -385,20 +383,18 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
385 383
386 lock_kernel(); 384 lock_kernel();
387 spin_lock(&proc_subdir_lock); 385 spin_lock(&proc_subdir_lock);
388 if (de) { 386 for (de = de->subdir; de ; de = de->next) {
389 for (de = de->subdir; de ; de = de->next) { 387 if (de->namelen != dentry->d_name.len)
390 if (de->namelen != dentry->d_name.len) 388 continue;
391 continue; 389 if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
392 if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { 390 unsigned int ino;
393 unsigned int ino;
394 391
395 ino = de->low_ino; 392 ino = de->low_ino;
396 de_get(de); 393 de_get(de);
397 spin_unlock(&proc_subdir_lock); 394 spin_unlock(&proc_subdir_lock);
398 error = -EINVAL; 395 error = -EINVAL;
399 inode = proc_get_inode(dir->i_sb, ino, de); 396 inode = proc_get_inode(dir->i_sb, ino, de);
400 goto out_unlock; 397 goto out_unlock;
401 }
402 } 398 }
403 } 399 }
404 spin_unlock(&proc_subdir_lock); 400 spin_unlock(&proc_subdir_lock);
@@ -410,7 +406,8 @@ out_unlock:
410 d_add(dentry, inode); 406 d_add(dentry, inode);
411 return NULL; 407 return NULL;
412 } 408 }
413 de_put(de); 409 if (de)
410 de_put(de);
414 return ERR_PTR(error); 411 return ERR_PTR(error);
415} 412}
416 413
@@ -440,10 +437,6 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
440 lock_kernel(); 437 lock_kernel();
441 438
442 ino = inode->i_ino; 439 ino = inode->i_ino;
443 if (!de) {
444 ret = -EINVAL;
445 goto out;
446 }
447 i = filp->f_pos; 440 i = filp->f_pos;
448 switch (i) { 441 switch (i) {
449 case 0: 442 case 0:
@@ -582,7 +575,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
582 /* make sure name is valid */ 575 /* make sure name is valid */
583 if (!name || !strlen(name)) goto out; 576 if (!name || !strlen(name)) goto out;
584 577
585 if (!(*parent) && xlate_proc_name(name, parent, &fn) != 0) 578 if (xlate_proc_name(name, parent, &fn) != 0)
586 goto out; 579 goto out;
587 580
588 /* At this point there must not be any '/' characters beyond *fn */ 581 /* At this point there must not be any '/' characters beyond *fn */
@@ -648,6 +641,23 @@ struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
648 return ent; 641 return ent;
649} 642}
650 643
644struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
645 struct proc_dir_entry *parent)
646{
647 struct proc_dir_entry *ent;
648
649 ent = __proc_create(&parent, name, S_IFDIR | S_IRUGO | S_IXUGO, 2);
650 if (ent) {
651 ent->data = net;
652 if (proc_register(parent, ent) < 0) {
653 kfree(ent);
654 ent = NULL;
655 }
656 }
657 return ent;
658}
659EXPORT_SYMBOL_GPL(proc_net_mkdir);
660
651struct proc_dir_entry *proc_mkdir(const char *name, 661struct proc_dir_entry *proc_mkdir(const char *name,
652 struct proc_dir_entry *parent) 662 struct proc_dir_entry *parent)
653{ 663{
@@ -682,9 +692,10 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
682 return ent; 692 return ent;
683} 693}
684 694
685struct proc_dir_entry *proc_create(const char *name, mode_t mode, 695struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
686 struct proc_dir_entry *parent, 696 struct proc_dir_entry *parent,
687 const struct file_operations *proc_fops) 697 const struct file_operations *proc_fops,
698 void *data)
688{ 699{
689 struct proc_dir_entry *pde; 700 struct proc_dir_entry *pde;
690 nlink_t nlink; 701 nlink_t nlink;
@@ -705,6 +716,7 @@ struct proc_dir_entry *proc_create(const char *name, mode_t mode,
705 if (!pde) 716 if (!pde)
706 goto out; 717 goto out;
707 pde->proc_fops = proc_fops; 718 pde->proc_fops = proc_fops;
719 pde->data = data;
708 if (proc_register(parent, pde) < 0) 720 if (proc_register(parent, pde) < 0)
709 goto out_free; 721 goto out_free;
710 return pde; 722 return pde;
@@ -734,55 +746,58 @@ void free_proc_entry(struct proc_dir_entry *de)
734void remove_proc_entry(const char *name, struct proc_dir_entry *parent) 746void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
735{ 747{
736 struct proc_dir_entry **p; 748 struct proc_dir_entry **p;
737 struct proc_dir_entry *de; 749 struct proc_dir_entry *de = NULL;
738 const char *fn = name; 750 const char *fn = name;
739 int len; 751 int len;
740 752
741 if (!parent && xlate_proc_name(name, &parent, &fn) != 0) 753 if (xlate_proc_name(name, &parent, &fn) != 0)
742 goto out; 754 return;
743 len = strlen(fn); 755 len = strlen(fn);
744 756
745 spin_lock(&proc_subdir_lock); 757 spin_lock(&proc_subdir_lock);
746 for (p = &parent->subdir; *p; p=&(*p)->next ) { 758 for (p = &parent->subdir; *p; p=&(*p)->next ) {
747 if (!proc_match(len, fn, *p)) 759 if (proc_match(len, fn, *p)) {
748 continue; 760 de = *p;
749 de = *p; 761 *p = de->next;
750 *p = de->next; 762 de->next = NULL;
751 de->next = NULL; 763 break;
752 764 }
753 spin_lock(&de->pde_unload_lock); 765 }
754 /* 766 spin_unlock(&proc_subdir_lock);
755 * Stop accepting new callers into module. If you're 767 if (!de)
756 * dynamically allocating ->proc_fops, save a pointer somewhere. 768 return;
757 */
758 de->proc_fops = NULL;
759 /* Wait until all existing callers into module are done. */
760 if (de->pde_users > 0) {
761 DECLARE_COMPLETION_ONSTACK(c);
762
763 if (!de->pde_unload_completion)
764 de->pde_unload_completion = &c;
765
766 spin_unlock(&de->pde_unload_lock);
767 spin_unlock(&proc_subdir_lock);
768 769
769 wait_for_completion(de->pde_unload_completion); 770 spin_lock(&de->pde_unload_lock);
771 /*
772 * Stop accepting new callers into module. If you're
773 * dynamically allocating ->proc_fops, save a pointer somewhere.
774 */
775 de->proc_fops = NULL;
776 /* Wait until all existing callers into module are done. */
777 if (de->pde_users > 0) {
778 DECLARE_COMPLETION_ONSTACK(c);
779
780 if (!de->pde_unload_completion)
781 de->pde_unload_completion = &c;
770 782
771 spin_lock(&proc_subdir_lock);
772 goto continue_removing;
773 }
774 spin_unlock(&de->pde_unload_lock); 783 spin_unlock(&de->pde_unload_lock);
775 784
785 wait_for_completion(de->pde_unload_completion);
786
787 goto continue_removing;
788 }
789 spin_unlock(&de->pde_unload_lock);
790
776continue_removing: 791continue_removing:
777 if (S_ISDIR(de->mode)) 792 if (S_ISDIR(de->mode))
778 parent->nlink--; 793 parent->nlink--;
779 de->nlink = 0; 794 de->nlink = 0;
780 WARN_ON(de->subdir); 795 if (de->subdir) {
781 if (atomic_dec_and_test(&de->count)) 796 printk(KERN_WARNING "%s: removing non-empty directory "
782 free_proc_entry(de); 797 "'%s/%s', leaking at least '%s'\n", __func__,
783 break; 798 de->parent->name, de->name, de->subdir->name);
799 WARN_ON(1);
784 } 800 }
785 spin_unlock(&proc_subdir_lock); 801 if (atomic_dec_and_test(&de->count))
786out: 802 free_proc_entry(de);
787 return;
788} 803}