diff options
author | Cyrill Gorcunov <gorcunov@openvz.org> | 2012-08-26 10:28:20 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-26 21:10:01 -0400 |
commit | ddd3e0771bc7b869c550687c204e21f0155d5496 (patch) | |
tree | 89d44ea09ddaf95bd7d6e56ab77cfe169bc8bf5a /fs/proc | |
parent | faf60af17f8da87e1c87a6be527344791025ce9e (diff) |
procfs: Convert /proc/pid/fdinfo/ handling routines to seq-file v2
This patch converts /proc/pid/fdinfo/ handling routines to seq-file which
is needed to extend seq operations and plug in auxiliary fdinfo provides
from subsystems like eventfd/eventpoll/fsnotify.
Note the proc_fd_link no longer call for proc_fd_info, simply because
the guts of proc_fd_info() got merged into ->show() of that seq_file
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/fd.c | 112 |
1 files changed, 64 insertions, 48 deletions
diff --git a/fs/proc/fd.c b/fs/proc/fd.c index 1b0f932b4bd9..9cef449c0f76 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c | |||
@@ -6,61 +6,68 @@ | |||
6 | #include <linux/namei.h> | 6 | #include <linux/namei.h> |
7 | #include <linux/pid.h> | 7 | #include <linux/pid.h> |
8 | #include <linux/security.h> | 8 | #include <linux/security.h> |
9 | #include <linux/file.h> | ||
10 | #include <linux/seq_file.h> | ||
9 | 11 | ||
10 | #include <linux/proc_fs.h> | 12 | #include <linux/proc_fs.h> |
11 | 13 | ||
12 | #include "internal.h" | 14 | #include "internal.h" |
13 | #include "fd.h" | 15 | #include "fd.h" |
14 | 16 | ||
15 | #define PROC_FDINFO_MAX 64 | 17 | static int seq_show(struct seq_file *m, void *v) |
16 | |||
17 | static int proc_fd_info(struct inode *inode, struct path *path, char *info) | ||
18 | { | 18 | { |
19 | struct task_struct *task = get_proc_task(inode); | ||
20 | struct files_struct *files = NULL; | 19 | struct files_struct *files = NULL; |
21 | int fd = proc_fd(inode); | 20 | int f_flags = 0, ret = -ENOENT; |
22 | struct file *file; | 21 | struct file *file = NULL; |
22 | struct task_struct *task; | ||
23 | |||
24 | task = get_proc_task(m->private); | ||
25 | if (!task) | ||
26 | return -ENOENT; | ||
27 | |||
28 | files = get_files_struct(task); | ||
29 | put_task_struct(task); | ||
23 | 30 | ||
24 | if (task) { | ||
25 | files = get_files_struct(task); | ||
26 | put_task_struct(task); | ||
27 | } | ||
28 | if (files) { | 31 | if (files) { |
29 | /* | 32 | int fd = proc_fd(m->private); |
30 | * We are not taking a ref to the file structure, so we must | 33 | |
31 | * hold ->file_lock. | ||
32 | */ | ||
33 | spin_lock(&files->file_lock); | 34 | spin_lock(&files->file_lock); |
34 | file = fcheck_files(files, fd); | 35 | file = fcheck_files(files, fd); |
35 | if (file) { | 36 | if (file) { |
36 | unsigned int f_flags; | 37 | struct fdtable *fdt = files_fdtable(files); |
37 | struct fdtable *fdt; | ||
38 | 38 | ||
39 | fdt = files_fdtable(files); | ||
40 | f_flags = file->f_flags & ~O_CLOEXEC; | 39 | f_flags = file->f_flags & ~O_CLOEXEC; |
41 | if (close_on_exec(fd, fdt)) | 40 | if (close_on_exec(fd, fdt)) |
42 | f_flags |= O_CLOEXEC; | 41 | f_flags |= O_CLOEXEC; |
43 | 42 | ||
44 | if (path) { | 43 | get_file(file); |
45 | *path = file->f_path; | 44 | ret = 0; |
46 | path_get(&file->f_path); | ||
47 | } | ||
48 | if (info) | ||
49 | snprintf(info, PROC_FDINFO_MAX, | ||
50 | "pos:\t%lli\n" | ||
51 | "flags:\t0%o\n", | ||
52 | (long long) file->f_pos, | ||
53 | f_flags); | ||
54 | spin_unlock(&files->file_lock); | ||
55 | put_files_struct(files); | ||
56 | return 0; | ||
57 | } | 45 | } |
58 | spin_unlock(&files->file_lock); | 46 | spin_unlock(&files->file_lock); |
59 | put_files_struct(files); | 47 | put_files_struct(files); |
60 | } | 48 | } |
61 | return -ENOENT; | 49 | |
50 | if (!ret) { | ||
51 | seq_printf(m, "pos:\t%lli\nflags:\t0%o\n", | ||
52 | (long long)file->f_pos, f_flags); | ||
53 | fput(file); | ||
54 | } | ||
55 | |||
56 | return ret; | ||
62 | } | 57 | } |
63 | 58 | ||
59 | static int seq_fdinfo_open(struct inode *inode, struct file *file) | ||
60 | { | ||
61 | return single_open(file, seq_show, inode); | ||
62 | } | ||
63 | |||
64 | static const struct file_operations proc_fdinfo_file_operations = { | ||
65 | .open = seq_fdinfo_open, | ||
66 | .read = seq_read, | ||
67 | .llseek = seq_lseek, | ||
68 | .release = single_release, | ||
69 | }; | ||
70 | |||
64 | static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) | 71 | static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) |
65 | { | 72 | { |
66 | struct files_struct *files; | 73 | struct files_struct *files; |
@@ -130,7 +137,32 @@ static const struct dentry_operations tid_fd_dentry_operations = { | |||
130 | 137 | ||
131 | static int proc_fd_link(struct dentry *dentry, struct path *path) | 138 | static int proc_fd_link(struct dentry *dentry, struct path *path) |
132 | { | 139 | { |
133 | return proc_fd_info(dentry->d_inode, path, NULL); | 140 | struct files_struct *files = NULL; |
141 | struct task_struct *task; | ||
142 | int ret = -ENOENT; | ||
143 | |||
144 | task = get_proc_task(dentry->d_inode); | ||
145 | if (task) { | ||
146 | files = get_files_struct(task); | ||
147 | put_task_struct(task); | ||
148 | } | ||
149 | |||
150 | if (files) { | ||
151 | int fd = proc_fd(dentry->d_inode); | ||
152 | struct file *fd_file; | ||
153 | |||
154 | spin_lock(&files->file_lock); | ||
155 | fd_file = fcheck_files(files, fd); | ||
156 | if (fd_file) { | ||
157 | *path = fd_file->f_path; | ||
158 | path_get(&fd_file->f_path); | ||
159 | ret = 0; | ||
160 | } | ||
161 | spin_unlock(&files->file_lock); | ||
162 | put_files_struct(files); | ||
163 | } | ||
164 | |||
165 | return ret; | ||
134 | } | 166 | } |
135 | 167 | ||
136 | static struct dentry * | 168 | static struct dentry * |
@@ -245,22 +277,6 @@ out_no_task: | |||
245 | return retval; | 277 | return retval; |
246 | } | 278 | } |
247 | 279 | ||
248 | static ssize_t proc_fdinfo_read(struct file *file, char __user *buf, | ||
249 | size_t len, loff_t *ppos) | ||
250 | { | ||
251 | char tmp[PROC_FDINFO_MAX]; | ||
252 | int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, tmp); | ||
253 | if (!err) | ||
254 | err = simple_read_from_buffer(buf, len, ppos, tmp, strlen(tmp)); | ||
255 | return err; | ||
256 | } | ||
257 | |||
258 | static const struct file_operations proc_fdinfo_file_operations = { | ||
259 | .open = nonseekable_open, | ||
260 | .read = proc_fdinfo_read, | ||
261 | .llseek = no_llseek, | ||
262 | }; | ||
263 | |||
264 | static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir) | 280 | static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir) |
265 | { | 281 | { |
266 | return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate); | 282 | return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate); |