Commit a8da01f7 authored by Zhao Heming's avatar Zhao Heming Committed by Song Liu

md/cluster: block reshape with remote resync job

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: default avatarZhao Heming <heming.zhao@suse.com>
Signed-off-by: default avatarSong Liu <songliubraving@fb.com>
parent a23f2aae
...@@ -7283,6 +7283,7 @@ static int update_raid_disks(struct mddev *mddev, int raid_disks) ...@@ -7283,6 +7283,7 @@ static int update_raid_disks(struct mddev *mddev, int raid_disks)
return -EINVAL; return -EINVAL;
if (mddev->sync_thread || if (mddev->sync_thread ||
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
test_bit(MD_RESYNCING_REMOTE, &mddev->recovery) ||
mddev->reshape_position != MaxSector) mddev->reshape_position != MaxSector)
return -EBUSY; return -EBUSY;
...@@ -9667,8 +9668,11 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev) ...@@ -9667,8 +9668,11 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
} }
} }
if (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) if (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) {
update_raid_disks(mddev, 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, * Since mddev->delta_disks has already updated in update_raid_disks,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment