Whamcloud - gitweb
LU-4603 lmv: a few fixes about readdir of striped dir.
[fs/lustre-release.git] / lustre / llite / dir.c
index 0f811aa..22c4a42 100644 (file)
@@ -162,16 +162,18 @@ struct lu_dirent *ll_dir_entry_start(struct inode *dir,
                                     struct md_op_data *op_data,
                                     struct page **ppage)
 {
-       struct lu_dirent *entry;
+       struct lu_dirent *entry = NULL;
        struct md_callback cb_op;
        int rc;
+       ENTRY;
 
        LASSERT(*ppage == NULL);
        cb_op.md_blocking_ast = ll_md_blocking_ast;
+       op_data->op_cli_flags &= ~CLI_NEXT_ENTRY;
        rc = md_read_entry(ll_i2mdexp(dir), op_data, &cb_op, &entry, ppage);
        if (rc != 0)
                entry = ERR_PTR(rc);
-       return entry;
+       RETURN(entry);
 }
 
 struct lu_dirent *ll_dir_entry_next(struct inode *dir,
@@ -179,20 +181,25 @@ struct lu_dirent *ll_dir_entry_next(struct inode *dir,
                                    struct lu_dirent *ent,
                                    struct page **ppage)
 {
-       struct lu_dirent *entry;
+       struct lu_dirent *entry = NULL;
        struct md_callback cb_op;
        int rc;
+       ENTRY;
 
-       LASSERT(*ppage != NULL);
-       cb_op.md_blocking_ast = ll_md_blocking_ast;
        op_data->op_hash_offset = le64_to_cpu(ent->lde_hash);
+
+       /* release last page */
+       LASSERT(*ppage != NULL);
        kunmap(*ppage);
        page_cache_release(*ppage);
-       *ppage = NULL;
+
+       cb_op.md_blocking_ast = ll_md_blocking_ast;
+       op_data->op_cli_flags |= CLI_NEXT_ENTRY;
        rc = md_read_entry(ll_i2mdexp(dir), op_data, &cb_op, &entry, ppage);
        if (rc != 0)
                entry = ERR_PTR(rc);
-       return entry;
+
+       RETURN(entry);
 }
 
 #ifdef HAVE_DIR_CONTEXT
@@ -212,7 +219,6 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data,
        int                     done = 0;
        int                     rc = 0;
        __u64                   hash = MDS_DIR_END_OFF;
-       __u64                   last_hash = MDS_DIR_END_OFF;
        struct page             *page = NULL;
        ENTRY;
 
@@ -260,15 +266,15 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data,
 #endif
                if (done) {
                        if (op_data->op_hash_offset != MDS_DIR_END_OFF)
-                               op_data->op_hash_offset = last_hash;
+                               op_data->op_hash_offset = hash;
                        break;
-               } else {
-                       last_hash = hash;
                }
        }
 
        if (IS_ERR(ent))
                rc = PTR_ERR(ent);
+       else if (ent == NULL)
+               op_data->op_hash_offset = MDS_DIR_END_OFF;
 
        if (page != NULL) {
                kunmap(page);
@@ -315,8 +321,29 @@ static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir)
        if (IS_ERR(op_data))
                GOTO(out, rc = PTR_ERR(op_data));
 
+       if (unlikely(op_data->op_mea1 != NULL)) {
+               /* This is only needed for striped dir to fill ..,
+                * see lmv_read_entry */
+               if (filp->f_dentry->d_parent != NULL &&
+                   filp->f_dentry->d_parent->d_inode != NULL) {
+                       __u64 ibits = MDS_INODELOCK_UPDATE;
+                       struct inode *parent =
+                               filp->f_dentry->d_parent->d_inode;
+
+                       if (ll_have_md_lock(parent, &ibits, LCK_MINMODE))
+                               op_data->op_fid3 = *ll_inode2fid(parent);
+               }
+
+               /* If it can not find in cache, do lookup .. on the master
+                * object */
+               if (fid_is_zero(&op_data->op_fid3)) {
+                       rc = ll_dir_get_parent_fid(inode, &op_data->op_fid3);
+                       if (rc != 0)
+                               RETURN(rc);
+               }
+       }
        op_data->op_hash_offset = pos;
-       op_data->op_max_pages = sbi->ll_md_brw_size >> PAGE_CACHE_SHIFT;
+       op_data->op_max_pages = sbi->ll_md_brw_pages;
 #ifdef HAVE_DIR_CONTEXT
        ctx->pos = pos;
        rc = ll_dir_read(inode, op_data, ctx);
@@ -590,9 +617,8 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size,
                if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC))
                        lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm);
                break;
-       case LMV_MAGIC:
-       case LMV_MAGIC_MIGRATE:
-               if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC))
+       case LMV_MAGIC_V1:
+               if (LMV_MAGIC != cpu_to_le32(LMV_MAGIC))
                        lustre_swab_lmv_mds_md((union lmv_mds_md *)lmm);
                break;
        case LMV_USER_MAGIC:
@@ -1184,7 +1210,7 @@ lmv_out_free:
 
                rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, &request,
                                      valid);
-               if (rc != 0 && rc != -ENODATA)
+               if (rc != 0)
                        GOTO(finish_req, rc);
 
                /* Get default LMV EA */
@@ -1201,38 +1227,29 @@ lmv_out_free:
                        GOTO(finish_req, rc);
                }
 
-               /* Get normal LMV EA */
-               if (rc == -ENODATA) {
-                       stripe_count = 1;
-               } else {
-                       LASSERT(lmm != NULL);
-                       stripe_count = lmv_mds_md_stripe_count_get(lmm);
-               }
-
+               stripe_count = lmv_mds_md_stripe_count_get(lmm);
                lum_size = lmv_user_md_size(stripe_count, LMV_MAGIC_V1);
                OBD_ALLOC(tmp, lum_size);
                if (tmp == NULL)
                        GOTO(finish_req, rc = -ENOMEM);
 
-               tmp->lum_magic = LMV_MAGIC_V1;
-               tmp->lum_stripe_count = 1;
                mdt_index = ll_get_mdt_idx(inode);
                if (mdt_index < 0)
                        GOTO(out_tmp, rc = -ENOMEM);
+
+               tmp->lum_magic = LMV_MAGIC_V1;
+               tmp->lum_stripe_count = 0;
                tmp->lum_stripe_offset = mdt_index;
-               tmp->lum_objects[0].lum_mds = mdt_index;
-               tmp->lum_objects[0].lum_fid = *ll_inode2fid(inode);
-               for (i = 1; i < stripe_count; i++) {
-                       struct lmv_mds_md_v1 *lmm1;
-
-                       lmm1 = &lmm->lmv_md_v1;
-                       mdt_index = ll_get_mdt_idx_by_fid(sbi,
-                                                    &lmm1->lmv_stripe_fids[i]);
+               for (i = 0; i < stripe_count; i++) {
+                       struct lu_fid   *fid;
+
+                       fid = &lmm->lmv_md_v1.lmv_stripe_fids[i];
+                       mdt_index = ll_get_mdt_idx_by_fid(sbi, fid);
                        if (mdt_index < 0)
                                GOTO(out_tmp, rc = mdt_index);
 
                        tmp->lum_objects[i].lum_mds = mdt_index;
-                       tmp->lum_objects[i].lum_fid = lmm1->lmv_stripe_fids[i];
+                       tmp->lum_objects[i].lum_fid = *fid;
                        tmp->lum_stripe_count++;
                }