{
struct obd_device *obd = exp->exp_obd;
struct lmv_obd *lmv = &obd->u.lmv;
+ struct obd_export *target_exp;
struct lmv_tgt_desc *src_tgt;
+ struct lmv_tgt_desc *tgt_tgt;
+ struct mdt_body *body;
int rc;
LASSERT(oldlen != 0);
if (rc)
return rc;
src_tgt = lmv_find_target(lmv, &op_data->op_fid3);
+ if (IS_ERR(src_tgt))
+ return PTR_ERR(src_tgt);
+
+ target_exp = src_tgt->ltd_exp;
} else {
if (op_data->op_mea1) {
struct lmv_stripe_md *lsm = op_data->op_mea1;
oldlen,
&op_data->op_fid1,
&op_data->op_mds);
- if (IS_ERR(src_tgt))
- return PTR_ERR(src_tgt);
} else {
src_tgt = lmv_find_target(lmv, &op_data->op_fid1);
- if (IS_ERR(src_tgt))
- return PTR_ERR(src_tgt);
-
- op_data->op_mds = src_tgt->ltd_idx;
}
+ if (IS_ERR(src_tgt))
+ return PTR_ERR(src_tgt);
if (op_data->op_mea2) {
struct lmv_stripe_md *lsm = op_data->op_mea2;
- const struct lmv_oinfo *oinfo;
- oinfo = lsm_name_to_stripe_info(lsm, new, newlen);
- if (IS_ERR(oinfo))
- return PTR_ERR(oinfo);
-
- op_data->op_fid2 = oinfo->lmo_fid;
+ tgt_tgt = lmv_locate_target_for_name(lmv, lsm, new,
+ newlen,
+ &op_data->op_fid2,
+ &op_data->op_mds);
+ } else {
+ tgt_tgt = lmv_find_target(lmv, &op_data->op_fid2);
}
+ if (IS_ERR(tgt_tgt))
+ return PTR_ERR(tgt_tgt);
+
+ target_exp = tgt_tgt->ltd_exp;
}
- if (IS_ERR(src_tgt))
- return PTR_ERR(src_tgt);
/*
* LOOKUP lock on src child (fid3) should also be cancelled for
return rc;
}
+retry_rename:
/*
* Cancel all the locks on tgt child (fid4).
*/
- if (fid_is_sane(&op_data->op_fid4))
+ if (fid_is_sane(&op_data->op_fid4)) {
+ struct lmv_tgt_desc *tgt;
+
rc = lmv_early_cancel(exp, NULL, op_data, src_tgt->ltd_idx,
LCK_EX, MDS_INODELOCK_FULL,
MF_MDC_CANCEL_FID4);
+ if (rc)
+ return rc;
- CDEBUG(D_INODE, DFID":m%d to "DFID"\n", PFID(&op_data->op_fid1),
- op_data->op_mds, PFID(&op_data->op_fid2));
+ tgt = lmv_find_target(lmv, &op_data->op_fid4);
+ if (IS_ERR(tgt))
+ return PTR_ERR(tgt);
- rc = md_rename(src_tgt->ltd_exp, op_data, old, oldlen,
- new, newlen, request);
- return rc;
+ /*
+ * Since the target child might be destroyed, and it might
+ * become orphan, and we can only check orphan on the local
+ * MDT right now, so we send rename request to the MDT where
+ * target child is located. If target child does not exist,
+ * then it will send the request to the target parent
+ */
+ target_exp = tgt->ltd_exp;
+ }
+
+ rc = md_rename(target_exp, op_data, old, oldlen, new, newlen, request);
+ if (rc && rc != -EREMOTE)
+ return rc;
+
+ body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY);
+ if (!body)
+ return -EPROTO;
+
+ /* Not cross-ref case, just get out of here. */
+ if (likely(!(body->mbo_valid & OBD_MD_MDS)))
+ return rc;
+
+ CDEBUG(D_INODE, "%s: try rename to another MDT for " DFID "\n",
+ exp->exp_obd->obd_name, PFID(&body->mbo_fid1));
+
+ op_data->op_fid4 = body->mbo_fid1;
+ ptlrpc_req_finished(*request);
+ *request = NULL;
+ goto retry_rename;
}
static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data,