static int sysfs_readdir(struct file *file, struct dir_context *ctx) { struct dentry *dentry = file->f_path.dentry; struct sysfs_dirent *parent_sd = dentry->d_fsdata; struct sysfs_dirent *pos = file->private_data; enum kobj_ns_type type; const void *ns; type = sysfs_ns_type(parent_sd); ns = sysfs_info(dentry->d_sb)->ns[type]; if (!dir_emit_dots(file, ctx)) return 0; mutex_lock(&sysfs_mutex); for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos); pos; pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) { const char *name = pos->s_name; unsigned int type = dt_type(pos); int len = strlen(name); ino_t ino = pos->s_ino; ctx->pos = pos->s_hash; file->private_data = sysfs_get(pos); mutex_unlock(&sysfs_mutex); if (!dir_emit(ctx, name, len, ino, type)) return 0; mutex_lock(&sysfs_mutex); } mutex_unlock(&sysfs_mutex); file->private_data = NULL; ctx->pos = INT_MAX; return 0; }
static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) { int over; struct p9_fid *fid; struct v9fs_session_info *v9ses; struct inode *inode; struct p9_stat *st; P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); inode = filp->f_path.dentry->d_inode; v9ses = v9fs_inode2v9ses(inode); fid = filp->private_data; while ((st = p9_client_dirread(fid, filp->f_pos)) != NULL) { if (IS_ERR(st)) return PTR_ERR(st); over = filldir(dirent, st->name.str, st->name.len, filp->f_pos, v9fs_qid2ino(&st->qid), dt_type(st)); if (over) break; filp->f_pos += st->size; kfree(st); st = NULL; } kfree(st); return 0; }
static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) { bool over; struct p9_wstat st; int err = 0; struct p9_fid *fid; int buflen; int reclen = 0; struct p9_rdir *rdir; struct kvec kvec; p9_debug(P9_DEBUG_VFS, "name %pD\n", file); fid = file->private_data; buflen = fid->clnt->msize - P9_IOHDRSZ; rdir = v9fs_alloc_rdir_buf(file, buflen); if (!rdir) return -ENOMEM; kvec.iov_base = rdir->buf; kvec.iov_len = buflen; while (1) { if (rdir->tail == rdir->head) { struct iov_iter to; int n; iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen); n = p9_client_read(file->private_data, ctx->pos, &to, &err); if (err) return err; rdir->head = 0; rdir->tail = n; } while (rdir->head < rdir->tail) { p9stat_init(&st); err = p9stat_read(fid->clnt, rdir->buf + rdir->head, rdir->tail - rdir->head, &st); if (err) { p9_debug(P9_DEBUG_VFS, "returned %d\n", err); p9stat_free(&st); return -EIO; } reclen = st.size+2; over = !dir_emit(ctx, st.name, strlen(st.name), v9fs_qid2ino(&st.qid), dt_type(&st)); p9stat_free(&st); if (over) return 0; rdir->head += reclen; ctx->pos += reclen; } } }
static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) { int over; struct p9_wstat st; int err; struct p9_fid *fid; int buflen; char *statbuf; int n, i = 0; P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); fid = filp->private_data; buflen = fid->clnt->msize - P9_IOHDRSZ; statbuf = kmalloc(buflen, GFP_KERNEL); if (!statbuf) return -ENOMEM; while (1) { err = v9fs_file_readn(filp, statbuf, NULL, buflen, fid->rdir_fpos); if (err <= 0) break; n = err; while (i < n) { err = p9stat_read(statbuf + i, buflen-i, &st, fid->clnt->dotu); if (err) { P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); err = -EIO; p9stat_free(&st); goto free_and_exit; } i += st.size+2; fid->rdir_fpos += st.size+2; over = filldir(dirent, st.name, strlen(st.name), filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st)); filp->f_pos += st.size+2; p9stat_free(&st); if (over) { err = 0; goto free_and_exit; } } } free_and_exit: kfree(statbuf); return err; }
static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { struct dentry *dentry = filp->f_path.dentry; struct sysfs_dirent * parent_sd = dentry->d_fsdata; struct sysfs_dirent *pos = filp->private_data; ino_t ino; if (filp->f_pos == 0) { ino = parent_sd->s_ino; if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) filp->f_pos++; } if (filp->f_pos == 1) { if (parent_sd->s_parent) ino = parent_sd->s_parent->s_ino; else ino = parent_sd->s_ino; if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) filp->f_pos++; } mutex_lock(&sysfs_mutex); for (pos = sysfs_dir_pos(parent_sd, filp->f_pos, pos); pos; pos = sysfs_dir_next_pos(parent_sd, filp->f_pos, pos)) { const char * name; unsigned int type; int len, ret; name = pos->s_name; len = strlen(name); ino = pos->s_ino; type = dt_type(pos); filp->f_pos = ino; filp->private_data = sysfs_get(pos); mutex_unlock(&sysfs_mutex); ret = filldir(dirent, name, len, filp->f_pos, ino, type); mutex_lock(&sysfs_mutex); if (ret < 0) break; } mutex_unlock(&sysfs_mutex); if ((filp->f_pos > 1) && !pos) { /* EOF */ filp->f_pos = INT_MAX; filp->private_data = NULL; } return 0; }
static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx) { struct dentry *dentry = file->f_path.dentry; struct kernfs_node *parent = dentry->d_fsdata; struct kernfs_node *pos = file->private_data; const void *ns = NULL; if (!dir_emit_dots(file, ctx)) return 0; mutex_lock(&kernfs_mutex); if (kernfs_ns_enabled(parent)) ns = kernfs_info(dentry->d_sb)->ns; for (pos = kernfs_dir_pos(ns, parent, ctx->pos, pos); pos; pos = kernfs_dir_next_pos(ns, parent, ctx->pos, pos)) { const char *name = pos->name; unsigned int type = dt_type(pos); int len = strlen(name); ino_t ino = pos->ino; ctx->pos = pos->hash; file->private_data = pos; kernfs_get(pos); mutex_unlock(&kernfs_mutex); if (!dir_emit(ctx, name, len, ino, type)) return 0; mutex_lock(&kernfs_mutex); } mutex_unlock(&kernfs_mutex); file->private_data = NULL; ctx->pos = INT_MAX; return 0; }
static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct v9fs_fcall *fcall = NULL; struct inode *inode = filp->f_path.dentry->d_inode; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); struct v9fs_fid *file = filp->private_data; unsigned int i, n, s; int fid = -1; int ret = 0; struct v9fs_stat stat; int over = 0; dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); fid = file->fid; if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) { kfree(file->rdir_fcall); file->rdir_fcall = NULL; } if (file->rdir_fcall) { n = file->rdir_fcall->params.rread.count; i = file->rdir_fpos; while (i < n) { s = v9fs_deserialize_stat( file->rdir_fcall->params.rread.data + i, n - i, &stat, v9ses->extended); if (s == 0) { dprintk(DEBUG_ERROR, "error while deserializing stat\n"); ret = -EIO; goto FreeStructs; } over = filldir(dirent, stat.name.str, stat.name.len, filp->f_pos, v9fs_qid2ino(&stat.qid), dt_type(&stat)); if (over) { file->rdir_fpos = i; file->rdir_pos = filp->f_pos; break; } i += s; filp->f_pos += s; } if (!over) { kfree(file->rdir_fcall); file->rdir_fcall = NULL; } } while (!over) { ret = v9fs_t_read(v9ses, fid, filp->f_pos, v9ses->maxdata-V9FS_IOHDRSZ, &fcall); if (ret < 0) { dprintk(DEBUG_ERROR, "error while reading: %d: %p\n", ret, fcall); goto FreeStructs; } else if (ret == 0) break; n = ret; i = 0; while (i < n) { s = v9fs_deserialize_stat(fcall->params.rread.data + i, n - i, &stat, v9ses->extended); if (s == 0) { dprintk(DEBUG_ERROR, "error while deserializing stat\n"); return -EIO; } over = filldir(dirent, stat.name.str, stat.name.len, filp->f_pos, v9fs_qid2ino(&stat.qid), dt_type(&stat)); if (over) { file->rdir_fcall = fcall; file->rdir_fpos = i; file->rdir_pos = filp->f_pos; fcall = NULL; break; } i += s; filp->f_pos += s; } kfree(fcall); } FreeStructs: kfree(fcall); return ret; }
static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { struct dentry *dentry = filp->f_path.dentry; struct sysfs_dirent * parent_sd = dentry->d_fsdata; struct sysfs_dirent *cursor = filp->private_data; struct sysfs_dirent **pos; ino_t ino; int i = filp->f_pos; switch (i) { case 0: ino = parent_sd->s_ino; if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) break; filp->f_pos++; i++; /* fallthrough */ case 1: if (parent_sd->s_parent) ino = parent_sd->s_parent->s_ino; else ino = parent_sd->s_ino; if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) break; filp->f_pos++; i++; /* fallthrough */ default: mutex_lock(&sysfs_mutex); pos = &parent_sd->s_children; while (*pos != cursor) pos = &(*pos)->s_sibling; /* unlink cursor */ *pos = cursor->s_sibling; if (filp->f_pos == 2) pos = &parent_sd->s_children; for ( ; *pos; pos = &(*pos)->s_sibling) { struct sysfs_dirent *next = *pos; const char * name; int len; if (!sysfs_type(next)) continue; name = next->s_name; len = strlen(name); ino = next->s_ino; if (filldir(dirent, name, len, filp->f_pos, ino, dt_type(next)) < 0) break; filp->f_pos++; } /* put cursor back in */ cursor->s_sibling = *pos; *pos = cursor; mutex_unlock(&sysfs_mutex); } return 0; }
static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) { int over; struct p9_wstat st; int err = 0; struct p9_fid *fid; int buflen; int reclen = 0; struct p9_rdir *rdir; P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); fid = filp->private_data; buflen = fid->clnt->msize - P9_IOHDRSZ; err = v9fs_alloc_rdir_buf(filp, buflen); if (err) goto exit; rdir = (struct p9_rdir *) fid->rdir; err = mutex_lock_interruptible(&rdir->mutex); if (err) return err; while (err == 0) { if (rdir->tail == rdir->head) { err = v9fs_file_readn(filp, rdir->buf, NULL, buflen, filp->f_pos); if (err <= 0) goto unlock_and_exit; rdir->head = 0; rdir->tail = err; } while (rdir->head < rdir->tail) { p9stat_init(&st); err = p9stat_read(rdir->buf + rdir->head, rdir->tail - rdir->head, &st, fid->clnt->proto_version); if (err) { P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); err = -EIO; p9stat_free(&st); goto unlock_and_exit; } reclen = st.size+2; over = filldir(dirent, st.name, strlen(st.name), filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st)); p9stat_free(&st); if (over) { err = 0; goto unlock_and_exit; } rdir->head += reclen; filp->f_pos += reclen; } } unlock_and_exit: mutex_unlock(&rdir->mutex); exit: return err; }
static int oprofilefs_readdir(struct file * filp, void * dirent, filldir_t filldir) { struct dentry *dentry = filp->f_dentry; struct dentry *cursor = filp->private_data; struct list_head *p, *q = &cursor->d_child; ino_t ino; int i = filp->f_pos; switch (i) { case 0: ino = dentry->d_inode->i_ino; if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) break; filp->f_pos++; i++; /* fallthrough */ case 1: if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) break; filp->f_pos++; i++; /* fallthrough */ default: spin_lock(&dcache_lock); if (filp->f_pos == 2) { list_del(q); list_add(q, &dentry->d_subdirs); } for (p=q->next; p != &dentry->d_subdirs; p=p->next) { struct dentry *next; next = list_entry(p, struct dentry, d_child); if (list_empty(&next->d_hash) || !next->d_inode) continue; spin_unlock(&dcache_lock); if (filldir(dirent, next->d_name.name, next->d_name.len, filp->f_pos, next->d_inode->i_ino, dt_type(next->d_inode)) < 0) return 0; spin_lock(&dcache_lock); /* next is still alive */ list_del(q); list_add(q, p); p = q; filp->f_pos++; } spin_unlock(&dcache_lock); } return 0; }