summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorNeil Brown <neilb@cse.unsw.edu.au>2003-03-14 02:09:06 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-03-14 02:09:06 -0800
commit264b2f7c01ecfa3c9dbb376c9cf5a3aeb28dba6b (patch)
treeb3972ced499cf007ab6e9e3b6d8555eae479ea5a /drivers
parent9578658e998baaf5bf36d1053b690bd28976b1ca (diff)
[PATCH] md: Fix bad interaction between sync checkpointing and recovery
Md devices (raid1/raid5) can resync or recover. There are similar but importantly different. resync happens after an unclean shutdown recovery happens when a failed drive is being replaced by a hot spare. The sync-checkpoint code confused the two somewhat and this causes problems. This patch makes sure "recovery_cp" only relates to resync, not recovery. It also fixes a small problem with recording spares in the superblock.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/md.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 5689df88774a..8a8dc92a527d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -713,7 +713,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->disks[0].state = (1<<MD_DISK_REMOVED);
ITERATE_RDEV(mddev,rdev2,tmp) {
mdp_disk_t *d;
- if (rdev2->raid_disk >= 0)
+ if (rdev2->raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty)
rdev2->desc_nr = rdev2->raid_disk;
else
rdev2->desc_nr = next_spare++;
@@ -722,7 +722,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
d->number = rdev2->desc_nr;
d->major = MAJOR(rdev2->bdev->bd_dev);
d->minor = MINOR(rdev2->bdev->bd_dev);
- if (rdev2->raid_disk >= 0)
+ if (rdev2->raid_disk >= 0 && rdev->in_sync && !rdev2->faulty)
d->raid_disk = rdev2->raid_disk;
else
d->raid_disk = rdev2->desc_nr; /* compatibility */
@@ -3020,9 +3020,13 @@ static void md_do_sync(mddev_t *mddev)
sysctl_speed_limit_max);
is_mddev_idle(mddev); /* this also initializes IO event counters */
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+ j = mddev->recovery_cp;
+ else
+ j = 0;
for (m = 0; m < SYNC_MARKS; m++) {
mark[m] = jiffies;
- mark_cnt[m] = mddev->recovery_cp;
+ mark_cnt[m] = j;
}
last_mark = 0;
mddev->resync_mark = mark[last_mark];
@@ -3039,10 +3043,10 @@ static void md_do_sync(mddev_t *mddev)
init_waitqueue_head(&mddev->recovery_wait);
last_check = 0;
- if (mddev->recovery_cp)
+ if (j)
printk(KERN_INFO "md: resuming recovery of md%d from checkpoint.\n", mdidx(mddev));
- for (j = mddev->recovery_cp; j < max_sectors;) {
+ while (j < max_sectors) {
int sectors;
sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min);