static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir) { struct inode *dir = file->f_dentry->d_inode; loff_t pos = file->f_pos - IMPLICIT_NODES; struct page *page; struct logfs_disk_dentry *dd; int full; BUG_ON(pos < 0); for (;; pos++) { if (beyond_eof(dir, pos)) break; if (!logfs_exist_block(dir, pos)) { /* deleted dentry */ pos = dir_seek_data(dir, pos); continue; } page = read_cache_page(dir->i_mapping, pos, (filler_t *)logfs_readpage, NULL); if (IS_ERR(page)) return PTR_ERR(page); dd = kmap(page); BUG_ON(dd->namelen == 0); full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen), pos, be64_to_cpu(dd->ino), dd->type); kunmap(page); page_cache_release(page); if (full) break; } file->f_pos = pos + IMPLICIT_NODES; return 0; }
/* FIXME: readdir currently has it's own dir_walk code. I don't see a good * way to combine the two copies */ static int logfs_readdir(struct file *file, struct dir_context *ctx) { struct inode *dir = file_inode(file); loff_t pos; struct page *page; struct logfs_disk_dentry *dd; if (ctx->pos < 0) return -EINVAL; if (!dir_emit_dots(file, ctx)) return 0; pos = ctx->pos - 2; BUG_ON(pos < 0); for (;; pos++, ctx->pos++) { bool full; if (beyond_eof(dir, pos)) break; if (!logfs_exist_block(dir, pos)) { /* deleted dentry */ pos = dir_seek_data(dir, pos); continue; } page = read_cache_page(dir->i_mapping, pos, (filler_t *)logfs_readpage, NULL); if (IS_ERR(page)) return PTR_ERR(page); dd = kmap(page); BUG_ON(dd->namelen == 0); full = !dir_emit(ctx, (char *)dd->name, be16_to_cpu(dd->namelen), be64_to_cpu(dd->ino), dd->type); kunmap(page); page_cache_release(page); if (full) break; } return 0; }