diff options
author | Alasdair Kergon <agk@redhat.com> | 2005-06-01 16:51:55 +0000 |
---|---|---|
committer | Alasdair Kergon <agk@redhat.com> | 2005-06-01 16:51:55 +0000 |
commit | 60f13f01d2af1cb1b05c20b11285c7c6c15acd6b (patch) | |
tree | 32895b7e9cb063b88bd00c568dc59f949cc716f2 /tools | |
parent | 8e6230ddd981539221bc82ed71ed9f2308148e2c (diff) | |
download | lvm2-60f13f01d2af1cb1b05c20b11285c7c6c15acd6b.tar.gz lvm2-60f13f01d2af1cb1b05c20b11285c7c6c15acd6b.tar.xz lvm2-60f13f01d2af1cb1b05c20b11285c7c6c15acd6b.zip |
Basic support for mirrors.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/args.h | 2 | ||||
-rw-r--r-- | tools/commands.h | 8 | ||||
-rw-r--r-- | tools/lvchange.c | 6 | ||||
-rw-r--r-- | tools/lvcreate.c | 188 | ||||
-rw-r--r-- | tools/lvremove.c | 6 | ||||
-rw-r--r-- | tools/toollib.c | 8 | ||||
-rw-r--r-- | tools/vgchange.c | 4 | ||||
-rw-r--r-- | tools/vgreduce.c | 4 | ||||
-rw-r--r-- | tools/vgsplit.c | 4 |
9 files changed, 201 insertions, 29 deletions
diff --git a/tools/args.h b/tools/args.h index e88a6618..80b5b9a3 100644 --- a/tools/args.h +++ b/tools/args.h @@ -85,6 +85,7 @@ arg(size_ARG, 'L', "size", size_mb_arg) arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign) arg(persistent_ARG, 'M', "persistent", yes_no_arg) arg(major_ARG, 'j', "major", major_arg) +arg(mirrors_ARG, 'm', "mirrors", int_arg) arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg) arg(maps_ARG, 'm', "maps", NULL) arg(name_ARG, 'n', "name", string_arg) @@ -100,6 +101,7 @@ arg(physicalvolume_ARG, 'P', "physicalvolume", NULL) arg(readahead_ARG, 'r', "readahead", int_arg) arg(resizefs_ARG, 'r', "resizefs", NULL) arg(reset_ARG, 'R', "reset", NULL) +arg(regionsize_ARG, 'R', "regionsize", size_mb_arg) arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg) arg(stdin_ARG, 's', "stdin", NULL) arg(snapshot_ARG, 's', "snapshot", NULL) diff --git a/tools/commands.h b/tools/commands.h index 22931f01..46ac265e 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -91,9 +91,11 @@ xx(lvcreate, "\t{-l|--extents LogicalExtentsNumber |\n" "\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n" "\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n" + "\t[-m|--mirrors Mirrors]\n" "\t[-n|--name LogicalVolumeName]\n" "\t[-p|--permission {r|rw}]\n" "\t[-r|--readahead ReadAheadSectors]\n" + "\t[-R|--regionsize MirrorLogRegionSize]\n" "\t[-t|--test]\n" "\t[--type VolumeType]\n" "\t[-v|--verbose]\n" @@ -122,9 +124,9 @@ xx(lvcreate, "\tOriginalLogicalVolume[Path] [PhysicalVolumePath...]\n\n", addtag_ARG, alloc_ARG, autobackup_ARG, chunksize_ARG, contiguous_ARG, - extents_ARG, major_ARG, minor_ARG, name_ARG, permission_ARG, - persistent_ARG, readahead_ARG, size_ARG, snapshot_ARG, stripes_ARG, - stripesize_ARG, test_ARG, type_ARG, zero_ARG) + extents_ARG, major_ARG, minor_ARG, mirrors_ARG, name_ARG, permission_ARG, + persistent_ARG, readahead_ARG, regionsize_ARG, size_ARG, snapshot_ARG, + stripes_ARG, stripesize_ARG, test_ARG, type_ARG, zero_ARG) xx(lvdisplay, "Display information about a logical volume", diff --git a/tools/lvchange.c b/tools/lvchange.c index d268134e..75251be2 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -405,6 +405,12 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv, return ECMD_FAILED; } + /* FIXME Test for VISIBLE instead? */ + if (lv->status & MIRROR_LOG) { + log_error("Unable to change mirror log LV %s directly", lv->name); + return ECMD_FAILED; + } + /* access permission change */ if (arg_count(cmd, permission_ARG)) { if (!archive(lv->vg)) diff --git a/tools/lvcreate.c b/tools/lvcreate.c index f2d65a97..7bd36111 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -14,6 +14,7 @@ */ #include "tools.h" +#include "lv_alloc.h" #include <fcntl.h> @@ -31,6 +32,7 @@ struct lvcreate_params { uint32_t stripes; uint32_t stripe_size; uint32_t chunk_size; + uint32_t region_size; uint32_t mirrors; @@ -228,6 +230,38 @@ static int _read_stripe_params(struct lvcreate_params *lp, return 1; } +static int _read_mirror_params(struct lvcreate_params *lp, + struct cmd_context *cmd, + int *pargc, char ***pargv) +{ + int argc = *pargc; + + if (argc && (unsigned) argc < lp->mirrors) { + log_error("Too few physical volumes on " + "command line for %d-way mirroring", lp->mirrors); + return 0; + } + + if (arg_count(cmd, regionsize_ARG)) { + if (arg_sign_value(cmd, regionsize_ARG, 0) == SIGN_MINUS) { + log_error("Negative regionsize is invalid"); + return 0; + } + lp->region_size = 2 * arg_uint_value(cmd, regionsize_ARG, 0); + } else + lp->region_size = 2 * find_config_int(cmd->cft->root, + "activation/mirror_region_size", + DEFAULT_MIRROR_REGION_SIZE); + + if (lp->region_size & (lp->region_size - 1)) { + log_error("Region size (%" PRIu32 ") must be a power of 2", + lp->region_size); + return 0; + } + + return 1; +} + static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd, int argc, char **argv) { @@ -249,6 +283,18 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd, if (arg_count(cmd, snapshot_ARG) || seg_is_snapshot(lp)) lp->snapshot = 1; + lp->mirrors = 1; + + /* Default to 2 mirrored areas if --type mirror */ + if (seg_is_mirrored(lp)) + lp->mirrors = 2; + + if (arg_count(cmd, mirrors_ARG)) { + lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1; + if (lp->mirrors == 1) + log_print("Redundant mirrors argument: default is 0"); + } + if (lp->snapshot) { if (arg_count(cmd, zero_ARG)) { log_error("-Z is incompatible with snapshots"); @@ -272,6 +318,25 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd, } } + if (lp->mirrors > 1) { + if (lp->snapshot) { + log_error("mirrors and snapshots are currently " + "incompatible"); + return 0; + } + + if (lp->stripes > 1) { + log_error("mirrors and stripes are currently " + "incompatible"); + return 0; + } + + if (!(lp->segtype = get_segtype_from_string(cmd, "mirror"))) { + stack; + return 0; + } + } + if (activation() && lp->segtype->ops->target_present && !lp->segtype->ops->target_present()) { log_error("%s: Required device-mapper target(s) not " @@ -281,8 +346,11 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd, if (!_read_name_params(lp, cmd, &argc, &argv) || !_read_size_params(lp, cmd, &argc, &argv) || - !_read_stripe_params(lp, cmd, &argc, &argv)) + !_read_stripe_params(lp, cmd, &argc, &argv) || + !_read_mirror_params(lp, cmd, &argc, &argv)) { + stack; return 0; + } /* * Should we zero the lv. @@ -392,14 +460,15 @@ static int _zero_lv(struct cmd_context *cmd, struct logical_volume *lv) static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) { - uint32_t size_rest; + uint32_t size_rest, region_max; uint32_t status = 0; uint64_t tmp_size; struct volume_group *vg; - struct logical_volume *lv, *org = NULL; + struct logical_volume *lv, *org = NULL, *log_lv = NULL; struct list *pvh; const char *tag; int consistent = 1; + struct alloc_handle *ah = NULL; status |= lp->permission | VISIBLE_LV; @@ -505,30 +574,98 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) return 0; } - if (lp->stripes > list_size(pvh)) { + if (lp->stripes > list_size(pvh) && lp->alloc != ALLOC_ANYWHERE) { log_error("Number of stripes (%u) must not exceed " "number of physical volumes (%d)", lp->stripes, list_size(pvh)); return 0; } - if (!(lv = lv_create_empty(vg->fid, lp->lv_name, "lvol%d", NULL, - status, lp->alloc, 0, vg))) { - stack; + if (lp->mirrors > 1 && !activation()) { + log_error("Can't create mirror without using " + "device-mapper kernel driver."); return 0; } /* The snapshot segment gets created later */ - if (lp->snapshot) - if (!(lp->segtype = get_segtype_from_string(cmd, "striped"))) { + if (lp->snapshot && + !(lp->segtype = get_segtype_from_string(cmd, "striped"))) { + stack; + return 0; + } + + if (!archive(vg)) + return 0; + + if (lp->mirrors > 1) { + /* FIXME Adjust lp->region_size if necessary */ + region_max = (1 << (ffs(lp->extents) - 1)) * vg->extent_size; + + if (region_max < lp->region_size) { + lp->region_size = region_max; + log_print("Using reduced mirror region size of %" PRIu32 + " sectors", lp->region_size); + } + + /* FIXME Calculate how many extents needed for the log */ + + if (!(log_lv = lv_create_empty(vg->fid, NULL, "mirrorlog%d", NULL, + VISIBLE_LV | LVM_READ | LVM_WRITE, + lp->alloc, 0, vg))) { stack; return 0; } - if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size, - lp->mirrors, lp->extents, NULL, 0u, 0u, pvh, lp->alloc)) { + if (!(ah = allocate_extents(vg, NULL, lp->segtype, lp->stripes, + lp->mirrors, 1, lp->extents, + NULL, 0, 0, pvh, lp->alloc))) { + stack; + return 0; + } + + if (!lv_add_log_segment(ah, log_lv)) { + stack; + goto error; + } + + /* store mirror log on disk(s) */ + if (!vg_write(vg)) { + stack; + goto error; + } + + backup(vg); + + if (!vg_commit(vg)) { + stack; + goto error; + } + + if (!activate_lv(cmd, log_lv->lvid.s)) { + log_error("Aborting. Failed to activate mirror log. " + "Remove new LVs and retry."); + goto error; + } + + if (activation() && !_zero_lv(cmd, log_lv)) { + log_error("Aborting. Failed to wipe mirror log. " + "Remove new LV and retry."); + goto error; + } + + if (!deactivate_lv(cmd, log_lv->lvid.s)) { + log_error("Aborting. Failed to deactivate mirror log. " + "Remove new LV and retry."); + goto error; + } + + log_lv->status &= ~VISIBLE_LV; + } + + if (!(lv = lv_create_empty(vg->fid, lp->lv_name, "lvol%d", NULL, + status, lp->alloc, 0, vg))) { stack; - return 0; + goto error; } if (lp->read_ahead) { @@ -547,24 +684,38 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) if (arg_count(cmd, addtag_ARG)) { if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) { log_error("Failed to get tag"); - return 0; + goto error; } if (!(lv->vg->fid->fmt->features & FMT_TAGS)) { log_error("Volume group %s does not support tags", lv->vg->name); - return 0; + goto error; } if (!str_list_add(cmd->mem, &lv->tags, tag)) { log_error("Failed to add tag %s to %s/%s", tag, lv->vg->name, lv->name); - return 0; + goto error; } } - if (!archive(vg)) + if (lp->mirrors > 1) { + if (!lv_add_segment(ah, 0, lp->mirrors, lv, lp->segtype, + lp->stripe_size, NULL, 0, 0, + lp->region_size, log_lv)) { + log_error("Aborting. Failed to add mirror segment. " + "Remove new LV and retry."); + goto error; + } + + 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)) { + stack; return 0; + } /* store vg on disk(s) */ if (!vg_write(vg)) { @@ -642,6 +793,11 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) */ return 1; + +error: + if (ah) + alloc_destroy(ah); + return 0; } int lvcreate(struct cmd_context *cmd, int argc, char **argv) diff --git a/tools/lvremove.c b/tools/lvremove.c index 94c22c3b..e5069a1f 100644 --- a/tools/lvremove.c +++ b/tools/lvremove.c @@ -34,6 +34,12 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv, return ECMD_FAILED; } + if (lv->status & MIRROR_LOG) { + log_error("Can't remove logical volume %s used as mirror log", + lv->name); + return ECMD_FAILED; + } + if (lv->status & LOCKED) { log_error("Can't remove locked LV %s", lv->name); return ECMD_FAILED; diff --git a/tools/toollib.c b/tools/toollib.c index 8882c72e..4c7cf160 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -110,9 +110,9 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, int ret = 0; int consistent; - struct list *slh, *tags_arg; + struct list *tags_arg; struct list *vgnames; /* VGs to process */ - struct str_list *sll; + struct str_list *sll, *strl; struct volume_group *vg; struct list tags, lvnames; struct list arg_lvnames; /* Cmdline vgname or vgname/lvname */ @@ -228,8 +228,8 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, } } - list_iterate(slh, vgnames) { - vgname = list_item(slh, struct str_list)->str; + list_iterate_items(strl, vgnames) { + vgname = strl->str; if (!vgname || !*vgname) continue; /* FIXME Unnecessary? */ if (!lock_vol(cmd, vgname, lock_type)) { diff --git a/tools/vgchange.c b/tools/vgchange.c index d30e32b6..efc23e27 100644 --- a/tools/vgchange.c +++ b/tools/vgchange.c @@ -30,10 +30,10 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd, if ((lv->status & SNAPSHOT) || lv_is_cow(lv)) continue; - /* Can't deactive a pvmove LV */ + /* Can't deactive a pvmove or log LV */ /* FIXME There needs to be a controlled way of doing this */ if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) && - (lv->status & PVMOVE)) + ((lv->status & PVMOVE) || (lv->status & MIRROR_LOG))) continue; if (activate == CHANGE_AN) { diff --git a/tools/vgreduce.c b/tools/vgreduce.c index db1afec9..64b797d3 100644 --- a/tools/vgreduce.c +++ b/tools/vgreduce.c @@ -129,12 +129,12 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg) /* Are any segments of this LV on missing PVs? */ list_iterate_items(seg, &lv->segments) { for (s = 0; s < seg->area_count; s++) { - if (seg->area[s].type != AREA_PV) + if (seg_type(seg, s) != AREA_PV) continue; /* FIXME Also check for segs on deleted LVs */ - pv = seg->area[s].u.pv.pvseg->pv; + pv = seg_pv(seg, s); if (!pv || !pv->dev) { if (!_remove_lv(cmd, lv, &list_unsafe)) { stack; diff --git a/tools/vgsplit.c b/tools/vgsplit.c index 4762ebd5..cf19ba1c 100644 --- a/tools/vgsplit.c +++ b/tools/vgsplit.c @@ -78,10 +78,10 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to) list_iterate_items(seg, &lv->segments) { for (s = 0; s < seg->area_count; s++) { /* FIXME Check AREA_LV too */ - if (seg->area[s].type != AREA_PV) + if (seg_type(seg, s) != AREA_PV) continue; - pv = seg->area[s].u.pv.pvseg->pv; + pv = seg_pv(seg, s); if (vg_with) { if (!pv_is_in_vg(vg_with, pv)) { log_error("Logical Volume %s " |