diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-03-29 19:27:05 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-04-09 14:13:05 -0400 |
commit | 021ada7dff22d0d9540ff596cb0f8bb866755ee1 (patch) | |
tree | 3f8a8a8c4ab35ff7cf3f968c079b855a1a18377c /fs/proc/self.c | |
parent | 0ecc833bac594099505a090cbca6ccd5b83d5975 (diff) |
procfs: switch /proc/self away from proc_dir_entry
Just have it pinned in dcache all along and let procfs ->kill_sb()
drop it before kill_anon_super().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/proc/self.c')
-rw-r--r-- | fs/proc/self.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/fs/proc/self.c b/fs/proc/self.c index d8a025296613..21940d89977e 100644 --- a/fs/proc/self.c +++ b/fs/proc/self.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include <linux/proc_fs.h> | ||
2 | #include <linux/sched.h> | 1 | #include <linux/sched.h> |
3 | #include <linux/namei.h> | 2 | #include <linux/namei.h> |
3 | #include <linux/pid_namespace.h> | ||
4 | #include "internal.h" | ||
4 | 5 | ||
5 | /* | 6 | /* |
6 | * /proc/self: | 7 | * /proc/self: |
@@ -48,12 +49,43 @@ static const struct inode_operations proc_self_inode_operations = { | |||
48 | .put_link = proc_self_put_link, | 49 | .put_link = proc_self_put_link, |
49 | }; | 50 | }; |
50 | 51 | ||
51 | void __init proc_self_init(void) | 52 | static unsigned self_inum; |
53 | |||
54 | int proc_setup_self(struct super_block *s) | ||
52 | { | 55 | { |
53 | struct proc_dir_entry *proc_self_symlink; | 56 | struct inode *root_inode = s->s_root->d_inode; |
54 | umode_t mode; | 57 | struct pid_namespace *ns = s->s_fs_info; |
58 | struct dentry *self; | ||
59 | |||
60 | mutex_lock(&root_inode->i_mutex); | ||
61 | self = d_alloc_name(s->s_root, "self"); | ||
62 | if (self) { | ||
63 | struct inode *inode = new_inode_pseudo(s); | ||
64 | if (inode) { | ||
65 | inode->i_ino = self_inum; | ||
66 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
67 | inode->i_mode = S_IFLNK | S_IRWXUGO; | ||
68 | inode->i_uid = GLOBAL_ROOT_UID; | ||
69 | inode->i_gid = GLOBAL_ROOT_GID; | ||
70 | inode->i_op = &proc_self_inode_operations; | ||
71 | d_add(self, inode); | ||
72 | } else { | ||
73 | dput(self); | ||
74 | self = ERR_PTR(-ENOMEM); | ||
75 | } | ||
76 | } else { | ||
77 | self = ERR_PTR(-ENOMEM); | ||
78 | } | ||
79 | mutex_unlock(&root_inode->i_mutex); | ||
80 | if (IS_ERR(self)) { | ||
81 | pr_err("proc_fill_super: can't allocate /proc/self\n"); | ||
82 | return PTR_ERR(self); | ||
83 | } | ||
84 | ns->proc_self = self; | ||
85 | return 0; | ||
86 | } | ||
55 | 87 | ||
56 | mode = S_IFLNK | S_IRWXUGO; | 88 | void __init proc_self_init(void) |
57 | proc_self_symlink = proc_create("self", mode, NULL, NULL ); | 89 | { |
58 | proc_self_symlink->proc_iops = &proc_self_inode_operations; | 90 | proc_alloc_inum(&self_inum); |
59 | } | 91 | } |