From: Mikulas Patocka Implement flush callee. It uses dm_io to send zero-size barrier synchronously and concurrently to all the mirror legs. Signed-off-by: Mikulas Patocka --- drivers/md/dm-raid1.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) Index: linux-2.6.30/drivers/md/dm-raid1.c =================================================================== --- linux-2.6.30.orig/drivers/md/dm-raid1.c +++ linux-2.6.30/drivers/md/dm-raid1.c @@ -237,6 +237,39 @@ out: schedule_work(&ms->trigger_event); } +static int mirror_flush(void *ms_) +{ + struct mirror_set *ms = ms_; + unsigned long error_bits; + + unsigned int i; + struct dm_io_region io[ms->nr_mirrors]; + struct mirror *m; + struct dm_io_request io_req = { + .bi_rw = WRITE | WRITE_BARRIER, + .mem.type = DM_IO_KMEM, + .mem.ptr.bvec = NULL, + .client = ms->io_client, + }; + + for (i = 0, m = ms->mirror; i < ms->nr_mirrors; i++, m++) { + io[i].bdev = m->dev->bdev; + io[i].sector = 0; + io[i].count = 0; + } + + error_bits = -1; + dm_io(&io_req, ms->nr_mirrors, io, &error_bits); + if (unlikely(error_bits != 0)) { + for (i = 0; i < ms->nr_mirrors; i++) + if (test_bit(i, &error_bits)) + fail_mirror(ms->mirror + i, DM_RAID1_WRITE_ERROR); + return -EIO; + } + + return 0; +} + /*----------------------------------------------------------------- * Recovery. * @@ -654,7 +687,7 @@ static void do_writes(struct mirror_set */ dm_rh_inc_pending(ms->rh, &sync); dm_rh_inc_pending(ms->rh, &nosync); - ms->log_failure = dm_rh_flush(ms->rh, NULL, NULL) ? 1 : 0; + ms->log_failure = dm_rh_flush(ms->rh, mirror_flush, ms) ? 1 : 0; /* * Dispatch io. @@ -755,7 +788,7 @@ static void do_mirror(struct work_struct bio_list_init(&ms->failures); spin_unlock_irqrestore(&ms->lock, flags); - dm_rh_update_states(ms->rh, errors_handled(ms), NULL, NULL); + dm_rh_update_states(ms->rh, errors_handled(ms), mirror_flush, ms); do_recovery(ms); do_reads(ms, &reads); do_writes(ms, &writes); @@ -1211,7 +1244,7 @@ static void mirror_postsuspend(struct dm struct mirror_set *ms = ti->private; struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); - if (log->type->postsuspend && log->type->postsuspend(log, NULL, NULL)) + if (log->type->postsuspend && log->type->postsuspend(log, mirror_flush, ms)) /* FIXME: need better error handling */ DMWARN("log postsuspend failed"); }