*
*/
struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data,
- __u64 offset)
+ __u64 offset, int *partial_readdir_rc)
{
- struct md_callback cb_op;
- struct page *page;
- int rc;
+ struct md_readdir_info mrinfo = {
+ .mr_blocking_ast = ll_md_blocking_ast };
+ struct page *page;
+ int rc;
- cb_op.md_blocking_ast = ll_md_blocking_ast;
- rc = md_read_page(ll_i2mdexp(dir), op_data, &cb_op, offset, &page);
+ rc = md_read_page(ll_i2mdexp(dir), op_data, &mrinfo, offset, &page);
if (rc != 0)
return ERR_PTR(rc);
+ if (partial_readdir_rc && mrinfo.mr_partial_readdir_rc)
+ *partial_readdir_rc = mrinfo.mr_partial_readdir_rc;
+
return page;
}
#ifdef HAVE_DIR_CONTEXT
int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data,
- struct dir_context *ctx)
+ struct dir_context *ctx, int *partial_readdir_rc)
{
#else
int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data,
- void *cookie, filldir_t filldir)
+ void *cookie, filldir_t filldir, int *partial_readdir_rc)
{
#endif
struct ll_sb_info *sbi = ll_i2sbi(inode);
RETURN(rc);
}
- page = ll_get_dir_page(inode, op_data, pos);
+ page = ll_get_dir_page(inode, op_data, pos, partial_readdir_rc);
while (rc == 0 && !done) {
struct lu_dirpage *dp;
le32_to_cpu(dp->ldp_flags) &
LDF_COLLIDE);
next = pos;
- page = ll_get_dir_page(inode, op_data, pos);
+ page = ll_get_dir_page(inode, op_data, pos,
+ partial_readdir_rc);
}
}
#ifdef HAVE_DIR_CONTEXT
struct md_op_data *op_data;
struct lu_fid pfid = { 0 };
ktime_t kstart = ktime_get();
+ /* result of possible partial readdir */
+ int partial_readdir_rc = 0;
__u64 pos;
int rc;
+
ENTRY;
- if (lfd != NULL)
- pos = lfd->lfd_pos;
- else
- pos = 0;
+ LASSERT(lfd != NULL);
+ pos = lfd->lfd_pos;
CDEBUG(D_VFSTRACE,
"VFS Op:inode="DFID"(%p) pos/size%lu/%llu 32bit_api %d\n",
#ifdef HAVE_DIR_CONTEXT
ctx->pos = pos;
- rc = ll_dir_read(inode, &pos, op_data, ctx);
+ rc = ll_dir_read(inode, &pos, op_data, ctx, &partial_readdir_rc);
pos = ctx->pos;
#else
- rc = ll_dir_read(inode, &pos, op_data, cookie, filldir);
+ rc = ll_dir_read(inode, &pos, op_data, cookie, filldir,
+ &partial_readdir_rc);
#endif
- if (lfd != NULL)
- lfd->lfd_pos = pos;
+ lfd->lfd_pos = pos;
+ if (!lfd->fd_partial_readdir_rc)
+ lfd->fd_partial_readdir_rc = partial_readdir_rc;
if (pos == MDS_DIR_END_OFF) {
if (api32)
RETURN(ll_file_release(inode, file));
}
+/* notify error if partially read striped directory */
+static int ll_dir_flush(struct file *file, fl_owner_t id)
+{
+ struct ll_file_data *lfd = file->private_data;
+ int rc = lfd->fd_partial_readdir_rc;
+
+ lfd->fd_partial_readdir_rc = 0;
+
+ return rc;
+}
+
const struct file_operations ll_dir_operations = {
.llseek = ll_dir_seek,
.open = ll_dir_open,
#endif
.unlocked_ioctl = ll_dir_ioctl,
.fsync = ll_fsync,
+ .flush = ll_dir_flush,
};