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

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

 



Hi,

在 2025/08/25 22:53, jeremias@xxxxxxxx 写道:
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@xxxxxxxx>
---
  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]);
  }

.






[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