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 | |
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')
-rw-r--r-- | fs/proc/base.c | 16 | ||||
-rw-r--r-- | fs/proc/inode.c | 2 | ||||
-rw-r--r-- | fs/proc/internal.h | 1 | ||||
-rw-r--r-- | fs/proc/root.c | 2 | ||||
-rw-r--r-- | fs/proc/self.c | 46 |
5 files changed, 55 insertions, 12 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 69078c7cef1f..593e7c5ddb49 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -2794,7 +2794,7 @@ retry: | |||
2794 | return iter; | 2794 | return iter; |
2795 | } | 2795 | } |
2796 | 2796 | ||
2797 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY) | 2797 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1) |
2798 | 2798 | ||
2799 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 2799 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
2800 | struct tgid_iter iter) | 2800 | struct tgid_iter iter) |
@@ -2817,13 +2817,21 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2817 | struct tgid_iter iter; | 2817 | struct tgid_iter iter; |
2818 | struct pid_namespace *ns; | 2818 | struct pid_namespace *ns; |
2819 | filldir_t __filldir; | 2819 | filldir_t __filldir; |
2820 | loff_t pos = filp->f_pos; | ||
2820 | 2821 | ||
2821 | if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) | 2822 | if (pos >= PID_MAX_LIMIT + TGID_OFFSET) |
2822 | goto out; | 2823 | goto out; |
2823 | 2824 | ||
2824 | ns = filp->f_dentry->d_sb->s_fs_info; | 2825 | if (pos == TGID_OFFSET - 1) { |
2826 | if (proc_fill_cache(filp, dirent, filldir, "self", 4, | ||
2827 | NULL, NULL, NULL) < 0) | ||
2828 | goto out; | ||
2829 | iter.tgid = 0; | ||
2830 | } else { | ||
2831 | iter.tgid = pos - TGID_OFFSET; | ||
2832 | } | ||
2825 | iter.task = NULL; | 2833 | iter.task = NULL; |
2826 | iter.tgid = filp->f_pos - TGID_OFFSET; | 2834 | ns = filp->f_dentry->d_sb->s_fs_info; |
2827 | for (iter = next_tgid(ns, iter); | 2835 | for (iter = next_tgid(ns, iter); |
2828 | iter.task; | 2836 | iter.task; |
2829 | iter.tgid += 1, iter = next_tgid(ns, iter)) { | 2837 | iter.tgid += 1, iter = next_tgid(ns, iter)) { |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 869116c2afbe..908e97457319 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -506,5 +506,5 @@ int proc_fill_super(struct super_block *s) | |||
506 | return -ENOMEM; | 506 | return -ENOMEM; |
507 | } | 507 | } |
508 | 508 | ||
509 | return 0; | 509 | return proc_setup_self(s); |
510 | } | 510 | } |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 85ff3a4598b3..9c93a53f371d 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -205,3 +205,4 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr); | |||
205 | extern const struct inode_operations proc_ns_dir_inode_operations; | 205 | extern const struct inode_operations proc_ns_dir_inode_operations; |
206 | extern const struct file_operations proc_ns_dir_operations; | 206 | extern const struct file_operations proc_ns_dir_operations; |
207 | 207 | ||
208 | extern int proc_setup_self(struct super_block *); | ||
diff --git a/fs/proc/root.c b/fs/proc/root.c index c6e9fac26bac..20834b3c8ea3 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -137,6 +137,8 @@ static void proc_kill_sb(struct super_block *sb) | |||
137 | struct pid_namespace *ns; | 137 | struct pid_namespace *ns; |
138 | 138 | ||
139 | ns = (struct pid_namespace *)sb->s_fs_info; | 139 | ns = (struct pid_namespace *)sb->s_fs_info; |
140 | if (ns->proc_self) | ||
141 | dput(ns->proc_self); | ||
140 | kill_anon_super(sb); | 142 | kill_anon_super(sb); |
141 | put_pid_ns(ns); | 143 | put_pid_ns(ns); |
142 | } | 144 | } |
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 | } |