diff options
Diffstat (limited to 'fs/proc/generic.c')
-rw-r--r-- | fs/proc/generic.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 39f3d6519035..8d49838e5554 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -374,9 +374,16 @@ static int proc_delete_dentry(struct dentry * dentry) | |||
374 | return 1; | 374 | return 1; |
375 | } | 375 | } |
376 | 376 | ||
377 | static int proc_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) | ||
378 | { | ||
379 | d_drop(dentry); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
377 | static struct dentry_operations proc_dentry_operations = | 383 | static struct dentry_operations proc_dentry_operations = |
378 | { | 384 | { |
379 | .d_delete = proc_delete_dentry, | 385 | .d_delete = proc_delete_dentry, |
386 | .d_revalidate = proc_revalidate_dentry, | ||
380 | }; | 387 | }; |
381 | 388 | ||
382 | /* | 389 | /* |
@@ -397,8 +404,11 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam | |||
397 | if (de->namelen != dentry->d_name.len) | 404 | if (de->namelen != dentry->d_name.len) |
398 | continue; | 405 | continue; |
399 | if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { | 406 | if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { |
400 | unsigned int ino = de->low_ino; | 407 | unsigned int ino; |
401 | 408 | ||
409 | if (de->shadow_proc) | ||
410 | de = de->shadow_proc(current, de); | ||
411 | ino = de->low_ino; | ||
402 | de_get(de); | 412 | de_get(de); |
403 | spin_unlock(&proc_subdir_lock); | 413 | spin_unlock(&proc_subdir_lock); |
404 | error = -EINVAL; | 414 | error = -EINVAL; |
@@ -585,6 +595,7 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, | |||
585 | ent->namelen = len; | 595 | ent->namelen = len; |
586 | ent->mode = mode; | 596 | ent->mode = mode; |
587 | ent->nlink = nlink; | 597 | ent->nlink = nlink; |
598 | atomic_set(&ent->count, 1); | ||
588 | ent->pde_users = 0; | 599 | ent->pde_users = 0; |
589 | spin_lock_init(&ent->pde_unload_lock); | 600 | spin_lock_init(&ent->pde_unload_lock); |
590 | ent->pde_unload_completion = NULL; | 601 | ent->pde_unload_completion = NULL; |
@@ -682,7 +693,6 @@ void free_proc_entry(struct proc_dir_entry *de) | |||
682 | 693 | ||
683 | /* | 694 | /* |
684 | * Remove a /proc entry and free it if it's not currently in use. | 695 | * Remove a /proc entry and free it if it's not currently in use. |
685 | * If it is in use, we set the 'deleted' flag. | ||
686 | */ | 696 | */ |
687 | void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | 697 | void remove_proc_entry(const char *name, struct proc_dir_entry *parent) |
688 | { | 698 | { |
@@ -731,13 +741,8 @@ continue_removing: | |||
731 | parent->nlink--; | 741 | parent->nlink--; |
732 | de->nlink = 0; | 742 | de->nlink = 0; |
733 | WARN_ON(de->subdir); | 743 | WARN_ON(de->subdir); |
734 | if (!atomic_read(&de->count)) | 744 | if (atomic_dec_and_test(&de->count)) |
735 | free_proc_entry(de); | 745 | free_proc_entry(de); |
736 | else { | ||
737 | de->deleted = 1; | ||
738 | printk("remove_proc_entry: %s/%s busy, count=%d\n", | ||
739 | parent->name, de->name, atomic_read(&de->count)); | ||
740 | } | ||
741 | break; | 746 | break; |
742 | } | 747 | } |
743 | spin_unlock(&proc_subdir_lock); | 748 | spin_unlock(&proc_subdir_lock); |