* [PATCH v3] md: Allow setting persistent superblock version for md= command line
[not found] <20250825144029.2924-1-jeremias@jears.at>
@ 2025-08-25 14:53 ` jeremias
2025-08-27 7:26 ` Yu Kuai
0 siblings, 1 reply; 3+ messages in thread
From: jeremias @ 2025-08-25 14:53 UTC (permalink / raw)
To: Linux Raid
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
v3: Change order of options so it stays with past pattern
Signed-off-by: Jeremias Stotter <jeremias@jears.at>
---
Documentation/admin-guide/md.rst | 8 +++++
drivers/md/md-autodetect.c | 59 ++++++++++++++++++++++++++++++--
2 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/md.rst
b/Documentation/admin-guide/md.rst
index 4ff2cc291d18..f57ae871c997 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=<md device no.>,v<superblock version no.>,dev0,dev1,...,devn
+
+for example, for a raid array with superblock version 1.2 it could look
like this::
+
+ md=0,v1.2,/dev/sda1,/dev/sdb1
+
``md device no.``
+++++++++++++++++
diff --git a/drivers/md/md-autodetect.c b/drivers/md/md-autodetect.c
index 4b80165afd23..67d38559ad50 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;
@@ -63,6 +65,7 @@ static int __init md_setup(char *str)
char *pername = "";
char *str1;
int ent;
+ int major_i = 0, minor_i = 0;
if (*str == 'd') {
partitioned = 1;
@@ -109,6 +112,49 @@ static int __init md_setup(char *str)
case 0:
md_setup_args[ent].level = LEVEL_NONE;
pername="super-block";
+
+ if (*str == 'v') { /* Superblock version */
+ char *version = ++str;
+ char *version_end = strchr(str, ',');
+
+ if (!version_end) {
+ pr_warn("md: Version (%s) has been specified wrongly, no ',' found,
use like this: md=<md dev. no.>,X.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 wrongly, no '.' to
separate major and minor version found, use like this: md=<md dev.
no.>,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 wrongly, couldn't convert
major '%s' to number, use like this: md=<md dev. no.>,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 wrongly, couldn't convert
minor '%s' to number, use like this: md=<md dev. no.>,vX.X,...\n",
+ minor_s);
+ return 0;
+ }
+ }
+
}
printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n",
@@ -116,6 +162,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 +248,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 +324,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]);
}
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v3] md: Allow setting persistent superblock version for md= command line
2025-08-25 14:53 ` [PATCH v3] md: Allow setting persistent superblock version for md= command line jeremias
@ 2025-08-27 7:26 ` Yu Kuai
2025-08-27 9:47 ` Yu Kuai
0 siblings, 1 reply; 3+ messages in thread
From: Yu Kuai @ 2025-08-27 7:26 UTC (permalink / raw)
To: jeremias, Linux Raid, yukuai (C)
Hi,
在 2025/08/25 22:53, jeremias@jears.at 写道:
> 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.
>
You should explain that current autodetect is only supported for 0.90
array.
> Also updated docs accordingly.
>
> v2: Use pr_warn instead of printk
>
> v3: Change order of options so it stays with past pattern
>
> Signed-off-by: Jeremias Stotter <jeremias@jears.at>
> ---
> Documentation/admin-guide/md.rst | 8 +++++
> drivers/md/md-autodetect.c | 59 ++++++++++++++++++++++++++++++--
> 2 files changed, 65 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/admin-guide/md.rst
> b/Documentation/admin-guide/md.rst
> index 4ff2cc291d18..f57ae871c997 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=<md device no.>,v<superblock version no.>,dev0,dev1,...,devn
> +
> +for example, for a raid array with superblock version 1.2 it could look
> like this::
> +
> + md=0,v1.2,/dev/sda1,/dev/sdb1
> +
> ``md device no.``
> +++++++++++++++++
>
What about md_autostart_arrays()? where 0.90 is still the only default
choice.
> diff --git a/drivers/md/md-autodetect.c b/drivers/md/md-autodetect.c
> index 4b80165afd23..67d38559ad50 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;
>
> @@ -63,6 +65,7 @@ static int __init md_setup(char *str)
> char *pername = "";
> char *str1;
> int ent;
> + int major_i = 0, minor_i = 0;
>
> if (*str == 'd') {
> partitioned = 1;
> @@ -109,6 +112,49 @@ static int __init md_setup(char *str)
> case 0:
> md_setup_args[ent].level = LEVEL_NONE;
> pername="super-block";
> +
> + if (*str == 'v') { /* Superblock version */
> + char *version = ++str;
> + char *version_end = strchr(str, ',');
> +
> + if (!version_end) {
> + pr_warn("md: Version (%s) has been specified wrongly,
> no ',' found, use like this: md=<md dev. no.>,X.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 wrongly,
> no '.' to separate major and minor version found, use like this: md=<md
> dev. no.>,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 wrongly,
> couldn't convert major '%s' to number, use like this: md=<md dev.
> no.>,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 wrongly,
> couldn't convert minor '%s' to number, use like this: md=<md dev.
> no.>,vX.X,...\n",
> + minor_s);
> + return 0;
> + }
> + }
> +
> }
>
> printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n",
> @@ -116,6 +162,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 +248,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;
I would expect to fix md_set_array_info() to hanlde this new case, to
make code more readable.
> +
> for (i = 0; i <= MD_SB_DISKS && devices[i]; i++) {
> struct mdu_disk_info_s dinfo = {
> .major = MAJOR(devices[i]),
> @@ -273,11 +324,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]);
> +
You just explain what you did in comment, Why do you change the order?
Thanks,
Kuai
> 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]);
> }
>
> .
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v3] md: Allow setting persistent superblock version for md= command line
2025-08-27 7:26 ` Yu Kuai
@ 2025-08-27 9:47 ` Yu Kuai
0 siblings, 0 replies; 3+ messages in thread
From: Yu Kuai @ 2025-08-27 9:47 UTC (permalink / raw)
To: Yu Kuai, jeremias, Linux Raid, yukuai (C)
Hi,
在 2025/08/27 15:26, Yu Kuai 写道:
> Hi,
>
> 在 2025/08/25 22:53, jeremias@jears.at 写道:
>> 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.
>>
>
> You should explain that current autodetect is only supported for 0.90
> array.
>
>> Also updated docs accordingly.
>>
>> v2: Use pr_warn instead of printk
>>
>> v3: Change order of options so it stays with past pattern
>>
>> Signed-off-by: Jeremias Stotter <jeremias@jears.at>
>> ---
>> Documentation/admin-guide/md.rst | 8 +++++
>> drivers/md/md-autodetect.c | 59 ++++++++++++++++++++++++++++++--
>> 2 files changed, 65 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/md.rst
>> b/Documentation/admin-guide/md.rst
>> index 4ff2cc291d18..f57ae871c997 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=<md device no.>,v<superblock version no.>,dev0,dev1,...,devn
>> +
>> +for example, for a raid array with superblock version 1.2 it could
>> look like this::
>> +
>> + md=0,v1.2,/dev/sda1,/dev/sdb1
>> +
>> ``md device no.``
>> +++++++++++++++++
>>
>
> What about md_autostart_arrays()? where 0.90 is still the only default
> choice.
>> diff --git a/drivers/md/md-autodetect.c b/drivers/md/md-autodetect.c
>> index 4b80165afd23..67d38559ad50 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;
>>
>> @@ -63,6 +65,7 @@ static int __init md_setup(char *str)
>> char *pername = "";
>> char *str1;
>> int ent;
>> + int major_i = 0, minor_i = 0;
>>
>> if (*str == 'd') {
>> partitioned = 1;
>> @@ -109,6 +112,49 @@ static int __init md_setup(char *str)
>> case 0:
>> md_setup_args[ent].level = LEVEL_NONE;
>> pername="super-block";
>> +
>> + if (*str == 'v') { /* Superblock version */
>> + char *version = ++str;
>> + char *version_end = strchr(str, ',');
>> +
>> + if (!version_end) {
>> + pr_warn("md: Version (%s) has been specified wrongly,
>> no ',' found, use like this: md=<md dev. no.>,X.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 wrongly,
>> no '.' to separate major and minor version found, use like this:
>> md=<md dev. no.>,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 wrongly,
>> couldn't convert major '%s' to number, use like this: md=<md dev.
>> no.>,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 wrongly,
>> couldn't convert minor '%s' to number, use like this: md=<md dev.
>> no.>,vX.X,...\n",
>> + minor_s);
>> + return 0;
>> + }
>> + }
>> +
>> }
>>
>> printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n",
>> @@ -116,6 +162,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 +248,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;
>
> I would expect to fix md_set_array_info() to hanlde this new case, to
> make code more readable.
>
>> +
>> for (i = 0; i <= MD_SB_DISKS && devices[i]; i++) {
>> struct mdu_disk_info_s dinfo = {
>> .major = MAJOR(devices[i]),
>> @@ -273,11 +324,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]);
>> +
And BTW, take a closer look at autodetect code, although you set
mddev->major_version to 1, however, md_set_array_info() will set
mddev->raid_disks while mddev->pers is still NULL, hence from
md_add_new_disk(), -EINVAL will be returned directly:
md_add_new_disk
if (!mddev->raid_disks)
......
return;
if (mddev->pers)
......
return;
/* otherwise, md_add_new_disk is only allowed
┊* for major_version==0 superblocks
┊*/
if (mddev->major_version != 0) {
pr_warn("%s: ADD_NEW_DISK not supported\n", mdname(mddev));
return -EINVAL;
}
What am I missing?
Thanks,
Kuai
>
> You just explain what you did in comment, Why do you change the order?
>
> Thanks,
> Kuai
>
>> 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]);
>> }
>>
>> .
>>
>
> .
>
And BTW, take a closer look at autodetect code, alouth
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-08-27 9:47 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20250825144029.2924-1-jeremias@jears.at>
2025-08-25 14:53 ` [PATCH v3] md: Allow setting persistent superblock version for md= command line jeremias
2025-08-27 7:26 ` Yu Kuai
2025-08-27 9:47 ` Yu Kuai
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).