diff options
Diffstat (limited to 'fs/proc/inode.c')
| -rw-r--r-- | fs/proc/inode.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 3ddb6068177..d6a7ca1fdac 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | static void proc_evict_inode(struct inode *inode) | 27 | static void proc_evict_inode(struct inode *inode) |
| 28 | { | 28 | { |
| 29 | struct proc_dir_entry *de; | 29 | struct proc_dir_entry *de; |
| 30 | struct ctl_table_header *head; | ||
| 30 | 31 | ||
| 31 | truncate_inode_pages(&inode->i_data, 0); | 32 | truncate_inode_pages(&inode->i_data, 0); |
| 32 | end_writeback(inode); | 33 | end_writeback(inode); |
| @@ -38,8 +39,11 @@ static void proc_evict_inode(struct inode *inode) | |||
| 38 | de = PROC_I(inode)->pde; | 39 | de = PROC_I(inode)->pde; |
| 39 | if (de) | 40 | if (de) |
| 40 | pde_put(de); | 41 | pde_put(de); |
| 41 | if (PROC_I(inode)->sysctl) | 42 | head = PROC_I(inode)->sysctl; |
| 42 | sysctl_head_put(PROC_I(inode)->sysctl); | 43 | if (head) { |
| 44 | rcu_assign_pointer(PROC_I(inode)->sysctl, NULL); | ||
| 45 | sysctl_head_put(head); | ||
| 46 | } | ||
| 43 | } | 47 | } |
| 44 | 48 | ||
| 45 | struct vfsmount *proc_mnt; | 49 | struct vfsmount *proc_mnt; |
| @@ -65,11 +69,18 @@ static struct inode *proc_alloc_inode(struct super_block *sb) | |||
| 65 | return inode; | 69 | return inode; |
| 66 | } | 70 | } |
| 67 | 71 | ||
| 68 | static void proc_destroy_inode(struct inode *inode) | 72 | static void proc_i_callback(struct rcu_head *head) |
| 69 | { | 73 | { |
| 74 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 75 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 70 | kmem_cache_free(proc_inode_cachep, PROC_I(inode)); | 76 | kmem_cache_free(proc_inode_cachep, PROC_I(inode)); |
| 71 | } | 77 | } |
| 72 | 78 | ||
| 79 | static void proc_destroy_inode(struct inode *inode) | ||
| 80 | { | ||
| 81 | call_rcu(&inode->i_rcu, proc_i_callback); | ||
| 82 | } | ||
| 83 | |||
| 73 | static void init_once(void *foo) | 84 | static void init_once(void *foo) |
| 74 | { | 85 | { |
| 75 | struct proc_inode *ei = (struct proc_inode *) foo; | 86 | struct proc_inode *ei = (struct proc_inode *) foo; |
| @@ -409,12 +420,11 @@ static const struct file_operations proc_reg_file_ops_no_compat = { | |||
| 409 | }; | 420 | }; |
| 410 | #endif | 421 | #endif |
| 411 | 422 | ||
| 412 | struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, | 423 | struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) |
| 413 | struct proc_dir_entry *de) | ||
| 414 | { | 424 | { |
| 415 | struct inode * inode; | 425 | struct inode * inode; |
| 416 | 426 | ||
| 417 | inode = iget_locked(sb, ino); | 427 | inode = iget_locked(sb, de->low_ino); |
| 418 | if (!inode) | 428 | if (!inode) |
| 419 | return NULL; | 429 | return NULL; |
| 420 | if (inode->i_state & I_NEW) { | 430 | if (inode->i_state & I_NEW) { |
| @@ -464,7 +474,7 @@ int proc_fill_super(struct super_block *s) | |||
| 464 | s->s_time_gran = 1; | 474 | s->s_time_gran = 1; |
| 465 | 475 | ||
| 466 | pde_get(&proc_root); | 476 | pde_get(&proc_root); |
| 467 | root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root); | 477 | root_inode = proc_get_inode(s, &proc_root); |
| 468 | if (!root_inode) | 478 | if (!root_inode) |
| 469 | goto out_no_root; | 479 | goto out_no_root; |
| 470 | root_inode->i_uid = 0; | 480 | root_inode->i_uid = 0; |
