Whamcloud - gitweb
LU-4603 lmv: a few fixes about readdir of striped dir.
[fs/lustre-release.git] / lustre / mdc / mdc_request.c
index 862687e..aca1807 100644 (file)
@@ -374,7 +374,7 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
        /* Flush local XATTR locks to get rid of a possible cancel RPC */
        if (opcode == MDS_REINT && fid_is_sane(fid) &&
            exp->exp_connect_data.ocd_ibits_known & MDS_INODELOCK_XATTR) {
-               CFS_LIST_HEAD(cancels);
+               struct list_head cancels = LIST_HEAD_INIT(cancels);
                int count;
 
                /* Without that packing would fail */
@@ -879,7 +879,7 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
                req_fmt = &RQF_MDS_RELEASE_CLOSE;
 
                /* allocate a FID for volatile file */
-               rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data);
+               rc = mdc_fid_alloc(NULL, exp, &op_data->op_fid2, op_data);
                if (rc < 0) {
                        CERROR("%s: "DFID" failed to allocate FID: %d\n",
                               obd->obd_name, PFID(&op_data->op_fid1), rc);
@@ -1240,8 +1240,8 @@ static struct page *mdc_page_locate(struct address_space *mapping, __u64 *hash,
                                LASSERTF(*start <= *hash, "start = "LPX64
                                         ",end = "LPX64",hash = "LPX64"\n",
                                         *start, *end, *hash);
-                       CDEBUG(D_VFSTRACE, "page%lu [%llu %llu], hash"LPU64"\n",
-                              offset, *start, *end, *hash);
+                       CDEBUG(D_VFSTRACE, "offset %lx ["LPX64" "LPX64"],"
+                             " hash "LPX64"\n", offset, *start, *end, *hash);
                        if (*hash > *end) {
                                kunmap(page);
                                mdc_release_page(page, 0);
@@ -1503,7 +1503,7 @@ static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data,
 {
        struct lookup_intent    it = { .it_op = IT_READDIR };
        struct page             *page;
-       struct inode            *dir = NULL;
+       struct inode            *dir = op_data->op_data;
        struct address_space    *mapping;
        struct lu_dirpage       *dp;
        __u64                   start = 0;
@@ -1517,15 +1517,7 @@ static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data,
 
        *ppage = NULL;
 
-       if (op_data->op_mea1 != NULL) {
-               __u32 index = op_data->op_stripe_offset;
-
-               dir = op_data->op_mea1->lsm_md_oinfo[index].lmo_root;
-       } else {
-               dir = op_data->op_data;
-       }
        LASSERT(dir != NULL);
-
        mapping = dir->i_mapping;
 
        rc = mdc_intent_lock(exp, op_data, &it, &enq_req,
@@ -1650,10 +1642,13 @@ int mdc_read_entry(struct obd_export *exp, struct md_op_data *op_data,
        struct lu_dirpage       *dp;
        struct lu_dirent        *ent;
        int                     rc = 0;
+       __u32                   same_hash_count;
+       __u64                   hash_offset = op_data->op_hash_offset;
        ENTRY;
 
-       CDEBUG(D_INFO, DFID "offset = "LPU64"\n", PFID(&op_data->op_fid1),
-              op_data->op_hash_offset);
+       CDEBUG(D_INFO, DFID " offset = "LPU64", flags %#x\n",
+              PFID(&op_data->op_fid1), op_data->op_hash_offset,
+              op_data->op_cli_flags);
 
        *ppage = NULL;
        *entp = NULL;
@@ -1665,6 +1660,9 @@ int mdc_read_entry(struct obd_export *exp, struct md_op_data *op_data,
        if (rc != 0)
                RETURN(rc);
 
+       /* same_hash_count means how many entries with this
+        * hash value has been read */
+       same_hash_count = op_data->op_same_hash_offset + 1;
        dp = page_address(page);
        for (ent = lu_dirent_start(dp); ent != NULL;
             ent = lu_dirent_next(ent)) {
@@ -1672,16 +1670,33 @@ int mdc_read_entry(struct obd_export *exp, struct md_op_data *op_data,
                if (le16_to_cpu(ent->lde_namelen) == 0)
                        continue;
 
-               if (le64_to_cpu(ent->lde_hash) > op_data->op_hash_offset)
-                       break;
+               if (le64_to_cpu(ent->lde_hash) <
+                               op_data->op_hash_offset)
+                       continue;
+
+               if (unlikely(le64_to_cpu(ent->lde_hash) ==
+                               op_data->op_hash_offset)) {
+                       /* If it is not for next entry, which usually from
+                        * ll_dir_entry_start, return this entry. */
+                       if (!(op_data->op_cli_flags & CLI_NEXT_ENTRY))
+                               break;
+
+                       /* Keep reading until all of entries being read are
+                        * skipped. */
+                       if (same_hash_count > 0) {
+                               same_hash_count--;
+                               continue;
+                       }
+               }
+               break;
        }
 
        /* If it can not find entry in current page, try next page. */
        if (ent == NULL) {
-               __u64 orig_offset = op_data->op_hash_offset;
-
                if (le64_to_cpu(dp->ldp_hash_end) == MDS_DIR_END_OFF) {
-                       mdc_release_page(page, 0);
+                       op_data->op_same_hash_offset = 0;
+                       mdc_release_page(page,
+                                le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE);
                        RETURN(0);
                }
 
@@ -1696,13 +1711,19 @@ int mdc_read_entry(struct obd_export *exp, struct md_op_data *op_data,
                        dp = page_address(page);
                        ent = lu_dirent_start(dp);
                }
+       }
 
-               op_data->op_hash_offset = orig_offset;
+       /* If the next hash is the same as the current hash, increase
+        * the op_same_hash_offset to resolve the same hash conflict */
+       if (ent != NULL && op_data->op_cli_flags & CLI_NEXT_ENTRY) {
+               if (unlikely(le64_to_cpu(ent->lde_hash) == hash_offset))
+                       op_data->op_same_hash_offset++;
+               else
+                       op_data->op_same_hash_offset = 0;
        }
 
        *ppage = page;
        *entp = ent;
-
        RETURN(rc);
 }
 
@@ -2407,7 +2428,7 @@ static int mdc_quotactl(struct obd_device *unused, struct obd_export *exp,
 static int mdc_ioc_swap_layouts(struct obd_export *exp,
                                struct md_op_data *op_data)
 {
-       CFS_LIST_HEAD(cancels);
+       struct list_head cancels = LIST_HEAD_INIT(cancels);
        struct ptlrpc_request   *req;
        int                      rc, count;
        struct mdc_swap_layouts *msl, *payload;
@@ -3067,13 +3088,13 @@ static int mdc_import_event(struct obd_device *obd, struct obd_import *imp,
         RETURN(rc);
 }
 
-int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid,
-                  struct md_op_data *op_data)
+int mdc_fid_alloc(const struct lu_env *env, struct obd_export *exp,
+                 struct lu_fid *fid, struct md_op_data *op_data)
 {
-        struct client_obd *cli = &exp->exp_obd->u.cli;
-        struct lu_client_seq *seq = cli->cl_seq;
-        ENTRY;
-        RETURN(seq_client_alloc_fid(NULL, seq, fid));
+       struct client_obd *cli = &exp->exp_obd->u.cli;
+       struct lu_client_seq *seq = cli->cl_seq;
+       ENTRY;
+       RETURN(seq_client_alloc_fid(env, seq, fid));
 }
 
 struct obd_uuid *mdc_get_uuid(struct obd_export *exp) {