summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAlasdair Kergon <agk@redhat.com>2007-12-20 15:42:55 +0000
committerAlasdair Kergon <agk@redhat.com>2007-12-20 15:42:55 +0000
commita69ab6527868dbc13483a742dd6e547600945705 (patch)
treee97457d63cb8a5ed5fc99bc071e2e2f5645b2bbb /tools
parent72199adfc3bd1930dae6800e07ced9a88a8ef75b (diff)
downloadlvm2-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.c100
-rw-r--r--tools/lvcreate.c74
-rw-r--r--tools/pvmove.c80
-rw-r--r--tools/toollib.c166
-rw-r--r--tools/toollib.h11
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);