slightly different from the current LVM1 method.
lvcreate --persistent y --minor 10 (to specify when created)
lvchange --persistent n (to turn off)
lvchange --persistent y --minor 11 (to change)
--persistent uses a new LV status flag stored on disk
minor number is stored on disk the same way as LVM1 does
(but major number stored is 0; any LVM1 major/minor setting gets lost)
lvchange -ay --minor 12 (to activate using minor 12, regardless of the
on-disk setting, which doesn't get changed)
--minor == -m
--persistent == -M
#include "names.h"
#include <limits.h>
+#include <linux/kdev_t.h>
int library_version(char *version, size_t size)
}
if (!((lv->status & LVM_WRITE) && (lv->vg->status & LVM_WRITE))) {
- if (!dm_task_set_ro(dmt))
+ if (!dm_task_set_ro(dmt)) {
log_error("Failed to set %s read-only during "
"activation.", lv->name);
- else
+ goto out;
+ } else
log_very_verbose("Activating %s read-only", lv->name);
}
+ if (lv->minor) {
+ if (!dm_task_set_minor(dmt, MINOR(lv->minor))) {
+ log_error("Failed to set minor number for %s to %d "
+ "during activation.", lv->name, lv->minor);
+ goto out;
+ } else
+ log_very_verbose("Set minor number for %s to %d.",
+ lv->name, lv->minor);
+ }
if (!(r = dm_task_run(dmt)))
stack;
log_print("Read ahead sectors %u", lv->read_ahead);
+ if (lv->status & FIXED_MINOR)
+ log_print("Persistent minor %d", lv->minor);
+
/****************
#ifdef LVM_FUTURE
printf("IO Timeout (seconds) ");
/* logical volume */
#define LV_ACTIVE 0x01 /* lv_status */
#define LV_SPINDOWN 0x02 /* " */
+#define LV_PERSISTENT_MINOR 0x04 /* " */
#define LV_READ 0x01 /* lv_access */
#define LV_WRITE 0x02 /* " */
#include <time.h>
#include <sys/utsname.h>
+#include <linux/kdev_t.h>
static int _check_vg_name(const char *name)
{
if (lvd->lv_status & LV_SPINDOWN)
lv->status |= SPINDOWN_LV;
+ if (lvd->lv_status & LV_PERSISTENT_MINOR) {
+ lv->status |= FIXED_MINOR;
+ lv->minor = MINOR(lvd->lv_dev);
+ } else
+ lv->minor = -1;
+
if (lvd->lv_access & LV_READ)
lv->status |= LVM_READ;
if (lv->status & SPINDOWN_LV)
lvd->lv_status |= LV_SPINDOWN;
+ if (lv->status & FIXED_MINOR) {
+ lvd->lv_status |= LV_PERSISTENT_MINOR;
+ lvd->lv_dev = MKDEV(0, lv->minor);
+ }
+
lvd->lv_read_ahead = lv->read_ahead;
lvd->lv_stripes = list_item(lv->segments.n,
struct stripe_segment)->stripes;
_out(f, "status = %s", buffer);
_out(f, "read_ahead = %u", lv->read_ahead);
+ if (lv->minor >= 0)
+ _out(f, "minor = %d", lv->minor);
_out(f, "segment_count = %u", _count_segments(lv));
_nl(f);
{ALLOC_CONTIGUOUS, "ALLOC_CONTIGUOUS"},
{SNAPSHOT, "SNASHOT"},
{SNAPSHOT_ORG, "SNAPSHOT_ORIGIN"},
+ {FIXED_MINOR, "FIXED_MINOR"},
{0, NULL}
};
return 0;
}
+ lv->minor = -1;
+ if ((lv->status & FIXED_MINOR) &&
+ !_read_int32(lvn, "minor", &lv->minor)) {
+ log_error("Couldn't read 'minor' value for logical volume.");
+ return 0;
+ }
+
if (!_read_int32(lvn, "read_ahead", &lv->read_ahead)) {
log_err("Couldn't read 'read_ahead' value for "
"logical volume.");
goto bad;
}
+ if (!(vg->system_id = pool_zalloc(mem, NAME_LEN))) {
+ stack;
+ goto bad;
+ }
+
vgn = vgn->child;
+
+ if ((cn = find_config_node(vgn, "system_id", '/')) && cn->v) {
+ if (!cn->v->v.str) {
+ log_error("system_id must be a string");
+ goto bad;
+ }
+ strncpy(vg->system_id, cn->v->v.str, NAME_LEN);
+ }
+
if (!_read_id(&vg->id, vgn, "id")) {
log_err("Couldn't read uuid for volume group %s.",
vg->name);
lv->status = status;
lv->read_ahead = 0;
+ lv->minor = -1;
lv->size = extents * vg->extent_size;
lv->le_count = extents;
lv->vg = vg;
#define SPINDOWN_LV 0x00000010 /* LV */
#define BADBLOCK_ON 0x00000020 /* LV */
+#define FIXED_MINOR 0x00000080 /* LV */
/* FIXME: do we really set read/write for a whole vg ? */
#define LVM_READ 0x00000100 /* LV VG */
uint32_t status;
uint32_t read_ahead;
+ int32_t minor;
uint64_t size;
uint32_t le_count;
arg(list_ARG, 'l', "list", NULL)
arg(size_ARG, 'L', "size", size_arg)
arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign)
+arg(persistent_ARG, 'M', "persistent", yes_no_arg)
+arg(minor_ARG, 'm', "minor", minor_arg)
arg(maps_ARG, 'm', "maps", NULL)
arg(name_ARG, 'n', "name", string_arg)
arg(oldpath_ARG, 'n', "oldpath", NULL)
"\t[-C/--contiguous y/n]\n"
"\t[-d/--debug]\n"
"\t[-h/-?/--help]\n"
+ "\t[-M/--persistent y/n] [--minor minor]\n"
"\t[-P/--partial] " "\n"
"\t[-p/--permission r/rw]\n"
"\t[-r/--readahead ReadAheadSectors]\n"
"\t[-v/--verbose]\n"
"\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
- autobackup_ARG, available_ARG, contiguous_ARG, partial_ARG,
+ autobackup_ARG, available_ARG, contiguous_ARG,
+ minor_ARG, persistent_ARG, partial_ARG,
permission_ARG, readahead_ARG, test_ARG)
xx(lvcreate,
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]" "\n"
"\t{-l|--extents LogicalExtentsNumber |" "\n"
"\t -L|--size LogicalVolumeSize[kKmMgGtT]} " "\n"
+ "\t[-M|--persistent {y|n}] [--minor minor]\n"
"\t[-n|--name LogicalVolumeName]" "\n"
"\t[-p|--permission {r|rw}] " "\n"
"\t[-r|--readahead ReadAheadSectors]" "\n"
snapshot_ARG,
*/
- autobackup_ARG, contiguous_ARG, stripes_ARG, stripesize_ARG,
+ autobackup_ARG, contiguous_ARG, stripes_ARG, stripesize_ARG,
extents_ARG, size_ARG, name_ARG, permission_ARG, readahead_ARG,
+ minor_ARG, persistent_ARG,
test_ARG, zero_ARG)
xx(lvdisplay,
static int lvchange_availability(struct logical_volume *lv);
static int lvchange_contiguous(struct logical_volume *lv);
static int lvchange_readahead(struct logical_volume *lv);
+static int lvchange_persistent(struct logical_volume *lv);
int lvchange(int argc, char **argv)
{
if (!arg_count(available_ARG) && !arg_count(contiguous_ARG)
- && !arg_count(permission_ARG) && !arg_count(readahead_ARG)) {
- log_error("One or more of -a, -C, -p or -r required");
+ && !arg_count(permission_ARG) && !arg_count(readahead_ARG)
+ && !arg_count(minor_ARG) && !arg_count(persistent_ARG)) {
+ log_error("One or more of -a, -C, -m, -M, -p or -r required");
return EINVALID_CMD_LINE;
}
return EINVALID_CMD_LINE;
}
+ if (arg_count(minor_ARG) && argc != 1) {
+ log_error("Only give one logical volume when specifying minor");
+ return EINVALID_CMD_LINE;
+ }
+
return process_each_lv(argc, argv, &lvchange_single);
}
if (!(lv->vg->status & LVM_WRITE) &&
(arg_count(contiguous_ARG) || arg_count(permission_ARG) ||
- arg_count(readahead_ARG))) {
- log_error("Only -a permitted with read-only volume group \"%s\"",
- lv->vg->name);
+ arg_count(readahead_ARG) || arg_count(persistent_ARG))) {
+ log_error("Only -a permitted with read-only volume "
+ "group \"%s\"", lv->vg->name);
return EINVALID_CMD_LINE;
}
}
if (lv->status & SNAPSHOT) {
- log_error("Can't change snapshot logical volume \"%s\"", lv->name);
+ log_error("Can't change snapshot logical volume \"%s\"",
+ lv->name);
return ECMD_FAILED;
}
doit += lvchange_readahead(lv);
}
+ /* read ahead sector change */
+ if (arg_count(persistent_ARG)) {
+ if (!archived && !archive(lv->vg))
+ return ECMD_FAILED;
+ archived = 1;
+ doit += lvchange_persistent(lv);
+ }
+
if (doit)
log_print("Logical volume \"%s\" changed", lv->name);
if (strcmp(arg_str_value(available_ARG, "n"), "n"))
activate = 1;
+ if (arg_count(minor_ARG)) {
+ lv->minor = arg_int_value(minor_ARG, -1);
+ }
+
if ((active = lv_active(lv)) < 0) {
log_error("Unable to determine status of \"%s\"", lv->name);
return 0;
}
if (activate && active) {
- log_verbose("Logical volume \"%s\" is already active", lv->name);
+ log_verbose("Logical volume \"%s\" is already active",
+ lv->name);
return 0;
}
if (!activate && !active) {
- log_verbose("Logical volume \"%s\" is already inactive", lv->name);
+ log_verbose("Logical volume \"%s\" is already inactive",
+ lv->name);
return 0;
}
return 1;
}
+
+static int lvchange_persistent(struct logical_volume *lv)
+{
+ if (!strcmp(arg_str_value(persistent_ARG, "n"), "n")) {
+ if (!(lv->status & FIXED_MINOR)) {
+ log_error("Minor number is already not persistent "
+ "for \"%s\"", lv->name);
+ return 0;
+ }
+ lv->status &= ~FIXED_MINOR;
+ lv->minor = -1;
+ log_verbose("Disabling persistent minor for \"%s\"", lv->name);
+ } else {
+ if (lv_active(lv)) {
+ log_error("Cannot change minor number when active");
+ return 0;
+ }
+ if (!arg_count(minor_ARG)) {
+ log_error("Minor number must be specified with -My");
+ return 0;
+ }
+ lv->status |= FIXED_MINOR;
+ lv->minor = arg_int_value(minor_ARG, -1);
+ log_verbose("Setting persistent minor number to %d for \"%s\"",
+ lv->minor, lv->name);
+ }
+
+ log_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+
+ if (!fid->ops->vg_write(fid, lv->vg))
+ return 0;
+
+ backup(lv->vg);
+
+ return 1;
+}
+
lv->read_ahead = read_ahead;
}
+ if (arg_count(minor_ARG)) {
+ lv->status |= FIXED_MINOR;
+ lv->minor = arg_int_value(minor_ARG, -1);
+ log_verbose("Setting minor number to %d", lv->minor);
+ }
+
+ if (arg_count(persistent_ARG)) {
+ if (!strcmp(arg_str_value(persistent_ARG, "n"), "n"))
+ lv->status &= ~FIXED_MINOR;
+ else
+ if (!arg_count(minor_ARG)) {
+ log_error("Please specify minor number with "
+ "--minor when using -My");
+ return ECMD_FAILED;
+ }
+ lv->status |= FIXED_MINOR;
+ }
+
/* store vg on disk(s) */
if (!fid->ops->vg_write(fid, vg))
return ECMD_FAILED;
return 1;
}
+int minor_arg(struct arg *a)
+{
+ char *ptr;
+
+ if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS))
+ return 0;
+
+ if (a->i_value > 255) {
+ log_error("Minor number outside range 0-255");
+ return 0;
+ }
+
+ return 1;
+}
+
int string_arg(struct arg *a)
{
return 1;
int size_arg(struct arg *a);
int int_arg(struct arg *a);
int int_arg_with_sign(struct arg *a);
+int minor_arg(struct arg *a);
int string_arg(struct arg *a);
int permission_arg(struct arg *a);