+static int
+echo_md_dir_stripe_choose(const struct lu_env *env, struct echo_device *ed,
+ struct lu_object *obj, const char *name,
+ unsigned int namelen, __u64 id,
+ struct lu_object **new_parent)
+{
+ struct echo_thread_info *info = echo_env_info(env);
+ struct md_attr *ma = &info->eti_ma;
+ struct lmv_mds_md_v1 *lmv;
+ struct lu_device *ld = ed->ed_next;
+ unsigned int idx;
+ struct lu_name tmp_ln_name;
+ struct lu_fid stripe_fid;
+ struct lu_object *stripe_obj;
+ int rc;
+
+ LASSERT(obj != NULL);
+ LASSERT(S_ISDIR(obj->lo_header->loh_attr));
+
+ memset(ma, 0, sizeof(*ma));
+ echo_set_lmm_size(env, ld, ma);
+ ma->ma_need = MA_LMV;
+ rc = echo_attr_get_complex(env, lu2md(obj), ma);
+ if (rc) {
+ CERROR("Can not getattr child "DFID": rc = %d\n",
+ PFID(lu_object_fid(obj)), rc);
+ return rc;
+ }
+
+ if (!(ma->ma_valid & MA_LMV)) {
+ *new_parent = obj;
+ return 0;
+ }
+
+ lmv = (struct lmv_mds_md_v1 *)ma->ma_lmm;
+ if (le32_to_cpu(lmv->lmv_magic) != LMV_MAGIC_V1) {
+ rc = -EINVAL;
+ CERROR("Invalid mds md magic %x "DFID": rc = %d\n",
+ le32_to_cpu(lmv->lmv_magic), PFID(lu_object_fid(obj)),
+ rc);
+ return rc;
+ }
+
+ if (name) {
+ tmp_ln_name.ln_name = name;
+ tmp_ln_name.ln_namelen = namelen;
+ } else {
+ LASSERT(id != -1);
+ echo_md_build_name(&tmp_ln_name, info->eti_name, id);
+ }
+
+ idx = lmv_name_to_stripe_index(LMV_HASH_TYPE_FNV_1A_64,
+ le32_to_cpu(lmv->lmv_stripe_count),
+ tmp_ln_name.ln_name, tmp_ln_name.ln_namelen);
+
+ LASSERT(idx < le32_to_cpu(lmv->lmv_stripe_count));
+ fid_le_to_cpu(&stripe_fid, &lmv->lmv_stripe_fids[idx]);
+
+ stripe_obj = lu_object_find_at(env, &ed->ed_cl.cd_lu_dev, &stripe_fid,
+ NULL);
+ if (IS_ERR(stripe_obj)) {
+ rc = PTR_ERR(stripe_obj);
+ CERROR("Can not find the parent "DFID": rc = %d\n",
+ PFID(&stripe_fid), rc);
+ return rc;
+ }
+
+ *new_parent = lu_object_locate(stripe_obj->lo_header, ld->ld_type);
+ if (!*new_parent) {
+ lu_object_put(env, stripe_obj);
+ RETURN(-ENXIO);
+ }
+
+ return rc;
+}
+