diff options
author | NeilBrown <neilb@suse.de> | 2014-01-14 10:38:09 +1100 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2014-02-15 19:20:16 +0000 |
commit | 11bbcdfc5e8d7983403952f37543d085be5d6f58 (patch) | |
tree | 08b528aa1361029e7aeb7dc4239494bd5fb3e8cb | |
parent | 861e3781037f4f7bafe6ae4967bd551157c8fcfc (diff) | |
download | lwn-11bbcdfc5e8d7983403952f37543d085be5d6f58.tar.gz lwn-11bbcdfc5e8d7983403952f37543d085be5d6f58.zip |
md/raid10: fix two bugs in handling of known-bad-blocks.
commit b50c259e25d9260b9108dc0c2964c26e5ecbe1c1 upstream.
If we discover a bad block when reading we split the request and
potentially read some of it from a different device.
The code path of this has two bugs in RAID10.
1/ we get a spin_lock with _irq, but unlock without _irq!!
2/ The calculation of 'sectors_handled' is wrong, as can be clearly
seen by comparison with raid1.c
This leads to at least 2 warnings and a probable crash is a RAID10
ever had known bad blocks.
Fixes: 856e08e23762dfb92ffc68fd0a8d228f9e152160
Reported-by: Damian Nowak <spam@nowaker.net>
URL: https://bugzilla.kernel.org/show_bug.cgi?id=68181
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r-- | drivers/md/raid10.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 8bba438a328e..c61067a9240c 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -997,7 +997,7 @@ read_again: /* Could not read all from this device, so we will * need another r10_bio. */ - sectors_handled = (r10_bio->sectors + max_sectors + sectors_handled = (r10_bio->sector + max_sectors - bio->bi_sector); r10_bio->sectors = max_sectors; spin_lock_irq(&conf->device_lock); @@ -1005,7 +1005,7 @@ read_again: bio->bi_phys_segments = 2; else bio->bi_phys_segments++; - spin_unlock(&conf->device_lock); + spin_unlock_irq(&conf->device_lock); /* Cannot call generic_make_request directly * as that will be queued in __generic_make_request * and subsequent mempool_alloc might block |