mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Basic support for persistent minor numbers;
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
This commit is contained in:
parent
dcde8bf026
commit
812c699c8d
@ -13,6 +13,7 @@
|
||||
#include "names.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <linux/kdev_t.h>
|
||||
|
||||
|
||||
int library_version(char *version, size_t size)
|
||||
@ -278,13 +279,23 @@ int _load(struct logical_volume *lv, int task)
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -353,6 +353,9 @@ int lvdisplay_full(struct logical_volume *lv)
|
||||
|
||||
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) ");
|
||||
|
@ -40,6 +40,7 @@
|
||||
/* 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 /* " */
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <linux/kdev_t.h>
|
||||
|
||||
static int _check_vg_name(const char *name)
|
||||
{
|
||||
@ -280,6 +281,12 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
|
||||
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;
|
||||
|
||||
@ -338,6 +345,11 @@ void export_lv(struct lv_disk *lvd, struct volume_group *vg,
|
||||
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;
|
||||
|
@ -351,6 +351,8 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
|
||||
_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);
|
||||
|
||||
|
@ -43,6 +43,7 @@ static struct flag _lv_flags[] = {
|
||||
{ALLOC_CONTIGUOUS, "ALLOC_CONTIGUOUS"},
|
||||
{SNAPSHOT, "SNASHOT"},
|
||||
{SNAPSHOT_ORG, "SNAPSHOT_ORIGIN"},
|
||||
{FIXED_MINOR, "FIXED_MINOR"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
|
@ -371,6 +371,13 @@ static int _read_lv(struct pool *mem,
|
||||
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.");
|
||||
@ -440,7 +447,21 @@ static struct volume_group *_read_vg(struct pool *mem, struct config_file *cf,
|
||||
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);
|
||||
|
@ -424,6 +424,7 @@ struct logical_volume *lv_create(struct format_instance *fi,
|
||||
|
||||
lv->status = status;
|
||||
lv->read_ahead = 0;
|
||||
lv->minor = -1;
|
||||
lv->size = extents * vg->extent_size;
|
||||
lv->le_count = extents;
|
||||
lv->vg = vg;
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
#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 */
|
||||
@ -119,6 +120,7 @@ struct logical_volume {
|
||||
|
||||
uint32_t status;
|
||||
uint32_t read_ahead;
|
||||
int32_t minor;
|
||||
|
||||
uint64_t size;
|
||||
uint32_t le_count;
|
||||
|
@ -44,6 +44,8 @@ arg(lvmpartition_ARG, 'l', "lvmpartition", NULL)
|
||||
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)
|
||||
|
@ -53,6 +53,7 @@ xx(lvchange,
|
||||
"\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"
|
||||
@ -60,7 +61,8 @@ xx(lvchange,
|
||||
"\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,
|
||||
@ -73,6 +75,7 @@ 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"
|
||||
@ -96,8 +99,9 @@ chunksize_ARG,
|
||||
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,
|
||||
|
@ -25,12 +25,14 @@ static int lvchange_permission(struct logical_volume *lv);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -39,6 +41,11 @@ int lvchange(int argc, char **argv)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -49,9 +56,9 @@ static int lvchange_single(struct logical_volume *lv)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -62,7 +69,8 @@ static int lvchange_single(struct logical_volume *lv)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -90,6 +98,14 @@ static int lvchange_single(struct logical_volume *lv)
|
||||
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);
|
||||
|
||||
@ -147,18 +163,24 @@ static int lvchange_availability(struct logical_volume *lv)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -261,3 +283,40 @@ static int lvchange_readahead(struct logical_volume *lv)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -213,6 +213,24 @@ int lvcreate(int argc, char **argv)
|
||||
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;
|
||||
|
15
tools/lvm.c
15
tools/lvm.c
@ -294,6 +294,21 @@ int int_arg_with_sign(struct arg *a)
|
||||
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;
|
||||
|
@ -109,6 +109,7 @@ int yes_no_arg(struct arg *a);
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user