diff options
Diffstat (limited to 'fs/proc/inode.c')
-rw-r--r-- | fs/proc/inode.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 9c2b5f484879..74b48cfa1bb2 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/limits.h> | 16 | #include <linux/limits.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/smp_lock.h> | ||
20 | #include <linux/sysctl.h> | 19 | #include <linux/sysctl.h> |
21 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
22 | 21 | ||
@@ -28,6 +27,8 @@ | |||
28 | static void proc_evict_inode(struct inode *inode) | 27 | static void proc_evict_inode(struct inode *inode) |
29 | { | 28 | { |
30 | struct proc_dir_entry *de; | 29 | struct proc_dir_entry *de; |
30 | struct ctl_table_header *head; | ||
31 | const struct proc_ns_operations *ns_ops; | ||
31 | 32 | ||
32 | truncate_inode_pages(&inode->i_data, 0); | 33 | truncate_inode_pages(&inode->i_data, 0); |
33 | end_writeback(inode); | 34 | end_writeback(inode); |
@@ -39,12 +40,17 @@ static void proc_evict_inode(struct inode *inode) | |||
39 | de = PROC_I(inode)->pde; | 40 | de = PROC_I(inode)->pde; |
40 | if (de) | 41 | if (de) |
41 | pde_put(de); | 42 | pde_put(de); |
42 | if (PROC_I(inode)->sysctl) | 43 | head = PROC_I(inode)->sysctl; |
43 | sysctl_head_put(PROC_I(inode)->sysctl); | 44 | if (head) { |
45 | rcu_assign_pointer(PROC_I(inode)->sysctl, NULL); | ||
46 | sysctl_head_put(head); | ||
47 | } | ||
48 | /* Release any associated namespace */ | ||
49 | ns_ops = PROC_I(inode)->ns_ops; | ||
50 | if (ns_ops && ns_ops->put) | ||
51 | ns_ops->put(PROC_I(inode)->ns); | ||
44 | } | 52 | } |
45 | 53 | ||
46 | struct vfsmount *proc_mnt; | ||
47 | |||
48 | static struct kmem_cache * proc_inode_cachep; | 54 | static struct kmem_cache * proc_inode_cachep; |
49 | 55 | ||
50 | static struct inode *proc_alloc_inode(struct super_block *sb) | 56 | static struct inode *proc_alloc_inode(struct super_block *sb) |
@@ -61,16 +67,25 @@ static struct inode *proc_alloc_inode(struct super_block *sb) | |||
61 | ei->pde = NULL; | 67 | ei->pde = NULL; |
62 | ei->sysctl = NULL; | 68 | ei->sysctl = NULL; |
63 | ei->sysctl_entry = NULL; | 69 | ei->sysctl_entry = NULL; |
70 | ei->ns = NULL; | ||
71 | ei->ns_ops = NULL; | ||
64 | inode = &ei->vfs_inode; | 72 | inode = &ei->vfs_inode; |
65 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 73 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
66 | return inode; | 74 | return inode; |
67 | } | 75 | } |
68 | 76 | ||
69 | static void proc_destroy_inode(struct inode *inode) | 77 | static void proc_i_callback(struct rcu_head *head) |
70 | { | 78 | { |
79 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
80 | INIT_LIST_HEAD(&inode->i_dentry); | ||
71 | kmem_cache_free(proc_inode_cachep, PROC_I(inode)); | 81 | kmem_cache_free(proc_inode_cachep, PROC_I(inode)); |
72 | } | 82 | } |
73 | 83 | ||
84 | static void proc_destroy_inode(struct inode *inode) | ||
85 | { | ||
86 | call_rcu(&inode->i_rcu, proc_i_callback); | ||
87 | } | ||
88 | |||
74 | static void init_once(void *foo) | 89 | static void init_once(void *foo) |
75 | { | 90 | { |
76 | struct proc_inode *ei = (struct proc_inode *) foo; | 91 | struct proc_inode *ei = (struct proc_inode *) foo; |
@@ -410,12 +425,11 @@ static const struct file_operations proc_reg_file_ops_no_compat = { | |||
410 | }; | 425 | }; |
411 | #endif | 426 | #endif |
412 | 427 | ||
413 | struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, | 428 | struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) |
414 | struct proc_dir_entry *de) | ||
415 | { | 429 | { |
416 | struct inode * inode; | 430 | struct inode * inode; |
417 | 431 | ||
418 | inode = iget_locked(sb, ino); | 432 | inode = iget_locked(sb, de->low_ino); |
419 | if (!inode) | 433 | if (!inode) |
420 | return NULL; | 434 | return NULL; |
421 | if (inode->i_state & I_NEW) { | 435 | if (inode->i_state & I_NEW) { |
@@ -465,7 +479,7 @@ int proc_fill_super(struct super_block *s) | |||
465 | s->s_time_gran = 1; | 479 | s->s_time_gran = 1; |
466 | 480 | ||
467 | pde_get(&proc_root); | 481 | pde_get(&proc_root); |
468 | root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root); | 482 | root_inode = proc_get_inode(s, &proc_root); |
469 | if (!root_inode) | 483 | if (!root_inode) |
470 | goto out_no_root; | 484 | goto out_no_root; |
471 | root_inode->i_uid = 0; | 485 | root_inode->i_uid = 0; |