]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
mdadm --create supports --logical-block-size option
authorWu Guanghao <wuguanghao3@huawei.com>
Thu, 9 Oct 2025 03:59:48 +0000 (11:59 +0800)
committerXiaoNi87 <xni@redhat.com>
Tue, 16 Dec 2025 07:32:11 +0000 (15:32 +0800)
The kernel block branch has started supporting the
configuration of logical block size after mergeing commit
62ed1b582246 (md:allow configuring logical block size),
therefore a new parameter should be added to allow specifying
the logical block size when creating a RAID device.

Links: https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux.git/commit/?h=for-6.19/block&id=62ed1b58224

Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
Create.c
ReadMe.c
mdadm.8.in
mdadm.c
mdadm.h

index 420b9136c2c26670308b082acc3cc23a611b3a31..4aa75b7e86673e814b14632405dfa282ebf0d2ee 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -1281,6 +1281,14 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
                                goto abort;
                        }
                } else {
+                       if (s->logical_block_size &&
+                               sysfs_set_num(&info, NULL, "logical_block_size",
+                                                         s->logical_block_size)) {
+                               pr_err("Failed to set logical_block_size %u\n",
+                                               s->logical_block_size);
+                               goto abort;
+                       }
+
                        /* param is not actually used */
                        mdu_param_t param;
                        if (ioctl(mdfd, RUN_ARRAY, &param)) {
index c2415c2678eea2d99e46fa0b456913e8610d44ff..137a80c99fc376526dac497996653715b34c153c 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -149,6 +149,7 @@ struct option long_options[] = {
        {"home-cluster", 1, 0, ClusterName},
        {"write-journal", 1, 0, WriteJournal},
        {"consistency-policy", 1, 0, 'k'},
+       {"logical-block-size", 1, 0, LogicalBlockSize},
 
        /* For assemble */
        {"uuid", 1, 0, 'u'},
@@ -331,6 +332,7 @@ char Help_create[] =
 "  --consistency-policy= : Specify the policy that determines how the array\n"
 "                     -k : maintains consistency in case of unexpected shutdown.\n"
 "  --write-zeroes        : Write zeroes to the disks before creating. This will bypass initial sync.\n"
+"  --logical-block-size= : Set the logical block size (in Byte) for the RAID.\n"
 "\n"
 ;
 
index 2a71e32237d492dedb7afb273636ab96d30ec40e..448ff2c9cdf9338a81fa3d422f28e893a9b1dedd 100644 (file)
@@ -989,6 +989,21 @@ Can be used with \-\-grow to change the consistency policy of an active array
 in some cases. See CONSISTENCY POLICY CHANGES below.
 .RE
 
+.TP
+.BR \-\-logical\-block\-size=
+The option can only be used in Create mode and metadata version is 1.x. If during
+creation, the member disks have mixed LBS values (512 and 4K), the array will
+default to using 4K as its LBS. However, if the 4K disk is removed and the system
+is rebooted, the array's LBS will fall back to 512. If the array's LBS is 512,
+then a disk with a 4K LBS cannot be added to the array.
+
+In general, choosing a large LBS for the array is beneficial, but it can
+introduce write-amplification. The larger the array's LBS, the larger the write
+size to each member disk. Therefore, users should evaluate their actual workload
+and choose an appropriate LBS accordingly.
+
+The option should be set by the user based on their own usage scenario, choosing
+an LBS value that best matches their needs.
 
 .SH For assemble:
 
diff --git a/mdadm.c b/mdadm.c
index 18ded25ee79da2c1eb276b56a9f3f0489ae666a5..2c769d00f934c6740a4446ecc4e14619e52b3bb1 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -30,6 +30,7 @@
 #include "xmalloc.h"
 
 #include <ctype.h>
+#include <limits.h>
 
 /**
  * set_bitmap_value() - set bitmap value.
@@ -76,6 +77,33 @@ static mdadm_status_t set_bitmap_value(struct shape *s, struct context *c, char
        return MDADM_STATUS_ERROR;
 }
 
+/*
+ * Logical block size settings only support metadata 1.x.
+ */
+static mdadm_status_t shape_set_logical_block_size(struct shape *s, char *optarg)
+{
+       char *end;
+       unsigned long size = strtoul(optarg, &end, 10);
+
+       if (end != optarg + strlen(optarg)) {
+               pr_err("logical block size [%s] can't be converted to an integer\n", optarg);
+               return MDADM_STATUS_ERROR;
+       } else if (errno == ERANGE) {
+               pr_err("logical block size [%s] more than ULONG_MAX\n", optarg);
+               return MDADM_STATUS_ERROR;
+       }
+
+       /* Here only perform a simple check, while detailed check will be handled in kernel */
+       if (size == 0 || size > UINT_MAX) {
+               pr_err("The range of logical-block-size is (0, %u], current is %lu\n",
+                               UINT_MAX, size);
+               return MDADM_STATUS_ERROR;
+       }
+
+       s->logical_block_size = size;
+       return MDADM_STATUS_SUCCESS;
+}
+
 static int scan_assemble(struct supertype *ss,
                         struct context *c,
                         struct mddev_ident *ident);
@@ -117,6 +145,7 @@ int main(int argc, char *argv[])
                .consistency_policy     = CONSISTENCY_POLICY_UNKNOWN,
                .data_offset = INVALID_SECTORS,
                .btype          = BitmapUnknown,
+               .logical_block_size = 0,
        };
 
        char sys_hostname[256];
@@ -1187,6 +1216,10 @@ int main(int argc, char *argv[])
                                exit(2);
                        }
                        continue;
+               case O(CREATE, LogicalBlockSize):
+                       if (shape_set_logical_block_size(&s, optarg) != MDADM_STATUS_SUCCESS)
+                               exit(2);
+                       continue;
                }
                /* We have now processed all the valid options. Anything else is
                 * an error
@@ -1202,6 +1235,18 @@ int main(int argc, char *argv[])
 
        }
 
+       /* When metadata is not specified using the -e option,
+        * metadata version is 1.2 by default. So the logical
+        * block size can be configured.
+        * When using the -e option, need to check if the
+        * metadata version is 1.x.
+        */
+       if (s.logical_block_size && ss && strcmp(ss->ss->name, "1.x")){
+               pr_err("The logical block size is only supported for metadata 1.x.\n");
+               pr_err("Current metadata version is %s\n", ss->ss->name);
+               exit(2);
+       }
+
        if (print_help) {
                char *help_text;
                if (print_help == 2)
diff --git a/mdadm.h b/mdadm.h
index 56925cf863f1ce9038816378a99b35d8211d4b1c..b63dded31a17c7d18cfbcae20f1e460a2cad8af2 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -498,6 +498,7 @@ enum special_options {
        ClusterConfirm,
        WriteJournal,
        ConsistencyPolicy,
+       LogicalBlockSize,
 };
 
 enum update_opt {
@@ -660,6 +661,7 @@ struct shape {
        unsigned long long data_offset;
        int     consistency_policy;
        change_dir_t direction;
+       unsigned int logical_block_size;
 };
 
 /* List of device names - wildcards expanded */