Whamcloud - gitweb
LU-11213 dne: add new dir hash type "space"
[fs/lustre-release.git] / lustre / lmv / lmv_obd.c
index 5a7945b..8278969 100644 (file)
@@ -212,6 +212,7 @@ static int lmv_connect(const struct lu_env *env,
 
        lmv->connected = 0;
        lmv->conn_data = *data;
+       lmv->lmv_cache = localdata;
 
        lmv->lmv_tgts_kobj = kobject_create_and_add("target_obds",
                                                    &obd->obd_kset.kobj);
@@ -310,7 +311,7 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
         }
 
        rc = obd_connect(NULL, &mdc_exp, mdc_obd, &obd->obd_uuid,
-                        &lmv->conn_data, NULL);
+                        &lmv->conn_data, lmv->lmv_cache);
         if (rc) {
                 CERROR("target %s connect error %d\n", tgt->ltd_uuid.uuid, rc);
                 RETURN(rc);
@@ -659,6 +660,7 @@ repeat_fid2path:
        if (remote_gf != NULL) {
                struct getinfo_fid2path *ori_gf;
                char *ptr;
+               int len;
 
                ori_gf = (struct getinfo_fid2path *)karg;
                if (strlen(ori_gf->gf_u.gf_path) + 1 +
@@ -667,13 +669,12 @@ repeat_fid2path:
 
                ptr = ori_gf->gf_u.gf_path;
 
-               memmove(ptr + strlen(gf->gf_u.gf_path) + 1, ptr,
-                       strlen(ori_gf->gf_u.gf_path));
-
-               strncpy(ptr, gf->gf_u.gf_path,
-                       strlen(gf->gf_u.gf_path));
-               ptr += strlen(gf->gf_u.gf_path);
-               *ptr = '/';
+               len = strlen(gf->gf_u.gf_path);
+               /* move the current path to the right to release space
+                * for closer-to-root part */
+               memmove(ptr + len + 1, ptr, strlen(ori_gf->gf_u.gf_path));
+               memcpy(ptr, gf->gf_u.gf_path, len);
+               ptr[len] = '/';
        }
 
        CDEBUG(D_INFO, "%s: get path %s "DFID" rec: %llu ln: %u\n",
@@ -1175,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;
@@ -1373,8 +1382,11 @@ static int lmv_select_statfs_mdt(struct lmv_obd *lmv, __u32 flags)
                        break;
 
                if (LNET_NETTYP(LNET_NIDNET(lnet_id.nid)) != LOLND) {
+                       /* We dont need a full 64-bit modulus, just enough
+                        * to distribute the requests across MDTs evenly.
+                        */
                        lmv->lmv_statfs_start =
-                               lnet_id.nid % lmv->desc.ld_tgt_count;
+                               (u32)lnet_id.nid % lmv->desc.ld_tgt_count;
                        break;
                }
        }
@@ -1407,8 +1419,8 @@ static int lmv_statfs(const struct lu_env *env, struct obd_export *exp,
                rc = obd_statfs(env, lmv->tgts[idx]->ltd_exp, temp,
                                max_age, flags);
                if (rc) {
-                       CERROR("can't stat MDS #%d (%s), error %d\n", i,
-                              lmv->tgts[idx]->ltd_exp->exp_obd->obd_name,
+                       CERROR("%s: can't stat MDS #%d: rc = %d\n",
+                              lmv->tgts[idx]->ltd_exp->exp_obd->obd_name, i,
                               rc);
                        GOTO(out_free_temp, rc);
                }
@@ -1629,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(). */
@@ -2425,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);
@@ -2692,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);
        }
@@ -2981,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));
        }
@@ -3007,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;
+
+                       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++)
-                       iput(lsm->lsm_md_oinfo[i].lmo_root);
+               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);
 
@@ -3037,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)
@@ -3340,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;
@@ -3347,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),