summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAlasdair Kergon <agk@redhat.com>2005-06-01 16:51:55 +0000
committerAlasdair Kergon <agk@redhat.com>2005-06-01 16:51:55 +0000
commit60f13f01d2af1cb1b05c20b11285c7c6c15acd6b (patch)
tree32895b7e9cb063b88bd00c568dc59f949cc716f2 /tools
parent8e6230ddd981539221bc82ed71ed9f2308148e2c (diff)
downloadlvm2-60f13f01d2af1cb1b05c20b11285c7c6c15acd6b.tar.gz
lvm2-60f13f01d2af1cb1b05c20b11285c7c6c15acd6b.tar.xz
lvm2-60f13f01d2af1cb1b05c20b11285c7c6c15acd6b.zip
Basic support for mirrors.
Diffstat (limited to 'tools')
-rw-r--r--tools/args.h2
-rw-r--r--tools/commands.h8
-rw-r--r--tools/lvchange.c6
-rw-r--r--tools/lvcreate.c188
-rw-r--r--tools/lvremove.c6
-rw-r--r--tools/toollib.c8
-rw-r--r--tools/vgchange.c4
-rw-r--r--tools/vgreduce.c4
-rw-r--r--tools/vgsplit.c4
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 "