diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-05-16 12:07:31 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:56:32 -0400 |
commit | f0c3b5093addc8bfe9fe3a5b01acb7ec7969eafa (patch) | |
tree | 3bad119186fd14fa95886cfc73c6953a4dd00e74 | |
parent | 68c61471138402e34489edc5efde4f0fc5beaa25 (diff) |
[readdir] convert procfs
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/hppfs/hppfs.c | 33 | ||||
-rw-r--r-- | fs/proc/base.c | 363 | ||||
-rw-r--r-- | fs/proc/fd.c | 96 | ||||
-rw-r--r-- | fs/proc/generic.c | 100 | ||||
-rw-r--r-- | fs/proc/internal.h | 8 | ||||
-rw-r--r-- | fs/proc/namespaces.c | 74 | ||||
-rw-r--r-- | fs/proc/proc_net.c | 9 | ||||
-rw-r--r-- | fs/proc/proc_sysctl.c | 71 | ||||
-rw-r--r-- | fs/proc/root.c | 19 |
9 files changed, 284 insertions, 489 deletions
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index cd3e38972c86..fc90ab11c340 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c | |||
@@ -542,8 +542,8 @@ static const struct file_operations hppfs_file_fops = { | |||
542 | }; | 542 | }; |
543 | 543 | ||
544 | struct hppfs_dirent { | 544 | struct hppfs_dirent { |
545 | void *vfs_dirent; | 545 | struct dir_context ctx; |
546 | filldir_t filldir; | 546 | struct dir_context *caller; |
547 | struct dentry *dentry; | 547 | struct dentry *dentry; |
548 | }; | 548 | }; |
549 | 549 | ||
@@ -555,34 +555,29 @@ static int hppfs_filldir(void *d, const char *name, int size, | |||
555 | if (file_removed(dirent->dentry, name)) | 555 | if (file_removed(dirent->dentry, name)) |
556 | return 0; | 556 | return 0; |
557 | 557 | ||
558 | return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset, | 558 | dirent->caller->pos = dirent->ctx.pos; |
559 | inode, type); | 559 | return !dir_emit(dirent->caller, name, size, inode, type); |
560 | } | 560 | } |
561 | 561 | ||
562 | static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) | 562 | static int hppfs_readdir(struct file *file, struct dir_context *ctx) |
563 | { | 563 | { |
564 | struct hppfs_private *data = file->private_data; | 564 | struct hppfs_private *data = file->private_data; |
565 | struct file *proc_file = data->proc_file; | 565 | struct file *proc_file = data->proc_file; |
566 | int (*readdir)(struct file *, void *, filldir_t); | 566 | struct hppfs_dirent d = { |
567 | struct hppfs_dirent dirent = ((struct hppfs_dirent) | 567 | .ctx.actor = hppfs_filldir, |
568 | { .vfs_dirent = ent, | 568 | .caller = ctx, |
569 | .filldir = filldir, | 569 | .dentry = file->f_path.dentry |
570 | .dentry = file->f_path.dentry | 570 | }; |
571 | }); | ||
572 | int err; | 571 | int err; |
573 | 572 | proc_file->f_pos = ctx->pos; | |
574 | readdir = file_inode(proc_file)->i_fop->readdir; | 573 | err = iterate_dir(proc_file, &d.ctx); |
575 | 574 | ctx->pos = d.ctx.pos; | |
576 | proc_file->f_pos = file->f_pos; | ||
577 | err = (*readdir)(proc_file, &dirent, hppfs_filldir); | ||
578 | file->f_pos = proc_file->f_pos; | ||
579 | |||
580 | return err; | 575 | return err; |
581 | } | 576 | } |
582 | 577 | ||
583 | static const struct file_operations hppfs_dir_fops = { | 578 | static const struct file_operations hppfs_dir_fops = { |
584 | .owner = NULL, | 579 | .owner = NULL, |
585 | .readdir = hppfs_readdir, | 580 | .iterate = hppfs_readdir, |
586 | .open = hppfs_dir_open, | 581 | .open = hppfs_dir_open, |
587 | .llseek = default_llseek, | 582 | .llseek = default_llseek, |
588 | .release = hppfs_release, | 583 | .release = hppfs_release, |
diff --git a/fs/proc/base.c b/fs/proc/base.c index c3834dad09b3..0016350ad95e 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1681,11 +1681,11 @@ const struct dentry_operations pid_dentry_operations = | |||
1681 | * reported by readdir in sync with the inode numbers reported | 1681 | * reported by readdir in sync with the inode numbers reported |
1682 | * by stat. | 1682 | * by stat. |
1683 | */ | 1683 | */ |
1684 | int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 1684 | bool proc_fill_cache(struct file *file, struct dir_context *ctx, |
1685 | const char *name, int len, | 1685 | const char *name, int len, |
1686 | instantiate_t instantiate, struct task_struct *task, const void *ptr) | 1686 | instantiate_t instantiate, struct task_struct *task, const void *ptr) |
1687 | { | 1687 | { |
1688 | struct dentry *child, *dir = filp->f_path.dentry; | 1688 | struct dentry *child, *dir = file->f_path.dentry; |
1689 | struct inode *inode; | 1689 | struct inode *inode; |
1690 | struct qstr qname; | 1690 | struct qstr qname; |
1691 | ino_t ino = 0; | 1691 | ino_t ino = 0; |
@@ -1720,7 +1720,7 @@ end_instantiate: | |||
1720 | ino = find_inode_number(dir, &qname); | 1720 | ino = find_inode_number(dir, &qname); |
1721 | if (!ino) | 1721 | if (!ino) |
1722 | ino = 1; | 1722 | ino = 1; |
1723 | return filldir(dirent, name, len, filp->f_pos, ino, type); | 1723 | return dir_emit(ctx, name, len, ino, type); |
1724 | } | 1724 | } |
1725 | 1725 | ||
1726 | #ifdef CONFIG_CHECKPOINT_RESTORE | 1726 | #ifdef CONFIG_CHECKPOINT_RESTORE |
@@ -1931,14 +1931,15 @@ static const struct inode_operations proc_map_files_inode_operations = { | |||
1931 | }; | 1931 | }; |
1932 | 1932 | ||
1933 | static int | 1933 | static int |
1934 | proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | 1934 | proc_map_files_readdir(struct file *file, struct dir_context *ctx) |
1935 | { | 1935 | { |
1936 | struct dentry *dentry = filp->f_path.dentry; | ||
1937 | struct inode *inode = dentry->d_inode; | ||
1938 | struct vm_area_struct *vma; | 1936 | struct vm_area_struct *vma; |
1939 | struct task_struct *task; | 1937 | struct task_struct *task; |
1940 | struct mm_struct *mm; | 1938 | struct mm_struct *mm; |
1941 | ino_t ino; | 1939 | unsigned long nr_files, pos, i; |
1940 | struct flex_array *fa = NULL; | ||
1941 | struct map_files_info info; | ||
1942 | struct map_files_info *p; | ||
1942 | int ret; | 1943 | int ret; |
1943 | 1944 | ||
1944 | ret = -EPERM; | 1945 | ret = -EPERM; |
@@ -1946,7 +1947,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1946 | goto out; | 1947 | goto out; |
1947 | 1948 | ||
1948 | ret = -ENOENT; | 1949 | ret = -ENOENT; |
1949 | task = get_proc_task(inode); | 1950 | task = get_proc_task(file_inode(file)); |
1950 | if (!task) | 1951 | if (!task) |
1951 | goto out; | 1952 | goto out; |
1952 | 1953 | ||
@@ -1955,91 +1956,73 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1955 | goto out_put_task; | 1956 | goto out_put_task; |
1956 | 1957 | ||
1957 | ret = 0; | 1958 | ret = 0; |
1958 | switch (filp->f_pos) { | 1959 | if (!dir_emit_dots(file, ctx)) |
1959 | case 0: | 1960 | goto out_put_task; |
1960 | ino = inode->i_ino; | ||
1961 | if (filldir(dirent, ".", 1, 0, ino, DT_DIR) < 0) | ||
1962 | goto out_put_task; | ||
1963 | filp->f_pos++; | ||
1964 | case 1: | ||
1965 | ino = parent_ino(dentry); | ||
1966 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) | ||
1967 | goto out_put_task; | ||
1968 | filp->f_pos++; | ||
1969 | default: | ||
1970 | { | ||
1971 | unsigned long nr_files, pos, i; | ||
1972 | struct flex_array *fa = NULL; | ||
1973 | struct map_files_info info; | ||
1974 | struct map_files_info *p; | ||
1975 | |||
1976 | mm = get_task_mm(task); | ||
1977 | if (!mm) | ||
1978 | goto out_put_task; | ||
1979 | down_read(&mm->mmap_sem); | ||
1980 | 1961 | ||
1981 | nr_files = 0; | 1962 | mm = get_task_mm(task); |
1963 | if (!mm) | ||
1964 | goto out_put_task; | ||
1965 | down_read(&mm->mmap_sem); | ||
1982 | 1966 | ||
1983 | /* | 1967 | nr_files = 0; |
1984 | * We need two passes here: | ||
1985 | * | ||
1986 | * 1) Collect vmas of mapped files with mmap_sem taken | ||
1987 | * 2) Release mmap_sem and instantiate entries | ||
1988 | * | ||
1989 | * otherwise we get lockdep complained, since filldir() | ||
1990 | * routine might require mmap_sem taken in might_fault(). | ||
1991 | */ | ||
1992 | 1968 | ||
1993 | for (vma = mm->mmap, pos = 2; vma; vma = vma->vm_next) { | 1969 | /* |
1994 | if (vma->vm_file && ++pos > filp->f_pos) | 1970 | * We need two passes here: |
1995 | nr_files++; | 1971 | * |
1996 | } | 1972 | * 1) Collect vmas of mapped files with mmap_sem taken |
1973 | * 2) Release mmap_sem and instantiate entries | ||
1974 | * | ||
1975 | * otherwise we get lockdep complained, since filldir() | ||
1976 | * routine might require mmap_sem taken in might_fault(). | ||
1977 | */ | ||
1997 | 1978 | ||
1998 | if (nr_files) { | 1979 | for (vma = mm->mmap, pos = 2; vma; vma = vma->vm_next) { |
1999 | fa = flex_array_alloc(sizeof(info), nr_files, | 1980 | if (vma->vm_file && ++pos > ctx->pos) |
2000 | GFP_KERNEL); | 1981 | nr_files++; |
2001 | if (!fa || flex_array_prealloc(fa, 0, nr_files, | 1982 | } |
2002 | GFP_KERNEL)) { | 1983 | |
2003 | ret = -ENOMEM; | 1984 | if (nr_files) { |
2004 | if (fa) | 1985 | fa = flex_array_alloc(sizeof(info), nr_files, |
2005 | flex_array_free(fa); | 1986 | GFP_KERNEL); |
2006 | up_read(&mm->mmap_sem); | 1987 | if (!fa || flex_array_prealloc(fa, 0, nr_files, |
2007 | mmput(mm); | 1988 | GFP_KERNEL)) { |
2008 | goto out_put_task; | 1989 | ret = -ENOMEM; |
2009 | } | 1990 | if (fa) |
2010 | for (i = 0, vma = mm->mmap, pos = 2; vma; | 1991 | flex_array_free(fa); |
2011 | vma = vma->vm_next) { | 1992 | up_read(&mm->mmap_sem); |
2012 | if (!vma->vm_file) | 1993 | mmput(mm); |
2013 | continue; | 1994 | goto out_put_task; |
2014 | if (++pos <= filp->f_pos) | ||
2015 | continue; | ||
2016 | |||
2017 | info.mode = vma->vm_file->f_mode; | ||
2018 | info.len = snprintf(info.name, | ||
2019 | sizeof(info.name), "%lx-%lx", | ||
2020 | vma->vm_start, vma->vm_end); | ||
2021 | if (flex_array_put(fa, i++, &info, GFP_KERNEL)) | ||
2022 | BUG(); | ||
2023 | } | ||
2024 | } | 1995 | } |
2025 | up_read(&mm->mmap_sem); | 1996 | for (i = 0, vma = mm->mmap, pos = 2; vma; |
2026 | 1997 | vma = vma->vm_next) { | |
2027 | for (i = 0; i < nr_files; i++) { | 1998 | if (!vma->vm_file) |
2028 | p = flex_array_get(fa, i); | 1999 | continue; |
2029 | ret = proc_fill_cache(filp, dirent, filldir, | 2000 | if (++pos <= ctx->pos) |
2030 | p->name, p->len, | 2001 | continue; |
2031 | proc_map_files_instantiate, | 2002 | |
2032 | task, | 2003 | info.mode = vma->vm_file->f_mode; |
2033 | (void *)(unsigned long)p->mode); | 2004 | info.len = snprintf(info.name, |
2034 | if (ret) | 2005 | sizeof(info.name), "%lx-%lx", |
2035 | break; | 2006 | vma->vm_start, vma->vm_end); |
2036 | filp->f_pos++; | 2007 | if (flex_array_put(fa, i++, &info, GFP_KERNEL)) |
2008 | BUG(); | ||
2037 | } | 2009 | } |
2038 | if (fa) | ||
2039 | flex_array_free(fa); | ||
2040 | mmput(mm); | ||
2041 | } | 2010 | } |
2011 | up_read(&mm->mmap_sem); | ||
2012 | |||
2013 | for (i = 0; i < nr_files; i++) { | ||
2014 | p = flex_array_get(fa, i); | ||
2015 | if (!proc_fill_cache(file, ctx, | ||
2016 | p->name, p->len, | ||
2017 | proc_map_files_instantiate, | ||
2018 | task, | ||
2019 | (void *)(unsigned long)p->mode)) | ||
2020 | break; | ||
2021 | ctx->pos++; | ||
2042 | } | 2022 | } |
2023 | if (fa) | ||
2024 | flex_array_free(fa); | ||
2025 | mmput(mm); | ||
2043 | 2026 | ||
2044 | out_put_task: | 2027 | out_put_task: |
2045 | put_task_struct(task); | 2028 | put_task_struct(task); |
@@ -2049,7 +2032,7 @@ out: | |||
2049 | 2032 | ||
2050 | static const struct file_operations proc_map_files_operations = { | 2033 | static const struct file_operations proc_map_files_operations = { |
2051 | .read = generic_read_dir, | 2034 | .read = generic_read_dir, |
2052 | .readdir = proc_map_files_readdir, | 2035 | .iterate = proc_map_files_readdir, |
2053 | .llseek = default_llseek, | 2036 | .llseek = default_llseek, |
2054 | }; | 2037 | }; |
2055 | 2038 | ||
@@ -2217,67 +2200,30 @@ out_no_task: | |||
2217 | return error; | 2200 | return error; |
2218 | } | 2201 | } |
2219 | 2202 | ||
2220 | static int proc_pident_fill_cache(struct file *filp, void *dirent, | 2203 | static int proc_pident_readdir(struct file *file, struct dir_context *ctx, |
2221 | filldir_t filldir, struct task_struct *task, const struct pid_entry *p) | ||
2222 | { | ||
2223 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, | ||
2224 | proc_pident_instantiate, task, p); | ||
2225 | } | ||
2226 | |||
2227 | static int proc_pident_readdir(struct file *filp, | ||
2228 | void *dirent, filldir_t filldir, | ||
2229 | const struct pid_entry *ents, unsigned int nents) | 2204 | const struct pid_entry *ents, unsigned int nents) |
2230 | { | 2205 | { |
2231 | int i; | 2206 | struct task_struct *task = get_proc_task(file_inode(file)); |
2232 | struct dentry *dentry = filp->f_path.dentry; | 2207 | const struct pid_entry *p; |
2233 | struct inode *inode = dentry->d_inode; | ||
2234 | struct task_struct *task = get_proc_task(inode); | ||
2235 | const struct pid_entry *p, *last; | ||
2236 | ino_t ino; | ||
2237 | int ret; | ||
2238 | 2208 | ||
2239 | ret = -ENOENT; | ||
2240 | if (!task) | 2209 | if (!task) |
2241 | goto out_no_task; | 2210 | return -ENOENT; |
2242 | 2211 | ||
2243 | ret = 0; | 2212 | if (!dir_emit_dots(file, ctx)) |
2244 | i = filp->f_pos; | 2213 | goto out; |
2245 | switch (i) { | 2214 | |
2246 | case 0: | 2215 | if (ctx->pos >= nents + 2) |
2247 | ino = inode->i_ino; | 2216 | goto out; |
2248 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | ||
2249 | goto out; | ||
2250 | i++; | ||
2251 | filp->f_pos++; | ||
2252 | /* fall through */ | ||
2253 | case 1: | ||
2254 | ino = parent_ino(dentry); | ||
2255 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | ||
2256 | goto out; | ||
2257 | i++; | ||
2258 | filp->f_pos++; | ||
2259 | /* fall through */ | ||
2260 | default: | ||
2261 | i -= 2; | ||
2262 | if (i >= nents) { | ||
2263 | ret = 1; | ||
2264 | goto out; | ||
2265 | } | ||
2266 | p = ents + i; | ||
2267 | last = &ents[nents - 1]; | ||
2268 | while (p <= last) { | ||
2269 | if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0) | ||
2270 | goto out; | ||
2271 | filp->f_pos++; | ||
2272 | p++; | ||
2273 | } | ||
2274 | } | ||
2275 | 2217 | ||
2276 | ret = 1; | 2218 | for (p = ents + (ctx->pos - 2); p <= ents + nents - 1; p++) { |
2219 | if (!proc_fill_cache(file, ctx, p->name, p->len, | ||
2220 | proc_pident_instantiate, task, p)) | ||
2221 | break; | ||
2222 | ctx->pos++; | ||
2223 | } | ||
2277 | out: | 2224 | out: |
2278 | put_task_struct(task); | 2225 | put_task_struct(task); |
2279 | out_no_task: | 2226 | return 0; |
2280 | return ret; | ||
2281 | } | 2227 | } |
2282 | 2228 | ||
2283 | #ifdef CONFIG_SECURITY | 2229 | #ifdef CONFIG_SECURITY |
@@ -2362,16 +2308,15 @@ static const struct pid_entry attr_dir_stuff[] = { | |||
2362 | REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), | 2308 | REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), |
2363 | }; | 2309 | }; |
2364 | 2310 | ||
2365 | static int proc_attr_dir_readdir(struct file * filp, | 2311 | static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx) |
2366 | void * dirent, filldir_t filldir) | ||
2367 | { | 2312 | { |
2368 | return proc_pident_readdir(filp,dirent,filldir, | 2313 | return proc_pident_readdir(file, ctx, |
2369 | attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff)); | 2314 | attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff)); |
2370 | } | 2315 | } |
2371 | 2316 | ||
2372 | static const struct file_operations proc_attr_dir_operations = { | 2317 | static const struct file_operations proc_attr_dir_operations = { |
2373 | .read = generic_read_dir, | 2318 | .read = generic_read_dir, |
2374 | .readdir = proc_attr_dir_readdir, | 2319 | .iterate = proc_attr_dir_readdir, |
2375 | .llseek = default_llseek, | 2320 | .llseek = default_llseek, |
2376 | }; | 2321 | }; |
2377 | 2322 | ||
@@ -2725,16 +2670,15 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2725 | #endif | 2670 | #endif |
2726 | }; | 2671 | }; |
2727 | 2672 | ||
2728 | static int proc_tgid_base_readdir(struct file * filp, | 2673 | static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx) |
2729 | void * dirent, filldir_t filldir) | ||
2730 | { | 2674 | { |
2731 | return proc_pident_readdir(filp,dirent,filldir, | 2675 | return proc_pident_readdir(file, ctx, |
2732 | tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff)); | 2676 | tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); |
2733 | } | 2677 | } |
2734 | 2678 | ||
2735 | static const struct file_operations proc_tgid_base_operations = { | 2679 | static const struct file_operations proc_tgid_base_operations = { |
2736 | .read = generic_read_dir, | 2680 | .read = generic_read_dir, |
2737 | .readdir = proc_tgid_base_readdir, | 2681 | .iterate = proc_tgid_base_readdir, |
2738 | .llseek = default_llseek, | 2682 | .llseek = default_llseek, |
2739 | }; | 2683 | }; |
2740 | 2684 | ||
@@ -2936,58 +2880,42 @@ retry: | |||
2936 | 2880 | ||
2937 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1) | 2881 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1) |
2938 | 2882 | ||
2939 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
2940 | struct tgid_iter iter) | ||
2941 | { | ||
2942 | char name[PROC_NUMBUF]; | ||
2943 | int len = snprintf(name, sizeof(name), "%d", iter.tgid); | ||
2944 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
2945 | proc_pid_instantiate, iter.task, NULL); | ||
2946 | } | ||
2947 | |||
2948 | static int fake_filldir(void *buf, const char *name, int namelen, | ||
2949 | loff_t offset, u64 ino, unsigned d_type) | ||
2950 | { | ||
2951 | return 0; | ||
2952 | } | ||
2953 | |||
2954 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 2883 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
2955 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | 2884 | int proc_pid_readdir(struct file *file, struct dir_context *ctx) |
2956 | { | 2885 | { |
2957 | struct tgid_iter iter; | 2886 | struct tgid_iter iter; |
2958 | struct pid_namespace *ns; | 2887 | struct pid_namespace *ns; |
2959 | filldir_t __filldir; | 2888 | loff_t pos = ctx->pos; |
2960 | loff_t pos = filp->f_pos; | ||
2961 | 2889 | ||
2962 | if (pos >= PID_MAX_LIMIT + TGID_OFFSET) | 2890 | if (pos >= PID_MAX_LIMIT + TGID_OFFSET) |
2963 | goto out; | 2891 | return 0; |
2964 | 2892 | ||
2965 | if (pos == TGID_OFFSET - 1) { | 2893 | if (pos == TGID_OFFSET - 1) { |
2966 | if (proc_fill_cache(filp, dirent, filldir, "self", 4, | 2894 | if (!proc_fill_cache(file, ctx, "self", 4, NULL, NULL, NULL)) |
2967 | NULL, NULL, NULL) < 0) | 2895 | return 0; |
2968 | goto out; | ||
2969 | iter.tgid = 0; | 2896 | iter.tgid = 0; |
2970 | } else { | 2897 | } else { |
2971 | iter.tgid = pos - TGID_OFFSET; | 2898 | iter.tgid = pos - TGID_OFFSET; |
2972 | } | 2899 | } |
2973 | iter.task = NULL; | 2900 | iter.task = NULL; |
2974 | ns = filp->f_dentry->d_sb->s_fs_info; | 2901 | ns = file->f_dentry->d_sb->s_fs_info; |
2975 | for (iter = next_tgid(ns, iter); | 2902 | for (iter = next_tgid(ns, iter); |
2976 | iter.task; | 2903 | iter.task; |
2977 | iter.tgid += 1, iter = next_tgid(ns, iter)) { | 2904 | iter.tgid += 1, iter = next_tgid(ns, iter)) { |
2978 | if (has_pid_permissions(ns, iter.task, 2)) | 2905 | char name[PROC_NUMBUF]; |
2979 | __filldir = filldir; | 2906 | int len; |
2980 | else | 2907 | if (!has_pid_permissions(ns, iter.task, 2)) |
2981 | __filldir = fake_filldir; | 2908 | continue; |
2982 | 2909 | ||
2983 | filp->f_pos = iter.tgid + TGID_OFFSET; | 2910 | len = snprintf(name, sizeof(name), "%d", iter.tgid); |
2984 | if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) { | 2911 | ctx->pos = iter.tgid + TGID_OFFSET; |
2912 | if (!proc_fill_cache(file, ctx, name, len, | ||
2913 | proc_pid_instantiate, iter.task, NULL)) { | ||
2985 | put_task_struct(iter.task); | 2914 | put_task_struct(iter.task); |
2986 | goto out; | 2915 | return 0; |
2987 | } | 2916 | } |
2988 | } | 2917 | } |
2989 | filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET; | 2918 | ctx->pos = PID_MAX_LIMIT + TGID_OFFSET; |
2990 | out: | ||
2991 | return 0; | 2919 | return 0; |
2992 | } | 2920 | } |
2993 | 2921 | ||
@@ -3075,11 +3003,10 @@ static const struct pid_entry tid_base_stuff[] = { | |||
3075 | #endif | 3003 | #endif |
3076 | }; | 3004 | }; |
3077 | 3005 | ||
3078 | static int proc_tid_base_readdir(struct file * filp, | 3006 | static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx) |
3079 | void * dirent, filldir_t filldir) | ||
3080 | { | 3007 | { |
3081 | return proc_pident_readdir(filp,dirent,filldir, | 3008 | return proc_pident_readdir(file, ctx, |
3082 | tid_base_stuff,ARRAY_SIZE(tid_base_stuff)); | 3009 | tid_base_stuff, ARRAY_SIZE(tid_base_stuff)); |
3083 | } | 3010 | } |
3084 | 3011 | ||
3085 | static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | 3012 | static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
@@ -3090,7 +3017,7 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den | |||
3090 | 3017 | ||
3091 | static const struct file_operations proc_tid_base_operations = { | 3018 | static const struct file_operations proc_tid_base_operations = { |
3092 | .read = generic_read_dir, | 3019 | .read = generic_read_dir, |
3093 | .readdir = proc_tid_base_readdir, | 3020 | .iterate = proc_tid_base_readdir, |
3094 | .llseek = default_llseek, | 3021 | .llseek = default_llseek, |
3095 | }; | 3022 | }; |
3096 | 3023 | ||
@@ -3231,30 +3158,16 @@ static struct task_struct *next_tid(struct task_struct *start) | |||
3231 | return pos; | 3158 | return pos; |
3232 | } | 3159 | } |
3233 | 3160 | ||
3234 | static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
3235 | struct task_struct *task, int tid) | ||
3236 | { | ||
3237 | char name[PROC_NUMBUF]; | ||
3238 | int len = snprintf(name, sizeof(name), "%d", tid); | ||
3239 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
3240 | proc_task_instantiate, task, NULL); | ||
3241 | } | ||
3242 | |||
3243 | /* for the /proc/TGID/task/ directories */ | 3161 | /* for the /proc/TGID/task/ directories */ |
3244 | static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) | 3162 | static int proc_task_readdir(struct file *file, struct dir_context *ctx) |
3245 | { | 3163 | { |
3246 | struct dentry *dentry = filp->f_path.dentry; | ||
3247 | struct inode *inode = dentry->d_inode; | ||
3248 | struct task_struct *leader = NULL; | 3164 | struct task_struct *leader = NULL; |
3249 | struct task_struct *task; | 3165 | struct task_struct *task = get_proc_task(file_inode(file)); |
3250 | int retval = -ENOENT; | ||
3251 | ino_t ino; | ||
3252 | int tid; | ||
3253 | struct pid_namespace *ns; | 3166 | struct pid_namespace *ns; |
3167 | int tid; | ||
3254 | 3168 | ||
3255 | task = get_proc_task(inode); | ||
3256 | if (!task) | 3169 | if (!task) |
3257 | goto out_no_task; | 3170 | return -ENOENT; |
3258 | rcu_read_lock(); | 3171 | rcu_read_lock(); |
3259 | if (pid_alive(task)) { | 3172 | if (pid_alive(task)) { |
3260 | leader = task->group_leader; | 3173 | leader = task->group_leader; |
@@ -3263,46 +3176,36 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
3263 | rcu_read_unlock(); | 3176 | rcu_read_unlock(); |
3264 | put_task_struct(task); | 3177 | put_task_struct(task); |
3265 | if (!leader) | 3178 | if (!leader) |
3266 | goto out_no_task; | 3179 | return -ENOENT; |
3267 | retval = 0; | ||
3268 | 3180 | ||
3269 | switch ((unsigned long)filp->f_pos) { | 3181 | if (!dir_emit_dots(file, ctx)) |
3270 | case 0: | 3182 | goto out; |
3271 | ino = inode->i_ino; | ||
3272 | if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0) | ||
3273 | goto out; | ||
3274 | filp->f_pos++; | ||
3275 | /* fall through */ | ||
3276 | case 1: | ||
3277 | ino = parent_ino(dentry); | ||
3278 | if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) < 0) | ||
3279 | goto out; | ||
3280 | filp->f_pos++; | ||
3281 | /* fall through */ | ||
3282 | } | ||
3283 | 3183 | ||
3284 | /* f_version caches the tgid value that the last readdir call couldn't | 3184 | /* f_version caches the tgid value that the last readdir call couldn't |
3285 | * return. lseek aka telldir automagically resets f_version to 0. | 3185 | * return. lseek aka telldir automagically resets f_version to 0. |
3286 | */ | 3186 | */ |
3287 | ns = filp->f_dentry->d_sb->s_fs_info; | 3187 | ns = file->f_dentry->d_sb->s_fs_info; |
3288 | tid = (int)filp->f_version; | 3188 | tid = (int)file->f_version; |
3289 | filp->f_version = 0; | 3189 | file->f_version = 0; |
3290 | for (task = first_tid(leader, tid, filp->f_pos - 2, ns); | 3190 | for (task = first_tid(leader, tid, ctx->pos - 2, ns); |
3291 | task; | 3191 | task; |
3292 | task = next_tid(task), filp->f_pos++) { | 3192 | task = next_tid(task), ctx->pos++) { |
3193 | char name[PROC_NUMBUF]; | ||
3194 | int len; | ||
3293 | tid = task_pid_nr_ns(task, ns); | 3195 | tid = task_pid_nr_ns(task, ns); |
3294 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { | 3196 | len = snprintf(name, sizeof(name), "%d", tid); |
3197 | if (!proc_fill_cache(file, ctx, name, len, | ||
3198 | proc_task_instantiate, task, NULL)) { | ||
3295 | /* returning this tgid failed, save it as the first | 3199 | /* returning this tgid failed, save it as the first |
3296 | * pid for the next readir call */ | 3200 | * pid for the next readir call */ |
3297 | filp->f_version = (u64)tid; | 3201 | file->f_version = (u64)tid; |
3298 | put_task_struct(task); | 3202 | put_task_struct(task); |
3299 | break; | 3203 | break; |
3300 | } | 3204 | } |
3301 | } | 3205 | } |
3302 | out: | 3206 | out: |
3303 | put_task_struct(leader); | 3207 | put_task_struct(leader); |
3304 | out_no_task: | 3208 | return 0; |
3305 | return retval; | ||
3306 | } | 3209 | } |
3307 | 3210 | ||
3308 | static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 3211 | static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
@@ -3328,6 +3231,6 @@ static const struct inode_operations proc_task_inode_operations = { | |||
3328 | 3231 | ||
3329 | static const struct file_operations proc_task_operations = { | 3232 | static const struct file_operations proc_task_operations = { |
3330 | .read = generic_read_dir, | 3233 | .read = generic_read_dir, |
3331 | .readdir = proc_task_readdir, | 3234 | .iterate = proc_task_readdir, |
3332 | .llseek = default_llseek, | 3235 | .llseek = default_llseek, |
3333 | }; | 3236 | }; |
diff --git a/fs/proc/fd.c b/fs/proc/fd.c index d7a4a28ef630..1441f143c43b 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c | |||
@@ -219,74 +219,58 @@ out_no_task: | |||
219 | return result; | 219 | return result; |
220 | } | 220 | } |
221 | 221 | ||
222 | static int proc_readfd_common(struct file * filp, void * dirent, | 222 | static int proc_readfd_common(struct file *file, struct dir_context *ctx, |
223 | filldir_t filldir, instantiate_t instantiate) | 223 | instantiate_t instantiate) |
224 | { | 224 | { |
225 | struct dentry *dentry = filp->f_path.dentry; | 225 | 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; | 226 | struct files_struct *files; |
229 | unsigned int fd, ino; | 227 | unsigned int fd; |
230 | int retval; | ||
231 | 228 | ||
232 | retval = -ENOENT; | ||
233 | if (!p) | 229 | if (!p) |
234 | goto out_no_task; | 230 | 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 | 231 | ||
264 | len = snprintf(name, sizeof(name), "%d", fd); | 232 | if (!dir_emit_dots(file, ctx)) |
265 | rv = proc_fill_cache(filp, dirent, filldir, | 233 | goto out; |
266 | name, len, instantiate, p, | 234 | if (!dir_emit_dots(file, ctx)) |
267 | (void *)(unsigned long)fd); | 235 | goto out; |
268 | if (rv < 0) | 236 | files = get_files_struct(p); |
269 | goto out_fd_loop; | 237 | if (!files) |
270 | rcu_read_lock(); | 238 | goto out; |
271 | } | 239 | |
272 | rcu_read_unlock(); | 240 | rcu_read_lock(); |
273 | out_fd_loop: | 241 | for (fd = ctx->pos - 2; |
274 | put_files_struct(files); | 242 | fd < files_fdtable(files)->max_fds; |
243 | fd++, ctx->pos++) { | ||
244 | char name[PROC_NUMBUF]; | ||
245 | int len; | ||
246 | |||
247 | if (!fcheck_files(files, fd)) | ||
248 | continue; | ||
249 | rcu_read_unlock(); | ||
250 | |||
251 | len = snprintf(name, sizeof(name), "%d", fd); | ||
252 | if (!proc_fill_cache(file, ctx, | ||
253 | name, len, instantiate, p, | ||
254 | (void *)(unsigned long)fd)) | ||
255 | goto out_fd_loop; | ||
256 | rcu_read_lock(); | ||
275 | } | 257 | } |
258 | rcu_read_unlock(); | ||
259 | out_fd_loop: | ||
260 | put_files_struct(files); | ||
276 | out: | 261 | out: |
277 | put_task_struct(p); | 262 | put_task_struct(p); |
278 | out_no_task: | 263 | return 0; |
279 | return retval; | ||
280 | } | 264 | } |
281 | 265 | ||
282 | static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir) | 266 | static int proc_readfd(struct file *file, struct dir_context *ctx) |
283 | { | 267 | { |
284 | return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate); | 268 | return proc_readfd_common(file, ctx, proc_fd_instantiate); |
285 | } | 269 | } |
286 | 270 | ||
287 | const struct file_operations proc_fd_operations = { | 271 | const struct file_operations proc_fd_operations = { |
288 | .read = generic_read_dir, | 272 | .read = generic_read_dir, |
289 | .readdir = proc_readfd, | 273 | .iterate = proc_readfd, |
290 | .llseek = default_llseek, | 274 | .llseek = default_llseek, |
291 | }; | 275 | }; |
292 | 276 | ||
@@ -351,9 +335,9 @@ proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags) | |||
351 | return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); | 335 | return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); |
352 | } | 336 | } |
353 | 337 | ||
354 | static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir) | 338 | static int proc_readfdinfo(struct file *file, struct dir_context *ctx) |
355 | { | 339 | { |
356 | return proc_readfd_common(filp, dirent, filldir, | 340 | return proc_readfd_common(file, ctx, |
357 | proc_fdinfo_instantiate); | 341 | proc_fdinfo_instantiate); |
358 | } | 342 | } |
359 | 343 | ||
@@ -364,6 +348,6 @@ const struct inode_operations proc_fdinfo_inode_operations = { | |||
364 | 348 | ||
365 | const struct file_operations proc_fdinfo_operations = { | 349 | const struct file_operations proc_fdinfo_operations = { |
366 | .read = generic_read_dir, | 350 | .read = generic_read_dir, |
367 | .readdir = proc_readfdinfo, | 351 | .iterate = proc_readfdinfo, |
368 | .llseek = default_llseek, | 352 | .llseek = default_llseek, |
369 | }; | 353 | }; |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index a2596afffae6..94441a407337 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -233,76 +233,52 @@ struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, | |||
233 | * value of the readdir() call, as long as it's non-negative | 233 | * value of the readdir() call, as long as it's non-negative |
234 | * for success.. | 234 | * for success.. |
235 | */ | 235 | */ |
236 | int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, | 236 | int proc_readdir_de(struct proc_dir_entry *de, struct file *file, |
237 | filldir_t filldir) | 237 | struct dir_context *ctx) |
238 | { | 238 | { |
239 | unsigned int ino; | ||
240 | int i; | 239 | int i; |
241 | struct inode *inode = file_inode(filp); | ||
242 | int ret = 0; | ||
243 | |||
244 | ino = inode->i_ino; | ||
245 | i = filp->f_pos; | ||
246 | switch (i) { | ||
247 | case 0: | ||
248 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | ||
249 | goto out; | ||
250 | i++; | ||
251 | filp->f_pos++; | ||
252 | /* fall through */ | ||
253 | case 1: | ||
254 | if (filldir(dirent, "..", 2, i, | ||
255 | parent_ino(filp->f_path.dentry), | ||
256 | DT_DIR) < 0) | ||
257 | goto out; | ||
258 | i++; | ||
259 | filp->f_pos++; | ||
260 | /* fall through */ | ||
261 | default: | ||
262 | spin_lock(&proc_subdir_lock); | ||
263 | de = de->subdir; | ||
264 | i -= 2; | ||
265 | for (;;) { | ||
266 | if (!de) { | ||
267 | ret = 1; | ||
268 | spin_unlock(&proc_subdir_lock); | ||
269 | goto out; | ||
270 | } | ||
271 | if (!i) | ||
272 | break; | ||
273 | de = de->next; | ||
274 | i--; | ||
275 | } | ||
276 | 240 | ||
277 | do { | 241 | if (!dir_emit_dots(file, ctx)) |
278 | struct proc_dir_entry *next; | 242 | return 0; |
279 | 243 | ||
280 | /* filldir passes info to user space */ | 244 | spin_lock(&proc_subdir_lock); |
281 | pde_get(de); | 245 | de = de->subdir; |
282 | spin_unlock(&proc_subdir_lock); | 246 | i = ctx->pos - 2; |
283 | if (filldir(dirent, de->name, de->namelen, filp->f_pos, | 247 | for (;;) { |
284 | de->low_ino, de->mode >> 12) < 0) { | 248 | if (!de) { |
285 | pde_put(de); | ||
286 | goto out; | ||
287 | } | ||
288 | spin_lock(&proc_subdir_lock); | ||
289 | filp->f_pos++; | ||
290 | next = de->next; | ||
291 | pde_put(de); | ||
292 | de = next; | ||
293 | } while (de); | ||
294 | spin_unlock(&proc_subdir_lock); | 249 | spin_unlock(&proc_subdir_lock); |
250 | return 0; | ||
251 | } | ||
252 | if (!i) | ||
253 | break; | ||
254 | de = de->next; | ||
255 | i--; | ||
295 | } | 256 | } |
296 | ret = 1; | 257 | |
297 | out: | 258 | do { |
298 | return ret; | 259 | struct proc_dir_entry *next; |
260 | pde_get(de); | ||
261 | spin_unlock(&proc_subdir_lock); | ||
262 | if (!dir_emit(ctx, de->name, de->namelen, | ||
263 | de->low_ino, de->mode >> 12)) { | ||
264 | pde_put(de); | ||
265 | return 0; | ||
266 | } | ||
267 | spin_lock(&proc_subdir_lock); | ||
268 | ctx->pos++; | ||
269 | next = de->next; | ||
270 | pde_put(de); | ||
271 | de = next; | ||
272 | } while (de); | ||
273 | spin_unlock(&proc_subdir_lock); | ||
274 | return 0; | ||
299 | } | 275 | } |
300 | 276 | ||
301 | int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) | 277 | int proc_readdir(struct file *file, struct dir_context *ctx) |
302 | { | 278 | { |
303 | struct inode *inode = file_inode(filp); | 279 | struct inode *inode = file_inode(file); |
304 | 280 | ||
305 | return proc_readdir_de(PDE(inode), filp, dirent, filldir); | 281 | return proc_readdir_de(PDE(inode), file, ctx); |
306 | } | 282 | } |
307 | 283 | ||
308 | /* | 284 | /* |
@@ -313,7 +289,7 @@ int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
313 | static const struct file_operations proc_dir_operations = { | 289 | static const struct file_operations proc_dir_operations = { |
314 | .llseek = generic_file_llseek, | 290 | .llseek = generic_file_llseek, |
315 | .read = generic_read_dir, | 291 | .read = generic_read_dir, |
316 | .readdir = proc_readdir, | 292 | .iterate = proc_readdir, |
317 | }; | 293 | }; |
318 | 294 | ||
319 | /* | 295 | /* |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index d600fb098b6a..4eae2e149f31 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -165,14 +165,14 @@ extern int proc_setattr(struct dentry *, struct iattr *); | |||
165 | extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *); | 165 | extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *); |
166 | extern int pid_revalidate(struct dentry *, unsigned int); | 166 | extern int pid_revalidate(struct dentry *, unsigned int); |
167 | extern int pid_delete_dentry(const struct dentry *); | 167 | extern int pid_delete_dentry(const struct dentry *); |
168 | extern int proc_pid_readdir(struct file *, void *, filldir_t); | 168 | extern int proc_pid_readdir(struct file *, struct dir_context *); |
169 | extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int); | 169 | extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int); |
170 | extern loff_t mem_lseek(struct file *, loff_t, int); | 170 | extern loff_t mem_lseek(struct file *, loff_t, int); |
171 | 171 | ||
172 | /* Lookups */ | 172 | /* Lookups */ |
173 | typedef struct dentry *instantiate_t(struct inode *, struct dentry *, | 173 | typedef struct dentry *instantiate_t(struct inode *, struct dentry *, |
174 | struct task_struct *, const void *); | 174 | struct task_struct *, const void *); |
175 | extern int proc_fill_cache(struct file *, void *, filldir_t, const char *, int, | 175 | extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, int, |
176 | instantiate_t, struct task_struct *, const void *); | 176 | instantiate_t, struct task_struct *, const void *); |
177 | 177 | ||
178 | /* | 178 | /* |
@@ -183,8 +183,8 @@ extern spinlock_t proc_subdir_lock; | |||
183 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); | 183 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); |
184 | extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, | 184 | extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, |
185 | struct dentry *); | 185 | struct dentry *); |
186 | extern int proc_readdir(struct file *, void *, filldir_t); | 186 | extern int proc_readdir(struct file *, struct dir_context *); |
187 | extern int proc_readdir_de(struct proc_dir_entry *, struct file *, void *, filldir_t); | 187 | extern int proc_readdir_de(struct proc_dir_entry *, struct file *, struct dir_context *); |
188 | 188 | ||
189 | static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde) | 189 | static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde) |
190 | { | 190 | { |
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 54bdc6701e9f..f6abbbbfad8a 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c | |||
@@ -213,74 +213,36 @@ out: | |||
213 | return error; | 213 | return error; |
214 | } | 214 | } |
215 | 215 | ||
216 | static int proc_ns_fill_cache(struct file *filp, void *dirent, | 216 | static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx) |
217 | filldir_t filldir, struct task_struct *task, | ||
218 | const struct proc_ns_operations *ops) | ||
219 | { | 217 | { |
220 | return proc_fill_cache(filp, dirent, filldir, | 218 | struct task_struct *task = get_proc_task(file_inode(file)); |
221 | ops->name, strlen(ops->name), | ||
222 | proc_ns_instantiate, task, ops); | ||
223 | } | ||
224 | |||
225 | static int proc_ns_dir_readdir(struct file *filp, void *dirent, | ||
226 | filldir_t filldir) | ||
227 | { | ||
228 | int i; | ||
229 | struct dentry *dentry = filp->f_path.dentry; | ||
230 | struct inode *inode = dentry->d_inode; | ||
231 | struct task_struct *task = get_proc_task(inode); | ||
232 | const struct proc_ns_operations **entry, **last; | 219 | const struct proc_ns_operations **entry, **last; |
233 | ino_t ino; | ||
234 | int ret; | ||
235 | 220 | ||
236 | ret = -ENOENT; | ||
237 | if (!task) | 221 | if (!task) |
238 | goto out_no_task; | 222 | return -ENOENT; |
239 | 223 | ||
240 | ret = 0; | 224 | if (!dir_emit_dots(file, ctx)) |
241 | i = filp->f_pos; | 225 | goto out; |
242 | switch (i) { | 226 | if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries)) |
243 | case 0: | 227 | goto out; |
244 | ino = inode->i_ino; | 228 | entry = ns_entries + (ctx->pos - 2); |
245 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | 229 | last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; |
246 | goto out; | 230 | while (entry <= last) { |
247 | i++; | 231 | const struct proc_ns_operations *ops = *entry; |
248 | filp->f_pos++; | 232 | if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name), |
249 | /* fall through */ | 233 | proc_ns_instantiate, task, ops)) |
250 | case 1: | 234 | break; |
251 | ino = parent_ino(dentry); | 235 | ctx->pos++; |
252 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | 236 | entry++; |
253 | goto out; | ||
254 | i++; | ||
255 | filp->f_pos++; | ||
256 | /* fall through */ | ||
257 | default: | ||
258 | i -= 2; | ||
259 | if (i >= ARRAY_SIZE(ns_entries)) { | ||
260 | ret = 1; | ||
261 | goto out; | ||
262 | } | ||
263 | entry = ns_entries + i; | ||
264 | last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; | ||
265 | while (entry <= last) { | ||
266 | if (proc_ns_fill_cache(filp, dirent, filldir, | ||
267 | task, *entry) < 0) | ||
268 | goto out; | ||
269 | filp->f_pos++; | ||
270 | entry++; | ||
271 | } | ||
272 | } | 237 | } |
273 | |||
274 | ret = 1; | ||
275 | out: | 238 | out: |
276 | put_task_struct(task); | 239 | put_task_struct(task); |
277 | out_no_task: | 240 | return 0; |
278 | return ret; | ||
279 | } | 241 | } |
280 | 242 | ||
281 | const struct file_operations proc_ns_dir_operations = { | 243 | const struct file_operations proc_ns_dir_operations = { |
282 | .read = generic_read_dir, | 244 | .read = generic_read_dir, |
283 | .readdir = proc_ns_dir_readdir, | 245 | .iterate = proc_ns_dir_readdir, |
284 | }; | 246 | }; |
285 | 247 | ||
286 | static struct dentry *proc_ns_dir_lookup(struct inode *dir, | 248 | static struct dentry *proc_ns_dir_lookup(struct inode *dir, |
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 986e83220d56..4677bb7dc7c2 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c | |||
@@ -160,16 +160,15 @@ const struct inode_operations proc_net_inode_operations = { | |||
160 | .getattr = proc_tgid_net_getattr, | 160 | .getattr = proc_tgid_net_getattr, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | static int proc_tgid_net_readdir(struct file *filp, void *dirent, | 163 | static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx) |
164 | filldir_t filldir) | ||
165 | { | 164 | { |
166 | int ret; | 165 | int ret; |
167 | struct net *net; | 166 | struct net *net; |
168 | 167 | ||
169 | ret = -EINVAL; | 168 | ret = -EINVAL; |
170 | net = get_proc_task_net(file_inode(filp)); | 169 | net = get_proc_task_net(file_inode(file)); |
171 | if (net != NULL) { | 170 | if (net != NULL) { |
172 | ret = proc_readdir_de(net->proc_net, filp, dirent, filldir); | 171 | ret = proc_readdir_de(net->proc_net, file, ctx); |
173 | put_net(net); | 172 | put_net(net); |
174 | } | 173 | } |
175 | return ret; | 174 | return ret; |
@@ -178,7 +177,7 @@ static int proc_tgid_net_readdir(struct file *filp, void *dirent, | |||
178 | const struct file_operations proc_net_operations = { | 177 | const struct file_operations proc_net_operations = { |
179 | .llseek = generic_file_llseek, | 178 | .llseek = generic_file_llseek, |
180 | .read = generic_read_dir, | 179 | .read = generic_read_dir, |
181 | .readdir = proc_tgid_net_readdir, | 180 | .iterate = proc_tgid_net_readdir, |
182 | }; | 181 | }; |
183 | 182 | ||
184 | static __net_init int proc_net_ns_init(struct net *net) | 183 | static __net_init int proc_net_ns_init(struct net *net) |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index ac05f33a0dde..f3a570e7c257 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
@@ -573,12 +573,12 @@ out: | |||
573 | return ret; | 573 | return ret; |
574 | } | 574 | } |
575 | 575 | ||
576 | static int proc_sys_fill_cache(struct file *filp, void *dirent, | 576 | static bool proc_sys_fill_cache(struct file *file, |
577 | filldir_t filldir, | 577 | struct dir_context *ctx, |
578 | struct ctl_table_header *head, | 578 | struct ctl_table_header *head, |
579 | struct ctl_table *table) | 579 | struct ctl_table *table) |
580 | { | 580 | { |
581 | struct dentry *child, *dir = filp->f_path.dentry; | 581 | struct dentry *child, *dir = file->f_path.dentry; |
582 | struct inode *inode; | 582 | struct inode *inode; |
583 | struct qstr qname; | 583 | struct qstr qname; |
584 | ino_t ino = 0; | 584 | ino_t ino = 0; |
@@ -595,38 +595,38 @@ static int proc_sys_fill_cache(struct file *filp, void *dirent, | |||
595 | inode = proc_sys_make_inode(dir->d_sb, head, table); | 595 | inode = proc_sys_make_inode(dir->d_sb, head, table); |
596 | if (!inode) { | 596 | if (!inode) { |
597 | dput(child); | 597 | dput(child); |
598 | return -ENOMEM; | 598 | return false; |
599 | } else { | 599 | } else { |
600 | d_set_d_op(child, &proc_sys_dentry_operations); | 600 | d_set_d_op(child, &proc_sys_dentry_operations); |
601 | d_add(child, inode); | 601 | d_add(child, inode); |
602 | } | 602 | } |
603 | } else { | 603 | } else { |
604 | return -ENOMEM; | 604 | return false; |
605 | } | 605 | } |
606 | } | 606 | } |
607 | inode = child->d_inode; | 607 | inode = child->d_inode; |
608 | ino = inode->i_ino; | 608 | ino = inode->i_ino; |
609 | type = inode->i_mode >> 12; | 609 | type = inode->i_mode >> 12; |
610 | dput(child); | 610 | dput(child); |
611 | return !!filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type); | 611 | return dir_emit(ctx, qname.name, qname.len, ino, type); |
612 | } | 612 | } |
613 | 613 | ||
614 | static int proc_sys_link_fill_cache(struct file *filp, void *dirent, | 614 | static bool proc_sys_link_fill_cache(struct file *file, |
615 | filldir_t filldir, | 615 | struct dir_context *ctx, |
616 | struct ctl_table_header *head, | 616 | struct ctl_table_header *head, |
617 | struct ctl_table *table) | 617 | struct ctl_table *table) |
618 | { | 618 | { |
619 | int err, ret = 0; | 619 | bool ret = true; |
620 | head = sysctl_head_grab(head); | 620 | head = sysctl_head_grab(head); |
621 | 621 | ||
622 | if (S_ISLNK(table->mode)) { | 622 | if (S_ISLNK(table->mode)) { |
623 | /* It is not an error if we can not follow the link ignore it */ | 623 | /* It is not an error if we can not follow the link ignore it */ |
624 | err = sysctl_follow_link(&head, &table, current->nsproxy); | 624 | int err = sysctl_follow_link(&head, &table, current->nsproxy); |
625 | if (err) | 625 | if (err) |
626 | goto out; | 626 | goto out; |
627 | } | 627 | } |
628 | 628 | ||
629 | ret = proc_sys_fill_cache(filp, dirent, filldir, head, table); | 629 | ret = proc_sys_fill_cache(file, ctx, head, table); |
630 | out: | 630 | out: |
631 | sysctl_head_finish(head); | 631 | sysctl_head_finish(head); |
632 | return ret; | 632 | return ret; |
@@ -634,67 +634,50 @@ out: | |||
634 | 634 | ||
635 | static int scan(struct ctl_table_header *head, ctl_table *table, | 635 | static int scan(struct ctl_table_header *head, ctl_table *table, |
636 | unsigned long *pos, struct file *file, | 636 | unsigned long *pos, struct file *file, |
637 | void *dirent, filldir_t filldir) | 637 | struct dir_context *ctx) |
638 | { | 638 | { |
639 | int res; | 639 | bool res; |
640 | 640 | ||
641 | if ((*pos)++ < file->f_pos) | 641 | if ((*pos)++ < ctx->pos) |
642 | return 0; | 642 | return true; |
643 | 643 | ||
644 | if (unlikely(S_ISLNK(table->mode))) | 644 | if (unlikely(S_ISLNK(table->mode))) |
645 | res = proc_sys_link_fill_cache(file, dirent, filldir, head, table); | 645 | res = proc_sys_link_fill_cache(file, ctx, head, table); |
646 | else | 646 | else |
647 | res = proc_sys_fill_cache(file, dirent, filldir, head, table); | 647 | res = proc_sys_fill_cache(file, ctx, head, table); |
648 | 648 | ||
649 | if (res == 0) | 649 | if (res) |
650 | file->f_pos = *pos; | 650 | ctx->pos = *pos; |
651 | 651 | ||
652 | return res; | 652 | return res; |
653 | } | 653 | } |
654 | 654 | ||
655 | static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir) | 655 | static int proc_sys_readdir(struct file *file, struct dir_context *ctx) |
656 | { | 656 | { |
657 | struct dentry *dentry = filp->f_path.dentry; | 657 | struct ctl_table_header *head = grab_header(file_inode(file)); |
658 | struct inode *inode = dentry->d_inode; | ||
659 | struct ctl_table_header *head = grab_header(inode); | ||
660 | struct ctl_table_header *h = NULL; | 658 | struct ctl_table_header *h = NULL; |
661 | struct ctl_table *entry; | 659 | struct ctl_table *entry; |
662 | struct ctl_dir *ctl_dir; | 660 | struct ctl_dir *ctl_dir; |
663 | unsigned long pos; | 661 | unsigned long pos; |
664 | int ret = -EINVAL; | ||
665 | 662 | ||
666 | if (IS_ERR(head)) | 663 | if (IS_ERR(head)) |
667 | return PTR_ERR(head); | 664 | return PTR_ERR(head); |
668 | 665 | ||
669 | ctl_dir = container_of(head, struct ctl_dir, header); | 666 | ctl_dir = container_of(head, struct ctl_dir, header); |
670 | 667 | ||
671 | ret = 0; | 668 | if (!dir_emit_dots(file, ctx)) |
672 | /* Avoid a switch here: arm builds fail with missing __cmpdi2 */ | 669 | return 0; |
673 | if (filp->f_pos == 0) { | 670 | |
674 | if (filldir(dirent, ".", 1, filp->f_pos, | ||
675 | inode->i_ino, DT_DIR) < 0) | ||
676 | goto out; | ||
677 | filp->f_pos++; | ||
678 | } | ||
679 | if (filp->f_pos == 1) { | ||
680 | if (filldir(dirent, "..", 2, filp->f_pos, | ||
681 | parent_ino(dentry), DT_DIR) < 0) | ||
682 | goto out; | ||
683 | filp->f_pos++; | ||
684 | } | ||
685 | pos = 2; | 671 | pos = 2; |
686 | 672 | ||
687 | for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) { | 673 | for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) { |
688 | ret = scan(h, entry, &pos, filp, dirent, filldir); | 674 | if (!scan(h, entry, &pos, file, ctx)) { |
689 | if (ret) { | ||
690 | sysctl_head_finish(h); | 675 | sysctl_head_finish(h); |
691 | break; | 676 | break; |
692 | } | 677 | } |
693 | } | 678 | } |
694 | ret = 1; | ||
695 | out: | ||
696 | sysctl_head_finish(head); | 679 | sysctl_head_finish(head); |
697 | return ret; | 680 | return 0; |
698 | } | 681 | } |
699 | 682 | ||
700 | static int proc_sys_permission(struct inode *inode, int mask) | 683 | static int proc_sys_permission(struct inode *inode, int mask) |
@@ -769,7 +752,7 @@ static const struct file_operations proc_sys_file_operations = { | |||
769 | 752 | ||
770 | static const struct file_operations proc_sys_dir_file_operations = { | 753 | static const struct file_operations proc_sys_dir_file_operations = { |
771 | .read = generic_read_dir, | 754 | .read = generic_read_dir, |
772 | .readdir = proc_sys_readdir, | 755 | .iterate = proc_sys_readdir, |
773 | .llseek = generic_file_llseek, | 756 | .llseek = generic_file_llseek, |
774 | }; | 757 | }; |
775 | 758 | ||
diff --git a/fs/proc/root.c b/fs/proc/root.c index 41a6ea93f486..229e366598da 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -202,21 +202,14 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr | |||
202 | return proc_pid_lookup(dir, dentry, flags); | 202 | return proc_pid_lookup(dir, dentry, flags); |
203 | } | 203 | } |
204 | 204 | ||
205 | static int proc_root_readdir(struct file * filp, | 205 | static int proc_root_readdir(struct file *file, struct dir_context *ctx) |
206 | void * dirent, filldir_t filldir) | ||
207 | { | 206 | { |
208 | unsigned int nr = filp->f_pos; | 207 | if (ctx->pos < FIRST_PROCESS_ENTRY) { |
209 | int ret; | 208 | proc_readdir(file, ctx); |
210 | 209 | ctx->pos = FIRST_PROCESS_ENTRY; | |
211 | if (nr < FIRST_PROCESS_ENTRY) { | ||
212 | int error = proc_readdir(filp, dirent, filldir); | ||
213 | if (error <= 0) | ||
214 | return error; | ||
215 | filp->f_pos = FIRST_PROCESS_ENTRY; | ||
216 | } | 210 | } |
217 | 211 | ||
218 | ret = proc_pid_readdir(filp, dirent, filldir); | 212 | return proc_pid_readdir(file, ctx); |
219 | return ret; | ||
220 | } | 213 | } |
221 | 214 | ||
222 | /* | 215 | /* |
@@ -226,7 +219,7 @@ static int proc_root_readdir(struct file * filp, | |||
226 | */ | 219 | */ |
227 | static const struct file_operations proc_root_operations = { | 220 | static const struct file_operations proc_root_operations = { |
228 | .read = generic_read_dir, | 221 | .read = generic_read_dir, |
229 | .readdir = proc_root_readdir, | 222 | .iterate = proc_root_readdir, |
230 | .llseek = default_llseek, | 223 | .llseek = default_llseek, |
231 | }; | 224 | }; |
232 | 225 | ||