struct dt_object *tobj;
struct lov_mds_md_v1 *lmm;
struct lov_ost_data_v1 *objs;
+ struct lustre_handle lh = { 0 };
int rc;
int i;
__u32 magic;
if (IS_ERR(tobj))
RETURN(PTR_ERR(tobj));
- dt_read_lock(env, tobj, 0);
if (dt_object_exists(tobj) == 0 ||
lfsck_is_dead_obj(tobj))
GOTO(out, rc = LLIT_UNMATCHED_PAIR);
}
if (lu_fid_eq(cfid, tfid)) {
- *lov_ea = *buf;
+ rc = lfsck_ibits_lock(env, com->lc_lfsck, tobj, &lh,
+ MDS_INODELOCK_UPDATE |
+ MDS_INODELOCK_LAYOUT |
+ MDS_INODELOCK_XATTR,
+ LCK_EX);
+ if (rc != 0)
+ GOTO(out, rc);
+
+ dt_read_lock(env, tobj, 0);
+
+ /* For local MDT-object, re-check existence
+ * after taken the lock. */
+ if (!dt_object_remote(tobj)) {
+ if (dt_object_exists(tobj) == 0 ||
+ lfsck_is_dead_obj(tobj)) {
+ rc = LLIT_UNMATCHED_PAIR;
+ } else {
+ *lov_ea = *buf;
+ rc = LLIT_MULTIPLE_REFERENCED;
+ }
+
+ GOTO(unlock, rc);
+ }
+
+ /* For migration case, the new MDT-object and old
+ * MDT-object may reference the same OST-object at
+ * some migration internal time.
+ *
+ * For remote MDT-object, the local MDT may not know
+ * whether it has been removed or not. Try checking
+ * for a non-existent xattr to check if this object
+ * has been been removed or not. */
+ rc = dt_xattr_get(env, tobj, &LU_BUF_NULL,
+ XATTR_NAME_DUMMY, BYPASS_CAPA);
+ if (unlikely(rc == -ENOENT || rc >= 0)) {
+ rc = LLIT_UNMATCHED_PAIR;
+ } else if (rc == -ENODATA) {
+ *lov_ea = *buf;
+ rc = LLIT_MULTIPLE_REFERENCED;
+ }
- GOTO(out, rc = LLIT_MULTIPLE_REFERENCED);
+ GOTO(unlock, rc);
}
}
GOTO(out, rc = LLIT_UNMATCHED_PAIR);
+unlock:
+ if (lustre_handle_is_used(&lh)) {
+ dt_read_unlock(env, tobj);
+ lfsck_ibits_unlock(&lh, LCK_EX);
+ }
+
out:
- dt_read_unlock(env, tobj);
lfsck_object_put(env, tobj);
return rc;