diff options
author | Jonathan Brassow <jbrassow@redhat.com> | 2013-08-23 08:40:13 -0500 |
---|---|---|
committer | Jonathan Brassow <jbrassow@redhat.com> | 2013-08-23 08:40:13 -0500 |
commit | f1e3640df31d0593e47ed82f3bb2f7e976b6569c (patch) | |
tree | 1f67ec1de765c8e1b09d5542778b7d296d5774d9 | |
parent | be9f4c77c93f347131f46a128013b0f4af8e5b32 (diff) | |
download | lvm2-f1e3640df31d0593e47ed82f3bb2f7e976b6569c.tar.gz |
Misc: Make get_pv_list_for_lv() available to more than just RAID
The function 'get_pv_list_for_lv' will assemble all the PVs that are
used by the specified LV. It uses 'for_each_sub_lv' to traverse all
of the sub-lvs which may compose it.
-rw-r--r-- | lib/metadata/lv_manip.c | 74 | ||||
-rw-r--r-- | lib/metadata/metadata-exported.h | 2 | ||||
-rw-r--r-- | lib/metadata/raid_manip.c | 45 |
3 files changed, 80 insertions, 41 deletions
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 24c66efc6..ef64d1209 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -161,6 +161,80 @@ int lv_is_on_pvs(struct logical_volume *lv, struct dm_list *pvs) return 0; } +struct dm_list_and_mempool { + struct dm_list *list; + struct dm_pool *mem; +}; +static int _get_pv_list_for_lv(struct cmd_context *cmd, + struct logical_volume *lv, void *data) +{ + int dup_found; + uint32_t s; + struct pv_list *pvl; + struct lv_segment *seg; + struct dm_list *pvs = ((struct dm_list_and_mempool *)data)->list; + struct dm_pool *mem = ((struct dm_list_and_mempool *)data)->mem; + + dm_list_iterate_items(seg, &lv->segments) { + for (s = 0; s < seg->area_count; s++) { + dup_found = 0; + + if (seg_type(seg, s) != AREA_PV) + continue; + + /* do not add duplicates */ + dm_list_iterate_items(pvl, pvs) + if (pvl->pv == seg_pv(seg, s)) + dup_found = 1; + + if (dup_found) + continue; + + if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) { + log_error("Failed to allocate memory"); + return 0; + } + + pvl->pv = seg_pv(seg, s); + log_debug_metadata(" %s/%s uses %s", lv->vg->name, + lv->name, pv_dev_name(pvl->pv)); + + dm_list_add(pvs, &pvl->list); + } + } + + return 1; +} + +/* + * get_pv_list_for_lv + * @mem - mempool to allocate the list from. + * @lv + * @pvs - The list to add pv_list items to. + * + * 'pvs' is filled with 'pv_list' items for PVs that compose the LV. + * If the 'pvs' list already has items in it, duplicates will not be + * added. So, it is safe to repeatedly call this function for different + * LVs and build up a list of PVs for them all. + * + * Memory to create the list is obtained from the mempool provided. + * + * Returns: 1 on success, 0 on error + */ +int get_pv_list_for_lv(struct dm_pool *mem, + struct logical_volume *lv, struct dm_list *pvs) +{ + struct dm_list_and_mempool context = { pvs, mem }; + + log_debug_metadata("Generating list of PVs that %s/%s uses:", + lv->vg->name, lv->name); + + if (!_get_pv_list_for_lv(lv->vg->cmd, lv, &context)) + return_0; + + return for_each_sub_lv(lv->vg->cmd, lv, &_get_pv_list_for_lv, &context); +} + /* * get_default_region_size * @cmd diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index d214fd23b..0df710c50 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -828,6 +828,8 @@ const char *find_vgname_from_pvid(struct cmd_context *cmd, int lv_is_on_pv(struct logical_volume *lv, struct physical_volume *pv); int lv_is_on_pvs(struct logical_volume *lv, struct dm_list *pvs); +int get_pv_list_for_lv(struct dm_pool *mem, + struct logical_volume *lv, struct dm_list *pvs); /* Find LV segment containing given LE */ diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c index 05f509acf..47c27881c 100644 --- a/lib/metadata/raid_manip.c +++ b/lib/metadata/raid_manip.c @@ -93,45 +93,6 @@ static int _activate_sublv_preserving_excl(struct logical_volume *top_lv, return 1; } -static int _get_pv_list_for_lv(struct logical_volume *lv, struct dm_list *pvs) -{ - uint32_t s; - struct pv_list *pvl; - struct lv_segment *seg = first_seg(lv); - - if (!seg_is_linear(seg)) { - log_error(INTERNAL_ERROR - "_get_pv_list_for_lv only handles linear volumes"); - return 0; - } - - log_debug_metadata("Getting list of PVs that %s/%s is on:", - lv->vg->name, lv->name); - - dm_list_iterate_items(seg, &lv->segments) { - for (s = 0; s < seg->area_count; s++) { - if (seg_type(seg, s) != AREA_PV) { - log_error(INTERNAL_ERROR - "Linear seg_type should be AREA_PV"); - return 0; - } - - if (!(pvl = dm_pool_zalloc(lv->vg->cmd->mem, - sizeof(*pvl)))) { - log_error("Failed to allocate memory"); - return 0; - } - - pvl->pv = seg_pv(seg, s); - log_debug_metadata(" %s/%s is on %s", lv->vg->name, lv->name, - pv_dev_name(pvl->pv)); - dm_list_add(pvs, &pvl->list); - } - } - - return 1; -} - /* * _raid_in_sync * @lv @@ -528,7 +489,8 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv, if ((p = strstr(base_name, "_mimage_"))) *p = '\0'; - if (!_get_pv_list_for_lv(data_lv, &allocatable_pvs)) { + if (!get_pv_list_for_lv(data_lv->vg->cmd->mem, + data_lv, &allocatable_pvs)) { log_error("Failed to build list of PVs for %s/%s", data_lv->vg->name, data_lv->name); return 0; @@ -1147,7 +1109,8 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name, /* Ensure we only split the tracking image */ dm_list_init(&tracking_pvs); splittable_pvs = &tracking_pvs; - if (!_get_pv_list_for_lv(tracking, splittable_pvs)) + if (!get_pv_list_for_lv(tracking->vg->cmd->mem, + tracking, splittable_pvs)) return_0; } } |