[PATCH] md: Allow setting persistent superblock version for md= command line

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This allows for setting a superblock version on the kernel command line to be
able to assemble version >=1.0 arrays. It can optionally be set like this:

md=vX.X,...

This will set the version of the array before assembly so it can be assembled
correctly.

Also updated docs accordingly.

Signed-off-by: Jeremias Stotter <jeremias@xxxxxxxx>
---
 Documentation/admin-guide/md.rst |  8 ++++
 drivers/md/md-autodetect.c       | 66 +++++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/Documentation/admin-guide/md.rst b/Documentation/admin-guide/md.rst
index 4ff2cc291d18..7b904d73ace0 100644
--- a/Documentation/admin-guide/md.rst
+++ b/Documentation/admin-guide/md.rst
@@ -23,6 +23,14 @@ or, to assemble a partitionable array::
 
   md=d<md device no.>,dev0,dev1,...,devn
 
+if you are using superblock versions greater than 0, use the following::
+
+  md=v<superblock version no.>,<md device no.>,dev0,dev1,...,devn
+
+for example, for a raid array with superblock version 1.2 it could look like this::
+
+  md=v1.2,0,/dev/sda1,/dev/sdb1
+
 ``md device no.``
 +++++++++++++++++
 
diff --git a/drivers/md/md-autodetect.c b/drivers/md/md-autodetect.c
index 4b80165afd23..955bf370d307 100644
--- a/drivers/md/md-autodetect.c
+++ b/drivers/md/md-autodetect.c
@@ -32,6 +32,8 @@ static struct md_setup_args {
 	int partitioned;
 	int level;
 	int chunk;
+	int major_version;
+	int minor_version;
 	char *device_names;
 } md_setup_args[256] __initdata;
 
@@ -56,6 +58,9 @@ static int md_setup_ents __initdata;
  * 2001-06-03: Dave Cinege <dcinege@xxxxxxxxxxxxx>
  *		Shifted name_to_kdev_t() and related operations to md_set_drive()
  *		for later execution. Rewrote section to make devfs compatible.
+ * 2025-08-24: Jeremias Stotter <jeremias@xxxxxxxx>
+ *              Allow setting of the superblock version:
+ *              md=vX.X,...
  */
 static int __init md_setup(char *str)
 {
@@ -63,6 +68,54 @@ static int __init md_setup(char *str)
 	char *pername = "";
 	char *str1;
 	int ent;
+	int major_i = 0, minor_i = 0;
+
+	if (*str == 'v') {
+		char *version = ++str;
+		char *version_end = strchr(str, ',');
+
+		if (!version_end) {
+			printk(KERN_WARNING
+			       "md: Version (%s) has been specified wrong, no ',' found, use like this: md=vX.X,...\n",
+			       version);
+			return 0;
+		}
+		*version_end = '\0';
+		str = version_end + 1;
+
+		char *separator = strchr(version, '.');
+
+		if (!separator) {
+			printk(KERN_WARNING
+			       "md: Version (%s) has been specified wrong, no '.' to separate major and minor version found, use like this: md=vX.X,...\n",
+			       version);
+			return 0;
+		}
+		*separator = '\0';
+		char *minor_s = separator + 1;
+
+		int ret = kstrtoint(version, 10, &major_i);
+
+		if (ret != 0) {
+			printk(KERN_WARNING
+			       "md: Version has been specified wrong, couldn't convert major '%s' to number, use like this: md=vX.X,...\n",
+			       version);
+			return 0;
+		}
+		if (major_i != 0 && major_i != 1) {
+			printk(KERN_WARNING
+			       "md: Major version %d is not valid, use 0 or 1\n",
+			       major_i);
+			return 0;
+		}
+		ret = kstrtoint(minor_s, 10, &minor_i);
+		if (ret != 0) {
+			printk(KERN_WARNING
+			       "md: Version has been specified wrong, couldn't convert minor '%s' to number, use like this: md=vX.X,...\n",
+			       minor_s);
+			return 0;
+		}
+	}
 
 	if (*str == 'd') {
 		partitioned = 1;
@@ -116,6 +169,8 @@ static int __init md_setup(char *str)
 	md_setup_args[ent].device_names = str;
 	md_setup_args[ent].partitioned = partitioned;
 	md_setup_args[ent].minor = minor;
+	md_setup_args[ent].minor_version = minor_i;
+	md_setup_args[ent].major_version = major_i;
 
 	return 1;
 }
@@ -200,6 +255,9 @@ static void __init md_setup_drive(struct md_setup_args *args)
 
 	err = md_set_array_info(mddev, &ainfo);
 
+	mddev->major_version = args->major_version;
+	mddev->minor_version = args->minor_version;
+
 	for (i = 0; i <= MD_SB_DISKS && devices[i]; i++) {
 		struct mdu_disk_info_s dinfo = {
 			.major	= MAJOR(devices[i]),
@@ -273,11 +331,15 @@ void __init md_run_setup(void)
 {
 	int ent;
 
+	/*
+	 * Assemble manually defined raids first
+	 */
+	for (ent = 0; ent < md_setup_ents; ent++)
+		md_setup_drive(&md_setup_args[ent]);
+
 	if (raid_noautodetect)
 		printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=autodetect will force)\n");
 	else
 		autodetect_raid();
 
-	for (ent = 0; ent < md_setup_ents; ent++)
-		md_setup_drive(&md_setup_args[ent]);
 }
-- 
2.49.1





[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux