dm raid1: handle log failure
When writing to a mirror, the log must be updated first. Failure to update the log could result in the log not properly reflecting the state of the mirror if the machine should crash. We change the return type of the rh_flush function to give us the ability to check if a log write was successful. If the log write was unsuccessful, we fail the writes to avoid the case where the log does not properly reflect the state of the mirror. A follow-up patch - which is dependent on the ability to requeue I/O's to core device-mapper - will requeue the I/O's for retry (allowing the mirror to be reconfigured.) Signed-off-by: Jonathan Brassow <jbrassow@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
f44db678ed
commit
fc1ff9588a
1 changed files with 8 additions and 4 deletions
|
@ -134,6 +134,7 @@ struct mirror_set {
|
||||||
/* recovery */
|
/* recovery */
|
||||||
region_t nr_regions;
|
region_t nr_regions;
|
||||||
int in_sync;
|
int in_sync;
|
||||||
|
int log_failure;
|
||||||
|
|
||||||
struct mirror *default_mirror; /* Default mirror */
|
struct mirror *default_mirror; /* Default mirror */
|
||||||
|
|
||||||
|
@ -589,9 +590,9 @@ static void rh_recovery_end(struct region *reg, int success)
|
||||||
wake(rh->ms);
|
wake(rh->ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rh_flush(struct region_hash *rh)
|
static int rh_flush(struct region_hash *rh)
|
||||||
{
|
{
|
||||||
rh->log->type->flush(rh->log);
|
return rh->log->type->flush(rh->log);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rh_delay(struct region_hash *rh, struct bio *bio)
|
static void rh_delay(struct region_hash *rh, struct bio *bio)
|
||||||
|
@ -892,12 +893,15 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
|
||||||
*/
|
*/
|
||||||
rh_inc_pending(&ms->rh, &sync);
|
rh_inc_pending(&ms->rh, &sync);
|
||||||
rh_inc_pending(&ms->rh, &nosync);
|
rh_inc_pending(&ms->rh, &nosync);
|
||||||
rh_flush(&ms->rh);
|
ms->log_failure = rh_flush(&ms->rh) ? 1 : 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dispatch io.
|
* Dispatch io.
|
||||||
*/
|
*/
|
||||||
while ((bio = bio_list_pop(&sync)))
|
if (unlikely(ms->log_failure))
|
||||||
|
while ((bio = bio_list_pop(&sync)))
|
||||||
|
bio_endio(bio, bio->bi_size, -EIO);
|
||||||
|
else while ((bio = bio_list_pop(&sync)))
|
||||||
do_write(ms, bio);
|
do_write(ms, bio);
|
||||||
|
|
||||||
while ((bio = bio_list_pop(&recover)))
|
while ((bio = bio_list_pop(&recover)))
|
||||||
|
|
Loading…
Reference in a new issue