struct lfsck_thread_info *info = lfsck_env_info(env);
struct lu_buf *buf = &info->lti_buf;
int size = sizeof(*lmv) + sizeof(struct lu_fid) * 2;
+ struct lmv_foreign_md *lfm;
int rc;
dt_read_lock(env, obj, 0);
rc = dt_xattr_get(env, obj, buf, XATTR_NAME_LMV);
if (unlikely(rc == -ERANGE)) {
buf = &info->lti_big_buf;
- lu_buf_check_and_alloc(buf, size);
- rc = dt_xattr_get(env, obj, buf, XATTR_NAME_LMV);
/* For the in-migration directory, its LMV EA contains
* not only the LMV header, but also the FIDs for both
- * source and target. So the LMV EA size is larger. */
- if (rc == size) {
- rc = sizeof(*lmv);
- memcpy(lmv, buf->lb_buf, rc);
+ * source and target. So the LMV EA size is larger.
+ * Or may be this is a foreign LMV */
+ rc = dt_xattr_get(env, obj, &LU_BUF_NULL, XATTR_NAME_LMV);
+ if (rc > sizeof(*lmv)) {
+ int rc1;
+
+ lu_buf_check_and_alloc(buf, rc);
+ rc1 = dt_xattr_get(env, obj, buf, XATTR_NAME_LMV);
+ if (rc != rc1)
+ rc = -EINVAL;
+ } else {
+ rc = -EINVAL;
}
}
dt_read_unlock(env, obj);
+
+ if (rc > 0 && rc > offsetof(typeof(*lfm), lfm_value) &&
+ *((__u32 *)buf->lb_buf) == LMV_MAGIC_FOREIGN) {
+ __u32 value_len;
+
+ lfm = buf->lb_buf;
+ value_len = le32_to_cpu(lfm->lfm_length);
+ CDEBUG(D_INFO,
+ "foreign LMV EA, magic %x, len %u, type %x, flags %x, for dir "DFID"\n",
+ le32_to_cpu(lfm->lfm_magic), value_len,
+ le32_to_cpu(lfm->lfm_type), le32_to_cpu(lfm->lfm_flags),
+ PFID(lfsck_dto2fid(obj)));
+
+ if (rc != value_len + offsetof(typeof(*lfm), lfm_value))
+ CDEBUG(D_LFSCK,
+ "foreign LMV EA internal size %u does not match EA full size %d for dir "DFID"\n",
+ value_len, rc, PFID(lfsck_dto2fid(obj)));
+
+ /* no further usage/decode of foreign LMV outside */
+ return -ENODATA;
+ }
+
+ if (rc == size) {
+ rc = sizeof(*lmv);
+ memcpy(lmv, buf->lb_buf, rc);
+ }
if (rc != sizeof(*lmv))
return rc > 0 ? -EINVAL : rc;
lfsck_lmv_header_le_to_cpu(lmv, lmv);
if ((lmv->lmv_magic == LMV_MAGIC &&
!(lmv->lmv_hash_type & LMV_HASH_FLAG_MIGRATION)) ||
- (lmv->lmv_magic == LMV_MAGIC_STRIPE &&
- !(lmv->lmv_hash_type & LMV_HASH_FLAG_DEAD)))
+ lmv->lmv_magic == LMV_MAGIC_STRIPE)
return 0;
return -ENODATA;
lmv3->lmv_magic = LMV_MAGIC;
lmv3->lmv_master_mdt_index = pidx;
+ lmv3->lmv_layout_version++;
if (flags & LEF_SET_LMV_ALL) {
rc = lfsck_allow_regenerate_master_lmv(env, com, obj,
GOTO(out, rc);
}
+ CFS_FAIL_TIMEOUT(OBD_FAIL_LFSCK_ENGINE_DELAY, cfs_fail_val);
+
parent = lfsck_object_find_bottom(env, lfsck, pfid);
if (IS_ERR(parent)) {
rc = lfsck_namespace_trace_update(env, com, cfid,
"%d "DFID" of the striped directory "DFID" with "
"dangling %s/%s, rename %s/%s, llinkea %s/%s, "
"repair_lmvea %s/%s: rc = %d\n", lfsck_lfsck2name(lfsck),
- i, PFID(cfid), PFID(&lnr->lnr_fid),
+ i, PFID(cfid), PFID(pfid),
create ? "yes" : "no", create_repaired ? "yes" : "no",
rename ? "yes" : "no", rename_repaired ? "yes" : "no",
repair_linkea ? "yes" : "no",