diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 6e8e851d8..e4ba73f2a 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -445,8 +445,19 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task) } /* - * Do we want a specific minor number ? + * Do we want a specific device number ? */ + if (dl->lv->major >= 0 && _get_flag(dl, VISIBLE)) { + if (!dm_task_set_major(dmt, dl->lv->major)) { + log_error("Failed to set major number for %s to %d " + "during activation.", dl->name, + dl->lv->major); + goto out; + } else + log_very_verbose("Set major number for %s to %d.", + dl->name, dl->lv->major); + } + if (dl->lv->minor >= 0 && _get_flag(dl, VISIBLE)) { if (!dm_task_set_minor(dmt, dl->lv->minor)) { log_error("Failed to set minor number for %s to %d " diff --git a/lib/config/defaults.h b/lib/config/defaults.h index 7961645e2..5f643c34d 100644 --- a/lib/config/defaults.h +++ b/lib/config/defaults.h @@ -71,7 +71,7 @@ #define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free" #define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size" -#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_minor,origin,snap_percent,lv_uuid" +#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,origin,snap_percent,lv_uuid" #define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid" #define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid" #define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize" diff --git a/lib/display/display.c b/lib/display/display.c index c860a32f9..7853faef7 100644 --- a/lib/display/display.c +++ b/lib/display/display.c @@ -461,8 +461,11 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv, log_print("Allocation %s", get_alloc_string(lv->alloc)); log_print("Read ahead sectors %u", lv->read_ahead); - if (lv->status & FIXED_MINOR) + if (lv->status & FIXED_MINOR) { + if (lv->major >= 0) + log_print("Persistent major %d", lv->major); log_print("Persistent minor %d", lv->minor); + } if (inkernel) log_print("Block device %d:%d", info.major, diff --git a/lib/format1/import-export.c b/lib/format1/import-export.c index 0fb5f3d79..3d0bc77dd 100644 --- a/lib/format1/import-export.c +++ b/lib/format1/import-export.c @@ -288,8 +288,11 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd) if (lvd->lv_status & LV_PERSISTENT_MINOR) { lv->status |= FIXED_MINOR; lv->minor = MINOR(lvd->lv_dev); - } else + lv->major = MAJOR(lvd->lv_dev); + } else { + lv->major = -1; lv->minor = -1; + } if (lvd->lv_access & LV_READ) lv->status |= LVM_READ; @@ -335,7 +338,7 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg, if (lv->status & FIXED_MINOR) { lvd->lv_status |= LV_PERSISTENT_MINOR; - lvd->lv_dev = MKDEV(0, lv->minor); + lvd->lv_dev = MKDEV(lv->major, lv->minor); } lvd->lv_read_ahead = lv->read_ahead; diff --git a/lib/format_text/export.c b/lib/format_text/export.c index 50b36a346..66609d397 100644 --- a/lib/format_text/export.c +++ b/lib/format_text/export.c @@ -547,6 +547,8 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg) get_alloc_string(lv->alloc)); if (lv->read_ahead) _outf(f, "read_ahead = %u", lv->read_ahead); + if (lv->major >= 0) + _outf(f, "major = %d", lv->major); if (lv->minor >= 0) _outf(f, "minor = %d", lv->minor); _outf(f, "segment_count = %u", _count_segments(lv)); diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index bf1e0b5a3..c10d765fb 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -532,9 +532,15 @@ static int _read_lv(struct format_instance *fid, struct pool *mem, if ((lv->status & FIXED_MINOR) && !_read_int32(lvn, "minor", &lv->minor)) { log_error("Couldn't read minor number for logical " - "volume."); + "volume %s.", lv->name); return 0; } + lv->major = -1; + if ((lv->status & FIXED_MINOR) && + !_read_int32(lvn, "major", &lv->major)) { + log_error("Couldn't read major number for logical " + "volume %s.", lv->name); + } vg->lv_count++; list_add(&vg->lvs, &lvl->list); diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 3fc8a7123..120ea4aee 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -425,6 +425,7 @@ struct logical_volume *lv_create(struct format_instance *fi, lv->status = status; lv->alloc = alloc; lv->read_ahead = 0; + lv->major = -1; lv->minor = -1; lv->size = (uint64_t) extents *vg->extent_size; lv->le_count = extents; diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index a99c7c37e..7c0c836d9 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -196,6 +196,7 @@ struct logical_volume { uint32_t status; alloc_policy_t alloc; uint32_t read_ahead; + int32_t major; int32_t minor; uint64_t size; diff --git a/lib/report/columns.h b/lib/report/columns.h index b2eb3cad2..3aa89670a 100644 --- a/lib/report/columns.h +++ b/lib/report/columns.h @@ -7,9 +7,12 @@ /* Report type, Containing struct, Field type, Report heading, * Data field with struct to pass to display function, Minimum display width, * Display Fn, Unique format identifier */ + +/* *INDENT-OFF* */ FIELD(LVS, lv, STR, "LV UUID", lvid.id[1], 38, uuid, "lv_uuid") FIELD(LVS, lv, STR, "LV", name, 4, string, "lv_name") FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, "lv_attr") +FIELD(LVS, lv, NUM, "Maj", major, 3, int32, "lv_major") FIELD(LVS, lv, NUM, "Min", minor, 3, int32, "lv_minor") FIELD(LVS, lv, NUM, "LSize", size, 5, size64, "lv_size") FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, "seg_count") @@ -49,4 +52,4 @@ FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize") FIELD(SEGS, seg, NUM, "Chunk", chunk_size, 5, size32, "chunksize") FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start") FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size") - +/* *INDENT-ON* */ diff --git a/tools/args.h b/tools/args.h index 326319018..df6c46604 100644 --- a/tools/args.h +++ b/tools/args.h @@ -8,6 +8,7 @@ * Put all long args that don't have a * corresponding short option first ... */ +/* *INDENT-OFF* */ arg(version_ARG, '\0', "version", NULL) arg(quiet_ARG, '\0', "quiet", NULL) arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", size_mb_arg) @@ -61,6 +62,7 @@ arg(list_ARG, 'l', "list", NULL) 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(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg) arg(minor_ARG, 'm', "minor", minor_arg) arg(maps_ARG, 'm', "maps", NULL) @@ -94,3 +96,4 @@ arg(zero_ARG, 'Z', "zero", yes_no_arg) /* this should always be last */ arg(ARG_COUNT, '-', "", NULL) +/* *INDENT-ON* */ diff --git a/tools/commands.h b/tools/commands.h index 4d8f9fd49..a4bd1bcc2 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -56,7 +56,7 @@ xx(lvchange, "\t[-d|--debug]\n" "\t[-h|--help]\n" "\t[--ignorelockingfailure]\n" - "\t[-M|--persistent y|n] [--minor minor]\n" + "\t[-M|--persistent y|n] [--major major] [--minor minor]\n" "\t[-P|--partial] " "\n" "\t[-p|--permission r|rw]\n" "\t[-r|--readahead ReadAheadSectors]\n" @@ -66,7 +66,7 @@ xx(lvchange, "\tLogicalVolume[Path] [LogicalVolume[Path]...]\n", autobackup_ARG, available_ARG, contiguous_ARG, - ignorelockingfailure_ARG, minor_ARG, partial_ARG, permission_ARG, + ignorelockingfailure_ARG, major_ARG, minor_ARG, partial_ARG, permission_ARG, persistent_ARG, readahead_ARG, test_ARG) xx(lvcreate, @@ -79,7 +79,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[-M|--persistent {y|n}] [--major major] [--minor minor]\n" "\t[-n|--name LogicalVolumeName]\n" "\t[-p|--permission {r|rw}]\n" "\t[-r|--readahead ReadAheadSectors]\n" @@ -98,7 +98,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[-M|--persistent {y|n}] [--major major] [--minor minor]\n" "\t[-n|--name LogicalVolumeName]\n" "\t[-p|--permission {r|rw}]\n" "\t[-r|--readahead ReadAheadSectors]\n" @@ -107,7 +107,7 @@ xx(lvcreate, "\t[--version]\n" "\tOriginalLogicalVolume[Path] [PhysicalVolumePath...]\n\n", - autobackup_ARG, chunksize_ARG, contiguous_ARG, extents_ARG, minor_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, zero_ARG) diff --git a/tools/lvchange.c b/tools/lvchange.c index 00010c047..b35c9bebb 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -80,10 +80,6 @@ static int lvchange_availability(struct cmd_context *cmd, if (strcmp(arg_str_value(cmd, available_ARG, "n"), "n")) activate = 1; - if (arg_count(cmd, minor_ARG)) { - lv->minor = arg_int_value(cmd, minor_ARG, -1); - } - if (activate) { /* FIXME Tighter locking if lv_is_origin() */ log_verbose("Activating logical volume \"%s\"", lv->name); @@ -218,12 +214,18 @@ static int lvchange_persistent(struct cmd_context *cmd, } lv->status &= ~FIXED_MINOR; lv->minor = -1; - log_verbose("Disabling persistent minor for \"%s\"", lv->name); + lv->major = -1; + log_verbose("Disabling persistent device number for \"%s\"", + lv->name); } else { - if (!arg_count(cmd, minor_ARG)) { + if (!arg_count(cmd, minor_ARG) && lv->minor < 0) { log_error("Minor number must be specified with -My"); return 0; } + if (!arg_count(cmd, major_ARG) && lv->major < 0) { + log_error("Major number must be specified with -My"); + return 0; + } log_verbose("Ensuring %s is inactive. Reactivate with -ay.", lv->name); if (!lock_vol(cmd, lv->lvid.s, LCK_LV_DEACTIVATE)) { @@ -231,9 +233,10 @@ static int lvchange_persistent(struct cmd_context *cmd, return 0; } lv->status |= FIXED_MINOR; - lv->minor = arg_int_value(cmd, minor_ARG, -1); - log_verbose("Setting persistent minor number to %d for \"%s\"", - lv->minor, lv->name); + lv->minor = arg_int_value(cmd, minor_ARG, lv->minor); + lv->major = arg_int_value(cmd, major_ARG, lv->major); + log_verbose("Setting persistent device number to (%d, %d) " + "for \"%s\"", lv->major, lv->minor, lv->name); } if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) { @@ -333,8 +336,10 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv) { if (!arg_count(cmd, available_ARG) && !arg_count(cmd, contiguous_ARG) && !arg_count(cmd, permission_ARG) && !arg_count(cmd, readahead_ARG) - && !arg_count(cmd, minor_ARG) && !arg_count(cmd, persistent_ARG)) { - log_error("One or more of -a, -C, -m, -M, -p or -r required"); + && !arg_count(cmd, minor_ARG) && !arg_count(cmd, major_ARG) + && !arg_count(cmd, persistent_ARG)) { + log_error + ("One or more of -a, -C, -j, -m, -M, -p or -r required"); return EINVALID_CMD_LINE; } @@ -350,6 +355,12 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv) return EINVALID_CMD_LINE; } + if ((arg_count(cmd, minor_ARG) || arg_count(cmd, major_ARG)) && + !arg_count(cmd, persistent_ARG)) { + log_error("--major and --minor require -My"); + return EINVALID_CMD_LINE; + } + if (arg_count(cmd, minor_ARG) && argc != 1) { log_error("Only give one logical volume when specifying minor"); return EINVALID_CMD_LINE; diff --git a/tools/lvcreate.c b/tools/lvcreate.c index 1b92fc7f4..83fea1f5f 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -14,6 +14,7 @@ struct lvcreate_params { int snapshot; int zero; int contiguous; + int major; int minor; char *origin; @@ -258,6 +259,7 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd, lp->permission = LVM_READ | LVM_WRITE; lp->minor = arg_int_value(cmd, minor_ARG, -1); + lp->major = arg_int_value(cmd, major_ARG, -1); /* Persistent minor */ if (arg_count(cmd, persistent_ARG)) { @@ -267,9 +269,15 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd, "--minor when using -My"); return 0; } + if (lp->major == -1) { + log_error("Please specify major number with " + "--major when using -My"); + return 0; + } } else { - if (lp->minor != -1) { - log_error("--minor not possible with -Mn"); + if ((lp->minor != -1) || (lp->major != -1)) { + log_error + ("--major and --minor incompatible with -Mn"); return 0; } } @@ -432,9 +440,11 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) } if (lp->minor >= 0) { + lv->major = lp->major; lv->minor = lp->minor; lv->status |= FIXED_MINOR; - log_verbose("Setting minor number to %d", lv->minor); + log_verbose("Setting device number to (%d, %d)", lv->major, + lv->minor); } if (!archive(vg)) diff --git a/tools/lvm.c b/tools/lvm.c index b94e98a0d..302c6aa48 100644 --- a/tools/lvm.c +++ b/tools/lvm.c @@ -213,6 +213,23 @@ int minor_arg(struct cmd_context *cmd, struct arg *a) return 1; } +int major_arg(struct cmd_context *cmd, 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("Major number outside range 0-255"); + return 0; + } + + /* FIXME Also Check against /proc/devices */ + + return 1; +} + int string_arg(struct cmd_context *cmd, struct arg *a) { return 1; diff --git a/tools/tools.h b/tools/tools.h index 7f131b2d4..873bad48b 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -101,6 +101,7 @@ int size_kb_arg(struct cmd_context *cmd, struct arg *a); int size_mb_arg(struct cmd_context *cmd, struct arg *a); int int_arg(struct cmd_context *cmd, struct arg *a); int int_arg_with_sign(struct cmd_context *cmd, struct arg *a); +int major_arg(struct cmd_context *cmd, struct arg *a); int minor_arg(struct cmd_context *cmd, struct arg *a); int string_arg(struct cmd_context *cmd, struct arg *a); int permission_arg(struct cmd_context *cmd, struct arg *a);