1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

vg: add radix_tree for lv uuids

When searching for committed LV by uuid, this search can
be expensive for commands like 'vgremove' - so for
this part introduce  'lv_uuids' radix_tree that is
build with first access to lv_committed().
This commit is contained in:
Zdenek Kabelac 2024-10-26 22:37:00 +02:00
parent db0f1b799f
commit c2afa7a116
3 changed files with 31 additions and 0 deletions

View File

@ -1667,6 +1667,13 @@ struct logical_volume *find_lv_in_vg_by_lvid(const struct volume_group *vg,
if (memcmp(&lvid->id[0], &vg->id, ID_LEN)) if (memcmp(&lvid->id[0], &vg->id, ID_LEN))
return NULL; /* Check VG does not match */ return NULL; /* Check VG does not match */
if (vg->lv_uuids)
/* Used only for committed read-only VG (which happens to be
* the only user of this 'find' function.
* ATM we do NOT update this radix_tree when LV is added/removed! */
return radix_tree_lookup_ptr(vg->lv_uuids, &lvid->id[1],
sizeof(lvid->id[1]));
dm_list_iterate_items(lvl, &vg->lvs) dm_list_iterate_items(lvl, &vg->lvs)
if (!memcmp(&lvid->id[1], &lvl->lv->lvid.id[1], sizeof(lvid->id[1]))) if (!memcmp(&lvid->id[1], &lvl->lv->lvid.id[1], sizeof(lvid->id[1])))
return lvl->lv; /* LV uuid match */ return lvl->lv; /* LV uuid match */
@ -4349,6 +4356,8 @@ const struct logical_volume *lv_committed(const struct logical_volume *lv)
{ {
struct volume_group *vg; struct volume_group *vg;
const struct logical_volume *found_lv; const struct logical_volume *found_lv;
struct lv_list *lvl;
int r;
if (!lv) if (!lv)
return NULL; return NULL;
@ -4358,6 +4367,24 @@ const struct logical_volume *lv_committed(const struct logical_volume *lv)
vg = lv->vg->vg_committed; vg = lv->vg->vg_committed;
if (!vg->lv_uuids &&
(vg->lv_uuids = radix_tree_create(NULL, NULL)))
/* Create radix_tree for the 'committed' VG, that should
* never be modified and is only used for 'activation'
* so the tree need to constructed just once. */
dm_list_iterate_items(lvl, &vg->lvs) {
if (!(r = radix_tree_uniq_insert_ptr(vg->lv_uuids,
&lvl->lv->lvid.id[1],
sizeof(lvl->lv->lvid.id[1]),
lvl->lv))) {
radix_tree_destroy(vg->lv_uuids);
vg->lv_uuids = NULL; /* fallback to linear search */
break;
}
if (r != 1) /* There is duplicate ID, but continue with 'best' effort */
log_warn("WARNING: Duplicate id found!");
}
if (!(found_lv = find_lv_in_vg_by_lvid(vg, &lv->lvid))) { if (!(found_lv = find_lv_in_vg_by_lvid(vg, &lv->lvid))) {
log_error(INTERNAL_ERROR "LV %s (UUID %s) not found in committed metadata.", log_error(INTERNAL_ERROR "LV %s (UUID %s) not found in committed metadata.",
display_lvname(lv), lv->lvid.s); display_lvname(lv), lv->lvid.s);

View File

@ -81,6 +81,9 @@ static void _free_vg(struct volume_group *vg)
if (vg->lv_names) if (vg->lv_names)
radix_tree_destroy(vg->lv_names); radix_tree_destroy(vg->lv_names);
if (vg->lv_uuids)
radix_tree_destroy(vg->lv_uuids);
if (vg->pv_names) if (vg->pv_names)
radix_tree_destroy(vg->pv_names); radix_tree_destroy(vg->pv_names);

View File

@ -65,6 +65,7 @@ struct volume_group {
uint64_t status; uint64_t status;
struct radix_tree *lv_names; /* maintained tree for LV names within VG */ struct radix_tree *lv_names; /* maintained tree for LV names within VG */
struct radix_tree *lv_uuids; /* LV uuid (when searching committed metadata) */
struct radix_tree *pv_names; /* PV names used for metadata import */ struct radix_tree *pv_names; /* PV names used for metadata import */
struct id id; struct id id;