Commit e3b9703e authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds

[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: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 193f1c93
...@@ -893,7 +893,6 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) ...@@ -893,7 +893,6 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
if (!uptodate) { if (!uptodate) {
md_error(r1_bio->mddev, md_error(r1_bio->mddev,
conf->mirrors[r1_bio->read_disk].rdev); conf->mirrors[r1_bio->read_disk].rdev);
set_bit(R1BIO_Degraded, &r1_bio->state);
} else } else
set_bit(R1BIO_Uptodate, &r1_bio->state); set_bit(R1BIO_Uptodate, &r1_bio->state);
rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev); 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,10 +917,9 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
mirror = i; mirror = i;
break; break;
} }
if (!uptodate) { if (!uptodate)
md_error(mddev, conf->mirrors[mirror].rdev); md_error(mddev, conf->mirrors[mirror].rdev);
set_bit(R1BIO_Degraded, &r1_bio->state);
}
update_head_pos(mirror, r1_bio); update_head_pos(mirror, r1_bio);
if (atomic_dec_and_test(&r1_bio->remaining)) { 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,6 +1107,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
int i; int i;
int write_targets = 0; int write_targets = 0;
int sync_blocks; int sync_blocks;
int still_degraded = 0;
if (!conf->r1buf_pool) if (!conf->r1buf_pool)
{ {
...@@ -1137,7 +1136,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i ...@@ -1137,7 +1136,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return 0; return 0;
} }
if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, mddev->degraded) && /* before building a request, check if we can skip these blocks..
* This call the bitmap_start_sync doesn't actually record anything
*/
if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
!conf->fullsync) { !conf->fullsync) {
/* We can skip this block, and probably several more */ /* We can skip this block, and probably several more */
*skipped = 1; *skipped = 1;
...@@ -1203,24 +1205,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i ...@@ -1203,24 +1205,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (i == disk) { if (i == disk) {
bio->bi_rw = READ; bio->bi_rw = READ;
bio->bi_end_io = end_sync_read; bio->bi_end_io = end_sync_read;
} else if (conf->mirrors[i].rdev && } else if (conf->mirrors[i].rdev == NULL ||
!conf->mirrors[i].rdev->faulty && conf->mirrors[i].rdev->faulty) {
(!conf->mirrors[i].rdev->in_sync || still_degraded = 1;
sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) { continue;
} else if (!conf->mirrors[i].rdev->in_sync ||
sector_nr + RESYNC_SECTORS > mddev->recovery_cp) {
bio->bi_rw = WRITE; bio->bi_rw = WRITE;
bio->bi_end_io = end_sync_write; bio->bi_end_io = end_sync_write;
write_targets ++; write_targets ++;
} else } else
/* no need to read or write here */
continue; continue;
bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset; bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
bio->bi_bdev = conf->mirrors[i].rdev->bdev; bio->bi_bdev = conf->mirrors[i].rdev->bdev;
bio->bi_private = r1_bio; bio->bi_private = r1_bio;
} }
if (write_targets + 1 < conf->raid_disks)
/* array degraded, can't clear bitmap */
set_bit(R1BIO_Degraded, &r1_bio->state);
if (write_targets == 0) { if (write_targets == 0) {
/* There is nowhere to write, so all non-sync /* There is nowhere to write, so all non-sync
* drives must be failed - so we are finished * 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,7 +1244,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
break; break;
if (sync_blocks == 0) { if (sync_blocks == 0) {
if (!bitmap_start_sync(mddev->bitmap, sector_nr, if (!bitmap_start_sync(mddev->bitmap, sector_nr,
&sync_blocks, mddev->degraded) && &sync_blocks, still_degraded) &&
!conf->fullsync) !conf->fullsync)
break; break;
if (sync_blocks < (PAGE_SIZE>>9)) if (sync_blocks < (PAGE_SIZE>>9))
......
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