X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Flfsck%2Flfsck_striped_dir.c;h=854504d7602563348021973937e296d3e4484591;hb=3274e573957e8b8a067ae28c3f7d7788d40f310e;hp=5cffac7cc80b4cf6834018fa827bb370df3b9fdc;hpb=f7c354096a810df0a9333dace2f538d6dfbe486f;p=fs%2Flustre-release.git diff --git a/lustre/lfsck/lfsck_striped_dir.c b/lustre/lfsck/lfsck_striped_dir.c index 5cffac7..854504d 100644 --- a/lustre/lfsck/lfsck_striped_dir.c +++ b/lustre/lfsck/lfsck_striped_dir.c @@ -168,14 +168,13 @@ void lfsck_lmv_put(const struct lu_env *env, struct lfsck_lmv *llmv) LASSERT(llmv->ll_lslr != NULL); - OBD_FREE_LARGE(llmv->ll_lslr, - sizeof(*llmv->ll_lslr) * - llmv->ll_stripes_allocated); + OBD_FREE_PTR_ARRAY_LARGE(llmv->ll_lslr, + llmv->ll_stripes_allocated); OBD_FREE_PTR(llu); } else { if (llmv->ll_lslr != NULL) - OBD_FREE_LARGE(llmv->ll_lslr, - sizeof(*llmv->ll_lslr) * + OBD_FREE_PTR_ARRAY_LARGE( + llmv->ll_lslr, llmv->ll_stripes_allocated); OBD_FREE_PTR(llmv); @@ -510,7 +509,7 @@ static int lfsck_record_lmv(const struct lu_env *env, int new_stripes = index + 1; size_t old_size = sizeof(*lslr) * llmv->ll_stripes_allocated; - OBD_ALLOC_LARGE(new_lslr, sizeof(*new_lslr) * new_stripes); + OBD_ALLOC_PTR_ARRAY_LARGE(new_lslr, new_stripes); if (new_lslr == NULL) { llmv->ll_failed = 1; @@ -836,42 +835,92 @@ out: return rc > 0 ? 0 : rc; } -int lfsck_read_stripe_lmv(const struct lu_env *env, struct dt_object *obj, +/** + * Read LMV from bottom object, so it doesn't contain stripe FIDs. + * + * TODO: test migrating/foreign directory lfsck + * + * \param[in] env thread env + * \param[in] lfsck lfsck instance + * \param[in] obj dt object + * \param[out] lmv LMV data pointer + * + * \retval 0 on success + * \retval -ENODATA on no LMV, corrupt LMV, dir is dead or foreign + * -ev on other failures + */ +int lfsck_read_stripe_lmv(const struct lu_env *env, + struct lfsck_instance *lfsck, + struct dt_object *obj, struct lmv_mds_md_v1 *lmv) { 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; + /* use bottom object to avoid reading in shard FIDs */ + obj = lfsck_object_find_bottom(env, lfsck, lu_object_fid(&obj->do_lu)); + if (IS_ERR(obj)) + return PTR_ERR(obj); + dt_read_lock(env, obj, 0); buf->lb_buf = lmv; buf->lb_len = sizeof(*lmv); 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); + /* this may be 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 = -ENODATA; + } else { + rc = -ENODATA; } } dt_read_unlock(env, obj); - 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))) - return 0; + lfsck_object_put(env, obj); - return -ENODATA; + if (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 == sizeof(*lmv)) { + rc = 0; + lfsck_lmv_header_le_to_cpu(lmv, lmv); + /* if LMV is corrupt, return -ENODATA */ + if (lmv->lmv_magic != LMV_MAGIC_V1 && + lmv->lmv_magic != LMV_MAGIC_STRIPE) + rc = -ENODATA; + } else if (rc >= 0) { + /* LMV is corrupt */ + rc = -ENODATA; + } + + return rc; } /** @@ -921,24 +970,30 @@ int lfsck_shard_name_to_index(const struct lu_env *env, const char *name, return idx; } +static inline bool lfsck_name_hash_match(struct lmv_mds_md_v1 *lmv, + const char *name, int namelen) +{ + int idx; + + idx = lmv_name_to_stripe_index_old(lmv, name, namelen); + if (idx == lmv->lmv_master_mdt_index) + return true; + + if (!lmv_hash_is_layout_changing(lmv->lmv_hash_type)) + return false; + + idx = lmv_name_to_stripe_index(lmv, name, namelen); + return (idx == lmv->lmv_master_mdt_index); +} + bool lfsck_is_valid_slave_name_entry(const struct lu_env *env, struct lfsck_lmv *llmv, const char *name, int namelen) { - struct lmv_mds_md_v1 *lmv; - int idx; - if (llmv == NULL || !llmv->ll_lmv_slave || !llmv->ll_lmv_verified) return true; - lmv = &llmv->ll_lmv; - idx = lmv_name_to_stripe_index(lmv->lmv_hash_type, - lmv->lmv_stripe_count, - name, namelen); - if (unlikely(idx != lmv->lmv_master_mdt_index)) - return false; - - return true; + return lfsck_name_hash_match(&llmv->ll_lmv, name, namelen); } /** @@ -960,15 +1015,15 @@ bool lfsck_is_valid_slave_name_entry(const struct lu_env *env, * \retval negative error number on failure */ int lfsck_namespace_check_name(const struct lu_env *env, + struct lfsck_instance *lfsck, struct dt_object *parent, struct dt_object *child, const struct lu_name *cname) { - struct lmv_mds_md_v1 *lmv = &lfsck_env_info(env)->lti_lmv; - int idx; - int rc; + struct lmv_mds_md_v1 *lmv = &lfsck_env_info(env)->lti_lmv; + int rc; - rc = lfsck_read_stripe_lmv(env, parent, lmv); + rc = lfsck_read_stripe_lmv(env, lfsck, parent, lmv); if (rc != 0) RETURN(rc == -ENODATA ? 0 : rc); @@ -976,11 +1031,8 @@ int lfsck_namespace_check_name(const struct lu_env *env, if (!lfsck_is_valid_slave_lmv(lmv)) return 0; - idx = lmv_name_to_stripe_index(lmv->lmv_hash_type, - lmv->lmv_stripe_count, - cname->ln_name, - cname->ln_namelen); - if (unlikely(idx != lmv->lmv_master_mdt_index)) + if (!lfsck_name_hash_match(lmv, cname->ln_name, + cname->ln_namelen)) return 1; } else if (lfsck_shard_name_to_index(env, cname->ln_name, cname->ln_namelen, lfsck_object_type(child), @@ -1292,7 +1344,7 @@ int lfsck_namespace_notify_lmv_master_local(const struct lu_env *env, if (lfsck->li_bookmark_ram.lb_param & LPF_DRYRUN) RETURN(0); - rc = lfsck_read_stripe_lmv(env, obj, lmv4); + rc = lfsck_read_stripe_lmv(env, lfsck, obj, lmv4); if (rc != 0) RETURN(rc); @@ -1307,7 +1359,7 @@ int lfsck_namespace_notify_lmv_master_local(const struct lu_env *env, else count = lmv4->lmv_stripe_count; - OBD_ALLOC_LARGE(lslr, sizeof(struct lfsck_slave_lmv_rec) * count); + OBD_ALLOC_PTR_ARRAY_LARGE(lslr, count); if (lslr == NULL) { OBD_FREE_PTR(llu); @@ -1401,7 +1453,7 @@ static int lfsck_namespace_set_lmv_master(const struct lu_env *env, if (rc != 0) GOTO(log, rc); - rc = lfsck_read_stripe_lmv(env, obj, lmv3); + rc = lfsck_read_stripe_lmv(env, lfsck, obj, lmv3); if (rc == -ENODATA) { if (!(flags & LEF_SET_LMV_ALL)) GOTO(log, rc); @@ -1419,6 +1471,7 @@ static int lfsck_namespace_set_lmv_master(const struct lu_env *env, 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, @@ -1578,7 +1631,7 @@ int lfsck_namespace_scan_shard(const struct lu_env *env, __u16 type; ENTRY; - rc = lfsck_read_stripe_lmv(env, child, lmv); + rc = lfsck_read_stripe_lmv(env, lfsck, child, lmv); if (rc != 0) RETURN(rc == -ENODATA ? 1 : rc); @@ -1718,6 +1771,8 @@ int lfsck_namespace_verify_stripe_slave(const struct lu_env *env, 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, @@ -1732,7 +1787,7 @@ int lfsck_namespace_verify_stripe_slave(const struct lu_env *env, if (unlikely(!dt_try_as_dir(env, parent))) GOTO(out, rc = -ENOTDIR); - rc = lfsck_read_stripe_lmv(env, parent, plmv); + rc = lfsck_read_stripe_lmv(env, lfsck, parent, plmv); if (rc != 0) { int rc1; @@ -2138,11 +2193,6 @@ repair: if (repair_linkea) { struct lustre_handle lh = { 0 }; - rc1 = linkea_links_new(&ldata, &info->lti_big_buf, - cname, lfsck_dto2fid(dir)); - if (rc1 != 0) - goto next; - if (dir == NULL) { dir = lfsck_assistant_object_load(env, lfsck, lso); @@ -2157,6 +2207,11 @@ repair: } } + rc1 = linkea_links_new(&ldata, &info->lti_big_buf, + cname, lfsck_dto2fid(dir)); + if (rc1 != 0) + goto next; + rc1 = lfsck_ibits_lock(env, lfsck, obj, &lh, MDS_INODELOCK_UPDATE | MDS_INODELOCK_XATTR, LCK_EX); @@ -2174,17 +2229,22 @@ repair: } next: - CDEBUG(D_LFSCK, "%s: namespace LFSCK repair the shard " - "%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), - create ? "yes" : "no", create_repaired ? "yes" : "no", - rename ? "yes" : "no", rename_repaired ? "yes" : "no", - repair_linkea ? "yes" : "no", - linkea_repaired ? "yes" : "no", - repair_lmvea ? "yes" : "no", - lmvea_repaired ? "yes" : "no", rc1); + if (create || rename || repair_linkea || repair_lmvea) { + CDEBUG(D_LFSCK, "%s: namespace LFSCK repair the shard " + "%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(pfid), + create ? "yes" : "no", + create_repaired ? "yes" : "no", + rename ? "yes" : "no", + rename_repaired ? "yes" : "no", + repair_linkea ? "yes" : "no", + linkea_repaired ? "yes" : "no", + repair_lmvea ? "yes" : "no", + lmvea_repaired ? "yes" : "no", rc1); + } if (obj != NULL && !IS_ERR(obj)) { lfsck_object_put(env, obj); @@ -2363,7 +2423,7 @@ dangling: GOTO(out, rc = 0); } - rc = lfsck_read_stripe_lmv(env, obj, lmv); + rc = lfsck_read_stripe_lmv(env, lfsck, obj, lmv); if (unlikely(rc == -ENOENT)) /* It may happen when the remote object has been removed, * but the local MDT does not aware of that. */