From 812c699c8d7fb0c0c57abeba1d39b21bfd0d9917 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Fri, 1 Feb 2002 17:54:39 +0000 Subject: [PATCH] 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 --- lib/activate/activate.c | 15 +++++++- lib/display/display.c | 3 ++ lib/format1/disk-rep.h | 1 + lib/format1/import-export.c | 12 ++++++ lib/format_text/export.c | 2 + lib/format_text/flags.c | 1 + lib/format_text/import.c | 21 +++++++++++ lib/metadata/lv_manip.c | 1 + lib/metadata/metadata.h | 2 + tools/args.h | 2 + tools/commands.h | 8 +++- tools/lvchange.c | 75 +++++++++++++++++++++++++++++++++---- tools/lvcreate.c | 18 +++++++++ tools/lvm.c | 15 ++++++++ tools/tools.h | 1 + 15 files changed, 165 insertions(+), 12 deletions(-) diff --git a/lib/activate/activate.c b/lib/activate/activate.c index fd2d250fc..2b673b6ca 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -13,6 +13,7 @@ #include "names.h" #include +#include 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; diff --git a/lib/display/display.c b/lib/display/display.c index 8fed0140b..07c8bdb4d 100644 --- a/lib/display/display.c +++ b/lib/display/display.c @@ -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) "); diff --git a/lib/format1/disk-rep.h b/lib/format1/disk-rep.h index c1fcc825f..fa42d7716 100644 --- a/lib/format1/disk-rep.h +++ b/lib/format1/disk-rep.h @@ -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 /* " */ diff --git a/lib/format1/import-export.c b/lib/format1/import-export.c index d1c74b4cf..8cec06fb1 100644 --- a/lib/format1/import-export.c +++ b/lib/format1/import-export.c @@ -16,6 +16,7 @@ #include #include +#include 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; diff --git a/lib/format_text/export.c b/lib/format_text/export.c index 45bff0666..343f0964d 100644 --- a/lib/format_text/export.c +++ b/lib/format_text/export.c @@ -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); diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c index 9a9630e40..b31491d35 100644 --- a/lib/format_text/flags.c +++ b/lib/format_text/flags.c @@ -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} }; diff --git a/lib/format_text/import.c b/lib/format_text/import.c index 6066ae050..4623419b5 100644 --- a/lib/format_text/import.c +++ b/lib/format_text/import.c @@ -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); diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 0022bf144..a99c14ac1 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -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; diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index cdd18b11a..ed2be736a 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -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; diff --git a/tools/args.h b/tools/args.h index 700c90ef2..67f98d19e 100644 --- a/tools/args.h +++ b/tools/args.h @@ -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) diff --git a/tools/commands.h b/tools/commands.h index 4a1bb84d1..6e5049c12 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -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, diff --git a/tools/lvchange.c b/tools/lvchange.c index abb1470c1..3272a2eb7 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -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; +} + diff --git a/tools/lvcreate.c b/tools/lvcreate.c index c852abc1e..979130fb0 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -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; diff --git a/tools/lvm.c b/tools/lvm.c index 9adc26c27..3d84cab3e 100644 --- a/tools/lvm.c +++ b/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; diff --git a/tools/tools.h b/tools/tools.h index 73006c294..bebee43f7 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -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); -- 2.43.5