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);