aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/inode.c')
-rw-r--r--fs/proc/inode.c34
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 @@
28static void proc_evict_inode(struct inode *inode) 27static 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
46struct vfsmount *proc_mnt;
47
48static struct kmem_cache * proc_inode_cachep; 54static struct kmem_cache * proc_inode_cachep;
49 55
50static struct inode *proc_alloc_inode(struct super_block *sb) 56static 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
69static void proc_destroy_inode(struct inode *inode) 77static 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
84static void proc_destroy_inode(struct inode *inode)
85{
86 call_rcu(&inode->i_rcu, proc_i_callback);
87}
88
74static void init_once(void *foo) 89static 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
413struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, 428struct 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;