| From e8d7c33232e5fdfa761c3416539bc5b4acd12db5 Mon Sep 17 00:00:00 2001 |
| From: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> |
| Date: Sun, 27 Nov 2016 19:32:32 +0300 |
| Subject: md/raid5: limit request size according to implementation limits |
| |
| From: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> |
| |
| commit e8d7c33232e5fdfa761c3416539bc5b4acd12db5 upstream. |
| |
| Current implementation employ 16bit counter of active stripes in lower |
| bits of bio->bi_phys_segments. If request is big enough to overflow |
| this counter bio will be completed and freed too early. |
| |
| Fortunately this not happens in default configuration because several |
| other limits prevent that: stripe_cache_size * nr_disks effectively |
| limits count of active stripes. And small max_sectors_kb at lower |
| disks prevent that during normal read/write operations. |
| |
| Overflow easily happens in discard if it's enabled by module parameter |
| "devices_handle_discard_safely" and stripe_cache_size is set big enough. |
| |
| This patch limits requests size with 256Mb - 8Kb to prevent overflows. |
| |
| Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> |
| Cc: Shaohua Li <shli@kernel.org> |
| Cc: Neil Brown <neilb@suse.com> |
| Signed-off-by: Shaohua Li <shli@fb.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/md/raid5.c | 9 +++++++++ |
| 1 file changed, 9 insertions(+) |
| |
| --- a/drivers/md/raid5.c |
| +++ b/drivers/md/raid5.c |
| @@ -7017,6 +7017,15 @@ static int raid5_run(struct mddev *mddev |
| stripe = (stripe | (stripe-1)) + 1; |
| mddev->queue->limits.discard_alignment = stripe; |
| mddev->queue->limits.discard_granularity = stripe; |
| + |
| + /* |
| + * We use 16-bit counter of active stripes in bi_phys_segments |
| + * (minus one for over-loaded initialization) |
| + */ |
| + blk_queue_max_hw_sectors(mddev->queue, 0xfffe * STRIPE_SECTORS); |
| + blk_queue_max_discard_sectors(mddev->queue, |
| + 0xfffe * STRIPE_SECTORS); |
| + |
| /* |
| * unaligned part of discard request will be ignored, so can't |
| * guarantee discard_zeroes_data |