diff options
Diffstat (limited to 'fs/proc/fd.c')
-rw-r--r-- | fs/proc/fd.c | 114 |
1 files changed, 48 insertions, 66 deletions
diff --git a/fs/proc/fd.c b/fs/proc/fd.c index d7a4a28ef630..75f2890abbd8 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c | |||
@@ -167,11 +167,10 @@ static int proc_fd_link(struct dentry *dentry, struct path *path) | |||
167 | return ret; | 167 | return ret; |
168 | } | 168 | } |
169 | 169 | ||
170 | static struct dentry * | 170 | static int |
171 | proc_fd_instantiate(struct inode *dir, struct dentry *dentry, | 171 | proc_fd_instantiate(struct inode *dir, struct dentry *dentry, |
172 | struct task_struct *task, const void *ptr) | 172 | struct task_struct *task, const void *ptr) |
173 | { | 173 | { |
174 | struct dentry *error = ERR_PTR(-ENOENT); | ||
175 | unsigned fd = (unsigned long)ptr; | 174 | unsigned fd = (unsigned long)ptr; |
176 | struct proc_inode *ei; | 175 | struct proc_inode *ei; |
177 | struct inode *inode; | 176 | struct inode *inode; |
@@ -194,9 +193,9 @@ proc_fd_instantiate(struct inode *dir, struct dentry *dentry, | |||
194 | 193 | ||
195 | /* Close the race of the process dying before we return the dentry */ | 194 | /* Close the race of the process dying before we return the dentry */ |
196 | if (tid_fd_revalidate(dentry, 0)) | 195 | if (tid_fd_revalidate(dentry, 0)) |
197 | error = NULL; | 196 | return 0; |
198 | out: | 197 | out: |
199 | return error; | 198 | return -ENOENT; |
200 | } | 199 | } |
201 | 200 | ||
202 | static struct dentry *proc_lookupfd_common(struct inode *dir, | 201 | static struct dentry *proc_lookupfd_common(struct inode *dir, |
@@ -204,7 +203,7 @@ static struct dentry *proc_lookupfd_common(struct inode *dir, | |||
204 | instantiate_t instantiate) | 203 | instantiate_t instantiate) |
205 | { | 204 | { |
206 | struct task_struct *task = get_proc_task(dir); | 205 | struct task_struct *task = get_proc_task(dir); |
207 | struct dentry *result = ERR_PTR(-ENOENT); | 206 | int result = -ENOENT; |
208 | unsigned fd = name_to_int(dentry); | 207 | unsigned fd = name_to_int(dentry); |
209 | 208 | ||
210 | if (!task) | 209 | if (!task) |
@@ -216,77 +215,61 @@ static struct dentry *proc_lookupfd_common(struct inode *dir, | |||
216 | out: | 215 | out: |
217 | put_task_struct(task); | 216 | put_task_struct(task); |
218 | out_no_task: | 217 | out_no_task: |
219 | return result; | 218 | return ERR_PTR(result); |
220 | } | 219 | } |
221 | 220 | ||
222 | static int proc_readfd_common(struct file * filp, void * dirent, | 221 | static int proc_readfd_common(struct file *file, struct dir_context *ctx, |
223 | filldir_t filldir, instantiate_t instantiate) | 222 | instantiate_t instantiate) |
224 | { | 223 | { |
225 | struct dentry *dentry = filp->f_path.dentry; | 224 | struct task_struct *p = get_proc_task(file_inode(file)); |
226 | struct inode *inode = dentry->d_inode; | ||
227 | struct task_struct *p = get_proc_task(inode); | ||
228 | struct files_struct *files; | 225 | struct files_struct *files; |
229 | unsigned int fd, ino; | 226 | unsigned int fd; |
230 | int retval; | ||
231 | 227 | ||
232 | retval = -ENOENT; | ||
233 | if (!p) | 228 | if (!p) |
234 | goto out_no_task; | 229 | return -ENOENT; |
235 | retval = 0; | ||
236 | |||
237 | fd = filp->f_pos; | ||
238 | switch (fd) { | ||
239 | case 0: | ||
240 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) | ||
241 | goto out; | ||
242 | filp->f_pos++; | ||
243 | case 1: | ||
244 | ino = parent_ino(dentry); | ||
245 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) | ||
246 | goto out; | ||
247 | filp->f_pos++; | ||
248 | default: | ||
249 | files = get_files_struct(p); | ||
250 | if (!files) | ||
251 | goto out; | ||
252 | rcu_read_lock(); | ||
253 | for (fd = filp->f_pos - 2; | ||
254 | fd < files_fdtable(files)->max_fds; | ||
255 | fd++, filp->f_pos++) { | ||
256 | char name[PROC_NUMBUF]; | ||
257 | int len; | ||
258 | int rv; | ||
259 | |||
260 | if (!fcheck_files(files, fd)) | ||
261 | continue; | ||
262 | rcu_read_unlock(); | ||
263 | 230 | ||
264 | len = snprintf(name, sizeof(name), "%d", fd); | 231 | if (!dir_emit_dots(file, ctx)) |
265 | rv = proc_fill_cache(filp, dirent, filldir, | 232 | goto out; |
266 | name, len, instantiate, p, | 233 | if (!dir_emit_dots(file, ctx)) |
267 | (void *)(unsigned long)fd); | 234 | goto out; |
268 | if (rv < 0) | 235 | files = get_files_struct(p); |
269 | goto out_fd_loop; | 236 | if (!files) |
270 | rcu_read_lock(); | 237 | goto out; |
271 | } | 238 | |
272 | rcu_read_unlock(); | 239 | rcu_read_lock(); |
273 | out_fd_loop: | 240 | for (fd = ctx->pos - 2; |
274 | put_files_struct(files); | 241 | fd < files_fdtable(files)->max_fds; |
242 | fd++, ctx->pos++) { | ||
243 | char name[PROC_NUMBUF]; | ||
244 | int len; | ||
245 | |||
246 | if (!fcheck_files(files, fd)) | ||
247 | continue; | ||
248 | rcu_read_unlock(); | ||
249 | |||
250 | len = snprintf(name, sizeof(name), "%d", fd); | ||
251 | if (!proc_fill_cache(file, ctx, | ||
252 | name, len, instantiate, p, | ||
253 | (void *)(unsigned long)fd)) | ||
254 | goto out_fd_loop; | ||
255 | rcu_read_lock(); | ||
275 | } | 256 | } |
257 | rcu_read_unlock(); | ||
258 | out_fd_loop: | ||
259 | put_files_struct(files); | ||
276 | out: | 260 | out: |
277 | put_task_struct(p); | 261 | put_task_struct(p); |
278 | out_no_task: | 262 | return 0; |
279 | return retval; | ||
280 | } | 263 | } |
281 | 264 | ||
282 | static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir) | 265 | static int proc_readfd(struct file *file, struct dir_context *ctx) |
283 | { | 266 | { |
284 | return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate); | 267 | return proc_readfd_common(file, ctx, proc_fd_instantiate); |
285 | } | 268 | } |
286 | 269 | ||
287 | const struct file_operations proc_fd_operations = { | 270 | const struct file_operations proc_fd_operations = { |
288 | .read = generic_read_dir, | 271 | .read = generic_read_dir, |
289 | .readdir = proc_readfd, | 272 | .iterate = proc_readfd, |
290 | .llseek = default_llseek, | 273 | .llseek = default_llseek, |
291 | }; | 274 | }; |
292 | 275 | ||
@@ -316,11 +299,10 @@ const struct inode_operations proc_fd_inode_operations = { | |||
316 | .setattr = proc_setattr, | 299 | .setattr = proc_setattr, |
317 | }; | 300 | }; |
318 | 301 | ||
319 | static struct dentry * | 302 | static int |
320 | proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry, | 303 | proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry, |
321 | struct task_struct *task, const void *ptr) | 304 | struct task_struct *task, const void *ptr) |
322 | { | 305 | { |
323 | struct dentry *error = ERR_PTR(-ENOENT); | ||
324 | unsigned fd = (unsigned long)ptr; | 306 | unsigned fd = (unsigned long)ptr; |
325 | struct proc_inode *ei; | 307 | struct proc_inode *ei; |
326 | struct inode *inode; | 308 | struct inode *inode; |
@@ -340,9 +322,9 @@ proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry, | |||
340 | 322 | ||
341 | /* Close the race of the process dying before we return the dentry */ | 323 | /* Close the race of the process dying before we return the dentry */ |
342 | if (tid_fd_revalidate(dentry, 0)) | 324 | if (tid_fd_revalidate(dentry, 0)) |
343 | error = NULL; | 325 | return 0; |
344 | out: | 326 | out: |
345 | return error; | 327 | return -ENOENT; |
346 | } | 328 | } |
347 | 329 | ||
348 | static struct dentry * | 330 | static struct dentry * |
@@ -351,9 +333,9 @@ proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags) | |||
351 | return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); | 333 | return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); |
352 | } | 334 | } |
353 | 335 | ||
354 | static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir) | 336 | static int proc_readfdinfo(struct file *file, struct dir_context *ctx) |
355 | { | 337 | { |
356 | return proc_readfd_common(filp, dirent, filldir, | 338 | return proc_readfd_common(file, ctx, |
357 | proc_fdinfo_instantiate); | 339 | proc_fdinfo_instantiate); |
358 | } | 340 | } |
359 | 341 | ||
@@ -364,6 +346,6 @@ const struct inode_operations proc_fdinfo_inode_operations = { | |||
364 | 346 | ||
365 | const struct file_operations proc_fdinfo_operations = { | 347 | const struct file_operations proc_fdinfo_operations = { |
366 | .read = generic_read_dir, | 348 | .read = generic_read_dir, |
367 | .readdir = proc_readfdinfo, | 349 | .iterate = proc_readfdinfo, |
368 | .llseek = default_llseek, | 350 | .llseek = default_llseek, |
369 | }; | 351 | }; |