X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Flod%2Flod_lov.c;h=6590d3c3982dbbc624fd5934b774db15f791622f;hp=e099a6c906a9b4e52562194ccc178f605c5aeb4d;hb=45222b2ef279d62ac3aab0e7babc55d77e3c93a2;hpb=47d6ce20cfd8b04f20f7fc7accc39b3902780900 diff --git a/lustre/lod/lod_lov.c b/lustre/lod/lod_lov.c index e099a6c..6590d3c 100644 --- a/lustre/lod/lod_lov.c +++ b/lustre/lod/lod_lov.c @@ -77,30 +77,23 @@ void lod_putref(struct lod_device *lod, struct lod_tgt_descs *ltd) if (ltd->ltd_refcount == 0 && ltd->ltd_death_row) { struct lod_tgt_desc *tgt_desc, *tmp; struct list_head kill; - unsigned int idx; CDEBUG(D_CONFIG, "destroying %d ltd desc\n", ltd->ltd_death_row); INIT_LIST_HEAD(&kill); - cfs_foreach_bit(ltd->ltd_tgt_bitmap, idx) { - tgt_desc = LTD_TGT(ltd, idx); + ltd_foreach_tgt_safe(ltd, tgt_desc, tmp) { LASSERT(tgt_desc); - if (!tgt_desc->ltd_reap) continue; list_add(&tgt_desc->ltd_kill, &kill); - LTD_TGT(ltd, idx) = NULL; /*FIXME: only support ost pool for now */ - if (ltd == &lod->lod_ost_descs) { - lod_ost_pool_remove(&lod->lod_pool_info, idx); - if (tgt_desc->ltd_active) - lod->lod_desc.ld_active_tgt_count--; - } - ltd->ltd_tgtnr--; - cfs_bitmap_clear(ltd->ltd_tgt_bitmap, idx); + if (ltd == &lod->lod_ost_descs) + lod_ost_pool_remove(<d->ltd_tgt_pool, + tgt_desc->ltd_index); + ltd_del_tgt(ltd, tgt_desc); ltd->ltd_death_row--; } mutex_unlock(<d->ltd_mutex); @@ -108,17 +101,8 @@ void lod_putref(struct lod_device *lod, struct lod_tgt_descs *ltd) list_for_each_entry_safe(tgt_desc, tmp, &kill, ltd_kill) { int rc; + list_del(&tgt_desc->ltd_kill); - if (ltd == &lod->lod_ost_descs) { - /* remove from QoS structures */ - rc = qos_del_tgt(lod, tgt_desc); - if (rc) - CERROR("%s: qos_del_tgt(%s) failed:" - "rc = %d\n", - lod2obd(lod)->obd_name, - obd_uuid2str(&tgt_desc->ltd_uuid), - rc); - } rc = obd_disconnect(tgt_desc->ltd_exp); if (rc) CERROR("%s: failed to disconnect %s: rc = %d\n", @@ -133,60 +117,6 @@ void lod_putref(struct lod_device *lod, struct lod_tgt_descs *ltd) } /** - * Expand size of target table. - * - * When the target table is full, we have to extend the table. To do so, - * we allocate new memory with some reserve, move data from the old table - * to the new one and release memory consumed by the old table. - * Notice we take ltd_rw_sem exclusively to ensure atomic switch. - * - * \param[in] ltd target table - * \param[in] newsize new size of the table - * - * \retval 0 on success - * \retval -ENOMEM if reallocation failed - */ -static int ltd_bitmap_resize(struct lod_tgt_descs *ltd, __u32 newsize) -{ - struct cfs_bitmap *new_bitmap, *old_bitmap = NULL; - int rc = 0; - ENTRY; - - /* grab write reference on the lod. Relocating the array requires - * exclusive access */ - - down_write(<d->ltd_rw_sem); - if (newsize <= ltd->ltd_tgts_size) - /* someone else has already resize the array */ - GOTO(out, rc = 0); - - /* allocate new bitmap */ - new_bitmap = CFS_ALLOCATE_BITMAP(newsize); - if (!new_bitmap) - GOTO(out, rc = -ENOMEM); - - if (ltd->ltd_tgts_size > 0) { - /* the bitmap already exists, we need - * to copy data from old one */ - cfs_bitmap_copy(new_bitmap, ltd->ltd_tgt_bitmap); - old_bitmap = ltd->ltd_tgt_bitmap; - } - - ltd->ltd_tgts_size = newsize; - ltd->ltd_tgt_bitmap = new_bitmap; - - if (old_bitmap) - CFS_FREE_BITMAP(old_bitmap); - - CDEBUG(D_CONFIG, "tgt size: %d\n", ltd->ltd_tgts_size); - - EXIT; -out: - up_write(<d->ltd_rw_sem); - return rc; -} - -/** * Connect LOD to a new OSP and add it to the target table. * * Connect to the OSP device passed, initialize all the internal @@ -219,7 +149,7 @@ int lod_add_device(const struct lu_env *env, struct lod_device *lod, struct lustre_cfg *lcfg; struct obd_uuid obd_uuid; bool for_ost; - bool lock = false; + bool connected = false; ENTRY; CDEBUG(D_CONFIG, "osp:%s idx:%d gen:%d\n", osp, index, gen); @@ -302,11 +232,12 @@ int lod_add_device(const struct lu_env *env, struct lod_device *lod, obd->obd_name, osp, rc); GOTO(out_cleanup, rc); } + connected = true; /* Allocate ost descriptor and fill it */ OBD_ALLOC_PTR(tgt_desc); if (!tgt_desc) - GOTO(out_conn, rc = -ENOMEM); + GOTO(out_cleanup, rc = -ENOMEM); tgt_desc->ltd_tgt = dt_dev; tgt_desc->ltd_exp = exp; @@ -315,73 +246,30 @@ int lod_add_device(const struct lu_env *env, struct lod_device *lod, tgt_desc->ltd_index = index; tgt_desc->ltd_active = active; - lod_getref(ltd); - if (index >= ltd->ltd_tgts_size) { - /* we have to increase the size of the lod_osts array */ - __u32 newsize; - - newsize = max(ltd->ltd_tgts_size, (__u32)2); - while (newsize < index + 1) - newsize = newsize << 1; - - /* lod_bitmap_resize() needs lod_rw_sem - * which we hold with th reference */ - lod_putref(lod, ltd); - - rc = ltd_bitmap_resize(ltd, newsize); - if (rc) - GOTO(out_desc, rc); - - lod_getref(ltd); - } - + down_write(<d->ltd_rw_sem); mutex_lock(<d->ltd_mutex); - lock = true; - if (cfs_bitmap_check(ltd->ltd_tgt_bitmap, index)) { - CERROR("%s: device %d is registered already\n", obd->obd_name, - index); - GOTO(out_mutex, rc = -EEXIST); - } + rc = ltd_add_tgt(ltd, tgt_desc); + if (rc) + GOTO(out_mutex, rc); - if (ltd->ltd_tgt_idx[index / TGT_PTRS_PER_BLOCK] == NULL) { - OBD_ALLOC_PTR(ltd->ltd_tgt_idx[index / TGT_PTRS_PER_BLOCK]); - if (ltd->ltd_tgt_idx[index / TGT_PTRS_PER_BLOCK] == NULL) { - CERROR("can't allocate index to add %s\n", - obd->obd_name); - GOTO(out_mutex, rc = -ENOMEM); - } - } + rc = lu_qos_add_tgt(<d->ltd_qos, tgt_desc); + if (rc) + GOTO(out_del_tgt, rc); if (for_ost) { - /* pool and qos are not supported for MDS stack yet */ - rc = lod_ost_pool_add(&lod->lod_pool_info, index, - lod->lod_osts_size); + /* pool is not supported for MDS stack yet */ + rc = lod_ost_pool_add(<d->ltd_tgt_pool, index, + ltd->ltd_tgts_size); if (rc) { CERROR("%s: can't set up pool, failed with %d\n", obd->obd_name, rc); - GOTO(out_mutex, rc); - } - - rc = qos_add_tgt(lod, tgt_desc); - if (rc) { - CERROR("%s: qos_add_tgt failed with %d\n", - obd->obd_name, rc); - GOTO(out_pool, rc); + GOTO(out_del_tgt, rc); } - - /* The new OST is now a full citizen */ - if (index >= lod->lod_desc.ld_tgt_count) - lod->lod_desc.ld_tgt_count = index + 1; - if (active) - lod->lod_desc.ld_active_tgt_count++; } - LTD_TGT(ltd, index) = tgt_desc; - cfs_bitmap_set(ltd->ltd_tgt_bitmap, index); - ltd->ltd_tgtnr++; mutex_unlock(<d->ltd_mutex); - lod_putref(lod, ltd); - lock = false; + up_write(<d->ltd_rw_sem); + if (lod->lod_recovery_completed) lu_dev->ld_ops->ldo_recovery_complete(env, lu_dev); @@ -405,29 +293,21 @@ out_fini_llog: lod_sub_fini_llog(env, tgt_desc->ltd_tgt, tgt_desc->ltd_recovery_thread); out_ltd: - lod_getref(ltd); + down_write(<d->ltd_rw_sem); mutex_lock(<d->ltd_mutex); - lock = true; if (!for_ost && LTD_TGT(ltd, index)->ltd_recovery_thread != NULL) { struct ptlrpc_thread *thread; thread = LTD_TGT(ltd, index)->ltd_recovery_thread; OBD_FREE_PTR(thread); } - ltd->ltd_tgtnr--; - cfs_bitmap_clear(ltd->ltd_tgt_bitmap, index); - LTD_TGT(ltd, index) = NULL; -out_pool: - lod_ost_pool_remove(&lod->lod_pool_info, index); + lod_ost_pool_remove(<d->ltd_tgt_pool, index); +out_del_tgt: + ltd_del_tgt(ltd, tgt_desc); out_mutex: - if (lock) { - mutex_unlock(<d->ltd_mutex); - lod_putref(lod, ltd); - } -out_desc: + mutex_unlock(<d->ltd_mutex); + up_write(<d->ltd_rw_sem); OBD_FREE_PTR(tgt_desc); -out_conn: - obd_disconnect(exp); out_cleanup: /* XXX OSP needs us to send down LCFG_CLEANUP because it uses * objects from the MDT stack. See LU-7184. */ @@ -437,6 +317,9 @@ out_cleanup: lcfg->lcfg_command = LCFG_CLEANUP; lu_dev->ld_ops->ldo_process_config(env, lu_dev, lcfg); + if (connected) + obd_disconnect(exp); + return rc; } @@ -450,27 +333,19 @@ out_cleanup: * \param[in] env execution environment for this thread * \param[in] lod LOD device the target table belongs to * \param[in] ltd target table - * \param[in] idx index of the target - * \param[in] for_ost type of the target: 0 - MDT, 1 - OST + * \param[in] tgt target */ static void __lod_del_device(const struct lu_env *env, struct lod_device *lod, - struct lod_tgt_descs *ltd, unsigned idx, - bool for_ost) + struct lod_tgt_descs *ltd, struct lu_tgt_desc *tgt) { - LASSERT(LTD_TGT(ltd, idx)); - - lfsck_del_target(env, lod->lod_child, LTD_TGT(ltd, idx)->ltd_tgt, - idx, for_ost); + lfsck_del_target(env, lod->lod_child, tgt->ltd_tgt, tgt->ltd_index, + !ltd->ltd_is_mdt); - if (!for_ost && LTD_TGT(ltd, idx)->ltd_recovery_thread != NULL) { - struct ptlrpc_thread *thread; - - thread = LTD_TGT(ltd, idx)->ltd_recovery_thread; - OBD_FREE_PTR(thread); - } + if (ltd->ltd_is_mdt && tgt->ltd_recovery_thread) + OBD_FREE_PTR(tgt->ltd_recovery_thread); - if (LTD_TGT(ltd, idx)->ltd_reap == 0) { - LTD_TGT(ltd, idx)->ltd_reap = 1; + if (!tgt->ltd_reap) { + tgt->ltd_reap = 1; ltd->ltd_death_row++; } } @@ -483,29 +358,26 @@ static void __lod_del_device(const struct lu_env *env, struct lod_device *lod, * \param[in] env execution environment for this thread * \param[in] lod LOD device the target table belongs to * \param[in] ltd target table - * \param[in] for_ost type of the target: MDT or OST * * \retval 0 always */ int lod_fini_tgt(const struct lu_env *env, struct lod_device *lod, - struct lod_tgt_descs *ltd, bool for_ost) + struct lod_tgt_descs *ltd) { - unsigned int idx; + struct lu_tgt_desc *tgt; if (ltd->ltd_tgts_size <= 0) return 0; + lod_getref(ltd); mutex_lock(<d->ltd_mutex); - cfs_foreach_bit(ltd->ltd_tgt_bitmap, idx) - __lod_del_device(env, lod, ltd, idx, for_ost); + ltd_foreach_tgt(ltd, tgt) + __lod_del_device(env, lod, ltd, tgt); mutex_unlock(<d->ltd_mutex); lod_putref(lod, ltd); - CFS_FREE_BITMAP(ltd->ltd_tgt_bitmap); - for (idx = 0; idx < TGT_PTRS; idx++) { - if (ltd->ltd_tgt_idx[idx]) - OBD_FREE_PTR(ltd->ltd_tgt_idx[idx]); - } - ltd->ltd_tgts_size = 0; + + lu_tgt_descs_fini(ltd); + return 0; } @@ -521,18 +393,19 @@ int lod_fini_tgt(const struct lu_env *env, struct lod_device *lod, * \param[in] osp name of OSP device to be removed * \param[in] idx index of the target * \param[in] gen generation number, not used currently - * \param[in] for_ost type of the target: 0 - MDT, 1 - OST * * \retval 0 if the device was scheduled for removal * \retval -EINVAL if no device was found */ int lod_del_device(const struct lu_env *env, struct lod_device *lod, - struct lod_tgt_descs *ltd, char *osp, unsigned idx, - unsigned gen, bool for_ost) + struct lod_tgt_descs *ltd, char *osp, unsigned int idx, + unsigned int gen) { struct obd_device *obd; - int rc = 0; - struct obd_uuid uuid; + struct lu_tgt_desc *tgt; + struct obd_uuid uuid; + int rc = 0; + ENTRY; CDEBUG(D_CONFIG, "osp:%s idx:%d gen:%d\n", osp, idx, gen); @@ -556,22 +429,21 @@ int lod_del_device(const struct lu_env *env, struct lod_device *lod, lod_getref(ltd); mutex_lock(<d->ltd_mutex); + tgt = LTD_TGT(ltd, idx); /* check that the index is allocated in the bitmap */ - if (!cfs_bitmap_check(ltd->ltd_tgt_bitmap, idx) || - !LTD_TGT(ltd, idx)) { + if (!cfs_bitmap_check(ltd->ltd_tgt_bitmap, idx) || !tgt) { CERROR("%s: device %d is not set up\n", obd->obd_name, idx); GOTO(out, rc = -EINVAL); } /* check that the UUID matches */ - if (!obd_uuid_equals(&uuid, <D_TGT(ltd, idx)->ltd_uuid)) { + if (!obd_uuid_equals(&uuid, &tgt->ltd_uuid)) { CERROR("%s: LOD target UUID %s at index %d does not match %s\n", - obd->obd_name, obd_uuid2str(<D_TGT(ltd,idx)->ltd_uuid), - idx, osp); + obd->obd_name, obd_uuid2str(&tgt->ltd_uuid), idx, osp); GOTO(out, rc = -EINVAL); } - __lod_del_device(env, lod, ltd, idx, for_ost); + __lod_del_device(env, lod, ltd, tgt); EXIT; out: mutex_unlock(<d->ltd_mutex); @@ -597,8 +469,6 @@ int lod_ea_store_resize(struct lod_thread_info *info, size_t size) { __u32 round = size_roundup_power2(size); - LASSERT(round <= - lov_mds_md_size(LOV_MAX_STRIPE_COUNT, LOV_MAGIC_V3)); if (info->lti_ea_store) { LASSERT(info->lti_ea_store_size); LASSERT(info->lti_ea_store_size < round); @@ -854,6 +724,11 @@ static int lod_gen_component_ea(const struct lu_env *env, objs = &v3->lmm_objects[0]; } stripe_count = lod_comp_entry_stripe_count(lo, lod_comp, is_dir); + if (stripe_count == 0 && !is_dir && + !(lod_comp->llc_pattern & LOV_PATTERN_F_RELEASED) && + !(lod_comp->llc_pattern & LOV_PATTERN_MDT)) + RETURN(-E2BIG); + if (!is_dir && lo->ldo_is_composite) lod_comp_shrink_stripe_count(lod_comp, &stripe_count); @@ -896,7 +771,8 @@ static int lod_gen_component_ea(const struct lu_env *env, PFID(&info->lti_fid), rc); RETURN(rc); } - } else if (lod_comp->llc_ostlist.op_array) { + } else if (lod_comp->llc_ostlist.op_array && + lod_comp->llc_ostlist.op_count) { /* user specified ost list */ ost_idx = lod_comp->llc_ostlist.op_array[i]; } @@ -936,7 +812,7 @@ int lod_generate_lovea(const struct lu_env *env, struct lod_object *lo, struct lov_comp_md_v1 *lcm; struct lod_layout_component *comp_entries; __u16 comp_cnt, mirror_cnt; - bool is_composite; + bool is_composite, is_foreign = false; int i, rc = 0, offset; ENTRY; @@ -951,9 +827,27 @@ int lod_generate_lovea(const struct lu_env *env, struct lod_object *lo, mirror_cnt = lo->ldo_mirror_count; comp_entries = lo->ldo_comp_entries; is_composite = lo->ldo_is_composite; + is_foreign = lo->ldo_is_foreign; } LASSERT(lmm_size != NULL); + + if (is_foreign) { + struct lov_foreign_md *lfm; + + lfm = (struct lov_foreign_md *)lmm; + memcpy(lfm, lo->ldo_foreign_lov, lo->ldo_foreign_lov_size); + /* need to store little-endian */ + if (cpu_to_le32(LOV_MAGIC_FOREIGN) != LOV_MAGIC_FOREIGN) { + __swab32s(&lfm->lfm_magic); + __swab32s(&lfm->lfm_length); + __swab32s(&lfm->lfm_type); + __swab32s(&lfm->lfm_flags); + } + *lmm_size = lo->ldo_foreign_lov_size; + RETURN(0); + } + LASSERT(comp_cnt != 0 && comp_entries != NULL); if (!is_composite) { @@ -985,6 +879,12 @@ int lod_generate_lovea(const struct lu_env *env, struct lod_object *lo, /* component could be un-inistantiated */ lcme->lcme_flags = cpu_to_le32(lod_comp->llc_flags); + if (lod_comp->llc_flags & LCME_FL_NOSYNC) + lcme->lcme_timestamp = + cpu_to_le64(lod_comp->llc_timestamp); + if (lod_comp->llc_flags & LCME_FL_EXTENSION && !is_dir) + lcm->lcm_magic = cpu_to_le32(LOV_MAGIC_SEL); + lcme->lcme_extent.e_start = cpu_to_le64(lod_comp->llc_extent.e_start); lcme->lcme_extent.e_end = @@ -1092,7 +992,7 @@ static int validate_lod_and_idx(struct lod_device *md, __u32 idx) return -EINVAL; } - if (unlikely(OST_TGT(md, idx)->ltd_ost == NULL)) { + if (unlikely(OST_TGT(md, idx)->ltd_tgt == NULL)) { CERROR("%s: invalid lod device, for idx: %d\n", lod2obd(md)->obd_name , idx); return -EINVAL; @@ -1121,15 +1021,16 @@ static int validate_lod_and_idx(struct lod_device *md, __u32 idx) int lod_initialize_objects(const struct lu_env *env, struct lod_object *lo, struct lov_ost_data_v1 *objs, int comp_idx) { - struct lod_layout_component *lod_comp; - struct lod_thread_info *info = lod_env_info(env); - struct lod_device *md; - struct lu_object *o, *n; - struct lu_device *nd; - struct dt_object **stripe; - int stripe_len; - int i, rc = 0; - __u32 idx; + struct lod_layout_component *lod_comp; + struct lod_thread_info *info = lod_env_info(env); + struct lod_device *md; + struct lu_object *o, *n; + struct lu_device *nd; + struct dt_object **stripe = NULL; + __u32 *ost_indices = NULL; + int stripe_len; + int i, rc = 0; + __u32 idx; ENTRY; LASSERT(lo != NULL); @@ -1146,6 +1047,9 @@ int lod_initialize_objects(const struct lu_env *env, struct lod_object *lo, OBD_ALLOC(stripe, sizeof(stripe[0]) * stripe_len); if (stripe == NULL) RETURN(-ENOMEM); + OBD_ALLOC(ost_indices, sizeof(*ost_indices) * stripe_len); + if (!ost_indices) + GOTO(out, rc = -ENOMEM); for (i = 0; i < lod_comp->llc_stripe_count; i++) { if (unlikely(lovea_slot_is_dummy(&objs[i]))) @@ -1166,7 +1070,7 @@ int lod_initialize_objects(const struct lu_env *env, struct lod_object *lo, GOTO(out, rc); } - nd = &OST_TGT(md,idx)->ltd_ost->dd_lu_dev; + nd = &OST_TGT(md, idx)->ltd_tgt->dd_lu_dev; lod_putref(md, &md->lod_ost_descs); /* In the function below, .hs_keycmp resolves to @@ -1180,6 +1084,7 @@ int lod_initialize_objects(const struct lu_env *env, struct lod_object *lo, LASSERT(n); stripe[i] = container_of(n, struct dt_object, do_lu); + ost_indices[i] = idx; } out: @@ -1190,8 +1095,12 @@ out: OBD_FREE(stripe, sizeof(stripe[0]) * stripe_len); lod_comp->llc_stripe_count = 0; + if (ost_indices) + OBD_FREE(ost_indices, + sizeof(*ost_indices) * stripe_len); } else { lod_comp->llc_stripe = stripe; + lod_comp->llc_ost_indices = ost_indices; lod_comp->llc_stripes_allocated = stripe_len; } @@ -1214,29 +1123,35 @@ out: int lod_parse_striping(const struct lu_env *env, struct lod_object *lo, const struct lu_buf *buf) { - struct lov_mds_md_v1 *lmm; - struct lov_comp_md_v1 *comp_v1 = NULL; - struct lov_ost_data_v1 *objs; - __u32 magic, pattern; - int i, j, rc = 0; - __u16 comp_cnt; - __u16 mirror_cnt = 0; + struct lov_mds_md_v1 *lmm; + struct lov_comp_md_v1 *comp_v1 = NULL; + struct lov_foreign_md *foreign = NULL; + struct lov_ost_data_v1 *objs; + __u32 magic, pattern; + __u16 mirror_cnt = 0; + __u16 comp_cnt; + int i, rc; ENTRY; LASSERT(buf); LASSERT(buf->lb_buf); LASSERT(buf->lb_len); + LASSERT(mutex_is_locked(&lo->ldo_layout_mutex)); lmm = (struct lov_mds_md_v1 *)buf->lb_buf; magic = le32_to_cpu(lmm->lmm_magic); if (magic != LOV_MAGIC_V1 && magic != LOV_MAGIC_V3 && - magic != LOV_MAGIC_COMP_V1) + magic != LOV_MAGIC_COMP_V1 && magic != LOV_MAGIC_FOREIGN && + magic != LOV_MAGIC_SEL) GOTO(out, rc = -EINVAL); - lod_free_comp_entries(lo); + if (lo->ldo_is_foreign) + lod_free_foreign_lov(lo); + else + lod_free_comp_entries(lo); - if (magic == LOV_MAGIC_COMP_V1) { + if (magic == LOV_MAGIC_COMP_V1 || magic == LOV_MAGIC_SEL) { comp_v1 = (struct lov_comp_md_v1 *)lmm; comp_cnt = le16_to_cpu(comp_v1->lcm_entry_count); if (comp_cnt == 0) @@ -1246,6 +1161,25 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo, lo->ldo_flr_state = le16_to_cpu(comp_v1->lcm_flags) & LCM_FL_FLR_MASK; mirror_cnt = le16_to_cpu(comp_v1->lcm_mirror_count) + 1; + } else if (magic == LOV_MAGIC_FOREIGN) { + size_t length; + + foreign = (struct lov_foreign_md *)buf->lb_buf; + length = offsetof(typeof(*foreign), lfm_value); + if (buf->lb_len < length || + buf->lb_len < (length + le32_to_cpu(foreign->lfm_length))) { + CDEBUG(D_LAYOUT, + "buf len %zu too small for lov_foreign_md\n", + buf->lb_len); + GOTO(out, rc = -EINVAL); + } + + /* just cache foreign LOV EA raw */ + rc = lod_alloc_foreign_lov(lo, length); + if (rc) + GOTO(out, rc); + memcpy(lo->ldo_foreign_lov, buf->lb_buf, length); + GOTO(out, rc); } else { comp_cnt = 1; lo->ldo_layout_gen = le16_to_cpu(lmm->lmm_layout_gen); @@ -1257,15 +1191,14 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo, GOTO(out, rc); for (i = 0; i < comp_cnt; i++) { - struct lod_layout_component *lod_comp; - struct lu_extent *ext; - __u32 offs; + struct lod_layout_component *lod_comp; + struct lu_extent *ext; + __u32 offs; lod_comp = &lo->ldo_comp_entries[i]; if (lo->ldo_is_composite) { offs = le32_to_cpu(comp_v1->lcm_entries[i].lcme_offset); lmm = (struct lov_mds_md_v1 *)((char *)comp_v1 + offs); - magic = le32_to_cpu(lmm->lmm_magic); ext = &comp_v1->lcm_entries[i].lcme_extent; lod_comp->llc_extent.e_start = @@ -1273,17 +1206,31 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo, lod_comp->llc_extent.e_end = le64_to_cpu(ext->e_end); lod_comp->llc_flags = le32_to_cpu(comp_v1->lcm_entries[i].lcme_flags); + if (lod_comp->llc_flags & LCME_FL_NOSYNC) + lod_comp->llc_timestamp = le64_to_cpu( + comp_v1->lcm_entries[i].lcme_timestamp); lod_comp->llc_id = le32_to_cpu(comp_v1->lcm_entries[i].lcme_id); if (lod_comp->llc_id == LCME_ID_INVAL) GOTO(out, rc = -EINVAL); + + if ((lod_comp->llc_flags & LCME_FL_EXTENSION) && + comp_v1->lcm_magic != cpu_to_le32(LOV_MAGIC_SEL)) { + struct lod_device *d = + lu2lod_dev(lo->ldo_obj.do_lu.lo_dev); + + CWARN("%s: EXTENSION flags=%x set on component[%u]=%x of non-SEL file "DFID" with magic=%#08x\n", + lod2obd(d)->obd_name, + lod_comp->llc_flags, lod_comp->llc_id, i, + PFID(lod_object_fid(lo)), + le32_to_cpu(comp_v1->lcm_magic)); + } } else { lod_comp_set_init(lod_comp); } pattern = le32_to_cpu(lmm->lmm_pattern); - if (lov_pattern(pattern) != LOV_PATTERN_RAID0 && - lov_pattern(pattern) != LOV_PATTERN_MDT) + if (!lov_pattern_supported(lov_pattern(pattern))) GOTO(out, rc = -EINVAL); lod_comp->llc_pattern = pattern; @@ -1291,8 +1238,9 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo, lod_comp->llc_stripe_count = le16_to_cpu(lmm->lmm_stripe_count); lod_comp->llc_layout_gen = le16_to_cpu(lmm->lmm_layout_gen); - if (magic == LOV_MAGIC_V3) { + if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) { struct lov_mds_md_v3 *v3 = (struct lov_mds_md_v3 *)lmm; + lod_set_pool(&lod_comp->llc_pool, v3->lmm_pool_name); objs = &v3->lmm_objects[0]; } else { @@ -1305,23 +1253,31 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo, * then user has specified ost list for this component. */ if (!lod_comp_inited(lod_comp)) { + __u16 stripe_count; + if (objs[0].l_ost_idx != (__u32)-1UL) { + int j; + + stripe_count = lod_comp_entry_stripe_count( + lo, lod_comp, false); + if (stripe_count == 0 && + !(lod_comp->llc_pattern & LOV_PATTERN_F_RELEASED) && + !(lod_comp->llc_pattern & LOV_PATTERN_MDT)) + GOTO(out, rc = -E2BIG); /** * load the user specified ost list, when this * component is instantiated later, it will be * used in lod_alloc_ost_list(). */ - lod_comp->llc_ostlist.op_count = - lod_comp->llc_stripe_count; + lod_comp->llc_ostlist.op_count = stripe_count; lod_comp->llc_ostlist.op_size = - lod_comp->llc_stripe_count * - sizeof(__u32); + stripe_count * sizeof(__u32); OBD_ALLOC(lod_comp->llc_ostlist.op_array, lod_comp->llc_ostlist.op_size); if (!lod_comp->llc_ostlist.op_array) GOTO(out, rc = -ENOMEM); - for (j = 0; j < lod_comp->llc_stripe_count; j++) + for (j = 0; j < stripe_count; j++) lod_comp->llc_ostlist.op_array[j] = le32_to_cpu(objs[j].l_ost_idx); @@ -1359,7 +1315,7 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo, out: if (rc) - lod_object_free_striping(env, lo); + lod_striping_free_nolock(env, lo); RETURN(rc); } @@ -1379,7 +1335,7 @@ static bool lod_striping_loaded(struct lod_object *lo) return true; if (S_ISDIR(lod2lu_obj(lo)->lo_header->loh_attr)) { - if (lo->ldo_stripe != NULL || lo->ldo_dir_stripe_loaded) + if (lo->ldo_dir_stripe_loaded) return true; /* Never load LMV stripe for slaves of striped dir */ @@ -1391,37 +1347,45 @@ static bool lod_striping_loaded(struct lod_object *lo) } /** - * Initialize the object representing the stripes. + * A generic function to initialize the stripe objects. * - * Unless the stripes are initialized already, fetch LOV (for regular - * objects) or LMV (for directory objects) EA and call lod_parse_striping() - * to instantiate the objects representing the stripes. Caller should - * hold the dt_write_lock(next). + * A protected version of lod_striping_load_locked() - load the striping + * information from storage, parse that and instantiate LU objects to + * represent the stripes. The LOD object \a lo supplies a pointer to the + * next sub-object in the LU stack so we can lock it. Also use \a lo to + * return an array of references to the newly instantiated objects. * * \param[in] env execution environment for this thread - * \param[in,out] lo LOD object + * \param[in,out] lo LOD object, where striping is stored and + * which gets an array of references * * \retval 0 if parsing and object creation succeed * \retval negative error number on failure - */ -int lod_load_striping_locked(const struct lu_env *env, struct lod_object *lo) + **/ +int lod_striping_load(const struct lu_env *env, struct lod_object *lo) { - struct lod_thread_info *info = lod_env_info(env); - struct lu_buf *buf = &info->lti_buf; - struct dt_object *next = dt_object_child(&lo->ldo_obj); - int rc = 0; + struct lod_thread_info *info = lod_env_info(env); + struct dt_object *next = dt_object_child(&lo->ldo_obj); + struct lu_buf *buf = &info->lti_buf; + int rc = 0; + ENTRY; if (!dt_object_exists(next)) - GOTO(out, rc = 0); + RETURN(0); if (lod_striping_loaded(lo)) - GOTO(out, rc = 0); + RETURN(0); + + mutex_lock(&lo->ldo_layout_mutex); + if (lod_striping_loaded(lo)) + GOTO(unlock, rc = 0); if (S_ISREG(lod2lu_obj(lo)->lo_header->loh_attr)) { rc = lod_get_lov_ea(env, lo); if (rc <= 0) - GOTO(out, rc); + GOTO(unlock, rc); + /* * there is LOV EA (striping information) in this object * let's parse it and create in-core objects for the stripes @@ -1433,14 +1397,30 @@ int lod_load_striping_locked(const struct lu_env *env, struct lod_object *lo) lo->ldo_comp_cached = 1; } else if (S_ISDIR(lod2lu_obj(lo)->lo_header->loh_attr)) { rc = lod_get_lmv_ea(env, lo); - if (rc < (typeof(rc))sizeof(struct lmv_mds_md_v1)) { + if (rc > sizeof(struct lmv_foreign_md)) { + struct lmv_foreign_md *lfm = info->lti_ea_store; + + if (le32_to_cpu(lfm->lfm_magic) == LMV_MAGIC_FOREIGN) { + lo->ldo_foreign_lmv = info->lti_ea_store; + lo->ldo_foreign_lmv_size = + info->lti_ea_store_size; + info->lti_ea_store = NULL; + info->lti_ea_store_size = 0; + + lo->ldo_dir_stripe_loaded = 1; + lo->ldo_dir_is_foreign = 1; + GOTO(unlock, rc = 0); + } + } + + if (rc < (int)sizeof(struct lmv_mds_md_v1)) { /* Let's set stripe_loaded to avoid further * stripe loading especially for non-stripe directory, * which can hurt performance. (See LU-9840) */ if (rc == 0) lo->ldo_dir_stripe_loaded = 1; - GOTO(out, rc = rc > 0 ? -EINVAL : rc); + GOTO(unlock, rc = rc > 0 ? -EINVAL : rc); } buf->lb_buf = info->lti_ea_store; buf->lb_len = info->lti_ea_store_size; @@ -1454,7 +1434,7 @@ int lod_load_striping_locked(const struct lu_env *env, struct lod_object *lo) } if (rc < 0) - GOTO(out, rc); + GOTO(unlock, rc); } /* @@ -1465,44 +1445,26 @@ int lod_load_striping_locked(const struct lu_env *env, struct lod_object *lo) if (rc == 0) lo->ldo_dir_stripe_loaded = 1; } -out: - RETURN(rc); + EXIT; +unlock: + mutex_unlock(&lo->ldo_layout_mutex); + + return rc; } -/** - * A generic function to initialize the stripe objects. - * - * A protected version of lod_load_striping_locked() - load the striping - * information from storage, parse that and instantiate LU objects to - * represent the stripes. The LOD object \a lo supplies a pointer to the - * next sub-object in the LU stack so we can lock it. Also use \a lo to - * return an array of references to the newly instantiated objects. - * - * \param[in] env execution environment for this thread - * \param[in,out] lo LOD object, where striping is stored and - * which gets an array of references - * - * \retval 0 if parsing and object creation succeed - * \retval negative error number on failure - **/ -int lod_load_striping(const struct lu_env *env, struct lod_object *lo) +int lod_striping_reload(const struct lu_env *env, struct lod_object *lo, + const struct lu_buf *buf) { - struct dt_object *next = dt_object_child(&lo->ldo_obj); - int rc; + int rc; - if (!dt_object_exists(next)) - return 0; + ENTRY; - /* Check without locking first */ - if (lod_striping_loaded(lo)) - return 0; + mutex_lock(&lo->ldo_layout_mutex); + lod_striping_free_nolock(env, lo); + rc = lod_parse_striping(env, lo, buf); + mutex_unlock(&lo->ldo_layout_mutex); - /* currently this code is supposed to be called from declaration - * phase only, thus the object is not expected to be locked by caller */ - dt_write_lock(env, next, 0); - rc = lod_load_striping_locked(env, lo); - dt_write_unlock(env, next); - return rc; + RETURN(rc); } /** @@ -1581,9 +1543,9 @@ static int lod_verify_v1v3(struct lod_device *d, const struct lu_buf *buf, if (!is_from_disk && stripe_offset != LOV_OFFSET_DEFAULT && lov_pattern(le32_to_cpu(lum->lmm_pattern)) != LOV_PATTERN_MDT) { /* if offset is not within valid range [0, osts_size) */ - if (stripe_offset >= d->lod_osts_size) { + if (stripe_offset >= d->lod_ost_descs.ltd_tgts_size) { CDEBUG(D_LAYOUT, "stripe offset %u >= bitmap size %u\n", - stripe_offset, d->lod_osts_size); + stripe_offset, d->lod_ost_descs.ltd_tgts_size); GOTO(out, rc = -EINVAL); } @@ -1642,6 +1604,124 @@ out: RETURN(rc); } +static inline +struct lov_comp_md_entry_v1 *comp_entry_v1(struct lov_comp_md_v1 *comp, int i) +{ + LASSERTF((le32_to_cpu(comp->lcm_magic) & ~LOV_MAGIC_DEFINED) == + LOV_USER_MAGIC_COMP_V1, "Wrong magic %x\n", + le32_to_cpu(comp->lcm_magic)); + LASSERTF(i >= 0 && i < le16_to_cpu(comp->lcm_entry_count), + "bad index %d, max = %d\n", + i, le16_to_cpu(comp->lcm_entry_count)); + + return &comp->lcm_entries[i]; +} + +#define for_each_comp_entry_v1(comp, entry) \ + for (entry = comp_entry_v1(comp, 0); \ + entry <= comp_entry_v1(comp, \ + le16_to_cpu(comp->lcm_entry_count) - 1); \ + entry++) + +int lod_erase_dom_stripe(struct lov_comp_md_v1 *comp_v1, + struct lov_comp_md_entry_v1 *dom_ent) +{ + struct lov_comp_md_entry_v1 *ent; + __u16 entries; + __u32 dom_off, dom_size, comp_size; + void *blob_src, *blob_dst; + unsigned int blob_size, blob_shift; + + entries = le16_to_cpu(comp_v1->lcm_entry_count) - 1; + /* if file has only DoM stripe return just error */ + if (entries == 0) + return -EFBIG; + + comp_size = le32_to_cpu(comp_v1->lcm_size); + dom_off = le32_to_cpu(dom_ent->lcme_offset); + dom_size = le32_to_cpu(dom_ent->lcme_size); + + /* shift entries array first */ + comp_v1->lcm_entry_count = cpu_to_le16(entries); + memmove(dom_ent, dom_ent + 1, + entries * sizeof(struct lov_comp_md_entry_v1)); + + /* now move blob of layouts */ + blob_dst = (void *)comp_v1 + dom_off - sizeof(*dom_ent); + blob_src = (void *)comp_v1 + dom_off + dom_size; + blob_size = (unsigned long)((void *)comp_v1 + comp_size - blob_src); + blob_shift = sizeof(*dom_ent) + dom_size; + + memmove(blob_dst, blob_src, blob_size); + + for_each_comp_entry_v1(comp_v1, ent) { + __u32 off; + + off = le32_to_cpu(ent->lcme_offset); + ent->lcme_offset = cpu_to_le32(off - blob_shift); + } + + comp_v1->lcm_size = cpu_to_le32(comp_size - blob_shift); + + /* notify a caller to re-check entry */ + return -ERESTART; +} + +int lod_fix_dom_stripe(struct lod_device *d, struct lov_comp_md_v1 *comp_v1, + struct lov_comp_md_entry_v1 *dom_ent) +{ + struct lov_comp_md_entry_v1 *ent; + struct lu_extent *dom_ext, *ext; + struct lov_user_md_v1 *lum; + __u32 stripe_size; + __u16 mid, dom_mid; + int rc = 0; + + dom_ext = &dom_ent->lcme_extent; + dom_mid = mirror_id_of(le32_to_cpu(dom_ent->lcme_id)); + stripe_size = d->lod_dom_max_stripesize; + + lum = (void *)comp_v1 + le32_to_cpu(dom_ent->lcme_offset); + CDEBUG(D_LAYOUT, "DoM component size %u was bigger than MDT limit %u, " + "new size is %u\n", le32_to_cpu(lum->lmm_stripe_size), + d->lod_dom_max_stripesize, stripe_size); + lum->lmm_stripe_size = cpu_to_le32(stripe_size); + + for_each_comp_entry_v1(comp_v1, ent) { + if (ent == dom_ent) + continue; + + mid = mirror_id_of(le32_to_cpu(ent->lcme_id)); + if (mid != dom_mid) + continue; + + ext = &ent->lcme_extent; + if (ext->e_start != dom_ext->e_end) + continue; + + /* Found next component after the DoM one with the same + * mirror_id and adjust its start with DoM component end. + * + * NOTE: we are considering here that there can be only one + * DoM component in a file, all replicas are located on OSTs + * always and don't need adjustment since use own layouts. + */ + ext->e_start = cpu_to_le64(stripe_size); + break; + } + + if (stripe_size == 0) { + /* DoM component size is zero due to server setting, + * remove it from the layout */ + rc = lod_erase_dom_stripe(comp_v1, dom_ent); + } else { + /* Update DoM extent end finally */ + dom_ext->e_end = cpu_to_le64(stripe_size); + } + + return rc; +} + /** * Verify LOV striping. * @@ -1657,7 +1737,7 @@ out: int lod_verify_striping(struct lod_device *d, struct lod_object *lo, const struct lu_buf *buf, bool is_from_disk) { - struct lov_desc *desc = &d->lod_desc; + struct lov_desc *desc = &d->lod_ost_descs.ltd_lov_desc; struct lov_user_md_v1 *lum; struct lov_comp_md_v1 *comp_v1; struct lov_comp_md_entry_v1 *ent; @@ -1666,20 +1746,52 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo, __u64 prev_end = 0; __u32 stripe_size = 0; __u16 prev_mid = -1, mirror_id = -1; - __u32 mirror_count = 0; + __u32 mirror_count; __u32 magic; - int rc = 0, i; + int rc = 0; ENTRY; + if (buf->lb_len < sizeof(lum->lmm_magic)) { + CDEBUG(D_LAYOUT, "invalid buf len %zu\n", buf->lb_len); + RETURN(-EINVAL); + } + lum = buf->lb_buf; + magic = le32_to_cpu(lum->lmm_magic) & ~LOV_MAGIC_DEFINED; + /* treat foreign LOV EA/object case first + * XXX is it expected to try setting again a foreign? + * XXX should we care about different current vs new layouts ? + */ + if (unlikely(magic == LOV_USER_MAGIC_FOREIGN)) { + struct lov_foreign_md *lfm = buf->lb_buf; + + if (buf->lb_len < offsetof(typeof(*lfm), lfm_value)) { + CDEBUG(D_LAYOUT, + "buf len %zu < min lov_foreign_md size (%zu)\n", + buf->lb_len, offsetof(typeof(*lfm), + lfm_value)); + RETURN(-EINVAL); + } + + if (foreign_size_le(lfm) > buf->lb_len) { + CDEBUG(D_LAYOUT, + "buf len %zu < this lov_foreign_md size (%zu)\n", + buf->lb_len, foreign_size_le(lfm)); + RETURN(-EINVAL); + } + /* Don't do anything with foreign layouts */ + RETURN(0); + } + + /* normal LOV/layout cases */ + if (buf->lb_len < sizeof(*lum)) { CDEBUG(D_LAYOUT, "buf len %zu too small for lov_user_md\n", buf->lb_len); RETURN(-EINVAL); } - magic = le32_to_cpu(lum->lmm_magic) & ~LOV_MAGIC_DEFINED; if (magic != LOV_USER_MAGIC_V1 && magic != LOV_USER_MAGIC_V3 && magic != LOV_USER_MAGIC_SPECIFIC && @@ -1700,6 +1812,8 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo, RETURN(-EINVAL); } +recheck: + mirror_count = 0; if (le16_to_cpu(comp_v1->lcm_entry_count) == 0) { CDEBUG(D_LAYOUT, "entry count is zero\n"); RETURN(-EINVAL); @@ -1716,11 +1830,10 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo, ++mirror_count; } - for (i = 0; i < le16_to_cpu(comp_v1->lcm_entry_count); i++) { - ent = &comp_v1->lcm_entries[i]; + for_each_comp_entry_v1(comp_v1, ent) { ext = &ent->lcme_extent; - if (le64_to_cpu(ext->e_start) >= le64_to_cpu(ext->e_end)) { + if (le64_to_cpu(ext->e_start) > le64_to_cpu(ext->e_end)) { CDEBUG(D_LAYOUT, "invalid extent "DEXT"\n", le64_to_cpu(ext->e_start), le64_to_cpu(ext->e_end)); @@ -1766,8 +1879,6 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo, RETURN(-EINVAL); } - prev_end = le64_to_cpu(ext->e_end); - tmp.lb_buf = (char *)comp_v1 + le32_to_cpu(ent->lcme_offset); tmp.lb_len = le32_to_cpu(ent->lcme_size); @@ -1775,16 +1886,17 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo, lum = tmp.lb_buf; if (lov_pattern(le32_to_cpu(lum->lmm_pattern)) == LOV_PATTERN_MDT) { - /* DoM component can be only the first entry */ - if (i > 0) { - CDEBUG(D_LAYOUT, "invalid DoM layout " - "entry found at %i index\n", i); + /* DoM component must be the first in a mirror */ + if (le64_to_cpu(ext->e_start) > 0) { + CDEBUG(D_LAYOUT, "invalid DoM component " + "with %llu extent start\n", + le64_to_cpu(ext->e_start)); RETURN(-EINVAL); } stripe_size = le32_to_cpu(lum->lmm_stripe_size); /* There is just one stripe on MDT and it must * cover whole component size. */ - if (stripe_size != prev_end) { + if (stripe_size != le64_to_cpu(ext->e_end)) { CDEBUG(D_LAYOUT, "invalid DoM layout " "stripe size %u != %llu " "(component size)\n", @@ -1797,10 +1909,19 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo, "%u is bigger than MDT limit %u, check " "dom_max_stripesize parameter\n", stripe_size, d->lod_dom_max_stripesize); - RETURN(-EINVAL); + rc = lod_fix_dom_stripe(d, comp_v1, ent); + if (rc == -ERESTART) { + /* DoM entry was removed, re-check + * new layout from start */ + goto recheck; + } else if (rc) { + RETURN(rc); + } } } + prev_end = le64_to_cpu(ext->e_end); + rc = lod_verify_v1v3(d, &tmp, is_from_disk); if (rc) RETURN(rc); @@ -1812,7 +1933,7 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo, stripe_size = le32_to_cpu(lum->lmm_stripe_size); if (stripe_size == 0) stripe_size = desc->ld_default_stripe_size; - if (stripe_size == 0 || (prev_end & (stripe_size - 1))) { + if (prev_end % stripe_size) { CDEBUG(D_LAYOUT, "stripe size isn't aligned, " "stripe_sz: %u, [%llu, %llu)\n", stripe_size, ext->e_start, prev_end); @@ -1879,9 +2000,8 @@ void lod_fix_desc_stripe_count(__u32 *val) void lod_fix_desc_pattern(__u32 *val) { /* from lov_setstripe */ - if ((*val != 0) && (*val != LOV_PATTERN_RAID0) && - (*val != LOV_PATTERN_MDT)) { - LCONSOLE_WARN("Unknown stripe pattern: %#x\n", *val); + if ((*val != 0) && !lov_pattern_supported_normal_comp(*val)) { + LCONSOLE_WARN("lod: Unknown stripe pattern: %#x\n", *val); *val = 0; } } @@ -1954,21 +2074,10 @@ int lod_pools_init(struct lod_device *lod, struct lustre_cfg *lcfg) lod_fix_desc(desc); desc->ld_active_tgt_count = 0; - lod->lod_desc = *desc; + lod->lod_ost_descs.ltd_lov_desc = *desc; lod->lod_sp_me = LUSTRE_SP_CLI; - /* Set up allocation policy (QoS and RR) */ - INIT_LIST_HEAD(&lod->lod_qos.lq_oss_list); - init_rwsem(&lod->lod_qos.lq_rw_sem); - lod->lod_qos.lq_dirty = 1; - lod->lod_qos.lq_rr.lqr_dirty = 1; - lod->lod_qos.lq_reset = 1; - /* Default priority is toward free space balance */ - lod->lod_qos.lq_prio_free = 232; - /* Default threshold for rr (roughly 17%) */ - lod->lod_qos.lq_threshold_rr = 43; - /* Set up OST pool environment */ lod->lod_pools_hash_body = cfs_hash_create("POOLS", HASH_POOLS_CUR_BITS, HASH_POOLS_MAX_BITS, @@ -1982,18 +2091,17 @@ int lod_pools_init(struct lod_device *lod, struct lustre_cfg *lcfg) INIT_LIST_HEAD(&lod->lod_pool_list); lod->lod_pool_count = 0; - rc = lod_ost_pool_init(&lod->lod_pool_info, 0); + rc = lod_ost_pool_init(&lod->lod_ost_descs.ltd_tgt_pool, 0); if (rc) GOTO(out_hash, rc); - lod_qos_rr_init(&lod->lod_qos.lq_rr); - rc = lod_ost_pool_init(&lod->lod_qos.lq_rr.lqr_pool, 0); + rc = lod_ost_pool_init(&lod->lod_ost_descs.ltd_qos.lq_rr.lqr_pool, 0); if (rc) GOTO(out_pool_info, rc); RETURN(0); out_pool_info: - lod_ost_pool_free(&lod->lod_pool_info); + lod_ost_pool_free(&lod->lod_ost_descs.ltd_tgt_pool); out_hash: cfs_hash_putref(lod->lod_pools_hash_body); @@ -2023,8 +2131,8 @@ int lod_pools_fini(struct lod_device *lod) } cfs_hash_putref(lod->lod_pools_hash_body); - lod_ost_pool_free(&(lod->lod_qos.lq_rr.lqr_pool)); - lod_ost_pool_free(&lod->lod_pool_info); + lod_ost_pool_free(&(lod->lod_ost_descs.ltd_qos.lq_rr.lqr_pool)); + lod_ost_pool_free(&lod->lod_ost_descs.ltd_tgt_pool); RETURN(0); }