diff options
-rw-r--r-- | drivers/md/raid1.c | 18 | ||||
-rw-r--r-- | include/linux/raid/raid1.h | 7 |
2 files changed, 18 insertions, 7 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 14a8fe0349c7..a8bc93d6ff63 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -154,7 +154,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio) | |||
154 | 154 | ||
155 | for (i = 0; i < conf->raid_disks; i++) { | 155 | for (i = 0; i < conf->raid_disks; i++) { |
156 | struct bio **bio = r1_bio->bios + i; | 156 | struct bio **bio = r1_bio->bios + i; |
157 | if (*bio) | 157 | if (*bio && *bio != IO_BLOCKED) |
158 | bio_put(*bio); | 158 | bio_put(*bio); |
159 | *bio = NULL; | 159 | *bio = NULL; |
160 | } | 160 | } |
@@ -419,11 +419,13 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) | |||
419 | new_disk = 0; | 419 | new_disk = 0; |
420 | 420 | ||
421 | for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); | 421 | for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); |
422 | r1_bio->bios[new_disk] == IO_BLOCKED || | ||
422 | !rdev || !test_bit(In_sync, &rdev->flags) | 423 | !rdev || !test_bit(In_sync, &rdev->flags) |
423 | || test_bit(WriteMostly, &rdev->flags); | 424 | || test_bit(WriteMostly, &rdev->flags); |
424 | rdev = rcu_dereference(conf->mirrors[++new_disk].rdev)) { | 425 | rdev = rcu_dereference(conf->mirrors[++new_disk].rdev)) { |
425 | 426 | ||
426 | if (rdev && test_bit(In_sync, &rdev->flags)) | 427 | if (rdev && test_bit(In_sync, &rdev->flags) && |
428 | r1_bio->bios[new_disk] != IO_BLOCKED) | ||
427 | wonly_disk = new_disk; | 429 | wonly_disk = new_disk; |
428 | 430 | ||
429 | if (new_disk == conf->raid_disks - 1) { | 431 | if (new_disk == conf->raid_disks - 1) { |
@@ -437,11 +439,13 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) | |||
437 | 439 | ||
438 | /* make sure the disk is operational */ | 440 | /* make sure the disk is operational */ |
439 | for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); | 441 | for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); |
442 | r1_bio->bios[new_disk] == IO_BLOCKED || | ||
440 | !rdev || !test_bit(In_sync, &rdev->flags) || | 443 | !rdev || !test_bit(In_sync, &rdev->flags) || |
441 | test_bit(WriteMostly, &rdev->flags); | 444 | test_bit(WriteMostly, &rdev->flags); |
442 | rdev = rcu_dereference(conf->mirrors[new_disk].rdev)) { | 445 | rdev = rcu_dereference(conf->mirrors[new_disk].rdev)) { |
443 | 446 | ||
444 | if (rdev && test_bit(In_sync, &rdev->flags)) | 447 | if (rdev && test_bit(In_sync, &rdev->flags) && |
448 | r1_bio->bios[new_disk] != IO_BLOCKED) | ||
445 | wonly_disk = new_disk; | 449 | wonly_disk = new_disk; |
446 | 450 | ||
447 | if (new_disk <= 0) | 451 | if (new_disk <= 0) |
@@ -478,7 +482,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) | |||
478 | 482 | ||
479 | rdev = rcu_dereference(conf->mirrors[disk].rdev); | 483 | rdev = rcu_dereference(conf->mirrors[disk].rdev); |
480 | 484 | ||
481 | if (!rdev || | 485 | if (!rdev || r1_bio->bios[disk] == IO_BLOCKED || |
482 | !test_bit(In_sync, &rdev->flags) || | 486 | !test_bit(In_sync, &rdev->flags) || |
483 | test_bit(WriteMostly, &rdev->flags)) | 487 | test_bit(WriteMostly, &rdev->flags)) |
484 | continue; | 488 | continue; |
@@ -1335,7 +1339,7 @@ static void raid1d(mddev_t *mddev) | |||
1335 | sector_t sect = r1_bio->sector; | 1339 | sector_t sect = r1_bio->sector; |
1336 | int sectors = r1_bio->sectors; | 1340 | int sectors = r1_bio->sectors; |
1337 | freeze_array(conf); | 1341 | freeze_array(conf); |
1338 | while(sectors) { | 1342 | if (mddev->ro == 0) while(sectors) { |
1339 | int s = sectors; | 1343 | int s = sectors; |
1340 | int d = r1_bio->read_disk; | 1344 | int d = r1_bio->read_disk; |
1341 | int success = 0; | 1345 | int success = 0; |
@@ -1388,7 +1392,6 @@ static void raid1d(mddev_t *mddev) | |||
1388 | sect += s; | 1392 | sect += s; |
1389 | } | 1393 | } |
1390 | 1394 | ||
1391 | |||
1392 | unfreeze_array(conf); | 1395 | unfreeze_array(conf); |
1393 | 1396 | ||
1394 | bio = r1_bio->bios[r1_bio->read_disk]; | 1397 | bio = r1_bio->bios[r1_bio->read_disk]; |
@@ -1399,7 +1402,8 @@ static void raid1d(mddev_t *mddev) | |||
1399 | (unsigned long long)r1_bio->sector); | 1402 | (unsigned long long)r1_bio->sector); |
1400 | raid_end_bio_io(r1_bio); | 1403 | raid_end_bio_io(r1_bio); |
1401 | } else { | 1404 | } else { |
1402 | r1_bio->bios[r1_bio->read_disk] = NULL; | 1405 | r1_bio->bios[r1_bio->read_disk] = |
1406 | mddev->ro ? IO_BLOCKED : NULL; | ||
1403 | r1_bio->read_disk = disk; | 1407 | r1_bio->read_disk = disk; |
1404 | bio_put(bio); | 1408 | bio_put(bio); |
1405 | bio = bio_clone(r1_bio->master_bio, GFP_NOIO); | 1409 | bio = bio_clone(r1_bio->master_bio, GFP_NOIO); |
diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h index cbe4238d3f9f..9d5494aaac0f 100644 --- a/include/linux/raid/raid1.h +++ b/include/linux/raid/raid1.h | |||
@@ -109,6 +109,13 @@ struct r1bio_s { | |||
109 | /* DO NOT PUT ANY NEW FIELDS HERE - bios array is contiguously alloced*/ | 109 | /* DO NOT PUT ANY NEW FIELDS HERE - bios array is contiguously alloced*/ |
110 | }; | 110 | }; |
111 | 111 | ||
112 | /* when we get a read error on a read-only array, we redirect to another | ||
113 | * device without failing the first device, or trying to over-write to | ||
114 | * correct the read error. To keep track of bad blocks on a per-bio | ||
115 | * level, we store IO_BLOCKED in the appropriate 'bios' pointer | ||
116 | */ | ||
117 | #define IO_BLOCKED ((struct bio*)1) | ||
118 | |||
112 | /* bits for r1bio.state */ | 119 | /* bits for r1bio.state */ |
113 | #define R1BIO_Uptodate 0 | 120 | #define R1BIO_Uptodate 0 |
114 | #define R1BIO_IsSync 1 | 121 | #define R1BIO_IsSync 1 |