]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
md/cluster: block reshape with remote resync job
authorZhao Heming <heming.zhao@suse.com>
Thu, 19 Nov 2020 11:41:33 +0000 (19:41 +0800)
committerPaolo Pisati <paolo.pisati@canonical.com>
Mon, 4 Jan 2021 15:48:06 +0000 (16:48 +0100)
BugLink: https://bugs.launchpad.net/bugs/1910111
commit a8da01f79c89755fad55ed0ea96e8d2103242a72 upstream.

Reshape request should be blocked with ongoing resync job. In cluster
env, a node can start resync job even if the resync cmd isn't executed
on it, e.g., user executes "mdadm --grow" on node A, sometimes node B
will start resync job. However, current update_raid_disks() only check
local recovery status, which is incomplete. As a result, we see user will
execute "mdadm --grow" successfully on local, while the remote node deny
to do reshape job when it doing resync job. The inconsistent handling
cause array enter unexpected status. If user doesn't observe this issue
and continue executing mdadm cmd, the array doesn't work at last.

Fix this issue by blocking reshape request. When node executes "--grow"
and detects ongoing resync, it should stop and report error to user.

The following script reproduces the issue with ~100% probability.
(two nodes share 3 iSCSI luns: sdg/sdh/sdi. Each lun size is 1GB)
```
 # on node1, node2 is the remote node.
ssh root@node2 "mdadm -S --scan"
mdadm -S --scan
for i in {g,h,i};do dd if=/dev/zero of=/dev/sd$i oflag=direct bs=1M \
count=20; done

mdadm -C /dev/md0 -b clustered -e 1.2 -n 2 -l mirror /dev/sdg /dev/sdh
ssh root@node2 "mdadm -A /dev/md0 /dev/sdg /dev/sdh"

sleep 5

mdadm --manage --add /dev/md0 /dev/sdi
mdadm --wait /dev/md0
mdadm --grow --raid-devices=3 /dev/md0

mdadm /dev/md0 --fail /dev/sdg
mdadm /dev/md0 --remove /dev/sdg
mdadm --grow --raid-devices=2 /dev/md0
```

Cc: stable@vger.kernel.org
Signed-off-by: Zhao Heming <heming.zhao@suse.com>
Signed-off-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
drivers/md/md.c

index 4136bd814289421750a0298d7ef3931affa8dc9b..55f9ddf6f44f43ecd20c69a32e2943b2ecf88946 100644 (file)
@@ -7278,6 +7278,7 @@ static int update_raid_disks(struct mddev *mddev, int raid_disks)
                return -EINVAL;
        if (mddev->sync_thread ||
            test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+           test_bit(MD_RESYNCING_REMOTE, &mddev->recovery) ||
            mddev->reshape_position != MaxSector)
                return -EBUSY;
 
@@ -9645,8 +9646,11 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
                }
        }
 
-       if (mddev->raid_disks != le32_to_cpu(sb->raid_disks))
-               update_raid_disks(mddev, le32_to_cpu(sb->raid_disks));
+       if (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) {
+               ret = update_raid_disks(mddev, le32_to_cpu(sb->raid_disks));
+               if (ret)
+                       pr_warn("md: updating array disks failed. %d\n", ret);
+       }
 
        /*
         * Since mddev->delta_disks has already updated in update_raid_disks,