diff options
author | NeilBrown <neilb@cse.unsw.edu.au> | 2005-08-04 15:53:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-08-04 16:00:54 -0400 |
commit | e3b9703e27aab3839dcdb76b00d98428b67d25b0 (patch) | |
tree | f9b62479cd7062c65e54641cc6190975f529a08b /drivers/md | |
parent | 193f1c931517592ec4188d15bf261e4bff368207 (diff) |
[PATCH] md: yet another attempt to get bitmap-based resync to do the right thing in all cases...
Firstly, R1BIO_Degraded was being set in a number of places in the resync
code, but is never used there, so get rid of those settings.
Then: When doing a resync, we want to clear the bit in the bitmap iff the
array will be non-degraded when the sync has completed. However the current
code would clear the bitmap if the array was non-degraded when the resync
*started*, which obviously isn't right (it is for 'resync' but not for
'recovery' - i.e. rebuilding a failed drive).
This patch calculated 'still_degraded' and uses the to tell bitmap_start_sync
whether this sync should clear the corresponding bit.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid1.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d3a64a04a6d8..51d9645ed09c 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -893,7 +893,6 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) | |||
893 | if (!uptodate) { | 893 | if (!uptodate) { |
894 | md_error(r1_bio->mddev, | 894 | md_error(r1_bio->mddev, |
895 | conf->mirrors[r1_bio->read_disk].rdev); | 895 | conf->mirrors[r1_bio->read_disk].rdev); |
896 | set_bit(R1BIO_Degraded, &r1_bio->state); | ||
897 | } else | 896 | } else |
898 | set_bit(R1BIO_Uptodate, &r1_bio->state); | 897 | set_bit(R1BIO_Uptodate, &r1_bio->state); |
899 | rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev); | 898 | rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev); |
@@ -918,10 +917,9 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) | |||
918 | mirror = i; | 917 | mirror = i; |
919 | break; | 918 | break; |
920 | } | 919 | } |
921 | if (!uptodate) { | 920 | if (!uptodate) |
922 | md_error(mddev, conf->mirrors[mirror].rdev); | 921 | md_error(mddev, conf->mirrors[mirror].rdev); |
923 | set_bit(R1BIO_Degraded, &r1_bio->state); | 922 | |
924 | } | ||
925 | update_head_pos(mirror, r1_bio); | 923 | update_head_pos(mirror, r1_bio); |
926 | 924 | ||
927 | if (atomic_dec_and_test(&r1_bio->remaining)) { | 925 | if (atomic_dec_and_test(&r1_bio->remaining)) { |
@@ -1109,6 +1107,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1109 | int i; | 1107 | int i; |
1110 | int write_targets = 0; | 1108 | int write_targets = 0; |
1111 | int sync_blocks; | 1109 | int sync_blocks; |
1110 | int still_degraded = 0; | ||
1112 | 1111 | ||
1113 | if (!conf->r1buf_pool) | 1112 | if (!conf->r1buf_pool) |
1114 | { | 1113 | { |
@@ -1137,7 +1136,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1137 | return 0; | 1136 | return 0; |
1138 | } | 1137 | } |
1139 | 1138 | ||
1140 | if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, mddev->degraded) && | 1139 | /* before building a request, check if we can skip these blocks.. |
1140 | * This call the bitmap_start_sync doesn't actually record anything | ||
1141 | */ | ||
1142 | if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) && | ||
1141 | !conf->fullsync) { | 1143 | !conf->fullsync) { |
1142 | /* We can skip this block, and probably several more */ | 1144 | /* We can skip this block, and probably several more */ |
1143 | *skipped = 1; | 1145 | *skipped = 1; |
@@ -1203,24 +1205,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1203 | if (i == disk) { | 1205 | if (i == disk) { |
1204 | bio->bi_rw = READ; | 1206 | bio->bi_rw = READ; |
1205 | bio->bi_end_io = end_sync_read; | 1207 | bio->bi_end_io = end_sync_read; |
1206 | } else if (conf->mirrors[i].rdev && | 1208 | } else if (conf->mirrors[i].rdev == NULL || |
1207 | !conf->mirrors[i].rdev->faulty && | 1209 | conf->mirrors[i].rdev->faulty) { |
1208 | (!conf->mirrors[i].rdev->in_sync || | 1210 | still_degraded = 1; |
1209 | sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) { | 1211 | continue; |
1212 | } else if (!conf->mirrors[i].rdev->in_sync || | ||
1213 | sector_nr + RESYNC_SECTORS > mddev->recovery_cp) { | ||
1210 | bio->bi_rw = WRITE; | 1214 | bio->bi_rw = WRITE; |
1211 | bio->bi_end_io = end_sync_write; | 1215 | bio->bi_end_io = end_sync_write; |
1212 | write_targets ++; | 1216 | write_targets ++; |
1213 | } else | 1217 | } else |
1218 | /* no need to read or write here */ | ||
1214 | continue; | 1219 | continue; |
1215 | bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset; | 1220 | bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset; |
1216 | bio->bi_bdev = conf->mirrors[i].rdev->bdev; | 1221 | bio->bi_bdev = conf->mirrors[i].rdev->bdev; |
1217 | bio->bi_private = r1_bio; | 1222 | bio->bi_private = r1_bio; |
1218 | } | 1223 | } |
1219 | 1224 | ||
1220 | if (write_targets + 1 < conf->raid_disks) | ||
1221 | /* array degraded, can't clear bitmap */ | ||
1222 | set_bit(R1BIO_Degraded, &r1_bio->state); | ||
1223 | |||
1224 | if (write_targets == 0) { | 1225 | if (write_targets == 0) { |
1225 | /* There is nowhere to write, so all non-sync | 1226 | /* There is nowhere to write, so all non-sync |
1226 | * drives must be failed - so we are finished | 1227 | * drives must be failed - so we are finished |
@@ -1243,7 +1244,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1243 | break; | 1244 | break; |
1244 | if (sync_blocks == 0) { | 1245 | if (sync_blocks == 0) { |
1245 | if (!bitmap_start_sync(mddev->bitmap, sector_nr, | 1246 | if (!bitmap_start_sync(mddev->bitmap, sector_nr, |
1246 | &sync_blocks, mddev->degraded) && | 1247 | &sync_blocks, still_degraded) && |
1247 | !conf->fullsync) | 1248 | !conf->fullsync) |
1248 | break; | 1249 | break; |
1249 | if (sync_blocks < (PAGE_SIZE>>9)) | 1250 | if (sync_blocks < (PAGE_SIZE>>9)) |