--- lib/activate/dev_manager.c | 31 +++++++++++++++ lib/commands/toolcontext.h | 1 + lib/metadata/metadata-exported.h | 3 + tools/toollib.c | 77 ++++++++++++++++++++++++++++++++++++- 4 files changed, 109 insertions(+), 3 deletions(-) diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 2a8bfcd..3e0c8ca 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -958,6 +958,7 @@ static int _add_replicator_dev_target_to_dtree(struct dev_manager *dm, { struct replicator_device *rdev; struct replicator_site *rsite; + int vg_missing = 0; /* only active replicator */ if (lv_is_active_replicator_dev(seg->lv)) { @@ -967,12 +968,42 @@ static int _add_replicator_dev_target_to_dtree(struct dev_manager *dm, return_0; dm_list_iterate_items(rsite, &seg->replicator->rsites) { + if (rsite->vg == NULL) { + if (!rsite->vg_name) + continue; + + if (dm->cmd->vgs_hash && + (rsite->vg = dm_hash_lookup(dm->cmd->vgs_hash, rsite->vg_name))) + continue; + + if (!dm->cmd->vgs_hash) + if (!(dm->cmd->vgs_hash = dm_hash_create(16))) + return_0; + vg_missing++; + + if (!(dm_hash_insert(dm->cmd->vgs_hash, rsite->vg_name, NULL))) + return_0; + + log_verbose("VG %s added as missing.", rsite->vg_name); + } + } + + if (vg_missing) { + log_verbose("Some VGs are missing, retry with them."); + return 0; + } + + dm_list_iterate_items(rsite, &seg->replicator->rsites) { dm_list_iterate_items(rdev, &rsite->rdevices) { if (rdev->slog && !_add_new_lv_to_dtree(dm, dtree, rdev->slog, NULL)) return_0; if ((rsite->state == REPLICATOR_STATE_ACTIVE) && (!rdev->lv || !_add_new_lv_to_dtree(dm, dtree, rdev->lv, NULL))) return_0; + if (rdev->rsite->vg && + (!rdev->name || + !_add_new_lv_to_dtree(dm, dtree, find_lv(rdev->rsite->vg, rdev->name), NULL))) + return_0; } } dm_list_iterate_items(rsite, &seg->replicator->rsites) { diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index aa3de14..37210cf 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -60,6 +60,7 @@ struct cmd_context { struct dm_list formats; /* Available formats */ struct dm_list segtypes; /* Available segment types */ + struct dm_hash_table *vgs_hash; /* Required read-only VGs */ const char *hostname; const char *kernel_vsn; diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index d2e3592..a4bc8c1 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -263,6 +263,9 @@ struct volume_group { * 0 for success else appropriate FAILURE_* bits set. */ uint32_t read_status; + + /* linked vg */ + struct dm_list vgs; }; /* There will be one area for each stripe */ diff --git a/tools/toollib.c b/tools/toollib.c index 39a6d69..0d0b78e 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -428,6 +428,11 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name, { struct volume_group *vg; int ret = 0; + struct dm_hash_node *n; + struct dm_list vg_list; + struct volume_group *rvg, *trvg; + const char *key; + int vg_missing; log_verbose("Finding volume group \"%s\"", vg_name); @@ -447,9 +452,65 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name, goto out; } - if ((ret = process_single(cmd, vg_name, vg, - handle)) > ret_max) - ret_max = ret; + dm_list_init(&vg_list); + dm_list_add_h(&vg_list, &vg->vgs); + for (;;) { + if ((ret = process_single(cmd, vg_name, vg, + handle)) > ret_max) + ret_max = ret; + + if (!cmd->vgs_hash) + break; + + /* release any currently hold VG in reverse order (add_h) */ + dm_list_iterate_items_gen_safe(rvg, trvg, &vg_list, vgs) + unlock_and_release_vg(cmd, rvg, rvg->name); + + vg_missing = 0; + dm_hash_iterate(n, cmd->vgs_hash) + if (!dm_hash_get_data(cmd->vgs_hash, n)) + vg_missing++; + + if (!vg_missing) + return ret_max; + + vg = NULL; + dm_list_init(&vg_list); + dm_hash_iterate(n, cmd->vgs_hash) { + key = dm_hash_get_key(cmd->vgs_hash, n); + + /* preserve alphabetic order */ + if (!vg && strcmp(key, vg_name) > 0) { + vg = vg_read(cmd, vg_name, vgid, flags); + if (vg_read_error(vg)) + goto rout; + dm_list_add_h(&vg_list, &vg->vgs); + } + + rvg = vg_read(cmd, key, NULL, flags); + if (vg_read_error(rvg)) { + vg = rvg; + goto rout; + } + dm_list_add_h(&vg_list, &rvg->vgs); + } + + if (!vg) { + vg = vg_read(cmd, vg_name, vgid, flags); + if (vg_read_error(vg)) { + goto rout; + } + dm_list_add_h(&vg_list, &vg->vgs); + } + + /* updated hashed VG pointers */ + dm_list_iterate_items_gen(rvg, &vg_list, vgs) { + if (rvg != vg) { + dm_hash_remove(cmd->vgs_hash, rvg->name); + dm_hash_insert(cmd->vgs_hash, rvg->name, rvg); + } + } + } out: if ((vg_read_error(vg) == FAILED_ALLOCATION)|| @@ -458,6 +519,16 @@ out: else unlock_and_release_vg(cmd, vg, vg_name); return ret_max; + +rout: + if ((vg_read_error(vg) == FAILED_ALLOCATION) || + (vg_read_error(vg) == FAILED_LOCKING)) + vg_release(vg); + + dm_list_iterate_items_gen_safe(rvg, trvg, &vg_list, vgs) + unlock_and_release_vg(cmd, rvg, rvg->name); + + return ECMD_FAILED; } int process_each_vg(struct cmd_context *cmd, int argc, char **argv, -- 1.6.5.2