From f42aef47064fcc3fa8f78beea9e9b7e7c028e123 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 10 Sep 2024 11:51:15 -0500 Subject: [PATCH] metadata: use lv_hash in segment-specific metadata parsing The lv_hash wasn't being passed to the seg-specific text import functions, so they were doing many find_lv() calls which consumes a lot of time when there are many LVs in the metadata. --- lib/cache_segtype/cache.c | 14 ++++++++------ lib/format_text/import_vsn1.c | 12 +++++++----- lib/integrity/integrity.c | 7 ++++--- lib/metadata/segtype.h | 3 ++- lib/mirror/mirrored.c | 5 +++-- lib/raid/raid.c | 12 +++++++----- lib/snapshot/snapshot.c | 7 ++++--- lib/striped/striped.c | 3 ++- lib/thin/thin.c | 25 ++++++++++++++----------- lib/unknown/unknown.c | 3 ++- lib/vdo/vdo.c | 10 ++++++---- lib/writecache/writecache.c | 7 ++++--- 12 files changed, 63 insertions(+), 45 deletions(-) diff --git a/lib/cache_segtype/cache.c b/lib/cache_segtype/cache.c index 027d5cda1..036f8d6f8 100644 --- a/lib/cache_segtype/cache.c +++ b/lib/cache_segtype/cache.c @@ -203,7 +203,8 @@ static int _settings_text_export(const struct lv_segment *seg, static int _cache_pool_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash __attribute__((unused))) + struct dm_hash_table *pv_hash __attribute__((unused)), + struct dm_hash_table *lv_hash) { struct logical_volume *data_lv, *meta_lv; const char *str = NULL; @@ -212,7 +213,7 @@ static int _cache_pool_text_import(struct lv_segment *seg, return SEG_LOG_ERROR("Cache data not specified in"); if (!(str = dm_config_find_str(sn, "data", NULL))) return SEG_LOG_ERROR("Cache data must be a string in"); - if (!(data_lv = find_lv(seg->lv->vg, str))) + if (!(data_lv = dm_hash_lookup(lv_hash, str))) return SEG_LOG_ERROR("Unknown logical volume %s specified for " "cache data in", str); @@ -220,7 +221,7 @@ static int _cache_pool_text_import(struct lv_segment *seg, return SEG_LOG_ERROR("Cache metadata not specified in"); if (!(str = dm_config_find_str(sn, "metadata", NULL))) return SEG_LOG_ERROR("Cache metadata must be a string in"); - if (!(meta_lv = find_lv(seg->lv->vg, str))) + if (!(meta_lv = dm_hash_lookup(lv_hash, str))) return SEG_LOG_ERROR("Unknown logical volume %s specified for " "cache metadata in", str); @@ -439,7 +440,8 @@ static const struct segtype_handler _cache_pool_ops = { static int _cache_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash __attribute__((unused))) + struct dm_hash_table *pv_hash __attribute__((unused)), + struct dm_hash_table *lv_hash) { struct logical_volume *pool_lv, *origin_lv; const char *name; @@ -449,7 +451,7 @@ static int _cache_text_import(struct lv_segment *seg, return SEG_LOG_ERROR("cache_pool not specified in"); if (!(name = dm_config_find_str(sn, "cache_pool", NULL))) return SEG_LOG_ERROR("cache_pool must be a string in"); - if (!(pool_lv = find_lv(seg->lv->vg, name))) + if (!(pool_lv = dm_hash_lookup(lv_hash, name))) return SEG_LOG_ERROR("Unknown logical volume %s specified for " "cache_pool in", name); @@ -457,7 +459,7 @@ static int _cache_text_import(struct lv_segment *seg, return SEG_LOG_ERROR("Cache origin not specified in"); if (!(name = dm_config_find_str(sn, "origin", NULL))) return SEG_LOG_ERROR("Cache origin must be a string in"); - if (!(origin_lv = find_lv(seg->lv->vg, name))) + if (!(origin_lv = dm_hash_lookup(lv_hash, name))) return SEG_LOG_ERROR("Unknown logical volume %s specified for " "cache origin in", name); if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0)) diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index 94dabf453..c713bd2e3 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -376,7 +376,8 @@ static int _read_segment(struct cmd_context *cmd, struct format_instance *fid, struct dm_pool *mem, struct logical_volume *lv, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash) + struct dm_hash_table *pv_hash, + struct dm_hash_table *lv_hash) { uint32_t area_count = 0u; struct lv_segment *seg; @@ -449,7 +450,7 @@ static int _read_segment(struct cmd_context *cmd, } if (seg->segtype->ops->text_import && - !seg->segtype->ops->text_import(seg, sn_child, pv_hash)) + !seg->segtype->ops->text_import(seg, sn_child, pv_hash, lv_hash)) return_0; /* Optional tags */ @@ -551,7 +552,8 @@ static int _read_segments(struct cmd_context *cmd, struct format_instance *fid, struct dm_pool *mem, struct logical_volume *lv, const struct dm_config_node *lvn, - struct dm_hash_table *pv_hash) + struct dm_hash_table *pv_hash, + struct dm_hash_table *lv_hash) { const struct dm_config_node *sn; int count = 0, seg_count; @@ -562,7 +564,7 @@ static int _read_segments(struct cmd_context *cmd, * All sub-sections are assumed to be segments. */ if (!sn->v) { - if (!_read_segment(cmd, fmt, fid, mem, lv, sn, pv_hash)) + if (!_read_segment(cmd, fmt, fid, mem, lv, sn, pv_hash, lv_hash)) return_0; count++; @@ -979,7 +981,7 @@ static int _read_lvsegs(struct cmd_context *cmd, memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0])); - if (!_read_segments(cmd, fmt, fid, mem, lv, lvn, pv_hash)) + if (!_read_segments(cmd, fmt, fid, mem, lv, lvn, pv_hash, lv_hash)) return_0; lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size; diff --git a/lib/integrity/integrity.c b/lib/integrity/integrity.c index b630f8e09..f9adace89 100644 --- a/lib/integrity/integrity.c +++ b/lib/integrity/integrity.c @@ -37,7 +37,8 @@ static void _integrity_display(const struct lv_segment *seg) static int _integrity_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash __attribute__((unused))) + struct dm_hash_table *pv_hash __attribute__((unused)), + struct dm_hash_table *lv_hash) { struct integrity_settings *set; struct logical_volume *origin_lv = NULL; @@ -58,7 +59,7 @@ static int _integrity_text_import(struct lv_segment *seg, if (!dm_config_get_str(sn, "origin", &origin_name)) return SEG_LOG_ERROR("origin must be a string in"); - if (!(origin_lv = find_lv(seg->lv->vg, origin_name))) + if (!(origin_lv = dm_hash_lookup(lv_hash, origin_name))) return SEG_LOG_ERROR("Unknown LV specified for integrity origin %s in", origin_name); if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0)) @@ -103,7 +104,7 @@ static int _integrity_text_import(struct lv_segment *seg, if (!dm_config_get_str(sn, "meta_dev", &meta_dev)) return SEG_LOG_ERROR("meta_dev must be a string in"); - if (!(meta_lv = find_lv(seg->lv->vg, meta_dev))) + if (!(meta_lv = dm_hash_lookup(lv_hash, meta_dev))) return SEG_LOG_ERROR("Unknown logical volume %s specified for integrity in", meta_dev); } diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h index 4a1fdb8e4..69a80eec3 100644 --- a/lib/metadata/segtype.h +++ b/lib/metadata/segtype.h @@ -255,7 +255,8 @@ struct segtype_handler { uint32_t *area_count); int (*text_import) (struct lv_segment * seg, const struct dm_config_node * sn, - struct dm_hash_table * pv_hash); + struct dm_hash_table * pv_hash, + struct dm_hash_table * lv_hash); int (*merge_segments) (struct lv_segment * seg1, struct lv_segment * seg2); int (*add_target_line) (struct dev_manager *dm, struct dm_pool *mem, diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c index f6f815bf4..072e17b3c 100644 --- a/lib/mirror/mirrored.c +++ b/lib/mirror/mirrored.c @@ -74,7 +74,8 @@ static int _mirrored_text_import_area_count(const struct dm_config_node *sn, uin } static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash) + struct dm_hash_table *pv_hash, + struct dm_hash_table *lv_hash) { const struct dm_config_value *cv; const char *logname = NULL; @@ -102,7 +103,7 @@ static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_ } if (dm_config_get_str(sn, "mirror_log", &logname)) { - if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) { + if (!(seg->log_lv = dm_hash_lookup(lv_hash, logname))) { log_error("Unrecognised mirror log in " "segment %s of logical volume %s.", dm_config_parent_name(sn), seg->lv->name); diff --git a/lib/raid/raid.c b/lib/raid/raid.c index 64ef4de78..f01124925 100644 --- a/lib/raid/raid.c +++ b/lib/raid/raid.c @@ -70,7 +70,8 @@ static int _raid_text_import_area_count(const struct dm_config_node *sn, static int _raid_text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn, - const struct dm_config_value *cv) + const struct dm_config_value *cv, + struct dm_hash_table *lv_hash) { unsigned int s; struct logical_volume *lv; @@ -88,7 +89,7 @@ static int _raid_text_import_areas(struct lv_segment *seg, } /* Metadata device comes first. */ - if (!(lv = find_lv(seg->lv->vg, cv->v.str))) { + if (!(lv = dm_hash_lookup(lv_hash, cv->v.str))) { log_error("Couldn't find volume '%s' for segment '%s'.", cv->v.str ? : "NULL", seg_name); return 0; @@ -106,7 +107,7 @@ static int _raid_text_import_areas(struct lv_segment *seg, } /* Data device comes second */ - if (!(lv = find_lv(seg->lv->vg, cv->v.str))) { + if (!(lv = dm_hash_lookup(lv_hash, cv->v.str))) { log_error("Couldn't find volume '%s' for segment '%s'.", cv->v.str ? : "NULL", seg_name); return 0; @@ -129,7 +130,8 @@ static int _raid_text_import_areas(struct lv_segment *seg, static int _raid_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash) + struct dm_hash_table *pv_hash, + struct dm_hash_table *lv_hash) { const struct dm_config_value *cv; const struct { @@ -171,7 +173,7 @@ static int _raid_text_import(struct lv_segment *seg, return 0; } - if (!_raid_text_import_areas(seg, sn, cv)) { + if (!_raid_text_import_areas(seg, sn, cv, lv_hash)) { log_error("Failed to import RAID component pairs."); return 0; } diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c index 0ec5320c5..455528e1e 100644 --- a/lib/snapshot/snapshot.c +++ b/lib/snapshot/snapshot.c @@ -36,7 +36,8 @@ static const char *_snap_target_name(const struct lv_segment *seg, } static int _snap_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash __attribute__((unused))) + struct dm_hash_table *pv_hash __attribute__((unused)), + struct dm_hash_table *lv_hash) { uint32_t chunk_size; struct logical_volume *org, *cow; @@ -71,11 +72,11 @@ static int _snap_text_import(struct lv_segment *seg, const struct dm_config_node if (!(org_name = dm_config_find_str(sn, "origin", NULL))) return SEG_LOG_ERROR("Snapshot origin must be a string in"); - if (!(cow = find_lv(seg->lv->vg, cow_name))) + if (!(cow = dm_hash_lookup(lv_hash, cow_name))) return SEG_LOG_ERROR("Unknown logical volume %s specified for " "snapshot cow store in", cow_name); - if (!(org = find_lv(seg->lv->vg, org_name))) + if (!(org = dm_hash_lookup(lv_hash, org_name))) return SEG_LOG_ERROR("Unknown logical volume %s specified for " "snapshot origin in", org_name); diff --git a/lib/striped/striped.c b/lib/striped/striped.c index 1ff1ebdad..ec4bc961d 100644 --- a/lib/striped/striped.c +++ b/lib/striped/striped.c @@ -70,7 +70,8 @@ static int _striped_text_import_area_count(const struct dm_config_node *sn, uint } static int _striped_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash) + struct dm_hash_table *pv_hash, + struct dm_hash_table *lv_hash) { const struct dm_config_value *cv; diff --git a/lib/thin/thin.c b/lib/thin/thin.c index ae382dc9d..0fbcfe9b2 100644 --- a/lib/thin/thin.c +++ b/lib/thin/thin.c @@ -53,7 +53,8 @@ static void _thin_pool_display(const struct lv_segment *seg) static int _thin_pool_add_message(struct lv_segment *seg, const char *key, - const struct dm_config_node *sn) + const struct dm_config_node *sn, + struct dm_hash_table *lv_hash) { const char *lv_name = NULL; struct logical_volume *lv = NULL; @@ -62,7 +63,7 @@ static int _thin_pool_add_message(struct lv_segment *seg, /* Message must have only one from: create, delete */ if (dm_config_get_str(sn, "create", &lv_name)) { - if (!(lv = find_lv(seg->lv->vg, lv_name))) + if (!(lv = dm_hash_lookup(lv_hash, lv_name))) return SEG_LOG_ERROR("Unknown LV %s for create message in", lv_name); /* FIXME: switch to _SNAP later, if the created LV has an origin */ @@ -80,7 +81,8 @@ static int _thin_pool_add_message(struct lv_segment *seg, static int _thin_pool_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash __attribute__((unused))) + struct dm_hash_table *pv_hash __attribute__((unused)), + struct dm_hash_table *lv_hash) { const char *lv_name; struct logical_volume *pool_data_lv, *pool_metadata_lv; @@ -91,13 +93,13 @@ static int _thin_pool_text_import(struct lv_segment *seg, if (!dm_config_get_str(sn, "metadata", &lv_name)) return SEG_LOG_ERROR("Metadata must be a string in"); - if (!(pool_metadata_lv = find_lv(seg->lv->vg, lv_name))) + if (!(pool_metadata_lv = dm_hash_lookup(lv_hash, lv_name))) return SEG_LOG_ERROR("Unknown metadata %s in", lv_name); if (!dm_config_get_str(sn, "pool", &lv_name)) return SEG_LOG_ERROR("Pool must be a string in"); - if (!(pool_data_lv = find_lv(seg->lv->vg, lv_name))) + if (!(pool_data_lv = dm_hash_lookup(lv_hash, lv_name))) return SEG_LOG_ERROR("Unknown pool %s in", lv_name); if (!attach_pool_data_lv(seg, pool_data_lv)) @@ -141,7 +143,7 @@ static int _thin_pool_text_import(struct lv_segment *seg, /* Read messages */ for (; sn; sn = sn->sib) - if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child)) + if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child, lv_hash)) return_0; return 1; @@ -468,7 +470,8 @@ static void _thin_display(const struct lv_segment *seg) static int _thin_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash __attribute__((unused))) + struct dm_hash_table *pv_hash __attribute__((unused)), + struct dm_hash_table *lv_hash) { const char *lv_name; struct logical_volume *pool_lv, *origin = NULL, *external_lv = NULL, *merge_lv = NULL; @@ -477,7 +480,7 @@ static int _thin_text_import(struct lv_segment *seg, if (!dm_config_get_str(sn, "thin_pool", &lv_name)) return SEG_LOG_ERROR("Thin pool must be a string in"); - if (!(pool_lv = find_lv(seg->lv->vg, lv_name))) + if (!(pool_lv = dm_hash_lookup(lv_hash, lv_name))) return SEG_LOG_ERROR("Unknown thin pool %s in", lv_name); if (!dm_config_get_uint64(sn, "transaction_id", &seg->transaction_id)) @@ -487,14 +490,14 @@ static int _thin_text_import(struct lv_segment *seg, if (!dm_config_get_str(sn, "origin", &lv_name)) return SEG_LOG_ERROR("Origin must be a string in"); - if (!(origin = find_lv(seg->lv->vg, lv_name))) + if (!(origin = dm_hash_lookup(lv_hash, lv_name))) return SEG_LOG_ERROR("Unknown origin %s in", lv_name); } if (dm_config_has_node(sn, "merge")) { if (!dm_config_get_str(sn, "merge", &lv_name)) return SEG_LOG_ERROR("Merge lv must be a string in"); - if (!(merge_lv = find_lv(seg->lv->vg, lv_name))) + if (!(merge_lv = dm_hash_lookup(lv_hash, lv_name))) return SEG_LOG_ERROR("Unknown merge lv %s in", lv_name); } @@ -509,7 +512,7 @@ static int _thin_text_import(struct lv_segment *seg, if (!dm_config_get_str(sn, "external_origin", &lv_name)) return SEG_LOG_ERROR("External origin must be a string in"); - if (!(external_lv = find_lv(seg->lv->vg, lv_name))) + if (!(external_lv = dm_hash_lookup(lv_hash, lv_name))) return SEG_LOG_ERROR("Unknown external origin %s in", lv_name); } diff --git a/lib/unknown/unknown.c b/lib/unknown/unknown.c index 51aaebba5..cc625d4e2 100644 --- a/lib/unknown/unknown.c +++ b/lib/unknown/unknown.c @@ -20,7 +20,8 @@ #include "lib/config/config.h" static int _unknown_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash) + struct dm_hash_table *pv_hash, + struct dm_hash_table *lv_hash) { struct dm_config_node *new, *last = NULL, *head = NULL; const struct dm_config_node *current; diff --git a/lib/vdo/vdo.c b/lib/vdo/vdo.c index 3a5abacd5..a609e4426 100644 --- a/lib/vdo/vdo.c +++ b/lib/vdo/vdo.c @@ -75,7 +75,8 @@ static void _vdo_display(const struct lv_segment *seg) static int _vdo_text_import(struct lv_segment *seg, const struct dm_config_node *n, - struct dm_hash_table *pv_hash __attribute__((unused))) + struct dm_hash_table *pv_hash __attribute__((unused)), + struct dm_hash_table *lv_hash) { struct logical_volume *vdo_pool_lv; const char *str; @@ -84,7 +85,7 @@ static int _vdo_text_import(struct lv_segment *seg, if (!dm_config_has_node(n, "vdo_pool") || !(str = dm_config_find_str(n, "vdo_pool", NULL))) return _bad_field("vdo_pool"); - if (!(vdo_pool_lv = find_lv(seg->lv->vg, str))) { + if (!(vdo_pool_lv = dm_hash_lookup(lv_hash, str))) { log_error("Unknown VDO pool logical volume %s.", str); return 0; } @@ -205,7 +206,8 @@ static int _vdo_pool_text_import_area_count(const struct dm_config_node *sn __at static int _vdo_pool_text_import(struct lv_segment *seg, const struct dm_config_node *n, - struct dm_hash_table *pv_hash __attribute__((unused))) + struct dm_hash_table *pv_hash __attribute__((unused)), + struct dm_hash_table *lv_hash) { struct dm_vdo_target_params *vtp = &seg->vdo_params; struct logical_volume *data_lv; @@ -214,7 +216,7 @@ static int _vdo_pool_text_import(struct lv_segment *seg, if (!dm_config_has_node(n, "data") || !(str = dm_config_find_str(n, "data", NULL))) return _bad_field("data"); - if (!(data_lv = find_lv(seg->lv->vg, str))) { + if (!(data_lv = dm_hash_lookup(lv_hash, str))) { log_error("Unknown logical volume %s.", str); return 0; } diff --git a/lib/writecache/writecache.c b/lib/writecache/writecache.c index 4d56317f5..c5604a7a4 100644 --- a/lib/writecache/writecache.c +++ b/lib/writecache/writecache.c @@ -40,7 +40,8 @@ static void _writecache_display(const struct lv_segment *seg) static int _writecache_text_import(struct lv_segment *seg, const struct dm_config_node *sn, - struct dm_hash_table *pv_hash __attribute__((unused))) + struct dm_hash_table *pv_hash __attribute__((unused)), + struct dm_hash_table *lv_hash) { struct logical_volume *origin_lv = NULL; struct logical_volume *fast_lv; @@ -53,7 +54,7 @@ static int _writecache_text_import(struct lv_segment *seg, if (!dm_config_get_str(sn, "origin", &origin_name)) return SEG_LOG_ERROR("origin must be a string in"); - if (!(origin_lv = find_lv(seg->lv->vg, origin_name))) + if (!(origin_lv = dm_hash_lookup(lv_hash, origin_name))) return SEG_LOG_ERROR("Unknown LV specified for writecache origin %s in", origin_name); if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0)) @@ -65,7 +66,7 @@ static int _writecache_text_import(struct lv_segment *seg, if (!dm_config_get_str(sn, "writecache", &fast_name)) return SEG_LOG_ERROR("writecache must be a string in"); - if (!(fast_lv = find_lv(seg->lv->vg, fast_name))) + if (!(fast_lv = dm_hash_lookup(lv_hash, fast_name))) return SEG_LOG_ERROR("Unknown logical volume %s specified for writecache in", fast_name);