<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">From: Mikulas Patocka &lt;mpatocka@redhat.com&gt;

Flush support for dm-raid1.

When it receives an empty barrier, submit it to al the devices via dm-io.

Signed-off-by: Mikulas Patocka &lt;mpatocka@redhat.com&gt;

---
 drivers/md/dm-raid1.c       |   13 +++++++++++--
 drivers/md/dm-region-hash.c |   25 +++++++++++++++++++++++--
 2 files changed, 34 insertions(+), 4 deletions(-)

Index: linux-2.6.31-rc8/drivers/md/dm-raid1.c
===================================================================
--- linux-2.6.31-rc8.orig/drivers/md/dm-raid1.c
+++ linux-2.6.31-rc8/drivers/md/dm-raid1.c
@@ -396,6 +396,8 @@ static int mirror_available(struct mirro
  */
 static sector_t map_sector(struct mirror *m, struct bio *bio)
 {
+	if (unlikely(!bio-&gt;bi_size))
+		return 0;
 	return m-&gt;offset + (bio-&gt;bi_sector - m-&gt;ms-&gt;ti-&gt;begin);
 }
 
@@ -562,7 +564,7 @@ static void do_write(struct mirror_set *
 	struct dm_io_region io[ms-&gt;nr_mirrors], *dest = io;
 	struct mirror *m;
 	struct dm_io_request io_req = {
-		.bi_rw = WRITE,
+		.bi_rw = WRITE | (bio-&gt;bi_rw &amp; WRITE_BARRIER),
 		.mem.type = DM_IO_BVEC,
 		.mem.ptr.bvec = bio-&gt;bi_io_vec + bio-&gt;bi_idx,
 		.notify.fn = write_callback,
@@ -603,6 +605,11 @@ static void do_writes(struct mirror_set 
 	bio_list_init(&amp;requeue);
 
 	while ((bio = bio_list_pop(writes))) {
+		if (unlikely(bio_empty_barrier(bio))) {
+			bio_list_add(&amp;sync, bio);
+			continue;
+		}
+
 		region = dm_rh_bio_to_region(ms-&gt;rh, bio);
 
 		if (log-&gt;type-&gt;is_remote_recovering &amp;&amp;
@@ -995,6 +1002,7 @@ static int mirror_ctr(struct dm_target *
 
 	ti-&gt;private = ms;
 	ti-&gt;split_io = dm_rh_get_region_size(ms-&gt;rh);
+	ti-&gt;num_flush_requests = 1;
 
 	ms-&gt;kmirrord_wq = create_singlethread_workqueue("kmirrord");
 	if (!ms-&gt;kmirrord_wq) {
@@ -1122,7 +1130,8 @@ static int mirror_end_io(struct dm_targe
 	 * We need to dec pending if this was a write.
 	 */
 	if (rw == WRITE) {
-		dm_rh_dec(ms-&gt;rh, map_context-&gt;ll);
+		if (likely(!bio_empty_barrier(bio)))
+			dm_rh_dec(ms-&gt;rh, map_context-&gt;ll);
 		return error;
 	}
 
Index: linux-2.6.31-rc8/drivers/md/dm-region-hash.c
===================================================================
--- linux-2.6.31-rc8.orig/drivers/md/dm-region-hash.c
+++ linux-2.6.31-rc8/drivers/md/dm-region-hash.c
@@ -79,6 +79,11 @@ struct dm_region_hash {
 	struct list_head recovered_regions;
 	struct list_head failed_recovered_regions;
 
+	/*
+	 * If there was a barrier failure no regions can be marked clean.
+	 */
+	int barrier_failure;
+
 	void *context;
 	sector_t target_begin;
 
@@ -211,6 +216,7 @@ struct dm_region_hash *dm_region_hash_cr
 	INIT_LIST_HEAD(&amp;rh-&gt;quiesced_regions);
 	INIT_LIST_HEAD(&amp;rh-&gt;recovered_regions);
 	INIT_LIST_HEAD(&amp;rh-&gt;failed_recovered_regions);
+	rh-&gt;barrier_failure = 0;
 
 	rh-&gt;region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
 						      sizeof(struct dm_region));
@@ -395,6 +401,11 @@ void dm_rh_mark_nosync(struct dm_region_
 	region_t region = dm_rh_bio_to_region(rh, bio);
 	int recovering = 0;
 
+	if (bio_empty_barrier(bio)) {
+		rh-&gt;barrier_failure = 1;
+		return;
+	}
+
 	/* We must inform the log that the sync count has changed. */
 	log-&gt;type-&gt;set_region_sync(log, region, 0);
 
@@ -515,8 +526,11 @@ void dm_rh_inc_pending(struct dm_region_
 {
 	struct bio *bio;
 
-	for (bio = bios-&gt;head; bio; bio = bio-&gt;bi_next)
+	for (bio = bios-&gt;head; bio; bio = bio-&gt;bi_next) {
+		if (bio_empty_barrier(bio))
+			continue;
 		rh_inc(rh, dm_rh_bio_to_region(rh, bio));
+	}
 }
 EXPORT_SYMBOL_GPL(dm_rh_inc_pending);
 
@@ -544,7 +558,14 @@ void dm_rh_dec(struct dm_region_hash *rh
 		 */
 
 		/* do nothing for DM_RH_NOSYNC */
-		if (reg-&gt;state == DM_RH_RECOVERING) {
+		if (unlikely(rh-&gt;barrier_failure)) {
+			/*
+			 * If a write barrier failed some time ago, we
+			 * don't know whether or not this write made it
+			 * to the disk, so we must resync the device.
+			 */
+			reg-&gt;state = DM_RH_NOSYNC;
+		} else if (reg-&gt;state == DM_RH_RECOVERING) {
 			list_add_tail(&amp;reg-&gt;list, &amp;rh-&gt;quiesced_regions);
 		} else if (reg-&gt;state == DM_RH_DIRTY) {
 			reg-&gt;state = DM_RH_CLEAN;
</pre></body></html>