Commit aba336bd authored by NeilBrown's avatar NeilBrown

md: raid1/raid10: fix problem with merge_bvec_fn

The new merge_bvec_fn which calls the corresponding function
in subsidiary devices requires that mddev->merge_check_needed
be set if any child has a merge_bvec_fn.

However were were only setting that when a device was hot-added,
not when a device was present from the start.

This bug was introduced in 3.4 so patch is suitable for 3.4.y
kernels.  However that are conflicts in raid10.c so a separate
patch will be needed for 3.4.y.

Cc: stable@vger.kernel.org
Reported-by: default avatarSebastian Riemer <sebastian.riemer@profitbricks.com>
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent 2aa4ee2a
...@@ -2550,6 +2550,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) ...@@ -2550,6 +2550,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
err = -EINVAL; err = -EINVAL;
spin_lock_init(&conf->device_lock); spin_lock_init(&conf->device_lock);
rdev_for_each(rdev, mddev) { rdev_for_each(rdev, mddev) {
struct request_queue *q;
int disk_idx = rdev->raid_disk; int disk_idx = rdev->raid_disk;
if (disk_idx >= mddev->raid_disks if (disk_idx >= mddev->raid_disks
|| disk_idx < 0) || disk_idx < 0)
...@@ -2562,6 +2563,9 @@ static struct r1conf *setup_conf(struct mddev *mddev) ...@@ -2562,6 +2563,9 @@ static struct r1conf *setup_conf(struct mddev *mddev)
if (disk->rdev) if (disk->rdev)
goto abort; goto abort;
disk->rdev = rdev; disk->rdev = rdev;
q = bdev_get_queue(rdev->bdev);
if (q->merge_bvec_fn)
mddev->merge_check_needed = 1;
disk->head_position = 0; disk->head_position = 0;
} }
......
...@@ -3475,6 +3475,7 @@ static int run(struct mddev *mddev) ...@@ -3475,6 +3475,7 @@ static int run(struct mddev *mddev)
rdev_for_each(rdev, mddev) { rdev_for_each(rdev, mddev) {
long long diff; long long diff;
struct request_queue *q;
disk_idx = rdev->raid_disk; disk_idx = rdev->raid_disk;
if (disk_idx < 0) if (disk_idx < 0)
...@@ -3493,6 +3494,9 @@ static int run(struct mddev *mddev) ...@@ -3493,6 +3494,9 @@ static int run(struct mddev *mddev)
goto out_free_conf; goto out_free_conf;
disk->rdev = rdev; disk->rdev = rdev;
} }
q = bdev_get_queue(rdev->bdev);
if (q->merge_bvec_fn)
mddev->merge_check_needed = 1;
diff = (rdev->new_data_offset - rdev->data_offset); diff = (rdev->new_data_offset - rdev->data_offset);
if (!mddev->reshape_backwards) if (!mddev->reshape_backwards)
diff = -diff; diff = -diff;
......
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