diff options
author | Alasdair Kergon <agk@redhat.com> | 2007-12-20 15:42:55 +0000 |
---|---|---|
committer | Alasdair Kergon <agk@redhat.com> | 2007-12-20 15:42:55 +0000 |
commit | a69ab6527868dbc13483a742dd6e547600945705 (patch) | |
tree | e97457d63cb8a5ed5fc99bc071e2e2f5645b2bbb /tools | |
parent | 72199adfc3bd1930dae6800e07ced9a88a8ef75b (diff) | |
download | lvm2-a69ab6527868dbc13483a742dd6e547600945705.tar.gz lvm2-a69ab6527868dbc13483a742dd6e547600945705.tar.xz lvm2-a69ab6527868dbc13483a742dd6e547600945705.zip |
Major restructuring of pvmove and lvconvert layer manipulation code
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lvconvert.c | 100 | ||||
-rw-r--r-- | tools/lvcreate.c | 74 | ||||
-rw-r--r-- | tools/pvmove.c | 80 | ||||
-rw-r--r-- | tools/toollib.c | 166 | ||||
-rw-r--r-- | tools/toollib.h | 11 |
5 files changed, 113 insertions, 318 deletions
diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 5d28bbdb..0f2a254f 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -232,10 +232,6 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l { struct lv_segment *seg; uint32_t existing_mirrors; - struct alloc_handle *ah = NULL; - struct logical_volume *log_lv; - struct list *parallel_areas; - float sync_percent; const char *mirrorlog; unsigned corelog = 0; @@ -312,8 +308,8 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l return 1; } - if (!remove_mirror_images(seg, 1, - lp->pv_count ? lp->pvh : NULL, 1)) + if (!lv_remove_mirrors(cmd, lv, existing_mirrors - 1, 1, + lp->pv_count ? lp->pvh : NULL, 0)) return_0; goto commit_changes; } @@ -332,33 +328,13 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l } } - if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv))) - return_0; - - if (!(ah = allocate_extents(lv->vg, NULL, lp->segtype, - 1, lp->mirrors - 1, - corelog ? 0U : 1U, - lv->le_count, lp->pvh, lp->alloc, - 1, parallel_areas))) - return_0; - - lp->region_size = adjusted_mirror_region_size(lv->vg->extent_size, - lv->le_count, - lp->region_size); - - log_lv = NULL; - if (!corelog && - !(log_lv = create_mirror_log(cmd, lv->vg, ah, - lp->alloc, - lv->name, 0, &lv->tags))) { - log_error("Failed to create mirror log."); - return 0; - } - - if (!create_mirror_layers(ah, 1, lp->mirrors, lv, - lp->segtype, 0, - lp->region_size, - log_lv)) + if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, 1, + adjusted_mirror_region_size( + lv->vg->extent_size, + lv->le_count, + lp->region_size), + corelog ? 0U : 1U, lp->pvh, lp->alloc, + MIRROR_BY_LV)) return_0; goto commit_changes; } @@ -375,54 +351,15 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l if (lp->mirrors == existing_mirrors) { if (!seg->log_lv && !corelog) { - /* No disk log present, add one. */ - if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv))) + if (!add_mirror_log(cmd, lv, 1, + adjusted_mirror_region_size( + lv->vg->extent_size, + lv->le_count, + lp->region_size), + lp->pvh, lp->alloc)) return_0; - if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) { - log_error("Unable to determine mirror sync status."); - return 0; - } - - if (!(ah = allocate_extents(lv->vg, NULL, lp->segtype, 0, - 0, 1, 0, lp->pvh, lp->alloc, - 1, parallel_areas))) { - stack; - return 0; - } - - if (sync_percent >= 100.0) - init_mirror_in_sync(1); - else - init_mirror_in_sync(0); - - if (!(log_lv = create_mirror_log(cmd, lv->vg, ah, - lp->alloc, lv->name, - (sync_percent >= 100.0) ? - 1 : 0, &lv->tags))) { - log_error("Failed to create mirror log."); - return 0; - } - seg->log_lv = log_lv; - log_lv->status |= MIRROR_LOG; - first_seg(log_lv)->mirror_seg = seg; } else if (seg->log_lv && corelog) { - /* Had disk log, switch to core. */ - if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) { - log_error("Unable to determine mirror sync status."); - return 0; - } - - if (sync_percent >= 100.0) - init_mirror_in_sync(1); - else { - /* A full resync will take place */ - lv->status &= ~MIRROR_NOTSYNCED; - init_mirror_in_sync(0); - } - - if (!remove_mirror_images(seg, lp->mirrors, - lp->pv_count ? - lp->pvh : NULL, 1)) + if (!remove_mirror_log(cmd, lv, lp->pvh)) return_0; } else { /* No change */ @@ -442,9 +379,8 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l return 0; } else { /* Reduce number of mirrors */ - if (!remove_mirror_images(seg, lp->mirrors, - lp->pv_count ? - lp->pvh : NULL, 0)) + if (!lv_remove_mirrors(cmd, lv, existing_mirrors - lp->mirrors, + 0, lp->pv_count ? lp->pvh : NULL, 0)) return_0; } diff --git a/tools/lvcreate.c b/tools/lvcreate.c index 336c7675..d2123cbe 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -409,7 +409,7 @@ static int _lvcreate_params(struct lvcreate_params *lp, struct cmd_context *cmd, return 0; } - if (!(lp->segtype = get_segtype_from_string(cmd, "mirror"))) { + if (!(lp->segtype = get_segtype_from_string(cmd, "striped"))) { stack; return 0; } @@ -524,11 +524,10 @@ static int _lvcreate(struct cmd_context *cmd, struct volume_group *vg, uint32_t size_rest; uint32_t status = 0; uint64_t tmp_size; - struct logical_volume *lv, *org = NULL, *log_lv = NULL; + struct logical_volume *lv, *org = NULL; struct list *pvh, tags; const char *tag = NULL; int origin_active = 0; - struct alloc_handle *ah = NULL; char lv_name_buf[128]; const char *lv_name; struct lvinfo info; @@ -745,38 +744,6 @@ static int _lvcreate(struct cmd_context *cmd, struct volume_group *vg, } } - if (lp->mirrors > 1) { - /* FIXME Calculate how many extents needed for the log */ - - if (!(ah = allocate_extents(vg, NULL, lp->segtype, lp->stripes, - lp->mirrors, lp->corelog ? 0U : 1U, - lp->extents, pvh, lp->alloc, 1, NULL))) - return_0; - - lp->region_size = adjusted_mirror_region_size(vg->extent_size, - lp->extents, - lp->region_size); - - init_mirror_in_sync(lp->nosync); - - if (lp->nosync) { - log_warn("WARNING: New mirror won't be synchronised. " - "Don't read what you didn't write!"); - status |= MIRROR_NOTSYNCED; - } - - list_init(&tags); - if (tag) - str_list_add(cmd->mem, &tags, tag); - - if (!lp->corelog && - !(log_lv = create_mirror_log(cmd, vg, ah, lp->alloc, - lv_name, lp->nosync, &tags))) { - log_error("Failed to create mirror log."); - return 0; - } - } - if (!(lv = lv_create_empty(lv_name ? lv_name : "lvol%d", NULL, status, lp->alloc, 0, vg))) { stack; @@ -802,19 +769,34 @@ static int _lvcreate(struct cmd_context *cmd, struct volume_group *vg, goto error; } + if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size, + 1, lp->extents, NULL, 0u, 0u, pvh, lp->alloc)) + return_0; + if (lp->mirrors > 1) { - if (!create_mirror_layers(ah, 0, lp->mirrors, lv, - lp->segtype, 0, - lp->region_size, log_lv)) { - stack; - goto error; + init_mirror_in_sync(lp->nosync); + + if (lp->nosync) { + log_warn("WARNING: New mirror won't be synchronised. " + "Don't read what you didn't write!"); + status |= MIRROR_NOTSYNCED; } - alloc_destroy(ah); - ah = NULL; - } else if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size, - lp->mirrors, lp->extents, NULL, 0u, 0u, pvh, lp->alloc)) - return_0; + list_init(&tags); + if (tag) + str_list_add(cmd->mem, &tags, tag); + + if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, lp->stripes, + adjusted_mirror_region_size( + vg->extent_size, + lv->le_count, + lp->region_size), + lp->corelog ? 0U : 1U, pvh, lp->alloc, + MIRROR_BY_LV)) { + stack; + goto revert_new_lv; + } + } /* store vg on disk(s) */ if (!vg_write(vg)) @@ -901,8 +883,6 @@ static int _lvcreate(struct cmd_context *cmd, struct volume_group *vg, return 1; error: - if (ah) - alloc_destroy(ah); return 0; deactivate_and_revert_new_lv: diff --git a/tools/pvmove.c b/tools/pvmove.c index e34e6d41..2438c6d7 100644 --- a/tools/pvmove.c +++ b/tools/pvmove.c @@ -106,6 +106,40 @@ static struct list *_get_allocatable_pvs(struct cmd_context *cmd, int argc, return allocatable_pvs; } +/* + * Replace any LV segments on given PV with temporary mirror. + * Returns list of LVs changed. + */ +static int _insert_pvmove_mirrors(struct cmd_context *cmd, + struct logical_volume *lv_mirr, + struct list *source_pvl, + struct logical_volume *lv, + struct list *lvs_changed) + +{ + struct pv_list *pvl; + uint32_t prev_le_count; + + /* Only 1 PV may feature in source_pvl */ + pvl = list_item(source_pvl->n, struct pv_list); + + prev_le_count = lv_mirr->le_count; + if (!insert_layer_for_segments_on_pv(cmd, lv, lv_mirr, PVMOVE, + pvl, lvs_changed)) + return_0; + + /* check if layer was inserted */ + if (lv_mirr->le_count - prev_le_count) { + lv->status |= LOCKED; + + log_verbose("Moving %u extents of logical volume %s/%s", + lv_mirr->le_count - prev_le_count, + lv->vg->name, lv->name); + } + + return 1; +} + /* Create new LV with mirror segments for the required copies */ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd, struct volume_group *vg, @@ -117,6 +151,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd, { struct logical_volume *lv_mirr, *lv; struct lv_list *lvl; + uint32_t log_count = 0; /* FIXME Cope with non-contiguous => splitting existing segments */ if (!(lv_mirr = lv_create_empty("pvmove%d", NULL, @@ -161,14 +196,8 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd, log_print("Skipping locked LV %s", lv->name); continue; } - /* FIXME Just insert the layer below - no allocation */ - // This knows nothing about pvmove - // insert_layer_for_segments_on_pv(cmd, lv, source_pvl, lv_mirr, *lvs_changed) - // - for each lv segment using that pv - // - call new fn insert_internal_layer() - if (!insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv, - allocatable_pvs, alloc, - *lvs_changed)) { + if (!_insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv, + *lvs_changed)) { stack; return NULL; } @@ -180,9 +209,16 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd, return NULL; } - /* FIXME Do allocation and convert to mirror */ - // again, this knows nothing about pvmove: it's a normal lvconvert lv_mirr to mirror with in-core log - // - a flag passed in requires that parent segs get split after the allocation (with failure if not possible) + if (!lv_add_mirrors(cmd, lv_mirr, 1, 1, 0, log_count, + allocatable_pvs, alloc, MIRROR_BY_SEG)) { + log_error("Failed to convert pvmove LV to mirrored"); + return_NULL; + } + + if (!split_parent_segments_for_layer(cmd, lv_mirr)) { + log_error("Failed to split segments being moved"); + return_NULL; + } return lv_mirr; } @@ -381,13 +417,22 @@ static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg, struct list *lvs_changed) { int r = 1; + struct list lvs_completed; + struct lv_list *lvl; /* Update metadata to remove mirror segments and break dependencies */ - if (!remove_pvmove_mirrors(vg, lv_mirr)) { + list_init(&lvs_completed); + if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, NULL, PVMOVE) || + !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE, + &lvs_completed)) { log_error("ABORTING: Removal of temporary mirror failed"); return 0; } + list_iterate_items(lvl, &lvs_completed) + /* FIXME Assumes only one pvmove at a time! */ + lvl->lv->status &= ~LOCKED; + /* Store metadata without dependencies on mirror segments */ if (!vg_write(vg)) { log_error("ABORTING: Failed to write new data locations " @@ -488,6 +533,17 @@ int pvmove(struct cmd_context *cmd, int argc, char **argv) char *pv_name = NULL; char *colon; int ret; + const struct segment_type *segtype; + + if (!(segtype = get_segtype_from_string(cmd, "mirror"))) + return_0; + + if (activation() && segtype->ops->target_present && + !segtype->ops->target_present(NULL)) { + log_error("%s: Required device-mapper target(s) not " + "detected in your kernel", segtype->name); + return 0; + } if (argc) { pv_name = argv[0]; diff --git a/tools/toollib.c b/tools/toollib.c index 161851da..32e99bda 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -1241,26 +1241,6 @@ int validate_new_vg_name(struct cmd_context *cmd, const char *vg_name) return 1; } -int generate_log_name_format(struct volume_group *vg __attribute((unused)), - const char *lv_name, char *buffer, size_t size) -{ - if (dm_snprintf(buffer, size, "%s_mlog", lv_name) < 0) { - stack; - return 0; - } - - /* FIXME I think we can cope without this. Cf. _add_lv_to_dtree() - if (find_lv_in_vg(vg, buffer) && - dm_snprintf(buffer, size, "%s_mlog_%%d", - lv_name) < 0) { - stack; - return 0; - } - *******/ - - return 1; -} - /* * Initialize the LV with 'value'. */ @@ -1307,149 +1287,3 @@ int set_lv(struct cmd_context *cmd, struct logical_volume *lv, return 1; } -/* - * This function writes a new header to the mirror log header to the lv - * - * Returns: 1 on success, 0 on failure - */ -static int _write_log_header(struct cmd_context *cmd, struct logical_volume *lv) -{ - struct device *dev; - char *name; - struct { /* The mirror log header */ - uint32_t magic; - uint32_t version; - uint64_t nr_regions; - } log_header; - - log_header.magic = xlate32(MIRROR_MAGIC); - log_header.version = xlate32(MIRROR_DISK_VERSION); - log_header.nr_regions = xlate64((uint64_t)-1); - - if (!(name = dm_pool_alloc(cmd->mem, PATH_MAX))) { - log_error("Name allocation failed - log header not written (%s)", - lv->name); - return 0; - } - - if (dm_snprintf(name, PATH_MAX, "%s%s/%s", cmd->dev_dir, - lv->vg->name, lv->name) < 0) { - log_error("Name too long - log header not written (%s)", lv->name); - return 0; - } - - log_verbose("Writing log header to device, %s", lv->name); - - if (!(dev = dev_cache_get(name, NULL))) { - log_error("%s: not found: log header not written", name); - return 0; - } - - if (!dev_open_quiet(dev)) - return 0; - - if (!dev_write(dev, UINT64_C(0), sizeof(log_header), &log_header)) { - log_error("Failed to write log header to %s", name); - dev_close_immediate(dev); - return 0; - } - - dev_close_immediate(dev); - - return 1; -} - -struct logical_volume *create_mirror_log(struct cmd_context *cmd, - struct volume_group *vg, - struct alloc_handle *ah, - alloc_policy_t alloc, - const char *lv_name, - int in_sync, - struct list *tags) -{ - struct logical_volume *log_lv; - char *log_name; - size_t len; - struct str_list *sl; - - if (!activation() && in_sync) { - log_error("Aborting. Unable to create in-sync mirror log " - "while activation is disabled."); - return NULL; - } - - len = strlen(lv_name) + 32; - if (!(log_name = alloca(len)) || - !(generate_log_name_format(vg, lv_name, log_name, len))) { - log_error("log_name allocation failed."); - return NULL; - } - - if (!(log_lv = lv_create_empty(log_name, NULL, - VISIBLE_LV | LVM_READ | LVM_WRITE, - alloc, 0, vg))) - return_NULL; - - if (!lv_add_log_segment(ah, log_lv)) - return_NULL; - - /* Temporary tag mirror log */ - list_iterate_items(sl, tags) - if (!str_list_add(cmd->mem, &log_lv->tags, sl->str)) { - log_error("Aborting. Unable to tag mirror log."); - return NULL; - } - - /* store mirror log on disk(s) */ - if (!vg_write(vg)) - return_NULL; - - backup(vg); - - if (!vg_commit(vg)) - return_NULL; - - if (!activate_lv(cmd, log_lv)) { - log_error("Aborting. Failed to activate mirror log."); - goto revert_new_lv; - } - - list_iterate_items(sl, tags) - if (!str_list_del(&log_lv->tags, sl->str)) - log_error("Failed to remove tag %s from mirror log.", - sl->str); - - if (activation() && !set_lv(cmd, log_lv, log_lv->size, - in_sync ? -1 : 0)) { - log_error("Aborting. Failed to wipe mirror log."); - goto deactivate_and_revert_new_lv; - } - - if (activation() && !_write_log_header(cmd, log_lv)) { - log_error("Aborting. Failed to write mirror log header."); - goto deactivate_and_revert_new_lv; - } - - if (!deactivate_lv(cmd, log_lv)) { - log_error("Aborting. Failed to deactivate mirror log. " - "Manual intervention required."); - return NULL; - } - - log_lv->status &= ~VISIBLE_LV; - - return log_lv; - -deactivate_and_revert_new_lv: - if (!deactivate_lv(cmd, log_lv)) { - log_error("Unable to deactivate mirror log LV. " - "Manual intervention required."); - return NULL; - } - -revert_new_lv: - if (!lv_remove(log_lv) || !vg_write(vg) || (backup(vg), !vg_commit(vg))) - log_error("Manual intervention may be required to remove " - "abandoned log LV before retrying."); - return NULL; -} diff --git a/tools/toollib.h b/tools/toollib.h index b89f0c3f..aad4f8a8 100644 --- a/tools/toollib.h +++ b/tools/toollib.h @@ -98,17 +98,6 @@ int apply_lvname_restrictions(const char *name); int validate_new_vg_name(struct cmd_context *cmd, const char *vg_name); -int generate_log_name_format(struct volume_group *vg, const char *lv_name, - char *buffer, size_t size); - -struct logical_volume *create_mirror_log(struct cmd_context *cmd, - struct volume_group *vg, - struct alloc_handle *ah, - alloc_policy_t alloc, - const char *lv_name, - int in_sync, - struct list *tags); - int set_lv(struct cmd_context *cmd, struct logical_volume *lv, uint64_t sectors, int value); |