+static int mdt_restripe(struct mdt_thread_info *info,
+ struct mdt_object *parent,
+ const struct lu_name *lname,
+ const struct lu_fid *tfid,
+ struct md_op_spec *spec,
+ struct md_attr *ma)
+{
+ struct mdt_device *mdt = info->mti_mdt;
+ struct lu_fid *fid = &info->mti_tmp_fid2;
+ struct ldlm_enqueue_info *einfo = &info->mti_einfo[0];
+ struct lmv_mds_md_v1 *lmv;
+ struct mdt_object *child;
+ struct mdt_lock_handle *lhp;
+ struct mdt_lock_handle *lhc;
+ struct mdt_body *repbody;
+ int rc;
+
+ ENTRY;
+ if (!mdt->mdt_enable_dir_restripe)
+ RETURN(-EPERM);
+
+ rc = mdt_version_get_check_save(info, parent, 0);
+ if (rc)
+ RETURN(rc);
+
+ lhp = &info->mti_lh[MDT_LH_PARENT];
+ mdt_lock_pdo_init(lhp, LCK_PW, lname);
+ rc = mdt_reint_object_lock(info, parent, lhp, MDS_INODELOCK_UPDATE,
+ true);
+ if (rc)
+ RETURN(rc);
+
+ rc = mdt_stripe_get(info, parent, ma, XATTR_NAME_LMV);
+ if (rc)
+ GOTO(unlock_parent, rc);
+
+ if (ma->ma_valid & MA_LMV) {
+ /* don't allow restripe if parent dir layout is changing */
+ lmv = &ma->ma_lmv->lmv_md_v1;
+ if (!lmv_is_sane(lmv))
+ GOTO(unlock_parent, rc = -EBADF);
+
+ if (lmv_is_layout_changing(lmv))
+ GOTO(unlock_parent, rc = -EBUSY);
+ }
+
+ fid_zero(fid);
+ rc = mdt_lookup_version_check(info, parent, lname, fid, 1);
+ if (rc)
+ GOTO(unlock_parent, rc);
+
+ child = mdt_object_find(info->mti_env, mdt, fid);
+ if (IS_ERR(child))
+ GOTO(unlock_parent, rc = PTR_ERR(child));
+
+ if (!mdt_object_exists(child))
+ GOTO(out_child, rc = -ENOENT);
+
+ if (mdt_object_remote(child)) {
+ struct mdt_body *repbody;
+
+ repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
+ if (!repbody)
+ GOTO(out_child, rc = -EPROTO);
+
+ repbody->mbo_fid1 = *fid;
+ repbody->mbo_valid |= (OBD_MD_FLID | OBD_MD_MDS);
+ GOTO(out_child, rc = -EREMOTE);
+ }
+
+ /* lock object */
+ lhc = &info->mti_lh[MDT_LH_CHILD];
+ mdt_lock_reg_init(lhc, LCK_EX);
+
+ /* enqueue object remote LOOKUP lock */
+ if (mdt_object_remote(parent)) {
+ rc = mdt_remote_object_lock(info, parent, fid,
+ &lhc->mlh_rreg_lh,
+ lhc->mlh_rreg_mode,
+ MDS_INODELOCK_LOOKUP, false);
+ if (rc != ELDLM_OK)
+ GOTO(out_child, rc);
+ }
+
+ rc = mdt_reint_striped_lock(info, child, lhc, MDS_INODELOCK_FULL, einfo,
+ true);
+ if (rc)
+ GOTO(unlock_child, rc);
+
+ tgt_vbr_obj_set(info->mti_env, mdt_obj2dt(child));
+ rc = mdt_version_get_check_save(info, child, 1);
+ if (rc)
+ GOTO(unlock_child, rc);
+
+ spin_lock(&mdt->mdt_restriper.mdr_lock);
+ if (child->mot_restriping) {
+ /* race? */
+ spin_unlock(&mdt->mdt_restriper.mdr_lock);
+ GOTO(unlock_child, rc = -EBUSY);
+ }
+ child->mot_restriping = 1;
+ spin_unlock(&mdt->mdt_restriper.mdr_lock);
+
+ *fid = *tfid;
+ rc = mdt_restripe_internal(info, parent, child, lname, fid, spec, ma);
+ if (rc)
+ GOTO(restriping_clear, rc);
+
+ repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
+ if (!repbody)
+ GOTO(restriping_clear, rc = -EPROTO);
+
+ mdt_pack_attr2body(info, repbody, &ma->ma_attr, fid);
+ EXIT;
+
+restriping_clear:
+ child->mot_restriping = 0;
+unlock_child:
+ mdt_reint_striped_unlock(info, child, lhc, einfo, rc);
+out_child:
+ mdt_object_put(info->mti_env, child);
+unlock_parent:
+ mdt_object_unlock(info, parent, lhp, rc);
+
+ return rc;
+}
+