From 6733116a19a11d8512294fcda4cb65b4fbc457b4 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Wed, 31 Mar 2010 17:23:18 +0000 Subject: [PATCH] Fix all segments memory is allocated from vg private mempool. Physical segments were still allocated from global command context mempool. This leads to very high memory usage when activating large VG (vgchange). (Memory usage was about 2G when >3000LVs). Fix it by properly using vg->vgmem private pool, so all the memory is released early. New memory pool parameter is needed here for pv_split_segment function. Also fix the same problem in some minor allocations (vg description, lv segment split). --- WHATS_NEW | 1 + lib/format_text/import.c | 2 +- lib/metadata/lv_manip.c | 2 +- lib/metadata/merge.c | 4 ++-- lib/metadata/pv_alloc.h | 3 ++- lib/metadata/pv_manip.c | 21 ++++++++++++--------- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index ba0664e61..3b0ac1f20 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.63 - ================================ + Allocate all segments memory from vg private mempool. Return newly allocated PV segment after segment split. Optimise PV segments search for the most last segment search case. Remove vg_validate call when parsing cached metadata. diff --git a/lib/format_text/import.c b/lib/format_text/import.c index 03ff99078..f686418a8 100644 --- a/lib/format_text/import.c +++ b/lib/format_text/import.c @@ -114,7 +114,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid, if (!(vg = (*vsn)->read_vg(fid, cft, 0))) goto_out; - (*vsn)->read_desc(fid->fmt->cmd->mem, cft, when, desc); + (*vsn)->read_desc(vg->vgmem, cft, when, desc); break; } diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 661b85b52..5aa9616d7 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -47,7 +47,7 @@ int add_seg_to_segs_using_this_lv(struct logical_volume *lv, log_very_verbose("Adding %s:%" PRIu32 " as an user of %s", seg->lv->name, seg->le, lv->name); - if (!(sl = dm_pool_zalloc(lv->vg->cmd->mem, sizeof(*sl)))) { + if (!(sl = dm_pool_zalloc(lv->vg->vgmem, sizeof(*sl)))) { log_error("Failed to allocate segment list"); return 0; } diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c index b05dad466..0ad01651f 100644 --- a/lib/metadata/merge.c +++ b/lib/metadata/merge.c @@ -268,7 +268,7 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg, } /* Clone the existing segment */ - if (!(split_seg = alloc_lv_segment(lv->vg->cmd->mem, seg->segtype, + if (!(split_seg = alloc_lv_segment(lv->vg->vgmem, seg->segtype, seg->lv, seg->le, seg->len, seg->status, seg->stripe_size, seg->log_lv, @@ -279,7 +279,7 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg, return 0; } - if (!str_list_dup(lv->vg->cmd->mem, &split_seg->tags, &seg->tags)) { + if (!str_list_dup(lv->vg->vgmem, &split_seg->tags, &seg->tags)) { log_error("LV segment tags duplication failed"); return 0; } diff --git a/lib/metadata/pv_alloc.h b/lib/metadata/pv_alloc.h index e7a4cf022..d894f313c 100644 --- a/lib/metadata/pv_alloc.h +++ b/lib/metadata/pv_alloc.h @@ -20,7 +20,8 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv, uint32_t pe, uint32_t area_len, struct lv_segment *seg, uint32_t area_num); -int pv_split_segment(struct physical_volume *pv, uint32_t pe, +int pv_split_segment(struct dm_pool *mem, + struct physical_volume *pv, uint32_t pe, struct pv_segment **pvseg_allocated); int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction); int check_pv_segments(struct volume_group *vg); diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c index 6bcf3f1a2..e6fe6c206 100644 --- a/lib/metadata/pv_manip.c +++ b/lib/metadata/pv_manip.c @@ -96,13 +96,14 @@ static struct pv_segment *find_peg_by_pe(const struct physical_volume *pv, * Split peg at given extent. * Second part is always not allocated to a LV and returned. */ -static struct pv_segment *_pv_split_segment(struct physical_volume *pv, +static struct pv_segment *_pv_split_segment(struct dm_pool *mem, + struct physical_volume *pv, struct pv_segment *peg, uint32_t pe) { struct pv_segment *peg_new; - if (!(peg_new = _alloc_pv_segment(pv->fmt->cmd->mem, peg->pv, pe, + if (!(peg_new = _alloc_pv_segment(mem, peg->pv, pe, peg->len + peg->pe - pe, NULL, 0))) return_NULL; @@ -122,7 +123,8 @@ static struct pv_segment *_pv_split_segment(struct physical_volume *pv, /* * Ensure there is a PV segment boundary at the given extent. */ -int pv_split_segment(struct physical_volume *pv, uint32_t pe, +int pv_split_segment(struct dm_pool *mem, + struct physical_volume *pv, uint32_t pe, struct pv_segment **pvseg_allocated) { struct pv_segment *pvseg, *pvseg_new = NULL; @@ -142,7 +144,7 @@ int pv_split_segment(struct physical_volume *pv, uint32_t pe, goto out; } - if (!(pvseg_new = _pv_split_segment(pv, pvseg, pe))) + if (!(pvseg_new = _pv_split_segment(mem, pv, pvseg, pe))) return_0; out: if (pvseg_allocated) @@ -167,8 +169,8 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv, if (!pv) return &null_pv_segment; - if (!pv_split_segment(pv, pe, &peg) || - !pv_split_segment(pv, pe + area_len, NULL)) + if (!pv_split_segment(seg->lv->vg->vgmem, pv, pe, &peg) || + !pv_split_segment(seg->lv->vg->vgmem, pv, pe + area_len, NULL)) return_NULL; if (!peg) { @@ -206,8 +208,9 @@ int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction) return 1; } - if (!pv_split_segment(peg->pv, peg->pe + peg->lvseg->area_len - - area_reduction, NULL)) + if (!pv_split_segment(peg->lvseg->lv->vg->vgmem, + peg->pv, peg->pe + peg->lvseg->area_len - + area_reduction, NULL)) return_0; return 1; @@ -380,7 +383,7 @@ static int _reduce_pv(struct physical_volume *pv, struct volume_group *vg, uint3 } } - if (!pv_split_segment(pv, new_pe_count, NULL)) + if (!pv_split_segment(vg->vgmem, pv, new_pe_count, NULL)) return_0; dm_list_iterate_items_safe(peg, pegt, &pv->segments) {