From 4e2e208c8d3e9ba0fae88136d7c4cd0292af73b0 Mon Sep 17 00:00:00 2001 From: Wu Guanghao Date: Tue, 11 Mar 2025 03:11:55 +0000 Subject: [PATCH 26/37] super1: Clear extra flags when initializing metadata 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 --- super1.c | 3 +++ tests/05r1-add-badblocks | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 tests/05r1-add-badblocks diff --git a/super1.c b/super1.c index fe3c4c64..c828b682 100644 --- 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 index 00000000..6192327a --- /dev/null +++ b/tests/05r1-add-badblocks @@ -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 + -- 2.41.0