diff -urN linux-2.6.12-00003/drivers/md/dm-log.h linux-2.6.12-00004/drivers/md/dm-log.h --- linux-2.6.12-00003/drivers/md/dm-log.h 2005-07-20 16:27:00.000000000 -0500 +++ linux-2.6.12-00004/drivers/md/dm-log.h 2005-07-20 16:33:23.000000000 -0500 @@ -49,6 +49,16 @@ int (*is_clean)(struct dirty_log *log, region_t region); /* + * Returns: 0, 1 + * + * This is necessary for cluster mirroring. It provides + * a way to detect recovery on another node, so we + * aren't writing concurrently. This function is likely + * to block (when a cluster log is used). + */ + int (*is_remote_recovering)(struct dirty_log *log, region_t region); + + /* * Returns: 0, 1, -EWOULDBLOCK, < 0 * * A predicate function to check the area given by diff -urN linux-2.6.12-00003/drivers/md/dm-raid1.c linux-2.6.12-00004/drivers/md/dm-raid1.c --- linux-2.6.12-00003/drivers/md/dm-raid1.c 2005-07-20 16:32:08.000000000 -0500 +++ linux-2.6.12-00004/drivers/md/dm-raid1.c 2005-07-21 10:44:00.576555874 -0500 @@ -984,6 +984,9 @@ int state; struct bio *bio; struct bio_list sync, nosync, recover, *this_list = NULL; + struct bio_list requeue; + struct dirty_log *log = ms->rh.log; + region_t region; if (!writes->head) return; @@ -994,9 +997,18 @@ bio_list_init(&sync); bio_list_init(&nosync); bio_list_init(&recover); + bio_list_init(&requeue); while ((bio = bio_list_pop(writes))) { - state = rh_state(&ms->rh, bio_to_region(&ms->rh, bio), 1); + region = bio_to_region(&ms->rh, bio); + + if (log->type->is_remote_recovering && + log->type->is_remote_recovering(log, region)) { + bio_list_add(&requeue, bio); + continue; + } + + state = rh_state(&ms->rh, region, 1); switch (state) { case RH_CLEAN: case RH_DIRTY: @@ -1015,6 +1027,8 @@ bio_list_add(this_list, bio); } + bio_list_merge(writes, &requeue); + /* * Increment the pending counts for any regions that will * be written to (writes to recover regions are going to