linux-raid.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] md: Allow setting persistent superblock version for md= command line
@ 2025-08-25 11:34 Jeremias Stotter
  2025-08-25 11:58 ` Paul Menzel
  0 siblings, 1 reply; 3+ messages in thread
From: Jeremias Stotter @ 2025-08-25 11:34 UTC (permalink / raw)
  To: linux-raid; +Cc: Jeremias Stotter

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.

v2: Use pr_warn instead of printk

Signed-off-by: Jeremias Stotter <jeremias@jears.at>
---
 Documentation/admin-guide/md.rst |  8 +++++
 drivers/md/md-autodetect.c       | 61 ++++++++++++++++++++++++++++++--
 2 files changed, 67 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..4c4775c33963 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@psychosis.com>
  *		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@jears.at>
+ *              Allow setting of the superblock version:
+ *              md=vX.X,...
  */
 static int __init md_setup(char *str)
 {
@@ -63,6 +68,49 @@ 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) {
+			pr_warn("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) {
+			pr_warn("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) {
+			pr_warn("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) {
+			pr_warn("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) {
+			pr_warn("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 +164,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 +250,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 +326,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


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] md: Allow setting persistent superblock version for md= command line
  2025-08-25 11:34 [PATCH v2] md: Allow setting persistent superblock version for md= command line Jeremias Stotter
@ 2025-08-25 11:58 ` Paul Menzel
  2025-08-25 13:34   ` jeremias
  0 siblings, 1 reply; 3+ messages in thread
From: Paul Menzel @ 2025-08-25 11:58 UTC (permalink / raw)
  To: Jeremias Stotter; +Cc: linux-raid

Dear Jeremias,


Thank you very much for your patch, and welcome to the Linux kernel 
community!

Am 25.08.25 um 13:34 schrieb Jeremias Stotter:
> 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:

Could you start by describing the problem. I am using several systems, 
where arrays with version ≥ can be assembled. What am I missing?

> 
> md=vX.X,...
> 
> This will set the version of the array before assembly so it can be assembled
> correctly.
> 
> Also updated docs accordingly.
> 
> v2: Use pr_warn instead of printk
> 
> Signed-off-by: Jeremias Stotter <jeremias@jears.at>
> ---
>   Documentation/admin-guide/md.rst |  8 +++++
>   drivers/md/md-autodetect.c       | 61 ++++++++++++++++++++++++++++++--
>   2 files changed, 67 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
> +

Why not keep the pattern of the other options to specify <md device no.> 
first?

>   ``md device no.``
>   +++++++++++++++++
>   
> diff --git a/drivers/md/md-autodetect.c b/drivers/md/md-autodetect.c
> index 4b80165afd23..4c4775c33963 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@psychosis.com>
>    *		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@jears.at>
> + *              Allow setting of the superblock version:
> + *              md=vX.X,...

I believe since git (and BitKeeper before) being used, these headers are 
not updated any more.

>    */
>   static int __init md_setup(char *str)
>   {
> @@ -63,6 +68,49 @@ 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) {
> +			pr_warn("md: Version (%s) has been specified wrong, no ',' found, use like this: md=vX.X,...\n",

s/wrong/incorrectly/?

Or wrong*ly*. Same below.

> +				version);
> +			return 0;
> +		}
> +		*version_end = '\0';
> +		str = version_end + 1;
> +
> +		char *separator = strchr(version, '.');
> +
> +		if (!separator) {
> +			pr_warn("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) {
> +			pr_warn("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) {
> +			pr_warn("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) {
> +			pr_warn("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 +164,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 +250,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 +326,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]);
>   }


Kind regards,

Paul

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] md: Allow setting persistent superblock version for md= command line
  2025-08-25 11:58 ` Paul Menzel
@ 2025-08-25 13:34   ` jeremias
  0 siblings, 0 replies; 3+ messages in thread
From: jeremias @ 2025-08-25 13:34 UTC (permalink / raw)
  To: Paul Menzel; +Cc: linux-raid

On 2025-08-25 13:58, Paul Menzel wrote:
> Dear Jeremias,
> 
> 
> Thank you very much for your patch, and welcome to the Linux kernel 
> community!
> 
> Am 25.08.25 um 13:34 schrieb Jeremias Stotter:
>> 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:
> 
> Could you start by describing the problem. I am using several systems, 
> where arrays with version ≥ can be assembled. What am I missing?
> 
>> 
>> md=vX.X,...
>> 
>> This will set the version of the array before assembly so it can be 
>> assembled
>> correctly.
>> 
>> Also updated docs accordingly.
>> 
>> v2: Use pr_warn instead of printk
>> 
>> Signed-off-by: Jeremias Stotter <jeremias@jears.at>
>> ---
>>   Documentation/admin-guide/md.rst |  8 +++++
>>   drivers/md/md-autodetect.c       | 61 
>> ++++++++++++++++++++++++++++++--
>>   2 files changed, 67 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
>> +
> 
> Why not keep the pattern of the other options to specify <md device 
> no.> first?
> 
>>   ``md device no.``
>>   +++++++++++++++++
>>   diff --git a/drivers/md/md-autodetect.c b/drivers/md/md-autodetect.c
>> index 4b80165afd23..4c4775c33963 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@psychosis.com>
>>    *		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@jears.at>
>> + *              Allow setting of the superblock version:
>> + *              md=vX.X,...
> 
> I believe since git (and BitKeeper before) being used, these headers 
> are not updated any more.
> 
>>    */
>>   static int __init md_setup(char *str)
>>   {
>> @@ -63,6 +68,49 @@ 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) {
>> +			pr_warn("md: Version (%s) has been specified wrong, no ',' found, 
>> use like this: md=vX.X,...\n",
> 
> s/wrong/incorrectly/?
> 
> Or wrong*ly*. Same below.
> 
>> +				version);
>> +			return 0;
>> +		}
>> +		*version_end = '\0';
>> +		str = version_end + 1;
>> +
>> +		char *separator = strchr(version, '.');
>> +
>> +		if (!separator) {
>> +			pr_warn("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) {
>> +			pr_warn("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) {
>> +			pr_warn("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) {
>> +			pr_warn("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 +164,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 +250,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 +326,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]);
>>   }
> 
> 
> Kind regards,
> 
> Paul
Hello Paul,

thanks for the feedback! This is my first patch, please excuse me for 
not being familiar with the kernel development process yet.
This is relevant, for example, when using an array with version 1.2 as 
root.
When assembling an array without an initrd that is version 1.2 for 
example, you get an invalid version 0.0 superblock error as the kernel 
tries to assemble the array with that version. There is no way right now 
to specify the superblock version from the kernel command line alone, so 
the array is just never assembled. Or am I missing something?

I will be sending you a patch taking into account your other concerns.

Kind regards,

Jeremias

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-08-25 13:35 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-25 11:34 [PATCH v2] md: Allow setting persistent superblock version for md= command line Jeremias Stotter
2025-08-25 11:58 ` Paul Menzel
2025-08-25 13:34   ` jeremias

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).