From: Mikulas Patocka <[email-masked]>

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 <[email-masked]>

---
 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");
 }