]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
super1: Clear extra flags when initializing metadata
authorWu Guanghao <wuguanghao3@huawei.com>
Tue, 11 Mar 2025 03:11:55 +0000 (03:11 +0000)
committerMariusz Tkaczyk <mtkaczyk@kernel.org>
Mon, 24 Mar 2025 09:44:20 +0000 (10:44 +0100)
When adding a disk to a RAID1 array, the metadata is read from the
existing member disks for sync. However, only the bad_blocks flag are
copied, the bad_blocks records are not copied, so the bad_blocks
records are all zeros. The kernel function super_1_load() detects
bad_blocks flag and reads the bad_blocks record, then sets the bad
block using badblocks_set().

After the kernel commit 1726c7746783 (badblocks: improve badblocks_set()
for multiple ranges handling) if the length of a bad_blocks record is 0,
it will return a failure. Therefore the device addition will fail.

So when adding a new disk, some flags cannot be sync and need to be clead.

Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
super1.c
tests/05r1-add-badblocks [new file with mode: 0644]

index fe3c4c64c66bf5b6e3280d440eefe4bdf4ddc12b..c828b68272fd7efb3b0147205d2b35e6d754c74e 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -1971,6 +1971,9 @@ static int write_init_super1(struct supertype *st)
        long bm_offset;
        bool raid0_need_layout = false;
 
+       /* Clear extra flags */
+       sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_BAD_BLOCKS | MD_FEATURE_REPLACEMENT);
+
        /* Since linux kernel v5.4, raid0 always has a layout */
        if (has_raid0_layout(sb) && get_linux_version() >= 5004000)
                raid0_need_layout = true;
diff --git a/tests/05r1-add-badblocks b/tests/05r1-add-badblocks
new file mode 100644 (file)
index 0000000..6192327
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# create a raid1 with a drive and set badblocks for the drive.
+# add a new drive does not cause an error.
+#
+
+# create raid1
+mdadm -CR $md0 -l1 -n2 -e1.0 $dev1 missing
+testdev $md0 1 $mdsize1a 64
+sleep 3
+
+# set badblocks for the drive
+dev1_name=$(basename $dev1)
+echo "100 100" > /sys/block/md0/md/dev-$dev1_name/bad_blocks
+echo "write_error" > /sys/block/md0/md/dev-$dev1_name/state
+
+# write badblocks to metadata
+dd if=/dev/zero of=$md0 bs=512 count=200 oflag=direct
+
+# re-add and recovery
+mdadm $md0 -a $dev2
+check recovery
+
+mdadm -S $md0
+