X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Flfsck%2Flfsck_striped_dir.c;h=a222e6e8c1220df7f62de6e517f976e1bda31758;hb=d6ce546eb7e250237141d3a11380f9d5389c50eb;hp=d9c7c3985fce4fe46dc441cbaebf998596c75693;hpb=5b3eef20c5a0e31d2cd9580f0cbaa0223783905a;p=fs%2Flustre-release.git diff --git a/lustre/lfsck/lfsck_striped_dir.c b/lustre/lfsck/lfsck_striped_dir.c index d9c7c39..a222e6e 100644 --- a/lustre/lfsck/lfsck_striped_dir.c +++ b/lustre/lfsck/lfsck_striped_dir.c @@ -20,7 +20,7 @@ * GPL HEADER END */ /* - * Copyright (c) 2014, Intel Corporation. + * Copyright (c) 2014, 2017, Intel Corporation. */ /* * lustre/lfsck/lfsck_striped_dir.c @@ -140,7 +140,6 @@ #define DEBUG_SUBSYSTEM S_LFSCK -#include #include #include #include @@ -148,7 +147,6 @@ #include #include #include -#include #include "lfsck_internal.h" @@ -196,7 +194,7 @@ void lfsck_lmv_put(const struct lu_env *env, struct lfsck_lmv *llmv) * \param[in] del_lmv true if need to drop the LMV EA * * \retval positive number if nothing to be done - * \retval zero for succeed + * \retval zero for success * \retval negative error number on failure */ static int lfsck_disable_master_lmv(const struct lu_env *env, @@ -295,7 +293,7 @@ static inline bool lfsck_is_valid_slave_lmv(struct lmv_mds_md_v1 *lmv) * striped directory to be handled and other information * * \retval positive number if nothing to be done - * \retval zero for succeed + * \retval zero for success * \retval negative error number on failure */ static int lfsck_remove_lmv(const struct lu_env *env, @@ -379,7 +377,7 @@ static int lfsck_remove_dirent(const struct lu_env *env, * \param[in] index the old shard's index in the striped directory * \param[in] flags the new shard's flags in the @lslr slot * - * \retval zero for succeed + * \retval zero for success * \retval negative error number on failure */ static int lfsck_replace_lmv(const struct lu_env *env, @@ -476,7 +474,7 @@ static int lfsck_replace_lmv(const struct lu_env *env, * we define the max depth can be called recursively * (LFSCK_REC_LMV_MAX_DEPTH) * - * \retval zero for succeed + * \retval zero for success * \retval "-ERANGE" for invalid @shard_idx * \retval "-EEXIST" for the required lslr slot has been * occupied by other shard @@ -838,26 +836,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; + 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); - rc = dt_xattr_get(env, obj, lfsck_buf_get(env, lmv, sizeof(*lmv)), - XATTR_NAME_LMV); + 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; + /* 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); + + 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; + } - 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; } /** @@ -946,6 +1010,7 @@ 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) @@ -954,7 +1019,7 @@ int lfsck_namespace_check_name(const struct lu_env *env, int idx; 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); @@ -1191,7 +1256,7 @@ out: * \param[in] index the MDT index on which the LFSCK instance to be notified * * \retval positive number if nothing to be done - * \retval zero for succeed + * \retval zero for success * \retval negative error number on failure */ static int lfsck_namespace_notify_lmv_remote(const struct lu_env *env, @@ -1258,7 +1323,7 @@ out: * \param[in] obj pointer to the striped directory to be rescanned * * \retval positive number if nothing to be done - * \retval zero for succeed + * \retval zero for success * \retval negative error number on failure */ int lfsck_namespace_notify_lmv_master_local(const struct lu_env *env, @@ -1278,7 +1343,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); @@ -1293,7 +1358,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_LARGE(lslr, sizeof(*lslr) * count); if (lslr == NULL) { OBD_FREE_PTR(llu); @@ -1320,6 +1385,7 @@ int lfsck_namespace_notify_lmv_master_local(const struct lu_env *env, lfsck_lmv_put(env, llmv); } else { ns->ln_striped_dirs_repaired++; + llmv->ll_counted = 1; spin_lock(&lfsck->li_lock); list_add_tail(&llu->llu_link, &lfsck->li_list_lmv); spin_unlock(&lfsck->li_lock); @@ -1353,7 +1419,7 @@ int lfsck_namespace_notify_lmv_master_local(const struct lu_env *env, * \param[in] flags to indicate which element(s) in the LMV EA will be set * * \retval positive number if nothing to be done - * \retval zero for succeed + * \retval zero for success * \retval negative error number on failure */ static int lfsck_namespace_set_lmv_master(const struct lu_env *env, @@ -1386,7 +1452,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); @@ -1404,6 +1470,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, @@ -1467,7 +1534,7 @@ log: * \param[in] name the name of the bad name hash * * \retval positive number if nothing to be done - * \retval zero for succeed + * \retval zero for success * \retval negative error number on failure */ int lfsck_namespace_repair_bad_name_hash(const struct lu_env *env, @@ -1493,6 +1560,12 @@ int lfsck_namespace_repair_bad_name_hash(const struct lu_env *env, if (IS_ERR(parent)) GOTO(log, rc = PTR_ERR(parent)); + if (unlikely(!dt_object_exists(parent))) + /* The parent object was previously accessed when verifying + * the slave LMV EA. If this condition is true it is because + * the striped directory is being removed. */ + GOTO(log, rc = 1); + *lmv2 = llmv->ll_lmv; lmv2->lmv_hash_type = LMV_HASH_TYPE_UNKNOWN | LMV_HASH_FLAG_BAD_TYPE; rc = lfsck_namespace_set_lmv_master(env, com, parent, lmv2, @@ -1557,7 +1630,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); @@ -1613,7 +1686,7 @@ int lfsck_namespace_scan_shard(const struct lu_env *env, ns->ln_flags |= LF_INCONSISTENT; rc = lfsck_namespace_repair_bad_name_hash(env, com, child, llmv, ent->lde_name); - if (rc >= 0) + if (rc == 0) ns->ln_name_hash_repaired++; } @@ -1659,7 +1732,8 @@ out: * \param[in] obj pointer to the object which LMV EA will be checked * \param[in] llmv pointer to buffer holding the slave LMV EA * - * \retval zero for succeed + * \retval positive number if nothing to be done + * \retval zero for success * \retval negative error number on failure */ int lfsck_namespace_verify_stripe_slave(const struct lu_env *env, @@ -1696,6 +1770,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, @@ -1704,10 +1780,13 @@ int lfsck_namespace_verify_stripe_slave(const struct lu_env *env, GOTO(out, rc); } + if (unlikely(!dt_object_exists(parent))) + GOTO(out, rc = 1); + 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; @@ -1801,7 +1880,7 @@ out: * \param[in] lnr pointer to the namespace request that contains the * striped directory or the shard * - * \retval zero for succeed + * \retval zero for success * \retval negative error number on failure */ int lfsck_namespace_striped_dir_rescan(const struct lu_env *env, @@ -1893,7 +1972,8 @@ int lfsck_namespace_striped_dir_rescan(const struct lu_env *env, RETURN(rc); ns->ln_striped_dirs_scanned++; - ns->ln_striped_dirs_repaired++; + if (!llmv->ll_counted) + ns->ln_striped_dirs_repaired++; } fld_range_set_mdt(range); @@ -1902,7 +1982,6 @@ int lfsck_namespace_striped_dir_rescan(const struct lu_env *env, const struct lu_fid *cfid = &lslr->lslr_fid; const struct lu_name *cname; struct linkea_data ldata = { NULL }; - int len; int rc1 = 0; bool repair_linkea = false; bool repair_lmvea = false; @@ -1917,12 +1996,13 @@ int lfsck_namespace_striped_dir_rescan(const struct lu_env *env, if (fid_is_zero(cfid)) continue; - len = snprintf(info->lti_tmpbuf, sizeof(info->lti_tmpbuf), - DFID":%u", PFID(cfid), i); - cname = lfsck_name_get_const(env, info->lti_tmpbuf, len); - memcpy(lnr->lnr_name, info->lti_tmpbuf, len); - - obj = lfsck_object_find_bottom_nowait(env, lfsck, cfid); + lnr->lnr_fid = *cfid; + lnr->lnr_namelen = snprintf(lnr->lnr_name, + lnr->lnr_size - sizeof(*lnr), + DFID":%u", PFID(cfid), i); + cname = lfsck_name_get_const(env, lnr->lnr_name, + lnr->lnr_namelen); + obj = lfsck_object_find_bottom(env, lfsck, cfid); if (IS_ERR(obj)) { if (dir == NULL) { dir = lfsck_assistant_object_load(env, lfsck, @@ -1974,7 +2054,7 @@ int lfsck_namespace_striped_dir_rescan(const struct lu_env *env, break; } - rc1 = lfsck_links_read(env, obj, &ldata); + rc1 = lfsck_links_read_with_rec(env, obj, &ldata); if (rc1 == -ENOENT) { create = true; goto repair; @@ -2112,7 +2192,8 @@ repair: if (repair_linkea) { struct lustre_handle lh = { 0 }; - rc1 = linkea_data_new(&ldata, &info->lti_big_buf); + rc1 = linkea_links_new(&ldata, &info->lti_big_buf, + cname, lfsck_dto2fid(dir)); if (rc1 != 0) goto next; @@ -2130,10 +2211,6 @@ repair: } } - rc1 = linkea_add_buf(&ldata, 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); @@ -2155,7 +2232,7 @@ next: "%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", @@ -2232,7 +2309,7 @@ out: * \param[in] lnr pointer to the namespace request that contains the * shard's name, parent object, parent's LMV, and ect. * - * \retval zero for succeed + * \retval zero for success * \retval negative error number on failure */ int lfsck_namespace_handle_striped_master(const struct lu_env *env, @@ -2289,7 +2366,7 @@ int lfsck_namespace_handle_striped_master(const struct lu_env *env, GOTO(out, rc); } - ltd = LTD_TGT(&lfsck->li_mdt_descs, shard_idx); + ltd = lfsck_ltd2tgt(&lfsck->li_mdt_descs, shard_idx); if (unlikely(ltd == NULL)) { CDEBUG(D_LFSCK, "%s: cannot talk with MDT %x which " "did not join the namespace LFSCK\n", @@ -2302,7 +2379,7 @@ int lfsck_namespace_handle_striped_master(const struct lu_env *env, dev = ltd->ltd_tgt; } - obj = lfsck_object_find_by_dev_nowait(env, dev, &lnr->lnr_fid); + obj = lfsck_object_find_by_dev(env, dev, &lnr->lnr_fid); if (IS_ERR(obj)) { if (lfsck_is_dead_obj(dir)) RETURN(0); @@ -2340,7 +2417,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. */