X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Flod%2Flod_object.c;h=f25a4903b0f242beb2b07454f5e646cd7e38e693;hb=c1d0a355a6;hp=e69ecf8f979d6d0dcb55d1521ccc642eec463ae8;hpb=ff5eb304fa371d879da38621fac3aec7d4548a5e;p=fs%2Flustre-release.git diff --git a/lustre/lod/lod_object.c b/lustre/lod/lod_object.c index e69ecf8..f25a490 100644 --- a/lustre/lod/lod_object.c +++ b/lustre/lod/lod_object.c @@ -1076,12 +1076,16 @@ static int lod_attr_get(const struct lu_env *env, } static inline void lod_adjust_stripe_info(struct lod_layout_component *comp, - struct lov_desc *desc) + struct lov_desc *desc, + int append_stripes) { if (comp->llc_pattern != LOV_PATTERN_MDT) { - if (!comp->llc_stripe_count) + if (append_stripes) { + comp->llc_stripe_count = append_stripes; + } else if (!comp->llc_stripe_count) { comp->llc_stripe_count = desc->ld_default_stripe_count; + } } if (comp->llc_stripe_size <= 0) comp->llc_stripe_size = desc->ld_default_stripe_size; @@ -1419,7 +1423,7 @@ static int lod_attr_set(const struct lu_env *env, buf->lb_len = info->lti_ea_store_size; lmm = info->lti_ea_store; magic = le32_to_cpu(lmm->lmm_magic); - if (magic == LOV_MAGIC_COMP_V1) { + if (magic == LOV_MAGIC_COMP_V1 || magic == LOV_MAGIC_SEL) { struct lov_comp_md_v1 *lcm = buf->lb_buf; struct lov_comp_md_entry_v1 *lcme = &lcm->lcm_entries[0]; @@ -1453,7 +1457,8 @@ static int lod_attr_set(const struct lu_env *env, buf->lb_buf = info->lti_ea_store; buf->lb_len = info->lti_ea_store_size; lcm = buf->lb_buf; - if (le32_to_cpu(lcm->lcm_magic) != LOV_MAGIC_COMP_V1) + if (le32_to_cpu(lcm->lcm_magic) != LOV_MAGIC_COMP_V1 && + le32_to_cpu(lcm->lcm_magic) != LOV_MAGIC_SEL) RETURN(-EINVAL); le32_add_cpu(&lcm->lcm_layout_gen, 1); @@ -1543,6 +1548,13 @@ static int lod_xattr_get(const struct lu_env *env, struct dt_object *dt, RETURN(rc = rc1 != 0 ? rc1 : rc); } + if ((rc > 0) && buf->lb_buf && strcmp(name, XATTR_NAME_LOV) == 0) { + struct lov_comp_md_v1 *lcm = buf->lb_buf; + + if (lcm->lcm_magic == cpu_to_le32(LOV_MAGIC_SEL)) + lcm->lcm_magic = cpu_to_le32(LOV_MAGIC_COMP_V1); + } + if (rc != -ENODATA || !S_ISDIR(dt->do_lu.lo_header->loh_attr & S_IFMT)) RETURN(rc); @@ -1559,7 +1571,7 @@ static int lod_xattr_get(const struct lu_env *env, struct dt_object *dt, if (is_root && strcmp(XATTR_NAME_LOV, name) == 0) { struct lov_user_md *lum = buf->lb_buf; - struct lov_desc *desc = &dev->lod_desc; + struct lov_desc *desc = &dev->lod_ost_descs.ltd_lov_desc; if (buf->lb_buf == NULL) { rc = sizeof(*lum); @@ -1933,74 +1945,73 @@ out: RETURN(rc); } -static int lod_prep_md_striped_create(const struct lu_env *env, - struct dt_object *dt, - struct lu_attr *attr, - const struct lmv_user_md_v1 *lum, - struct dt_object_format *dof, - struct thandle *th) +/** + * Allocate a striping on a predefined set of MDTs. + * + * Allocates new striping using the MDT index range provided by the data from + * the lum_obejcts contained in the lmv_user_md passed to this method if + * \a is_specific is true; or allocates new layout starting from MDT index in + * lo->ldo_dir_stripe_offset. The exact order of MDTs is not important and + * varies depending on MDT status. The number of stripes needed and stripe + * offset are taken from the object. If that number cannot be met, then the + * function returns an error and then it's the caller's responsibility to + * release the stripes allocated. All the internal structures are protected, + * but no concurrent allocation is allowed on the same objects. + * + * \param[in] env execution environment for this thread + * \param[in] lo LOD object + * \param[out] stripes striping created + * \param[out] mdt_indices MDT indices of striping created + * \param[in] is_specific true if the MDTs are provided by lum; false if + * only the starting MDT index is provided + * + * \retval positive stripes allocated, including the first stripe allocated + * outside + * \retval negative errno on failure + */ +static int lod_mdt_alloc_specific(const struct lu_env *env, + struct lod_object *lo, + struct dt_object **stripes, + __u32 *mdt_indices, bool is_specific) { struct lod_thread_info *info = lod_env_info(env); - struct lod_device *lod = lu2lod_dev(dt->do_lu.lo_dev); - struct lod_tgt_descs *ltd = &lod->lod_mdt_descs; - struct lod_object *lo = lod_dt_obj(dt); - struct dt_object **stripe; - __u32 stripe_count; - int *idx_array; - __u32 master_index; - int rc = 0; - __u32 i; - __u32 j; - bool is_specific = false; - ENTRY; - - /* The lum has been verifed in lod_verify_md_striping */ - LASSERT(le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC || - le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC_SPECIFIC); - - stripe_count = lo->ldo_dir_stripe_count; - - OBD_ALLOC(idx_array, sizeof(idx_array[0]) * stripe_count); - if (idx_array == NULL) - RETURN(-ENOMEM); - - OBD_ALLOC(stripe, sizeof(stripe[0]) * stripe_count); - if (stripe == NULL) - GOTO(out_free, rc = -ENOMEM); + struct lod_device *lod = lu2lod_dev(lo->ldo_obj.do_lu.lo_dev); + struct lu_tgt_descs *ltd = &lod->lod_mdt_descs; + struct lu_tgt_desc *tgt = NULL; + struct lu_object_conf conf = { .loc_flags = LOC_F_NEW }; + struct dt_device *tgt_dt = NULL; + struct lu_fid fid = { 0 }; + struct dt_object *dto; + u32 master_index; + u32 stripe_count = lo->ldo_dir_stripe_count; + int stripe_idx = 1; + int j; + int idx; + int rc; - /* Start index must be the master MDT */ master_index = lu_site2seq(lod2lu_dev(lod)->ld_site)->ss_node_id; - idx_array[0] = master_index; - if (le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC_SPECIFIC) { - is_specific = true; - for (i = 1; i < stripe_count; i++) - idx_array[i] = le32_to_cpu(lum->lum_objects[i].lum_mds); - } - - for (i = 0; i < stripe_count; i++) { - struct lod_tgt_desc *tgt = NULL; - struct dt_object *dto; - struct lu_fid fid = { 0 }; - int idx; - struct lu_object_conf conf = { 0 }; - struct dt_device *tgt_dt = NULL; + if (stripe_count > 1) + /* Set the start index for the 2nd stripe allocation */ + mdt_indices[1] = (mdt_indices[0] + 1) % + (lod->lod_remote_mdt_count + 1); + for (; stripe_idx < stripe_count; stripe_idx++) { /* Try to find next avaible target */ - idx = idx_array[i]; + idx = mdt_indices[stripe_idx]; for (j = 0; j < lod->lod_remote_mdt_count; j++, idx = (idx + 1) % (lod->lod_remote_mdt_count + 1)) { bool already_allocated = false; __u32 k; CDEBUG(D_INFO, "try idx %d, mdt cnt %u, allocated %u\n", - idx, lod->lod_remote_mdt_count + 1, i); + idx, lod->lod_remote_mdt_count + 1, stripe_idx); if (likely(!is_specific && !OBD_FAIL_CHECK(OBD_FAIL_LARGE_STRIPE))) { /* check whether the idx already exists * in current allocated array */ - for (k = 0; k < i; k++) { - if (idx_array[k] == idx) { + for (k = 0; k < stripe_idx; k++) { + if (mdt_indices[k] == idx) { already_allocated = true; break; } @@ -2021,29 +2032,25 @@ static int lod_prep_md_striped_create(const struct lu_env *env, rc = obd_fid_alloc(env, lod->lod_child_exp, &fid, NULL); if (rc < 0) - GOTO(out_put, rc); + continue; tgt_dt = lod->lod_child; break; } /* check the status of the OSP */ tgt = LTD_TGT(ltd, idx); - if (tgt == NULL) + if (!tgt) continue; tgt_dt = tgt->ltd_tgt; - rc = dt_statfs(env, tgt_dt, &info->lti_osfs, NULL); - if (rc) { + rc = dt_statfs(env, tgt_dt, &info->lti_osfs); + if (rc) /* this OSP doesn't feel well */ - rc = 0; continue; - } rc = obd_fid_alloc(env, tgt->ltd_exp, &fid, NULL); - if (rc < 0) { - rc = 0; + if (rc < 0) continue; - } break; } @@ -2051,15 +2058,16 @@ static int lod_prep_md_striped_create(const struct lu_env *env, /* Can not allocate more stripes */ if (j == lod->lod_remote_mdt_count) { CDEBUG(D_INFO, "%s: require stripes %u only get %d\n", - lod2obd(lod)->obd_name, stripe_count, i); + lod2obd(lod)->obd_name, stripe_count, + stripe_idx); break; } CDEBUG(D_INFO, "Get idx %d, for stripe %d "DFID"\n", - idx, i, PFID(&fid)); - idx_array[i] = idx; + idx, stripe_idx, PFID(&fid)); + mdt_indices[stripe_idx] = idx; /* Set the start index for next stripe allocation */ - if (!is_specific && i < stripe_count - 1) { + if (!is_specific && stripe_idx < stripe_count - 1) { /* * for large dir test, put all other slaves on one * remote MDT, otherwise we may save too many local @@ -2067,7 +2075,7 @@ static int lod_prep_md_striped_create(const struct lu_env *env, */ if (unlikely(OBD_FAIL_CHECK(OBD_FAIL_LARGE_STRIPE))) idx = master_index; - idx_array[i + 1] = (idx + 1) % + mdt_indices[stripe_idx + 1] = (idx + 1) % (lod->lod_remote_mdt_count + 1); } /* tgt_dt and fid must be ready after search avaible OSP @@ -2076,47 +2084,124 @@ static int lod_prep_md_striped_create(const struct lu_env *env, LASSERT(fid_is_sane(&fid)); /* fail a remote stripe FID allocation */ - if (i && OBD_FAIL_CHECK(OBD_FAIL_MDS_STRIPE_FID)) + if (stripe_idx && OBD_FAIL_CHECK(OBD_FAIL_MDS_STRIPE_FID)) continue; - conf.loc_flags = LOC_F_NEW; dto = dt_locate_at(env, tgt_dt, &fid, - dt->do_lu.lo_dev->ld_site->ls_top_dev, - &conf); - if (IS_ERR(dto)) - GOTO(out_put, rc = PTR_ERR(dto)); - stripe[i] = dto; + lo->ldo_obj.do_lu.lo_dev->ld_site->ls_top_dev, + &conf); + if (IS_ERR(dto)) { + rc = PTR_ERR(dto); + goto error; + } + + stripes[stripe_idx] = dto; + } + + return stripe_idx; + +error: + for (j = 1; j < stripe_idx; j++) { + LASSERT(stripes[j] != NULL); + dt_object_put(env, stripes[j]); + stripes[j] = NULL; + } + return rc; +} + +static int lod_prep_md_striped_create(const struct lu_env *env, + struct dt_object *dt, + struct lu_attr *attr, + const struct lmv_user_md_v1 *lum, + struct dt_object_format *dof, + struct thandle *th) +{ + struct lod_device *lod = lu2lod_dev(dt->do_lu.lo_dev); + struct lod_object *lo = lod_dt_obj(dt); + struct dt_object **stripes; + struct lu_object_conf conf = { .loc_flags = LOC_F_NEW }; + struct lu_fid fid = { 0 }; + __u32 stripe_count; + int i; + int rc = 0; + + ENTRY; + + /* The lum has been verifed in lod_verify_md_striping */ + LASSERT(le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC || + le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC_SPECIFIC); + + stripe_count = lo->ldo_dir_stripe_count; + + OBD_ALLOC(stripes, sizeof(stripes[0]) * stripe_count); + if (!stripes) + RETURN(-ENOMEM); + + /* Allocate the first stripe locally */ + rc = obd_fid_alloc(env, lod->lod_child_exp, &fid, NULL); + if (rc < 0) + GOTO(out, rc); + + stripes[0] = dt_locate_at(env, lod->lod_child, &fid, + dt->do_lu.lo_dev->ld_site->ls_top_dev, &conf); + if (IS_ERR(stripes[0])) + GOTO(out, rc = PTR_ERR(stripes[0])); + + if (lo->ldo_dir_stripe_offset == LMV_OFFSET_DEFAULT) { + lod_qos_statfs_update(env, lod, &lod->lod_mdt_descs); + rc = lod_mdt_alloc_qos(env, lo, stripes); + if (rc == -EAGAIN) + rc = lod_mdt_alloc_rr(env, lo, stripes); + } else { + int *idx_array; + bool is_specific = false; + + OBD_ALLOC(idx_array, sizeof(idx_array[0]) * stripe_count); + if (!idx_array) + GOTO(out, rc = -ENOMEM); + + if (le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC_SPECIFIC) { + is_specific = true; + for (i = 0; i < stripe_count; i++) + idx_array[i] = + le32_to_cpu(lum->lum_objects[i].lum_mds); + } + + /* stripe 0 is local */ + idx_array[0] = + lu_site2seq(lod2lu_dev(lod)->ld_site)->ss_node_id; + rc = lod_mdt_alloc_specific(env, lo, stripes, idx_array, + is_specific); + OBD_FREE(idx_array, sizeof(idx_array[0]) * stripe_count); } + if (rc < 0) + GOTO(out, rc); + + LASSERT(rc > 0); + lo->ldo_dir_striped = 1; - lo->ldo_stripe = stripe; - lo->ldo_dir_stripe_count = i; + lo->ldo_stripe = stripes; + lo->ldo_dir_stripe_count = rc; lo->ldo_dir_stripes_allocated = stripe_count; smp_mb(); lo->ldo_dir_stripe_loaded = 1; - if (lo->ldo_dir_stripe_count == 0) - GOTO(out_put, rc = -ENOSPC); - rc = lod_dir_declare_create_stripes(env, dt, attr, dof, th); - if (rc != 0) - GOTO(out_put, rc); + if (rc < 0) + lod_striping_free(env, lo); -out_put: - if (rc < 0) { - for (i = 0; i < stripe_count; i++) - if (stripe[i] != NULL) - dt_object_put(env, stripe[i]); - OBD_FREE(stripe, sizeof(stripe[0]) * stripe_count); - lo->ldo_dir_stripe_count = 0; - lo->ldo_dir_stripes_allocated = 0; - lo->ldo_stripe = NULL; - } + RETURN(rc); -out_free: - OBD_FREE(idx_array, sizeof(idx_array[0]) * stripe_count); +out: + LASSERT(rc < 0); + if (!IS_ERR_OR_NULL(stripes[0])) + dt_object_put(env, stripes[0]); + for (i = 1; i < stripe_count; i++) + LASSERT(!stripes[i]); + OBD_FREE(stripes, sizeof(stripes[0]) * stripe_count); - RETURN(rc); + return rc; } /** @@ -2673,7 +2758,7 @@ inline __u16 lod_comp_entry_stripe_count(struct lod_object *lo, else if (lod_comp_inited(entry)) return entry->llc_stripe_count; else if ((__u16)-1 == entry->llc_stripe_count) - return lod->lod_desc.ld_tgt_count; + return lod->lod_ost_count; else return lod_get_stripe_count(lod, lo, entry->llc_stripe_count, false); @@ -2744,14 +2829,14 @@ static int lod_declare_layout_add(const struct lu_env *env, { struct lod_thread_info *info = lod_env_info(env); struct lod_layout_component *comp_array, *lod_comp, *old_array; - struct lod_device *d = lu2lod_dev(dt->do_lu.lo_dev); + struct lod_device *d = lu2lod_dev(dt->do_lu.lo_dev); struct dt_object *next = dt_object_child(dt); - struct lov_desc *desc = &d->lod_desc; - struct lod_object *lo = lod_dt_obj(dt); - struct lov_user_md_v3 *v3; - struct lov_comp_md_v1 *comp_v1 = buf->lb_buf; - __u32 magic; - int i, rc, array_cnt, old_array_cnt; + struct lov_desc *desc = &d->lod_ost_descs.ltd_lov_desc; + struct lod_object *lo = lod_dt_obj(dt); + struct lov_user_md_v3 *v3; + struct lov_comp_md_v1 *comp_v1 = buf->lb_buf; + __u32 magic; + int i, rc, array_cnt, old_array_cnt; ENTRY; LASSERT(lo->ldo_is_composite); @@ -2796,7 +2881,7 @@ static int lod_declare_layout_add(const struct lu_env *env, lod_comp->llc_stripe_count = v1->lmm_stripe_count; lod_comp->llc_stripe_size = v1->lmm_stripe_size; - lod_adjust_stripe_info(lod_comp, desc); + lod_adjust_stripe_info(lod_comp, desc, 0); if (v1->lmm_magic == LOV_USER_MAGIC_V3) { v3 = (struct lov_user_md_v3 *) v1; @@ -2848,6 +2933,42 @@ error: } /** + * lod_last_non_stale_mirror() - Check if a mirror is the last non-stale mirror. + * @mirror_id: Mirror id to be checked. + * @lo: LOD object. + * + * This function checks if a mirror with specified @mirror_id is the last + * non-stale mirror of a LOD object @lo. + * + * Return: true or false. + */ +static inline +bool lod_last_non_stale_mirror(__u16 mirror_id, struct lod_object *lo) +{ + struct lod_layout_component *lod_comp; + bool has_stale_flag; + int i; + + for (i = 0; i < lo->ldo_mirror_count; i++) { + if (lo->ldo_mirrors[i].lme_id == mirror_id || + lo->ldo_mirrors[i].lme_stale) + continue; + + has_stale_flag = false; + lod_foreach_mirror_comp(lod_comp, lo, i) { + if (lod_comp->llc_flags & LCME_FL_STALE) { + has_stale_flag = true; + break; + } + } + if (!has_stale_flag) + return false; + } + + return true; +} + +/** * Declare component set. The xattr is name XATTR_LUSTRE_LOV.set.$field, * the '$field' can only be 'flags' now. The xattr value is binary * lov_comp_md_v1 which contains the component ID(s) and the value of @@ -2902,6 +3023,7 @@ static int lod_declare_layout_set(const struct lu_env *env, __u32 id = comp_v1->lcm_entries[i].lcme_id; __u32 flags = comp_v1->lcm_entries[i].lcme_flags; __u32 mirror_flag = flags & LCME_MIRROR_FLAGS; + __u16 mirror_id = mirror_id_of(id); bool neg = flags & LCME_FL_NEG; if (flags & LCME_FL_INIT) { @@ -2916,7 +3038,7 @@ static int lod_declare_layout_set(const struct lu_env *env, /* lfs only put one flag in each entry */ if ((flags && id != lod_comp->llc_id) || - (mirror_flag && mirror_id_of(id) != + (mirror_flag && mirror_id != mirror_id_of(lod_comp->llc_id))) continue; @@ -2926,8 +3048,13 @@ static int lod_declare_layout_set(const struct lu_env *env, if (mirror_flag) lod_comp->llc_flags &= ~mirror_flag; } else { - if (flags) + if (flags) { + if ((flags & LCME_FL_STALE) && + lod_last_non_stale_mirror(mirror_id, + lo)) + RETURN(-EUCLEAN); lod_comp->llc_flags |= flags; + } if (mirror_flag) { lod_comp->llc_flags |= mirror_flag; if (mirror_flag & LCME_FL_NOSYNC) @@ -3228,6 +3355,7 @@ static int lod_declare_layout_merge(const struct lu_env *env, struct lov_comp_md_v1 *cur_lcm; struct lov_comp_md_v1 *merge_lcm; struct lov_comp_md_entry_v1 *lcme; + struct lov_mds_md_v1 *lmm; size_t size = 0; size_t offset; __u16 cur_entry_count; @@ -3236,6 +3364,8 @@ static int lod_declare_layout_merge(const struct lu_env *env, __u16 mirror_id = 0; __u32 mirror_count; int rc, i; + bool merge_has_dom; + ENTRY; merge_lcm = mbuf->lb_buf; @@ -3264,6 +3394,7 @@ static int lod_declare_layout_merge(const struct lu_env *env, rc = lod_layout_convert(info); break; case LOV_MAGIC_COMP_V1: + case LOV_MAGIC_SEL: rc = 0; break; default: @@ -3322,6 +3453,13 @@ static int lod_declare_layout_merge(const struct lu_env *env, } mirror_id = mirror_id_of(id) + 1; + + /* check if first entry in new layout is DOM */ + lmm = (struct lov_mds_md_v1 *)((char *)merge_lcm + + merge_lcm->lcm_entries[0].lcme_offset); + merge_has_dom = lov_pattern(le32_to_cpu(lmm->lmm_pattern)) == + LOV_PATTERN_MDT; + for (i = 0; i < merge_entry_count; i++) { struct lov_comp_md_entry_v1 *merge_lcme; @@ -3330,6 +3468,8 @@ static int lod_declare_layout_merge(const struct lu_env *env, *lcme = *merge_lcme; lcme->lcme_offset = cpu_to_le32(offset); + if (merge_has_dom && i == 0) + lcme->lcme_flags |= cpu_to_le32(LCME_FL_STALE); id = pflr_id(mirror_id, i + 1); lcme->lcme_id = cpu_to_le32(id); @@ -3630,8 +3770,23 @@ static int lod_xattr_set_lov_on_dir(const struct lu_env *env, pool_name); break; case LOV_USER_MAGIC_COMP_V1: + { + struct lov_comp_md_v1 *lcm = (struct lov_comp_md_v1 *)lum; + struct lov_comp_md_entry_v1 *lcme; + int i, comp_cnt; + + comp_cnt = le16_to_cpu(lcm->lcm_entry_count); + for (i = 0; i < comp_cnt; i++) { + lcme = &lcm->lcm_entries[i]; + if (lcme->lcme_flags & cpu_to_le32(LCME_FL_EXTENSION)) { + lcm->lcm_magic = cpu_to_le32(LOV_MAGIC_SEL); + break; + } + } + is_del = false; break; + } default: CERROR("Invalid magic %x\n", lum->lmm_magic); RETURN(-EINVAL); @@ -3688,8 +3843,7 @@ static int lod_xattr_set_default_lmv_on_dir(const struct lu_env *env, if (LMVEA_DELETE_VALUES((le32_to_cpu(lum->lum_stripe_count)), le32_to_cpu(lum->lum_stripe_offset)) && - le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC && - !(le32_to_cpu(lum->lum_hash_type) & LMV_HASH_FLAG_SPACE)) { + le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC) { rc = lod_xattr_del_internal(env, dt, name, th); if (rc == -ENODATA) rc = 0; @@ -3793,7 +3947,7 @@ static int lod_xattr_set_lmv(const struct lu_env *env, struct dt_object *dt, /* if it's source stripe of migrating directory, don't create */ if (!((lo->ldo_dir_hash_type & LMV_HASH_FLAG_MIGRATION) && i >= lo->ldo_dir_migrate_offset)) { - dt_write_lock(env, dto, MOR_TGT_CHILD); + dt_write_lock(env, dto, DT_TGT_CHILD); rc = lod_sub_create(env, dto, attr, NULL, dof, th); if (rc != 0) { dt_write_unlock(env, dto); @@ -4119,6 +4273,112 @@ static int lod_generate_and_set_lovea(const struct lu_env *env, RETURN(rc); } +static __u32 lod_gen_component_id(struct lod_object *lo, + int mirror_id, int comp_idx); + +/** + * Repeat an existing component + * + * Creates a new layout by replicating an existing component. Uses striping + * policy from previous component as a template for the striping for the new + * new component. + * + * New component starts with zero length, will be extended (or removed) before + * returning layout to client. + * + * NB: Reallocates layout components array (lo->ldo_comp_entries), invalidating + * any pre-existing pointers to components. Handle with care. + * + * \param[in] env execution environment for this thread + * \param[in,out] lo object to update the layout of + * \param[in] index index of component to copy + * + * \retval 0 on success + * \retval negative errno on error + */ +static int lod_layout_repeat_comp(const struct lu_env *env, + struct lod_object *lo, int index) +{ + struct lod_layout_component *lod_comp; + struct lod_layout_component *new_comp = NULL; + struct lod_layout_component *comp_array; + int rc = 0, i, new_cnt = lo->ldo_comp_cnt + 1; + __u16 mirror_id; + int offset = 0; + ENTRY; + + lod_comp = &lo->ldo_comp_entries[index]; + LASSERT(lod_comp_inited(lod_comp) && lod_comp->llc_id != LCME_ID_INVAL); + + CDEBUG(D_LAYOUT, "repeating component %d\n", index); + + OBD_ALLOC(comp_array, sizeof(*comp_array) * new_cnt); + if (comp_array == NULL) + GOTO(out, rc = -ENOMEM); + + for (i = 0; i < lo->ldo_comp_cnt; i++) { + memcpy(&comp_array[i + offset], &lo->ldo_comp_entries[i], + sizeof(*comp_array)); + + /* Duplicate this component in to the next slot */ + if (i == index) { + new_comp = &comp_array[i + 1]; + memcpy(&comp_array[i + 1], &lo->ldo_comp_entries[i], + sizeof(*comp_array)); + /* We must now skip this new component when copying */ + offset = 1; + } + } + + /* Set up copied component */ + new_comp->llc_flags &= ~LCME_FL_INIT; + new_comp->llc_stripe = NULL; + new_comp->llc_stripes_allocated = 0; + new_comp->llc_stripe_offset = LOV_OFFSET_DEFAULT; + /* for uninstantiated components, layout gen stores default stripe + * offset */ + new_comp->llc_layout_gen = lod_comp->llc_stripe_offset; + /* This makes the repeated component zero-length, placed at the end of + * the preceding component */ + new_comp->llc_extent.e_start = new_comp->llc_extent.e_end; + new_comp->llc_timestamp = lod_comp->llc_timestamp; + new_comp->llc_pool = NULL; + + rc = lod_set_pool(&new_comp->llc_pool, lod_comp->llc_pool); + if (rc) + GOTO(out, rc); + + if (new_comp->llc_ostlist.op_array) { + __u32 *op_array = NULL; + + OBD_ALLOC(op_array, new_comp->llc_ostlist.op_size); + if (!op_array) + GOTO(out, rc = -ENOMEM); + memcpy(op_array, &new_comp->llc_ostlist.op_array, + new_comp->llc_ostlist.op_size); + new_comp->llc_ostlist.op_array = op_array; + } + + OBD_FREE(lo->ldo_comp_entries, + sizeof(*comp_array) * lo->ldo_comp_cnt); + lo->ldo_comp_entries = comp_array; + lo->ldo_comp_cnt = new_cnt; + + /* Generate an id for the new component */ + mirror_id = mirror_id_of(new_comp->llc_id); + new_comp->llc_id = LCME_ID_INVAL; + new_comp->llc_id = lod_gen_component_id(lo, mirror_id, index + 1); + if (new_comp->llc_id == LCME_ID_INVAL) + GOTO(out, rc = -ERANGE); + + EXIT; +out: + if (rc) + OBD_FREE(comp_array, sizeof(*comp_array) * new_cnt); + + return rc; +} + static int lod_layout_data_init(struct lod_thread_info *info, __u32 comp_cnt) { ENTRY; @@ -4173,6 +4433,9 @@ static int lod_layout_del_prep_layout(const struct lu_env *env, ENTRY; + LASSERT(lo->ldo_is_composite); + LASSERT(lo->ldo_comp_cnt > 0 && lo->ldo_comp_entries != NULL); + rc = lod_layout_data_init(info, lo->ldo_comp_cnt); if (rc) RETURN(rc); @@ -4282,9 +4545,7 @@ static int lod_layout_del(const struct lu_env *env, struct dt_object *dt, struct lu_attr *attr = &lod_env_info(env)->lti_attr; int rc; - LASSERT(lo->ldo_is_composite); LASSERT(lo->ldo_mirror_count == 1); - LASSERT(lo->ldo_comp_cnt > 0 && lo->ldo_comp_entries != NULL); rc = lod_layout_del_prep_layout(env, lo, th); if (rc < 0) @@ -4320,7 +4581,8 @@ out: static int lod_get_default_lov_striping(const struct lu_env *env, struct lod_object *lo, - struct lod_default_striping *lds); + struct lod_default_striping *lds, + struct dt_allocation_hint *ah); /** * Implementation of dt_object_operations::do_xattr_set. * @@ -4376,7 +4638,8 @@ static int lod_xattr_set(const struct lu_env *env, bool is_del; /* get existing striping config */ - rc = lod_get_default_lov_striping(env, lod_dt_obj(dt), lds); + rc = lod_get_default_lov_striping(env, lod_dt_obj(dt), lds, + NULL); if (rc) RETURN(rc); @@ -4507,7 +4770,13 @@ static int lod_declare_xattr_del(const struct lu_env *env, if (!S_ISDIR(dt->do_lu.lo_header->loh_attr)) RETURN(0); - /* set xattr to each stripes, if needed */ + /* NB: don't delete stripe LMV, because when we do this, normally we + * will remove stripes, besides, if directory LMV is corrupt, this will + * prevent deleting its LMV and fixing it (via LFSCK). + */ + if (!strcmp(name, XATTR_NAME_LMV)) + RETURN(0); + rc = lod_striping_load(env, lo); if (rc != 0) RETURN(rc); @@ -4553,6 +4822,9 @@ static int lod_xattr_del(const struct lu_env *env, struct dt_object *dt, if (rc != 0 || !S_ISDIR(dt->do_lu.lo_header->loh_attr)) RETURN(rc); + if (!strcmp(name, XATTR_NAME_LMV)) + RETURN(0); + if (lo->ldo_dir_stripe_count == 0) RETURN(0); @@ -4646,7 +4918,8 @@ skip: */ static int lod_get_default_lov_striping(const struct lu_env *env, struct lod_object *lo, - struct lod_default_striping *lds) + struct lod_default_striping *lds, + struct dt_allocation_hint *ah) { struct lod_thread_info *info = lod_env_info(env); struct lov_user_md_v1 *v1 = NULL; @@ -4677,17 +4950,21 @@ static int lod_get_default_lov_striping(const struct lu_env *env, lustre_swab_lov_user_md_v3(v3); lustre_swab_lov_user_md_objects(v3->lmm_objects, v3->lmm_stripe_count); - } else if (v1->lmm_magic == __swab32(LOV_USER_MAGIC_COMP_V1)) { + } else if (v1->lmm_magic == __swab32(LOV_USER_MAGIC_COMP_V1) || + v1->lmm_magic == __swab32(LOV_USER_MAGIC_SEL)) { comp_v1 = (struct lov_comp_md_v1 *)v1; lustre_swab_lov_comp_md_v1(comp_v1); } if (v1->lmm_magic != LOV_MAGIC_V3 && v1->lmm_magic != LOV_MAGIC_V1 && v1->lmm_magic != LOV_MAGIC_COMP_V1 && + v1->lmm_magic != LOV_MAGIC_SEL && v1->lmm_magic != LOV_USER_MAGIC_SPECIFIC) RETURN(-ENOTSUPP); - if (v1->lmm_magic == LOV_MAGIC_COMP_V1) { + if ((v1->lmm_magic == LOV_MAGIC_COMP_V1 || + v1->lmm_magic == LOV_MAGIC_SEL) && + !(ah && ah->dah_append_stripes)) { comp_v1 = (struct lov_comp_md_v1 *)v1; comp_cnt = comp_v1->lcm_entry_count; if (comp_cnt == 0) @@ -4738,19 +5015,24 @@ static int lod_get_default_lov_striping(const struct lu_env *env, RETURN(-EINVAL); } - CDEBUG(D_LAYOUT, DFID" stripe_count=%d stripe_size=%d " - "stripe_offset=%d\n", + CDEBUG(D_LAYOUT, DFID" stripe_count=%d stripe_size=%d stripe_offset=%d append_stripes=%d\n", PFID(lu_object_fid(&lo->ldo_obj.do_lu)), (int)v1->lmm_stripe_count, (int)v1->lmm_stripe_size, - (int)v1->lmm_stripe_offset); + (int)v1->lmm_stripe_offset, + ah ? ah->dah_append_stripes : 0); - lod_comp->llc_stripe_count = v1->lmm_stripe_count; + if (ah && ah->dah_append_stripes) + lod_comp->llc_stripe_count = ah->dah_append_stripes; + else + lod_comp->llc_stripe_count = v1->lmm_stripe_count; lod_comp->llc_stripe_size = v1->lmm_stripe_size; lod_comp->llc_stripe_offset = v1->lmm_stripe_offset; lod_comp->llc_pattern = v1->lmm_pattern; pool = NULL; - if (v1->lmm_magic == LOV_USER_MAGIC_V3) { + if (ah && ah->dah_append_pool && ah->dah_append_pool[0]) { + pool = ah->dah_append_pool; + } else if (v1->lmm_magic == LOV_USER_MAGIC_V3) { /* XXX: sanity check here */ v3 = (struct lov_user_md_v3 *) v1; if (v3->lmm_pool_name[0] != '\0') @@ -4832,7 +5114,7 @@ static int lod_get_default_striping(const struct lu_env *env, { int rc, rc1; - rc = lod_get_default_lov_striping(env, lo, lds); + rc = lod_get_default_lov_striping(env, lo, lds, NULL); rc1 = lod_get_default_lmv_striping(env, lo, lds); if (rc == 0 && rc1 < 0) rc = rc1; @@ -4855,10 +5137,11 @@ static void lod_striping_from_default(struct lod_object *lo, umode_t mode) { struct lod_device *d = lu2lod_dev(lo->ldo_obj.do_lu.lo_dev); - struct lov_desc *desc = &d->lod_desc; int i, rc; if (lds->lds_def_striping_set && S_ISREG(mode)) { + struct lov_desc *desc = &d->lod_ost_descs.ltd_lov_desc; + rc = lod_alloc_comp_entries(lo, lds->lds_def_mirror_cnt, lds->lds_def_comp_cnt); if (rc != 0) @@ -4915,7 +5198,7 @@ static void lod_striping_from_default(struct lod_object *lo, if (!lo->ldo_is_composite) continue; - lod_adjust_stripe_info(obj_comp, desc); + lod_adjust_stripe_info(obj_comp, desc, 0); } } else if (lds->lds_dir_def_striping_set && S_ISDIR(mode)) { if (lo->ldo_dir_stripe_count == 0) @@ -4925,8 +5208,7 @@ static void lod_striping_from_default(struct lod_object *lo, lo->ldo_dir_stripe_offset = lds->lds_dir_def_stripe_offset; if (lo->ldo_dir_hash_type == 0) - lo->ldo_dir_hash_type = lds->lds_dir_def_hash_type & - ~LMV_HASH_FLAG_SPACE; + lo->ldo_dir_hash_type = lds->lds_dir_def_hash_type; CDEBUG(D_LAYOUT, "striping from default dir: count:%hu, " "offset:%u, hash_type:%u\n", @@ -4935,7 +5217,8 @@ static void lod_striping_from_default(struct lod_object *lo, } } -static inline bool lod_need_inherit_more(struct lod_object *lo, bool from_root) +static inline bool lod_need_inherit_more(struct lod_object *lo, bool from_root, + char *append_pool) { struct lod_layout_component *lod_comp; @@ -4955,6 +5238,9 @@ static inline bool lod_need_inherit_more(struct lod_object *lo, bool from_root) lod_comp->llc_stripe_offset == LOV_OFFSET_DEFAULT)) return true; + if (append_pool && append_pool[0]) + return true; + return false; } @@ -4989,6 +5275,10 @@ static void lod_ah_init(const struct lu_env *env, LASSERT(child); + if (ah->dah_append_stripes == -1) + ah->dah_append_stripes = + d->lod_ost_descs.ltd_lov_desc.ld_tgt_count; + if (likely(parent)) { nextp = dt_object_child(parent); lp = lod_dt_obj(parent); @@ -5027,12 +5317,15 @@ static void lod_ah_init(const struct lu_env *env, * If parent object is not root directory, * then get default striping from parent object. */ - if (likely(lp != NULL) && !fid_is_root(lod_object_fid(lp))) + if (likely(lp != NULL)) { lod_get_default_striping(env, lp, lds); - /* set child default striping info, default value is NULL */ - if (lds->lds_def_striping_set || lds->lds_dir_def_striping_set) - lc->ldo_def_striping = lds; + /* inherit default striping except ROOT */ + if ((lds->lds_def_striping_set || + lds->lds_dir_def_striping_set) && + !fid_is_root(lod_object_fid(lp))) + lc->ldo_def_striping = lds; + } /* It should always honour the specified stripes */ /* Note: old client (< 2.7)might also do lfs mkdir, whose EA @@ -5090,7 +5383,7 @@ static void lod_ah_init(const struct lu_env *env, * Try from the parent first. */ if (likely(lp != NULL)) { - rc = lod_get_default_lov_striping(env, lp, lds); + rc = lod_get_default_lov_striping(env, lp, lds, ah); if (rc == 0) lod_striping_from_default(lc, lds, child_mode); } @@ -5118,8 +5411,10 @@ static void lod_ah_init(const struct lu_env *env, * - parent has plain(v1/v3) default layout, and some attributes * are not specified in the default layout; */ - if (d->lod_md_root != NULL && lod_need_inherit_more(lc, true)) { - rc = lod_get_default_lov_striping(env, d->lod_md_root, lds); + if (d->lod_md_root != NULL && + lod_need_inherit_more(lc, true, ah->dah_append_pool)) { + rc = lod_get_default_lov_striping(env, d->lod_md_root, lds, + ah); if (rc) goto out; if (lc->ldo_comp_cnt == 0) { @@ -5150,7 +5445,7 @@ out: * fs default striping may not be explicitly set, or historically set * in config log, use them. */ - if (lod_need_inherit_more(lc, false)) { + if (lod_need_inherit_more(lc, false, ah->dah_append_pool)) { if (lc->ldo_comp_cnt == 0) { rc = lod_alloc_comp_entries(lc, 0, 1); if (rc) @@ -5163,8 +5458,10 @@ out: } LASSERT(!lc->ldo_is_composite); lod_comp = &lc->ldo_comp_entries[0]; - desc = &d->lod_desc; - lod_adjust_stripe_info(lod_comp, desc); + desc = &d->lod_ost_descs.ltd_lov_desc; + lod_adjust_stripe_info(lod_comp, desc, ah->dah_append_stripes); + if (ah->dah_append_pool && ah->dah_append_pool[0]) + lod_obj_set_pool(lc, 0, ah->dah_append_pool); } EXIT; @@ -5367,7 +5664,7 @@ static inline int dt_object_qos_mkdir(const struct lu_env *env, return -EINVAL; lmu = info->lti_ea_store; - return !!(le32_to_cpu(lmu->lum_hash_type) & LMV_HASH_FLAG_SPACE); + return le32_to_cpu(lmu->lum_stripe_offset) == LMV_OFFSET_DEFAULT; } /** @@ -5433,32 +5730,31 @@ static int lod_declare_create(const struct lu_env *env, struct dt_object *dt, if (OBD_FAIL_CHECK(OBD_FAIL_MDS_STALE_DIR_LAYOUT)) GOTO(out, rc = -EREMOTE); - if (lo->ldo_dir_stripe_offset == -1) { + if (lo->ldo_dir_stripe_offset == LMV_OFFSET_DEFAULT) { + struct lod_default_striping *lds; + + lds = lo->ldo_def_striping; /* - * child and parent should be in the same MDT, - * but if parent has plain layout, it's allowed. + * child and parent should be on the same MDT, + * but if parent has default LMV, and the start + * MDT offset is -1, it's allowed. This check + * is not necessary after 2.12.22 because client + * follows this already, but old client may not. */ if (hint->dah_parent && - dt_object_remote(hint->dah_parent)) { - rc = dt_object_qos_mkdir(env, - lo->ldo_obj.do_lu.lo_dev, - hint->dah_parent); - if (rc <= 0) - GOTO(out, rc ? rc : -EREMOTE); - } + dt_object_remote(hint->dah_parent) && lds && + lds->lds_dir_def_stripe_offset != + LMV_OFFSET_DEFAULT) + GOTO(out, rc = -EREMOTE); } else if (lo->ldo_dir_stripe_offset != ss->ss_node_id) { struct lod_device *lod; - struct lod_tgt_descs *ltd; - struct lod_tgt_desc *tgt = NULL; + struct lu_tgt_desc *mdt = NULL; bool found_mdt = false; - int i; lod = lu2lod_dev(lo->ldo_obj.do_lu.lo_dev); - ltd = &lod->lod_mdt_descs; - cfs_foreach_bit(ltd->ltd_tgt_bitmap, i) { - tgt = LTD_TGT(ltd, i); - if (tgt->ltd_index == + lod_foreach_mdt(lod, mdt) { + if (mdt->ltd_index == lo->ldo_dir_stripe_offset) { found_mdt = true; break; @@ -5876,7 +6172,7 @@ static int lod_destroy(const struct lu_env *env, struct dt_object *dt, if (!OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LOST_SPEOBJ) || i == cfs_fail_val) { - dt_write_lock(env, stripe, MOR_TGT_CHILD); + dt_write_lock(env, stripe, DT_TGT_CHILD); rc = lod_sub_ref_del(env, stripe, th); dt_write_unlock(env, stripe); if (rc != 0) @@ -6221,7 +6517,7 @@ static bool lod_sel_osts_allowed(const struct lu_env *env, break; } - rc = dt_statfs(env, ost->ltd_ost, sfs, &info); + rc = dt_statfs_info(env, ost->ltd_tgt, sfs, &info); if (rc) { CDEBUG(D_LAYOUT, "statfs failed for ost %d, error %d\n", index, rc); @@ -6359,6 +6655,16 @@ static __u64 lod_extension_new_end(__u64 extension_size, __u64 extent_end, return new_end; } +/* As lod_sel_handler() could be re-entered for the same component several + * times, this is the data for the next call. Fields could be changed to + * component indexes when needed, (e.g. if there is no need to instantiate + * all the previous components up to the current position) to tell the caller + * where to start over from. */ +struct sel_data { + int sd_force; + int sd_repeat; +}; + /** * Process extent updates for a particular layout component * @@ -6381,8 +6687,15 @@ static __u64 lod_extension_new_end(__u64 extension_size, __u64 extent_end, * extension space component, move the start of the next component down * accordingly, then notify the caller to restart processing w/the new * layout. - * b. If there is no following component, we extend the current component - * regardless. + * b. If there is no following component, we try repeating the current + * component, creating a new component using the current one as a + * template (keeping its stripe properties but not specific striping), + * and try assigning striping for this component. If there is sufficient + * free space on the OSTs chosen for this component, it is instantiated + * and i/o continues there. + * + * If there is not sufficient space on the new OSTs, we remove this new + * component & extend the current component. * * Note further that uninited components followed by extension space can be zero * length meaning that we will try to extend them before initializing them, and @@ -6415,7 +6728,8 @@ static int lod_sel_handler(const struct lu_env *env, struct lod_object *lo, struct lu_extent *extent, struct thandle *th, int *max_comp, - int index, int write, int *force) + int index, int write, + struct sel_data *sd) { struct lod_device *d = lu2lod_dev(lo->ldo_obj.do_lu.lo_dev); struct lod_thread_info *info = lod_env_info(env); @@ -6424,6 +6738,7 @@ static int lod_sel_handler(const struct lu_env *env, struct lod_layout_component *next = NULL; __u64 extension_size; __u64 new_end = 0; + bool repeated; int change = 0; int rc = 0; ENTRY; @@ -6463,21 +6778,24 @@ static int lod_sel_handler(const struct lu_env *env, info->lti_count = 1; info->lti_comp_idx[0] = index - 1; rc = lod_declare_instantiate_components(env, lo, th); - /* ENOSPC tells us we can't use this component, so it's the - * same as if check_extension failed. But if there is no next, - * we have no fall back if we failed to stripe this, and we - * should return the error. */ - if (rc == -ENOSPC && next) + /* ENOSPC tells us we can't use this component. If there is + * a next or we are repeating, we either spill over (next) or + * extend the original comp (repeat). Otherwise, return the + * error to the user. */ + if (rc == -ENOSPC && (next || sd->sd_repeat)) rc = 1; if (rc < 0) RETURN(rc); } - if (*force == 0 && rc == 0) + if (sd->sd_force == 0 && rc == 0) rc = !lod_sel_osts_allowed(env, lo, index - 1, extension_size, extent, &lod_comp->llc_extent, write); - *force = 0; + + repeated = !!(sd->sd_repeat); + sd->sd_repeat = 0; + sd->sd_force = 0; /* Extend previous component */ if (rc == 0) { @@ -6509,8 +6827,29 @@ static int lod_sel_handler(const struct lu_env *env, change--; } lod_sel_adjust_extents(env, lo, *max_comp, index); + } else if (lod_comp_inited(prev)) { + /* If there is no next, and the previous component is + * INIT'ed, try repeating the previous component. */ + LASSERT(repeated == 0); + rc = lod_layout_repeat_comp(env, lo, index - 1); + if (rc < 0) + RETURN(rc); + change++; + /* The previous component is a repeated component. + * Record this so we don't keep trying to repeat it. */ + sd->sd_repeat = 1; } else { - *force = 1; + /* If the previous component is not INIT'ed, this may + * be a component we have just instantiated but failed + * to extend. Or even a repeated component we failed + * to prepare a striping for. Do not repeat but instead + * remove the repeated component & force the extention + * of the original one */ + sd->sd_force = 1; + if (repeated) { + prev->llc_id = LCME_ID_INVAL; + change--; + } } } @@ -6564,12 +6903,12 @@ static int lod_declare_update_extents(const struct lu_env *env, struct lod_thread_info *info = lod_env_info(env); struct lod_layout_component *lod_comp; bool layout_changed = false; + struct sel_data sd = { 0 }; int start_index; int i = 0; int max_comp = 0; int rc = 0, rc2; int change = 0; - int force = 0; ENTRY; /* This makes us work on the components of the chosen mirror */ @@ -6590,7 +6929,7 @@ static int lod_declare_update_extents(const struct lu_env *env, if (lod_comp->llc_flags & LCME_FL_EXTENSION) { layout_changed = true; rc = lod_sel_handler(env, lo, extent, th, &max_comp, - i, write, &force); + i, write, &sd); if (rc < 0) GOTO(out, rc); @@ -6600,10 +6939,9 @@ static int lod_declare_update_extents(const struct lu_env *env, } } - /* We may have removed components. If so, we must update the start & - * ends of all the mirrors after the current one, and the end of the - * current mirror. - */ + /* We may have added or removed components. If so, we must update the + * start & ends of all the mirrors after the current one, and the end + * of the current mirror. */ change = max_comp - 1 - lo->ldo_mirrors[pick].lme_end; if (change) { lo->ldo_mirrors[pick].lme_end += change; @@ -6786,15 +7124,21 @@ static inline int lod_comp_index(struct lod_object *lo, /** * Stale other mirrors by writing extent. */ -static void lod_stale_components(struct lod_object *lo, int primary, - struct lu_extent *extent) +static int lod_stale_components(const struct lu_env *env, struct lod_object *lo, + int primary, struct lu_extent *extent, + struct thandle *th) { struct lod_layout_component *pri_comp, *lod_comp; + struct lu_extent pri_extent; + int rc = 0; int i; + ENTRY; /* The writing extent decides which components in the primary * are affected... */ CDEBUG(D_LAYOUT, "primary mirror %d, "DEXT"\n", primary, PEXT(extent)); + +restart: lod_foreach_mirror_comp(pri_comp, lo, primary) { if (!lu_extent_is_overlapped(extent, &pri_comp->llc_extent)) continue; @@ -6803,15 +7147,27 @@ static void lod_stale_components(struct lod_object *lo, int primary, lod_comp_index(lo, pri_comp), PEXT(&pri_comp->llc_extent)); + pri_extent.e_start = pri_comp->llc_extent.e_start; + pri_extent.e_end = pri_comp->llc_extent.e_end; + for (i = 0; i < lo->ldo_mirror_count; i++) { if (i == primary) continue; + rc = lod_declare_update_extents(env, lo, &pri_extent, + th, i, 0); + /* if update_extents changed the layout, it may have + * reallocated the component array, so start over to + * avoid using stale pointers */ + if (rc == 1) + goto restart; + if (rc < 0) + RETURN(rc); /* ... and then stale other components that are * overlapping with primary components */ lod_foreach_mirror_comp(lod_comp, lo, i) { if (!lu_extent_is_overlapped( - &pri_comp->llc_extent, + &pri_extent, &lod_comp->llc_extent)) continue; @@ -6823,6 +7179,8 @@ static void lod_stale_components(struct lod_object *lo, int primary, } } } + + RETURN(rc); } /** @@ -6894,7 +7252,7 @@ static int lod_primary_pick(const struct lu_env *env, struct lod_object *lo, * This algo can be revised later after knowing the topology of * cluster. */ - lod_qos_statfs_update(env, lod); + lod_qos_statfs_update(env, lod, &lod->lod_ost_descs); for (i = 0; i < lo->ldo_mirror_count; i++) { bool ost_avail = true; int index = (i + seq) % lo->ldo_mirror_count; @@ -7058,6 +7416,7 @@ static int lod_declare_update_rdonly(const struct lu_env *env, if (mlc->mlc_opc == MD_LAYOUT_WRITE) { struct layout_intent *layout = mlc->mlc_intent; + int write = layout->li_opc == LAYOUT_INTENT_WRITE; int picked; extent = layout->li_extent; @@ -7072,6 +7431,12 @@ static int lod_declare_update_rdonly(const struct lu_env *env, PFID(lod_object_fid(lo)), lo->ldo_mirrors[picked].lme_id); + /* Update extents of primary before staling */ + rc = lod_declare_update_extents(env, lo, &extent, th, picked, + write); + if (rc < 0) + GOTO(out, rc); + if (layout->li_opc == LAYOUT_INTENT_TRUNC) { /** * trunc transfers [0, size) in the intent extent, we'd @@ -7082,7 +7447,9 @@ static int lod_declare_update_rdonly(const struct lu_env *env, } /* stale overlapping components from other mirrors */ - lod_stale_components(lo, picked, &extent); + rc = lod_stale_components(env, lo, picked, &extent, th); + if (rc < 0) + GOTO(out, rc); /* restore truncate intent extent */ if (layout->li_opc == LAYOUT_INTENT_TRUNC) @@ -7222,6 +7589,9 @@ static int lod_declare_update_write_pending(const struct lu_env *env, * 2. transfer layout version to all objects to close write era. */ if (mlc->mlc_opc == MD_LAYOUT_WRITE) { + struct layout_intent *layout = mlc->mlc_intent; + int write = layout->li_opc == LAYOUT_INTENT_WRITE; + LASSERT(mlc->mlc_intent != NULL); extent = mlc->mlc_intent->li_extent; @@ -7229,6 +7599,12 @@ static int lod_declare_update_write_pending(const struct lu_env *env, CDEBUG(D_LAYOUT, DFID": intent to write: "DEXT"\n", PFID(lod_object_fid(lo)), PEXT(&extent)); + /* 1. Update extents of primary before staling */ + rc = lod_declare_update_extents(env, lo, &extent, th, primary, + write); + if (rc < 0) + GOTO(out, rc); + if (mlc->mlc_intent->li_opc == LAYOUT_INTENT_TRUNC) { /** * trunc transfers [0, size) in the intent extent, we'd @@ -7237,10 +7613,13 @@ static int lod_declare_update_write_pending(const struct lu_env *env, extent.e_start = extent.e_end; extent.e_end = OBD_OBJECT_EOF; } - /* 1. stale overlapping components */ - lod_stale_components(lo, primary, &extent); - /* 2. find out the components need instantiating. + /* 2. stale overlapping components */ + rc = lod_stale_components(env, lo, primary, &extent, th); + if (rc < 0) + GOTO(out, rc); + + /* 3. find the components which need instantiating. * instantiate [0, mlc->mlc_intent->e_end) */ /* restore truncate intent extent */ @@ -7380,9 +7759,9 @@ static int lod_declare_update_sync_pending(const struct lu_env *env, GOTO(out, rc = -EINVAL); } - CDEBUG(D_LAYOUT, DFID": resynced %u/%zu components\n", + CDEBUG(D_LAYOUT, DFID": synced %u resynced %u/%zu components\n", PFID(lod_object_fid(lo)), - resync_components, mlc->mlc_resync_count); + sync_components, resync_components, mlc->mlc_resync_count); lo->ldo_flr_state = LCM_FL_RDONLY; lod_obj_inc_layout_gen(lo); @@ -7597,16 +7976,8 @@ static int lod_object_init(const struct lu_env *env, struct lu_object *lo, ENTRY; rc = lod_fld_lookup(env, lod, lu_object_fid(lo), &idx, &type); - if (rc != 0) { - /* Note: Sometimes, it will Return EAGAIN here, see - * ptrlpc_import_delay_req(), which might confuse - * lu_object_find_at() and make it wait there incorrectly. - * so we convert it to EIO here.*/ - if (rc == -EAGAIN) - rc = -EIO; - + if (rc != 0) RETURN(rc); - } if (type == LU_SEQ_RANGE_MDT && idx == lu_site2seq(lo->lo_dev->ld_site)->ss_node_id) {