Whamcloud - gitweb
LU-11213 dne: add new dir hash type "space"
[fs/lustre-release.git] / lustre / lmv / lmv_obd.c
index 2df8aa3..8278969 100644 (file)
@@ -1176,15 +1176,23 @@ static int lmv_placement_policy(struct obd_device *obd,
         * 1. See if the stripe offset is specified by lum.
         * 2. Then check if there is default stripe offset.
         * 3. Finally choose MDS by name hash if the parent
-        *    is striped directory. (see lmv_locate_tgt()). */
+        *    is striped directory. (see lmv_locate_tgt()).
+        *
+        * presently explicit MDT location is not supported
+        * for foreign dirs (as it can't be embedded into free
+        * format LMV, like with lum_stripe_offset), so we only
+        * rely on default stripe offset or then name hashing.
+        */
        if (op_data->op_cli_flags & CLI_SET_MEA && lum != NULL &&
+           le32_to_cpu(lum->lum_magic != LMV_MAGIC_FOREIGN) &&
            le32_to_cpu(lum->lum_stripe_offset) != (__u32)-1) {
                *mds = le32_to_cpu(lum->lum_stripe_offset);
        } else if (op_data->op_default_stripe_offset != (__u32)-1) {
                *mds = op_data->op_default_stripe_offset;
                op_data->op_mds = *mds;
                /* Correct the stripe offset in lum */
-               if (lum != NULL)
+               if (lum != NULL &&
+                   le32_to_cpu(lum->lum_magic != LMV_MAGIC_FOREIGN))
                        lum->lum_stripe_offset = cpu_to_le32(*mds);
        } else {
                *mds = op_data->op_mds;
@@ -1633,6 +1641,10 @@ lmv_locate_tgt(struct lmv_obd *lmv, struct md_op_data *op_data,
        struct lmv_oinfo *oinfo;
        struct lmv_tgt_desc *tgt;
 
+       /* foreign dir is not striped dir */
+       if (lsm && lsm->lsm_md_magic == LMV_MAGIC_FOREIGN)
+               return ERR_PTR(-ENODATA);
+
        /* During creating VOLATILE file, it should honor the mdt
         * index if the file under striped dir is being restored, see
         * ct_restore(). */
@@ -2429,6 +2441,11 @@ static struct lu_dirent *stripe_dirent_load(struct lmv_dir_ctxt *ctxt,
                }
 
                oinfo = &op_data->op_mea1->lsm_md_oinfo[stripe_index];
+               if (!oinfo->lmo_root) {
+                       rc = -ENOENT;
+                       break;
+               }
+
                tgt = lmv_get_target(ctxt->ldc_lmv, oinfo->lmo_mds, NULL);
                if (IS_ERR(tgt)) {
                        rc = PTR_ERR(tgt);
@@ -2696,6 +2713,10 @@ int lmv_read_page(struct obd_export *exp, struct md_op_data *op_data,
        ENTRY;
 
        if (unlikely(lsm != NULL)) {
+               /* foreign dir is not striped dir */
+               if (lsm->lsm_md_magic == LMV_MAGIC_FOREIGN)
+                       return -ENODATA;
+
                rc = lmv_striped_read_page(exp, op_data, cb_op, offset, ppage);
                RETURN(rc);
        }
@@ -2985,10 +3006,22 @@ static int lmv_unpack_md_v1(struct obd_export *exp, struct lmv_stripe_md *lsm,
        for (i = 0; i < stripe_count; i++) {
                fid_le_to_cpu(&lsm->lsm_md_oinfo[i].lmo_fid,
                              &lmm1->lmv_stripe_fids[i]);
+               /*
+                * set default value -1, so lmv_locate_tgt() knows this stripe
+                * target is not initialized.
+                */
+               lsm->lsm_md_oinfo[i].lmo_mds = (u32)-1;
+               if (!fid_is_sane(&lsm->lsm_md_oinfo[i].lmo_fid))
+                       continue;
+
                rc = lmv_fld_lookup(lmv, &lsm->lsm_md_oinfo[i].lmo_fid,
                                    &lsm->lsm_md_oinfo[i].lmo_mds);
-               if (rc != 0)
+               if (rc == -ENOENT)
+                       continue;
+
+               if (rc)
                        RETURN(rc);
+
                CDEBUG(D_INFO, "unpack fid #%d "DFID"\n", i,
                       PFID(&lsm->lsm_md_oinfo[i].lmo_fid));
        }
@@ -3011,15 +3044,46 @@ static int lmv_unpackmd(struct obd_export *exp, struct lmv_stripe_md **lsmp,
        /* Free memmd */
        if (lsm != NULL && lmm == NULL) {
                int i;
+               struct lmv_foreign_md *lfm = (struct lmv_foreign_md *)lsm;
+
+               if (lfm->lfm_magic == LMV_MAGIC_FOREIGN) {
+                       size_t lfm_size;
 
-               for (i = 0; i < lsm->lsm_md_stripe_count; i++)
-                       iput(lsm->lsm_md_oinfo[i].lmo_root);
+                       lfm_size = lfm->lfm_length + offsetof(typeof(*lfm),
+                                                             lfm_value[0]);
+                       OBD_FREE_LARGE(lfm, lfm_size);
+                       RETURN(0);
+               }
+
+               for (i = 0; i < lsm->lsm_md_stripe_count; i++) {
+                       if (lsm->lsm_md_oinfo[i].lmo_root)
+                               iput(lsm->lsm_md_oinfo[i].lmo_root);
+               }
                lsm_size = lmv_stripe_md_size(lsm->lsm_md_stripe_count);
                OBD_FREE(lsm, lsm_size);
                *lsmp = NULL;
                RETURN(0);
        }
 
+       /* foreign lmv case */
+       if (le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_FOREIGN) {
+               struct lmv_foreign_md *lfm = (struct lmv_foreign_md *)lsm;
+
+               if (lfm == NULL) {
+                       OBD_ALLOC_LARGE(lfm, lmm_size);
+                       if (lfm == NULL)
+                               RETURN(-ENOMEM);
+                       *lsmp = (struct lmv_stripe_md *)lfm;
+               }
+               lfm->lfm_magic = le32_to_cpu(lmm->lmv_foreign_md.lfm_magic);
+               lfm->lfm_length = le32_to_cpu(lmm->lmv_foreign_md.lfm_length);
+               lfm->lfm_type = le32_to_cpu(lmm->lmv_foreign_md.lfm_type);
+               lfm->lfm_flags = le32_to_cpu(lmm->lmv_foreign_md.lfm_flags);
+               memcpy(&lfm->lfm_value, &lmm->lmv_foreign_md.lfm_value,
+                      lfm->lfm_length);
+               RETURN(lmm_size);
+       }
+
        if (le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_STRIPE)
                RETURN(-EPERM);
 
@@ -3041,7 +3105,6 @@ static int lmv_unpackmd(struct obd_export *exp, struct lmv_stripe_md **lsmp,
                 */
                lsm_size = lmv_stripe_md_size(0);
 
-       lsm_size = lmv_stripe_md_size(lmv_mds_md_stripe_count_get(lmm));
        if (lsm == NULL) {
                OBD_ALLOC(lsm, lsm_size);
                if (lsm == NULL)
@@ -3344,6 +3407,10 @@ static int lmv_merge_attr(struct obd_export *exp,
        int rc;
        int i;
 
+       /* foreign dir is not striped dir */
+       if (lsm->lsm_md_magic == LMV_MAGIC_FOREIGN)
+               return 0;
+
        rc = lmv_revalidate_slaves(exp, lsm, cb_blocking, 0);
        if (rc < 0)
                return rc;
@@ -3351,6 +3418,9 @@ static int lmv_merge_attr(struct obd_export *exp,
        for (i = 0; i < lsm->lsm_md_stripe_count; i++) {
                struct inode *inode = lsm->lsm_md_oinfo[i].lmo_root;
 
+               if (!inode)
+                       continue;
+
                CDEBUG(D_INFO,
                       "" DFID " size %llu, blocks %llu nlink %u, atime %lld ctime %lld, mtime %lld.\n",
                       PFID(&lsm->lsm_md_oinfo[i].lmo_fid),