aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2010-07-10 17:52:49 -0400
committerEric W. Biederman <ebiederm@xmission.com>2012-11-19 06:09:34 -0500
commite656d8a6f7fdf7612d2f5771f0ddfca9487f59d9 (patch)
tree66479ae4b636517e0e54e78b4ec95acadd0aec7a /fs/proc
parentdd34ad35c32bb3d16789d8d4084aead7e68a7b09 (diff)
procfs: Use the proc generic infrastructure for proc/self.
I had visions at one point of splitting proc into two filesystems. If that had happened proc/self being the the part of proc that actually deals with pids would have been a nice cleanup. As it is proc/self requires a lot of unnecessary infrastructure for a single file. The only user visible change is that a mounted /proc for a pid namespace that is dead now shows a broken proc symlink, instead of being completely invisible. I don't think anyone will notice or care. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/Makefile1
-rw-r--r--fs/proc/base.c154
-rw-r--r--fs/proc/internal.h1
-rw-r--r--fs/proc/root.c1
-rw-r--r--fs/proc/self.c59
5 files changed, 64 insertions, 152 deletions
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 99349efbbc2b..981b05601931 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -21,6 +21,7 @@ proc-y += uptime.o
21proc-y += version.o 21proc-y += version.o
22proc-y += softirqs.o 22proc-y += softirqs.o
23proc-y += namespaces.o 23proc-y += namespaces.o
24proc-y += self.o
24proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o 25proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o
25proc-$(CONFIG_NET) += proc_net.o 26proc-$(CONFIG_NET) += proc_net.o
26proc-$(CONFIG_PROC_KCORE) += kcore.o 27proc-$(CONFIG_PROC_KCORE) += kcore.o
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 144a96732dd7..cbe454e94af8 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2237,146 +2237,6 @@ static const struct file_operations proc_coredump_filter_operations = {
2237}; 2237};
2238#endif 2238#endif
2239 2239
2240/*
2241 * /proc/self:
2242 */
2243static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
2244 int buflen)
2245{
2246 struct pid_namespace *ns = dentry->d_sb->s_fs_info;
2247 pid_t tgid = task_tgid_nr_ns(current, ns);
2248 char tmp[PROC_NUMBUF];
2249 if (!tgid)
2250 return -ENOENT;
2251 sprintf(tmp, "%d", tgid);
2252 return vfs_readlink(dentry,buffer,buflen,tmp);
2253}
2254
2255static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
2256{
2257 struct pid_namespace *ns = dentry->d_sb->s_fs_info;
2258 pid_t tgid = task_tgid_nr_ns(current, ns);
2259 char *name = ERR_PTR(-ENOENT);
2260 if (tgid) {
2261 /* 11 for max length of signed int in decimal + NULL term */
2262 name = kmalloc(12, GFP_KERNEL);
2263 if (!name)
2264 name = ERR_PTR(-ENOMEM);
2265 else
2266 sprintf(name, "%d", tgid);
2267 }
2268 nd_set_link(nd, name);
2269 return NULL;
2270}
2271
2272static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
2273 void *cookie)
2274{
2275 char *s = nd_get_link(nd);
2276 if (!IS_ERR(s))
2277 kfree(s);
2278}
2279
2280static const struct inode_operations proc_self_inode_operations = {
2281 .readlink = proc_self_readlink,
2282 .follow_link = proc_self_follow_link,
2283 .put_link = proc_self_put_link,
2284};
2285
2286/*
2287 * proc base
2288 *
2289 * These are the directory entries in the root directory of /proc
2290 * that properly belong to the /proc filesystem, as they describe
2291 * describe something that is process related.
2292 */
2293static const struct pid_entry proc_base_stuff[] = {
2294 NOD("self", S_IFLNK|S_IRWXUGO,
2295 &proc_self_inode_operations, NULL, {}),
2296};
2297
2298static struct dentry *proc_base_instantiate(struct inode *dir,
2299 struct dentry *dentry, struct task_struct *task, const void *ptr)
2300{
2301 const struct pid_entry *p = ptr;
2302 struct inode *inode;
2303 struct proc_inode *ei;
2304 struct dentry *error;
2305
2306 /* Allocate the inode */
2307 error = ERR_PTR(-ENOMEM);
2308 inode = new_inode(dir->i_sb);
2309 if (!inode)
2310 goto out;
2311
2312 /* Initialize the inode */
2313 ei = PROC_I(inode);
2314 inode->i_ino = get_next_ino();
2315 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
2316
2317 /*
2318 * grab the reference to the task.
2319 */
2320 ei->pid = get_task_pid(task, PIDTYPE_PID);
2321 if (!ei->pid)
2322 goto out_iput;
2323
2324 inode->i_mode = p->mode;
2325 if (S_ISDIR(inode->i_mode))
2326 set_nlink(inode, 2);
2327 if (S_ISLNK(inode->i_mode))
2328 inode->i_size = 64;
2329 if (p->iop)
2330 inode->i_op = p->iop;
2331 if (p->fop)
2332 inode->i_fop = p->fop;
2333 ei->op = p->op;
2334 d_add(dentry, inode);
2335 error = NULL;
2336out:
2337 return error;
2338out_iput:
2339 iput(inode);
2340 goto out;
2341}
2342
2343static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
2344{
2345 struct dentry *error;
2346 struct task_struct *task = get_proc_task(dir);
2347 const struct pid_entry *p, *last;
2348
2349 error = ERR_PTR(-ENOENT);
2350
2351 if (!task)
2352 goto out_no_task;
2353
2354 /* Lookup the directory entry */
2355 last = &proc_base_stuff[ARRAY_SIZE(proc_base_stuff) - 1];
2356 for (p = proc_base_stuff; p <= last; p++) {
2357 if (p->len != dentry->d_name.len)
2358 continue;
2359 if (!memcmp(dentry->d_name.name, p->name, p->len))
2360 break;
2361 }
2362 if (p > last)
2363 goto out;
2364
2365 error = proc_base_instantiate(dir, dentry, task, p);
2366
2367out:
2368 put_task_struct(task);
2369out_no_task:
2370 return error;
2371}
2372
2373static int proc_base_fill_cache(struct file *filp, void *dirent,
2374 filldir_t filldir, struct task_struct *task, const struct pid_entry *p)
2375{
2376 return proc_fill_cache(filp, dirent, filldir, p->name, p->len,
2377 proc_base_instantiate, task, p);
2378}
2379
2380#ifdef CONFIG_TASK_IO_ACCOUNTING 2240#ifdef CONFIG_TASK_IO_ACCOUNTING
2381static int do_io_accounting(struct task_struct *task, char *buffer, int whole) 2241static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
2382{ 2242{
@@ -2767,15 +2627,11 @@ out:
2767 2627
2768struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) 2628struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
2769{ 2629{
2770 struct dentry *result; 2630 struct dentry *result = NULL;
2771 struct task_struct *task; 2631 struct task_struct *task;
2772 unsigned tgid; 2632 unsigned tgid;
2773 struct pid_namespace *ns; 2633 struct pid_namespace *ns;
2774 2634
2775 result = proc_base_lookup(dir, dentry);
2776 if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT)
2777 goto out;
2778
2779 tgid = name_to_int(dentry); 2635 tgid = name_to_int(dentry);
2780 if (tgid == ~0U) 2636 if (tgid == ~0U)
2781 goto out; 2637 goto out;
@@ -2838,7 +2694,7 @@ retry:
2838 return iter; 2694 return iter;
2839} 2695}
2840 2696
2841#define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) 2697#define TGID_OFFSET (FIRST_PROCESS_ENTRY)
2842 2698
2843static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, 2699static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
2844 struct tgid_iter iter) 2700 struct tgid_iter iter)
@@ -2872,12 +2728,6 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
2872 if (!reaper) 2728 if (!reaper)
2873 goto out_no_task; 2729 goto out_no_task;
2874 2730
2875 for (; nr < ARRAY_SIZE(proc_base_stuff); filp->f_pos++, nr++) {
2876 const struct pid_entry *p = &proc_base_stuff[nr];
2877 if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0)
2878 goto out;
2879 }
2880
2881 ns = filp->f_dentry->d_sb->s_fs_info; 2731 ns = filp->f_dentry->d_sb->s_fs_info;
2882 iter.task = NULL; 2732 iter.task = NULL;
2883 iter.tgid = filp->f_pos - TGID_OFFSET; 2733 iter.tgid = filp->f_pos - TGID_OFFSET;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 43973b084abf..252544c05207 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -15,6 +15,7 @@ struct ctl_table_header;
15struct mempolicy; 15struct mempolicy;
16 16
17extern struct proc_dir_entry proc_root; 17extern struct proc_dir_entry proc_root;
18extern void proc_self_init(void);
18#ifdef CONFIG_PROC_SYSCTL 19#ifdef CONFIG_PROC_SYSCTL
19extern int proc_sys_init(void); 20extern int proc_sys_init(void);
20extern void sysctl_head_put(struct ctl_table_header *head); 21extern void sysctl_head_put(struct ctl_table_header *head);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 9889a92d2e01..5da984959edc 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -169,6 +169,7 @@ void __init proc_root_init(void)
169 return; 169 return;
170 } 170 }
171 171
172 proc_self_init();
172 proc_symlink("mounts", NULL, "self/mounts"); 173 proc_symlink("mounts", NULL, "self/mounts");
173 174
174 proc_net_init(); 175 proc_net_init();
diff --git a/fs/proc/self.c b/fs/proc/self.c
new file mode 100644
index 000000000000..aa5cc3bff140
--- /dev/null
+++ b/fs/proc/self.c
@@ -0,0 +1,59 @@
1#include <linux/proc_fs.h>
2#include <linux/sched.h>
3#include <linux/namei.h>
4
5/*
6 * /proc/self:
7 */
8static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
9 int buflen)
10{
11 struct pid_namespace *ns = dentry->d_sb->s_fs_info;
12 pid_t tgid = task_tgid_nr_ns(current, ns);
13 char tmp[PROC_NUMBUF];
14 if (!tgid)
15 return -ENOENT;
16 sprintf(tmp, "%d", tgid);
17 return vfs_readlink(dentry,buffer,buflen,tmp);
18}
19
20static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
21{
22 struct pid_namespace *ns = dentry->d_sb->s_fs_info;
23 pid_t tgid = task_tgid_nr_ns(current, ns);
24 char *name = ERR_PTR(-ENOENT);
25 if (tgid) {
26 /* 11 for max length of signed int in decimal + NULL term */
27 name = kmalloc(12, GFP_KERNEL);
28 if (!name)
29 name = ERR_PTR(-ENOMEM);
30 else
31 sprintf(name, "%d", tgid);
32 }
33 nd_set_link(nd, name);
34 return NULL;
35}
36
37static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
38 void *cookie)
39{
40 char *s = nd_get_link(nd);
41 if (!IS_ERR(s))
42 kfree(s);
43}
44
45static const struct inode_operations proc_self_inode_operations = {
46 .readlink = proc_self_readlink,
47 .follow_link = proc_self_follow_link,
48 .put_link = proc_self_put_link,
49};
50
51void __init proc_self_init(void)
52{
53 struct proc_dir_entry *proc_self_symlink;
54 mode_t mode;
55
56 mode = S_IFLNK | S_IRWXUGO;
57 proc_self_symlink = proc_create("self", mode, NULL, NULL );
58 proc_self_symlink->proc_iops = &proc_self_inode_operations;
59}