Loading fs/hppfs/hppfs.c +14 −19 Original line number Diff line number Diff line Loading @@ -542,8 +542,8 @@ static const struct file_operations hppfs_file_fops = { }; struct hppfs_dirent { void *vfs_dirent; filldir_t filldir; struct dir_context ctx; struct dir_context *caller; struct dentry *dentry; }; Loading @@ -555,34 +555,29 @@ static int hppfs_filldir(void *d, const char *name, int size, if (file_removed(dirent->dentry, name)) return 0; return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset, inode, type); dirent->caller->pos = dirent->ctx.pos; return !dir_emit(dirent->caller, name, size, inode, type); } static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) static int hppfs_readdir(struct file *file, struct dir_context *ctx) { struct hppfs_private *data = file->private_data; struct file *proc_file = data->proc_file; int (*readdir)(struct file *, void *, filldir_t); struct hppfs_dirent dirent = ((struct hppfs_dirent) { .vfs_dirent = ent, .filldir = filldir, struct hppfs_dirent d = { .ctx.actor = hppfs_filldir, .caller = ctx, .dentry = file->f_path.dentry }); }; int err; readdir = file_inode(proc_file)->i_fop->readdir; proc_file->f_pos = file->f_pos; err = (*readdir)(proc_file, &dirent, hppfs_filldir); file->f_pos = proc_file->f_pos; proc_file->f_pos = ctx->pos; err = iterate_dir(proc_file, &d.ctx); ctx->pos = d.ctx.pos; return err; } static const struct file_operations hppfs_dir_fops = { .owner = NULL, .readdir = hppfs_readdir, .iterate = hppfs_readdir, .open = hppfs_dir_open, .llseek = default_llseek, .release = hppfs_release, Loading fs/proc/base.c +133 −230 Original line number Diff line number Diff line Loading @@ -1681,11 +1681,11 @@ const struct dentry_operations pid_dentry_operations = * reported by readdir in sync with the inode numbers reported * by stat. */ int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, bool proc_fill_cache(struct file *file, struct dir_context *ctx, const char *name, int len, instantiate_t instantiate, struct task_struct *task, const void *ptr) { struct dentry *child, *dir = filp->f_path.dentry; struct dentry *child, *dir = file->f_path.dentry; struct inode *inode; struct qstr qname; ino_t ino = 0; Loading Loading @@ -1720,7 +1720,7 @@ end_instantiate: ino = find_inode_number(dir, &qname); if (!ino) ino = 1; return filldir(dirent, name, len, filp->f_pos, ino, type); return dir_emit(ctx, name, len, ino, type); } #ifdef CONFIG_CHECKPOINT_RESTORE Loading Loading @@ -1931,14 +1931,15 @@ static const struct inode_operations proc_map_files_inode_operations = { }; static int proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) proc_map_files_readdir(struct file *file, struct dir_context *ctx) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct vm_area_struct *vma; struct task_struct *task; struct mm_struct *mm; ino_t ino; unsigned long nr_files, pos, i; struct flex_array *fa = NULL; struct map_files_info info; struct map_files_info *p; int ret; ret = -EPERM; Loading @@ -1946,7 +1947,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) goto out; ret = -ENOENT; task = get_proc_task(inode); task = get_proc_task(file_inode(file)); if (!task) goto out; Loading @@ -1955,23 +1956,8 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) goto out_put_task; ret = 0; switch (filp->f_pos) { case 0: ino = inode->i_ino; if (filldir(dirent, ".", 1, 0, ino, DT_DIR) < 0) if (!dir_emit_dots(file, ctx)) goto out_put_task; filp->f_pos++; case 1: ino = parent_ino(dentry); if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) goto out_put_task; filp->f_pos++; default: { unsigned long nr_files, pos, i; struct flex_array *fa = NULL; struct map_files_info info; struct map_files_info *p; mm = get_task_mm(task); if (!mm) Loading @@ -1991,7 +1977,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) */ for (vma = mm->mmap, pos = 2; vma; vma = vma->vm_next) { if (vma->vm_file && ++pos > filp->f_pos) if (vma->vm_file && ++pos > ctx->pos) nr_files++; } Loading @@ -2011,7 +1997,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) vma = vma->vm_next) { if (!vma->vm_file) continue; if (++pos <= filp->f_pos) if (++pos <= ctx->pos) continue; info.mode = vma->vm_file->f_mode; Loading @@ -2026,20 +2012,17 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) for (i = 0; i < nr_files; i++) { p = flex_array_get(fa, i); ret = proc_fill_cache(filp, dirent, filldir, if (!proc_fill_cache(file, ctx, p->name, p->len, proc_map_files_instantiate, task, (void *)(unsigned long)p->mode); if (ret) (void *)(unsigned long)p->mode)) break; filp->f_pos++; ctx->pos++; } if (fa) flex_array_free(fa); mmput(mm); } } out_put_task: put_task_struct(task); Loading @@ -2049,7 +2032,7 @@ out: static const struct file_operations proc_map_files_operations = { .read = generic_read_dir, .readdir = proc_map_files_readdir, .iterate = proc_map_files_readdir, .llseek = default_llseek, }; Loading Loading @@ -2217,67 +2200,30 @@ out_no_task: return error; } static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct task_struct *task, const struct pid_entry *p) { return proc_fill_cache(filp, dirent, filldir, p->name, p->len, proc_pident_instantiate, task, p); } static int proc_pident_readdir(struct file *filp, void *dirent, filldir_t filldir, static int proc_pident_readdir(struct file *file, struct dir_context *ctx, const struct pid_entry *ents, unsigned int nents) { int i; struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct task_struct *task = get_proc_task(inode); const struct pid_entry *p, *last; ino_t ino; int ret; struct task_struct *task = get_proc_task(file_inode(file)); const struct pid_entry *p; ret = -ENOENT; if (!task) goto out_no_task; return -ENOENT; ret = 0; i = filp->f_pos; switch (i) { case 0: ino = inode->i_ino; if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) if (!dir_emit_dots(file, ctx)) goto out; i++; filp->f_pos++; /* fall through */ case 1: ino = parent_ino(dentry); if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) goto out; i++; filp->f_pos++; /* fall through */ default: i -= 2; if (i >= nents) { ret = 1; goto out; } p = ents + i; last = &ents[nents - 1]; while (p <= last) { if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0) if (ctx->pos >= nents + 2) goto out; filp->f_pos++; p++; } } ret = 1; for (p = ents + (ctx->pos - 2); p <= ents + nents - 1; p++) { if (!proc_fill_cache(file, ctx, p->name, p->len, proc_pident_instantiate, task, p)) break; ctx->pos++; } out: put_task_struct(task); out_no_task: return ret; return 0; } #ifdef CONFIG_SECURITY Loading Loading @@ -2362,16 +2308,15 @@ static const struct pid_entry attr_dir_stuff[] = { REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), }; static int proc_attr_dir_readdir(struct file * filp, void * dirent, filldir_t filldir) static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx) { return proc_pident_readdir(filp,dirent,filldir, return proc_pident_readdir(file, ctx, attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff)); } static const struct file_operations proc_attr_dir_operations = { .read = generic_read_dir, .readdir = proc_attr_dir_readdir, .iterate = proc_attr_dir_readdir, .llseek = default_llseek, }; Loading Loading @@ -2725,16 +2670,15 @@ static const struct pid_entry tgid_base_stuff[] = { #endif }; static int proc_tgid_base_readdir(struct file * filp, void * dirent, filldir_t filldir) static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx) { return proc_pident_readdir(filp,dirent,filldir, return proc_pident_readdir(file, ctx, tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); } static const struct file_operations proc_tgid_base_operations = { .read = generic_read_dir, .readdir = proc_tgid_base_readdir, .iterate = proc_tgid_base_readdir, .llseek = default_llseek, }; Loading Loading @@ -2936,58 +2880,42 @@ retry: #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1) static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct tgid_iter iter) { char name[PROC_NUMBUF]; int len = snprintf(name, sizeof(name), "%d", iter.tgid); return proc_fill_cache(filp, dirent, filldir, name, len, proc_pid_instantiate, iter.task, NULL); } static int fake_filldir(void *buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type) { return 0; } /* for the /proc/ directory itself, after non-process stuff has been done */ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) int proc_pid_readdir(struct file *file, struct dir_context *ctx) { struct tgid_iter iter; struct pid_namespace *ns; filldir_t __filldir; loff_t pos = filp->f_pos; loff_t pos = ctx->pos; if (pos >= PID_MAX_LIMIT + TGID_OFFSET) goto out; return 0; if (pos == TGID_OFFSET - 1) { if (proc_fill_cache(filp, dirent, filldir, "self", 4, NULL, NULL, NULL) < 0) goto out; if (!proc_fill_cache(file, ctx, "self", 4, NULL, NULL, NULL)) return 0; iter.tgid = 0; } else { iter.tgid = pos - TGID_OFFSET; } iter.task = NULL; ns = filp->f_dentry->d_sb->s_fs_info; ns = file->f_dentry->d_sb->s_fs_info; for (iter = next_tgid(ns, iter); iter.task; iter.tgid += 1, iter = next_tgid(ns, iter)) { if (has_pid_permissions(ns, iter.task, 2)) __filldir = filldir; else __filldir = fake_filldir; char name[PROC_NUMBUF]; int len; if (!has_pid_permissions(ns, iter.task, 2)) continue; filp->f_pos = iter.tgid + TGID_OFFSET; if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) { len = snprintf(name, sizeof(name), "%d", iter.tgid); ctx->pos = iter.tgid + TGID_OFFSET; if (!proc_fill_cache(file, ctx, name, len, proc_pid_instantiate, iter.task, NULL)) { put_task_struct(iter.task); goto out; return 0; } } filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET; out: ctx->pos = PID_MAX_LIMIT + TGID_OFFSET; return 0; } Loading Loading @@ -3075,10 +3003,9 @@ static const struct pid_entry tid_base_stuff[] = { #endif }; static int proc_tid_base_readdir(struct file * filp, void * dirent, filldir_t filldir) static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx) { return proc_pident_readdir(filp,dirent,filldir, return proc_pident_readdir(file, ctx, tid_base_stuff, ARRAY_SIZE(tid_base_stuff)); } Loading @@ -3090,7 +3017,7 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den static const struct file_operations proc_tid_base_operations = { .read = generic_read_dir, .readdir = proc_tid_base_readdir, .iterate = proc_tid_base_readdir, .llseek = default_llseek, }; Loading Loading @@ -3231,30 +3158,16 @@ static struct task_struct *next_tid(struct task_struct *start) return pos; } static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct task_struct *task, int tid) { char name[PROC_NUMBUF]; int len = snprintf(name, sizeof(name), "%d", tid); return proc_fill_cache(filp, dirent, filldir, name, len, proc_task_instantiate, task, NULL); } /* for the /proc/TGID/task/ directories */ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) static int proc_task_readdir(struct file *file, struct dir_context *ctx) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct task_struct *leader = NULL; struct task_struct *task; int retval = -ENOENT; ino_t ino; int tid; struct task_struct *task = get_proc_task(file_inode(file)); struct pid_namespace *ns; int tid; task = get_proc_task(inode); if (!task) goto out_no_task; return -ENOENT; rcu_read_lock(); if (pid_alive(task)) { leader = task->group_leader; Loading @@ -3263,46 +3176,36 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi rcu_read_unlock(); put_task_struct(task); if (!leader) goto out_no_task; retval = 0; return -ENOENT; switch ((unsigned long)filp->f_pos) { case 0: ino = inode->i_ino; if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0) goto out; filp->f_pos++; /* fall through */ case 1: ino = parent_ino(dentry); if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) < 0) if (!dir_emit_dots(file, ctx)) goto out; filp->f_pos++; /* fall through */ } /* f_version caches the tgid value that the last readdir call couldn't * return. lseek aka telldir automagically resets f_version to 0. */ ns = filp->f_dentry->d_sb->s_fs_info; tid = (int)filp->f_version; filp->f_version = 0; for (task = first_tid(leader, tid, filp->f_pos - 2, ns); ns = file->f_dentry->d_sb->s_fs_info; tid = (int)file->f_version; file->f_version = 0; for (task = first_tid(leader, tid, ctx->pos - 2, ns); task; task = next_tid(task), filp->f_pos++) { task = next_tid(task), ctx->pos++) { char name[PROC_NUMBUF]; int len; tid = task_pid_nr_ns(task, ns); if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { len = snprintf(name, sizeof(name), "%d", tid); if (!proc_fill_cache(file, ctx, name, len, proc_task_instantiate, task, NULL)) { /* returning this tgid failed, save it as the first * pid for the next readir call */ filp->f_version = (u64)tid; file->f_version = (u64)tid; put_task_struct(task); break; } } out: put_task_struct(leader); out_no_task: return retval; return 0; } static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) Loading @@ -3328,6 +3231,6 @@ static const struct inode_operations proc_task_inode_operations = { static const struct file_operations proc_task_operations = { .read = generic_read_dir, .readdir = proc_task_readdir, .iterate = proc_task_readdir, .llseek = default_llseek, }; fs/proc/fd.c +40 −56 Original line number Diff line number Diff line Loading @@ -219,74 +219,58 @@ out_no_task: return result; } static int proc_readfd_common(struct file * filp, void * dirent, filldir_t filldir, instantiate_t instantiate) static int proc_readfd_common(struct file *file, struct dir_context *ctx, instantiate_t instantiate) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct task_struct *p = get_proc_task(inode); struct task_struct *p = get_proc_task(file_inode(file)); struct files_struct *files; unsigned int fd, ino; int retval; unsigned int fd; retval = -ENOENT; if (!p) goto out_no_task; retval = 0; return -ENOENT; fd = filp->f_pos; switch (fd) { case 0: if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) if (!dir_emit_dots(file, ctx)) goto out; filp->f_pos++; case 1: ino = parent_ino(dentry); if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) if (!dir_emit_dots(file, ctx)) goto out; filp->f_pos++; default: files = get_files_struct(p); if (!files) goto out; rcu_read_lock(); for (fd = filp->f_pos - 2; for (fd = ctx->pos - 2; fd < files_fdtable(files)->max_fds; fd++, filp->f_pos++) { fd++, ctx->pos++) { char name[PROC_NUMBUF]; int len; int rv; if (!fcheck_files(files, fd)) continue; rcu_read_unlock(); len = snprintf(name, sizeof(name), "%d", fd); rv = proc_fill_cache(filp, dirent, filldir, if (!proc_fill_cache(file, ctx, name, len, instantiate, p, (void *)(unsigned long)fd); if (rv < 0) (void *)(unsigned long)fd)) goto out_fd_loop; rcu_read_lock(); } rcu_read_unlock(); out_fd_loop: put_files_struct(files); } out: put_task_struct(p); out_no_task: return retval; return 0; } static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir) static int proc_readfd(struct file *file, struct dir_context *ctx) { return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate); return proc_readfd_common(file, ctx, proc_fd_instantiate); } const struct file_operations proc_fd_operations = { .read = generic_read_dir, .readdir = proc_readfd, .iterate = proc_readfd, .llseek = default_llseek, }; Loading Loading @@ -351,9 +335,9 @@ proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags) return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); } static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir) static int proc_readfdinfo(struct file *file, struct dir_context *ctx) { return proc_readfd_common(filp, dirent, filldir, return proc_readfd_common(file, ctx, proc_fdinfo_instantiate); } Loading @@ -364,6 +348,6 @@ const struct inode_operations proc_fdinfo_inode_operations = { const struct file_operations proc_fdinfo_operations = { .read = generic_read_dir, .readdir = proc_readfdinfo, .iterate = proc_readfdinfo, .llseek = default_llseek, }; fs/proc/generic.c +38 −62 Original line number Diff line number Diff line Loading @@ -233,40 +233,21 @@ struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, * value of the readdir() call, as long as it's non-negative * for success.. */ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, filldir_t filldir) int proc_readdir_de(struct proc_dir_entry *de, struct file *file, struct dir_context *ctx) { unsigned int ino; int i; struct inode *inode = file_inode(filp); int ret = 0; ino = inode->i_ino; i = filp->f_pos; switch (i) { case 0: if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) goto out; i++; filp->f_pos++; /* fall through */ case 1: if (filldir(dirent, "..", 2, i, parent_ino(filp->f_path.dentry), DT_DIR) < 0) goto out; i++; filp->f_pos++; /* fall through */ default: if (!dir_emit_dots(file, ctx)) return 0; spin_lock(&proc_subdir_lock); de = de->subdir; i -= 2; i = ctx->pos - 2; for (;;) { if (!de) { ret = 1; spin_unlock(&proc_subdir_lock); goto out; return 0; } if (!i) break; Loading @@ -276,33 +257,28 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, do { struct proc_dir_entry *next; /* filldir passes info to user space */ pde_get(de); spin_unlock(&proc_subdir_lock); if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino, de->mode >> 12) < 0) { if (!dir_emit(ctx, de->name, de->namelen, de->low_ino, de->mode >> 12)) { pde_put(de); goto out; return 0; } spin_lock(&proc_subdir_lock); filp->f_pos++; ctx->pos++; next = de->next; pde_put(de); de = next; } while (de); spin_unlock(&proc_subdir_lock); } ret = 1; out: return ret; return 0; } int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) int proc_readdir(struct file *file, struct dir_context *ctx) { struct inode *inode = file_inode(filp); struct inode *inode = file_inode(file); return proc_readdir_de(PDE(inode), filp, dirent, filldir); return proc_readdir_de(PDE(inode), file, ctx); } /* Loading @@ -313,7 +289,7 @@ int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) static const struct file_operations proc_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = proc_readdir, .iterate = proc_readdir, }; /* Loading fs/proc/internal.h +4 −4 Original line number Diff line number Diff line Loading @@ -165,14 +165,14 @@ extern int proc_setattr(struct dentry *, struct iattr *); extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *); extern int pid_revalidate(struct dentry *, unsigned int); extern int pid_delete_dentry(const struct dentry *); extern int proc_pid_readdir(struct file *, void *, filldir_t); extern int proc_pid_readdir(struct file *, struct dir_context *); extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int); extern loff_t mem_lseek(struct file *, loff_t, int); /* Lookups */ typedef struct dentry *instantiate_t(struct inode *, struct dentry *, struct task_struct *, const void *); extern int proc_fill_cache(struct file *, void *, filldir_t, const char *, int, extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, int, instantiate_t, struct task_struct *, const void *); /* Loading @@ -183,8 +183,8 @@ extern spinlock_t proc_subdir_lock; extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, struct dentry *); extern int proc_readdir(struct file *, void *, filldir_t); extern int proc_readdir_de(struct proc_dir_entry *, struct file *, void *, filldir_t); extern int proc_readdir(struct file *, struct dir_context *); extern int proc_readdir_de(struct proc_dir_entry *, struct file *, struct dir_context *); static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde) { Loading Loading
fs/hppfs/hppfs.c +14 −19 Original line number Diff line number Diff line Loading @@ -542,8 +542,8 @@ static const struct file_operations hppfs_file_fops = { }; struct hppfs_dirent { void *vfs_dirent; filldir_t filldir; struct dir_context ctx; struct dir_context *caller; struct dentry *dentry; }; Loading @@ -555,34 +555,29 @@ static int hppfs_filldir(void *d, const char *name, int size, if (file_removed(dirent->dentry, name)) return 0; return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset, inode, type); dirent->caller->pos = dirent->ctx.pos; return !dir_emit(dirent->caller, name, size, inode, type); } static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) static int hppfs_readdir(struct file *file, struct dir_context *ctx) { struct hppfs_private *data = file->private_data; struct file *proc_file = data->proc_file; int (*readdir)(struct file *, void *, filldir_t); struct hppfs_dirent dirent = ((struct hppfs_dirent) { .vfs_dirent = ent, .filldir = filldir, struct hppfs_dirent d = { .ctx.actor = hppfs_filldir, .caller = ctx, .dentry = file->f_path.dentry }); }; int err; readdir = file_inode(proc_file)->i_fop->readdir; proc_file->f_pos = file->f_pos; err = (*readdir)(proc_file, &dirent, hppfs_filldir); file->f_pos = proc_file->f_pos; proc_file->f_pos = ctx->pos; err = iterate_dir(proc_file, &d.ctx); ctx->pos = d.ctx.pos; return err; } static const struct file_operations hppfs_dir_fops = { .owner = NULL, .readdir = hppfs_readdir, .iterate = hppfs_readdir, .open = hppfs_dir_open, .llseek = default_llseek, .release = hppfs_release, Loading
fs/proc/base.c +133 −230 Original line number Diff line number Diff line Loading @@ -1681,11 +1681,11 @@ const struct dentry_operations pid_dentry_operations = * reported by readdir in sync with the inode numbers reported * by stat. */ int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, bool proc_fill_cache(struct file *file, struct dir_context *ctx, const char *name, int len, instantiate_t instantiate, struct task_struct *task, const void *ptr) { struct dentry *child, *dir = filp->f_path.dentry; struct dentry *child, *dir = file->f_path.dentry; struct inode *inode; struct qstr qname; ino_t ino = 0; Loading Loading @@ -1720,7 +1720,7 @@ end_instantiate: ino = find_inode_number(dir, &qname); if (!ino) ino = 1; return filldir(dirent, name, len, filp->f_pos, ino, type); return dir_emit(ctx, name, len, ino, type); } #ifdef CONFIG_CHECKPOINT_RESTORE Loading Loading @@ -1931,14 +1931,15 @@ static const struct inode_operations proc_map_files_inode_operations = { }; static int proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) proc_map_files_readdir(struct file *file, struct dir_context *ctx) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct vm_area_struct *vma; struct task_struct *task; struct mm_struct *mm; ino_t ino; unsigned long nr_files, pos, i; struct flex_array *fa = NULL; struct map_files_info info; struct map_files_info *p; int ret; ret = -EPERM; Loading @@ -1946,7 +1947,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) goto out; ret = -ENOENT; task = get_proc_task(inode); task = get_proc_task(file_inode(file)); if (!task) goto out; Loading @@ -1955,23 +1956,8 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) goto out_put_task; ret = 0; switch (filp->f_pos) { case 0: ino = inode->i_ino; if (filldir(dirent, ".", 1, 0, ino, DT_DIR) < 0) if (!dir_emit_dots(file, ctx)) goto out_put_task; filp->f_pos++; case 1: ino = parent_ino(dentry); if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) goto out_put_task; filp->f_pos++; default: { unsigned long nr_files, pos, i; struct flex_array *fa = NULL; struct map_files_info info; struct map_files_info *p; mm = get_task_mm(task); if (!mm) Loading @@ -1991,7 +1977,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) */ for (vma = mm->mmap, pos = 2; vma; vma = vma->vm_next) { if (vma->vm_file && ++pos > filp->f_pos) if (vma->vm_file && ++pos > ctx->pos) nr_files++; } Loading @@ -2011,7 +1997,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) vma = vma->vm_next) { if (!vma->vm_file) continue; if (++pos <= filp->f_pos) if (++pos <= ctx->pos) continue; info.mode = vma->vm_file->f_mode; Loading @@ -2026,20 +2012,17 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) for (i = 0; i < nr_files; i++) { p = flex_array_get(fa, i); ret = proc_fill_cache(filp, dirent, filldir, if (!proc_fill_cache(file, ctx, p->name, p->len, proc_map_files_instantiate, task, (void *)(unsigned long)p->mode); if (ret) (void *)(unsigned long)p->mode)) break; filp->f_pos++; ctx->pos++; } if (fa) flex_array_free(fa); mmput(mm); } } out_put_task: put_task_struct(task); Loading @@ -2049,7 +2032,7 @@ out: static const struct file_operations proc_map_files_operations = { .read = generic_read_dir, .readdir = proc_map_files_readdir, .iterate = proc_map_files_readdir, .llseek = default_llseek, }; Loading Loading @@ -2217,67 +2200,30 @@ out_no_task: return error; } static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct task_struct *task, const struct pid_entry *p) { return proc_fill_cache(filp, dirent, filldir, p->name, p->len, proc_pident_instantiate, task, p); } static int proc_pident_readdir(struct file *filp, void *dirent, filldir_t filldir, static int proc_pident_readdir(struct file *file, struct dir_context *ctx, const struct pid_entry *ents, unsigned int nents) { int i; struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct task_struct *task = get_proc_task(inode); const struct pid_entry *p, *last; ino_t ino; int ret; struct task_struct *task = get_proc_task(file_inode(file)); const struct pid_entry *p; ret = -ENOENT; if (!task) goto out_no_task; return -ENOENT; ret = 0; i = filp->f_pos; switch (i) { case 0: ino = inode->i_ino; if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) if (!dir_emit_dots(file, ctx)) goto out; i++; filp->f_pos++; /* fall through */ case 1: ino = parent_ino(dentry); if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) goto out; i++; filp->f_pos++; /* fall through */ default: i -= 2; if (i >= nents) { ret = 1; goto out; } p = ents + i; last = &ents[nents - 1]; while (p <= last) { if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0) if (ctx->pos >= nents + 2) goto out; filp->f_pos++; p++; } } ret = 1; for (p = ents + (ctx->pos - 2); p <= ents + nents - 1; p++) { if (!proc_fill_cache(file, ctx, p->name, p->len, proc_pident_instantiate, task, p)) break; ctx->pos++; } out: put_task_struct(task); out_no_task: return ret; return 0; } #ifdef CONFIG_SECURITY Loading Loading @@ -2362,16 +2308,15 @@ static const struct pid_entry attr_dir_stuff[] = { REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), }; static int proc_attr_dir_readdir(struct file * filp, void * dirent, filldir_t filldir) static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx) { return proc_pident_readdir(filp,dirent,filldir, return proc_pident_readdir(file, ctx, attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff)); } static const struct file_operations proc_attr_dir_operations = { .read = generic_read_dir, .readdir = proc_attr_dir_readdir, .iterate = proc_attr_dir_readdir, .llseek = default_llseek, }; Loading Loading @@ -2725,16 +2670,15 @@ static const struct pid_entry tgid_base_stuff[] = { #endif }; static int proc_tgid_base_readdir(struct file * filp, void * dirent, filldir_t filldir) static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx) { return proc_pident_readdir(filp,dirent,filldir, return proc_pident_readdir(file, ctx, tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); } static const struct file_operations proc_tgid_base_operations = { .read = generic_read_dir, .readdir = proc_tgid_base_readdir, .iterate = proc_tgid_base_readdir, .llseek = default_llseek, }; Loading Loading @@ -2936,58 +2880,42 @@ retry: #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1) static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct tgid_iter iter) { char name[PROC_NUMBUF]; int len = snprintf(name, sizeof(name), "%d", iter.tgid); return proc_fill_cache(filp, dirent, filldir, name, len, proc_pid_instantiate, iter.task, NULL); } static int fake_filldir(void *buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type) { return 0; } /* for the /proc/ directory itself, after non-process stuff has been done */ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) int proc_pid_readdir(struct file *file, struct dir_context *ctx) { struct tgid_iter iter; struct pid_namespace *ns; filldir_t __filldir; loff_t pos = filp->f_pos; loff_t pos = ctx->pos; if (pos >= PID_MAX_LIMIT + TGID_OFFSET) goto out; return 0; if (pos == TGID_OFFSET - 1) { if (proc_fill_cache(filp, dirent, filldir, "self", 4, NULL, NULL, NULL) < 0) goto out; if (!proc_fill_cache(file, ctx, "self", 4, NULL, NULL, NULL)) return 0; iter.tgid = 0; } else { iter.tgid = pos - TGID_OFFSET; } iter.task = NULL; ns = filp->f_dentry->d_sb->s_fs_info; ns = file->f_dentry->d_sb->s_fs_info; for (iter = next_tgid(ns, iter); iter.task; iter.tgid += 1, iter = next_tgid(ns, iter)) { if (has_pid_permissions(ns, iter.task, 2)) __filldir = filldir; else __filldir = fake_filldir; char name[PROC_NUMBUF]; int len; if (!has_pid_permissions(ns, iter.task, 2)) continue; filp->f_pos = iter.tgid + TGID_OFFSET; if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) { len = snprintf(name, sizeof(name), "%d", iter.tgid); ctx->pos = iter.tgid + TGID_OFFSET; if (!proc_fill_cache(file, ctx, name, len, proc_pid_instantiate, iter.task, NULL)) { put_task_struct(iter.task); goto out; return 0; } } filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET; out: ctx->pos = PID_MAX_LIMIT + TGID_OFFSET; return 0; } Loading Loading @@ -3075,10 +3003,9 @@ static const struct pid_entry tid_base_stuff[] = { #endif }; static int proc_tid_base_readdir(struct file * filp, void * dirent, filldir_t filldir) static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx) { return proc_pident_readdir(filp,dirent,filldir, return proc_pident_readdir(file, ctx, tid_base_stuff, ARRAY_SIZE(tid_base_stuff)); } Loading @@ -3090,7 +3017,7 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den static const struct file_operations proc_tid_base_operations = { .read = generic_read_dir, .readdir = proc_tid_base_readdir, .iterate = proc_tid_base_readdir, .llseek = default_llseek, }; Loading Loading @@ -3231,30 +3158,16 @@ static struct task_struct *next_tid(struct task_struct *start) return pos; } static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct task_struct *task, int tid) { char name[PROC_NUMBUF]; int len = snprintf(name, sizeof(name), "%d", tid); return proc_fill_cache(filp, dirent, filldir, name, len, proc_task_instantiate, task, NULL); } /* for the /proc/TGID/task/ directories */ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) static int proc_task_readdir(struct file *file, struct dir_context *ctx) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct task_struct *leader = NULL; struct task_struct *task; int retval = -ENOENT; ino_t ino; int tid; struct task_struct *task = get_proc_task(file_inode(file)); struct pid_namespace *ns; int tid; task = get_proc_task(inode); if (!task) goto out_no_task; return -ENOENT; rcu_read_lock(); if (pid_alive(task)) { leader = task->group_leader; Loading @@ -3263,46 +3176,36 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi rcu_read_unlock(); put_task_struct(task); if (!leader) goto out_no_task; retval = 0; return -ENOENT; switch ((unsigned long)filp->f_pos) { case 0: ino = inode->i_ino; if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0) goto out; filp->f_pos++; /* fall through */ case 1: ino = parent_ino(dentry); if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) < 0) if (!dir_emit_dots(file, ctx)) goto out; filp->f_pos++; /* fall through */ } /* f_version caches the tgid value that the last readdir call couldn't * return. lseek aka telldir automagically resets f_version to 0. */ ns = filp->f_dentry->d_sb->s_fs_info; tid = (int)filp->f_version; filp->f_version = 0; for (task = first_tid(leader, tid, filp->f_pos - 2, ns); ns = file->f_dentry->d_sb->s_fs_info; tid = (int)file->f_version; file->f_version = 0; for (task = first_tid(leader, tid, ctx->pos - 2, ns); task; task = next_tid(task), filp->f_pos++) { task = next_tid(task), ctx->pos++) { char name[PROC_NUMBUF]; int len; tid = task_pid_nr_ns(task, ns); if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { len = snprintf(name, sizeof(name), "%d", tid); if (!proc_fill_cache(file, ctx, name, len, proc_task_instantiate, task, NULL)) { /* returning this tgid failed, save it as the first * pid for the next readir call */ filp->f_version = (u64)tid; file->f_version = (u64)tid; put_task_struct(task); break; } } out: put_task_struct(leader); out_no_task: return retval; return 0; } static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) Loading @@ -3328,6 +3231,6 @@ static const struct inode_operations proc_task_inode_operations = { static const struct file_operations proc_task_operations = { .read = generic_read_dir, .readdir = proc_task_readdir, .iterate = proc_task_readdir, .llseek = default_llseek, };
fs/proc/fd.c +40 −56 Original line number Diff line number Diff line Loading @@ -219,74 +219,58 @@ out_no_task: return result; } static int proc_readfd_common(struct file * filp, void * dirent, filldir_t filldir, instantiate_t instantiate) static int proc_readfd_common(struct file *file, struct dir_context *ctx, instantiate_t instantiate) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct task_struct *p = get_proc_task(inode); struct task_struct *p = get_proc_task(file_inode(file)); struct files_struct *files; unsigned int fd, ino; int retval; unsigned int fd; retval = -ENOENT; if (!p) goto out_no_task; retval = 0; return -ENOENT; fd = filp->f_pos; switch (fd) { case 0: if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) if (!dir_emit_dots(file, ctx)) goto out; filp->f_pos++; case 1: ino = parent_ino(dentry); if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) if (!dir_emit_dots(file, ctx)) goto out; filp->f_pos++; default: files = get_files_struct(p); if (!files) goto out; rcu_read_lock(); for (fd = filp->f_pos - 2; for (fd = ctx->pos - 2; fd < files_fdtable(files)->max_fds; fd++, filp->f_pos++) { fd++, ctx->pos++) { char name[PROC_NUMBUF]; int len; int rv; if (!fcheck_files(files, fd)) continue; rcu_read_unlock(); len = snprintf(name, sizeof(name), "%d", fd); rv = proc_fill_cache(filp, dirent, filldir, if (!proc_fill_cache(file, ctx, name, len, instantiate, p, (void *)(unsigned long)fd); if (rv < 0) (void *)(unsigned long)fd)) goto out_fd_loop; rcu_read_lock(); } rcu_read_unlock(); out_fd_loop: put_files_struct(files); } out: put_task_struct(p); out_no_task: return retval; return 0; } static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir) static int proc_readfd(struct file *file, struct dir_context *ctx) { return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate); return proc_readfd_common(file, ctx, proc_fd_instantiate); } const struct file_operations proc_fd_operations = { .read = generic_read_dir, .readdir = proc_readfd, .iterate = proc_readfd, .llseek = default_llseek, }; Loading Loading @@ -351,9 +335,9 @@ proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags) return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); } static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir) static int proc_readfdinfo(struct file *file, struct dir_context *ctx) { return proc_readfd_common(filp, dirent, filldir, return proc_readfd_common(file, ctx, proc_fdinfo_instantiate); } Loading @@ -364,6 +348,6 @@ const struct inode_operations proc_fdinfo_inode_operations = { const struct file_operations proc_fdinfo_operations = { .read = generic_read_dir, .readdir = proc_readfdinfo, .iterate = proc_readfdinfo, .llseek = default_llseek, };
fs/proc/generic.c +38 −62 Original line number Diff line number Diff line Loading @@ -233,40 +233,21 @@ struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, * value of the readdir() call, as long as it's non-negative * for success.. */ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, filldir_t filldir) int proc_readdir_de(struct proc_dir_entry *de, struct file *file, struct dir_context *ctx) { unsigned int ino; int i; struct inode *inode = file_inode(filp); int ret = 0; ino = inode->i_ino; i = filp->f_pos; switch (i) { case 0: if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) goto out; i++; filp->f_pos++; /* fall through */ case 1: if (filldir(dirent, "..", 2, i, parent_ino(filp->f_path.dentry), DT_DIR) < 0) goto out; i++; filp->f_pos++; /* fall through */ default: if (!dir_emit_dots(file, ctx)) return 0; spin_lock(&proc_subdir_lock); de = de->subdir; i -= 2; i = ctx->pos - 2; for (;;) { if (!de) { ret = 1; spin_unlock(&proc_subdir_lock); goto out; return 0; } if (!i) break; Loading @@ -276,33 +257,28 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, do { struct proc_dir_entry *next; /* filldir passes info to user space */ pde_get(de); spin_unlock(&proc_subdir_lock); if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino, de->mode >> 12) < 0) { if (!dir_emit(ctx, de->name, de->namelen, de->low_ino, de->mode >> 12)) { pde_put(de); goto out; return 0; } spin_lock(&proc_subdir_lock); filp->f_pos++; ctx->pos++; next = de->next; pde_put(de); de = next; } while (de); spin_unlock(&proc_subdir_lock); } ret = 1; out: return ret; return 0; } int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) int proc_readdir(struct file *file, struct dir_context *ctx) { struct inode *inode = file_inode(filp); struct inode *inode = file_inode(file); return proc_readdir_de(PDE(inode), filp, dirent, filldir); return proc_readdir_de(PDE(inode), file, ctx); } /* Loading @@ -313,7 +289,7 @@ int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) static const struct file_operations proc_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = proc_readdir, .iterate = proc_readdir, }; /* Loading
fs/proc/internal.h +4 −4 Original line number Diff line number Diff line Loading @@ -165,14 +165,14 @@ extern int proc_setattr(struct dentry *, struct iattr *); extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *); extern int pid_revalidate(struct dentry *, unsigned int); extern int pid_delete_dentry(const struct dentry *); extern int proc_pid_readdir(struct file *, void *, filldir_t); extern int proc_pid_readdir(struct file *, struct dir_context *); extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int); extern loff_t mem_lseek(struct file *, loff_t, int); /* Lookups */ typedef struct dentry *instantiate_t(struct inode *, struct dentry *, struct task_struct *, const void *); extern int proc_fill_cache(struct file *, void *, filldir_t, const char *, int, extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, int, instantiate_t, struct task_struct *, const void *); /* Loading @@ -183,8 +183,8 @@ extern spinlock_t proc_subdir_lock; extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, struct dentry *); extern int proc_readdir(struct file *, void *, filldir_t); extern int proc_readdir_de(struct proc_dir_entry *, struct file *, void *, filldir_t); extern int proc_readdir(struct file *, struct dir_context *); extern int proc_readdir_de(struct proc_dir_entry *, struct file *, struct dir_context *); static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde) { Loading