<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">	brassow

The logging API needs an extra function to make cluster mirroring
possible.  This new function allows us to check whether a mirror
region is being recovered on another machine in the cluster.  This
helps us prevent simultaneous recovery I/O and process I/O to the
same locations on disk.

Cluster-aware log modules will implement this function.  Single
machine log modules will not.  So, there is no performance
penalty for single machine mirrors.

Signed-off-by: Jonathan Brassow &lt;jbrassow@redhat.com&gt;

---
 drivers/md/dm-raid1.c        |   24 +++++++++++++++++++++++-
 include/linux/dm-dirty-log.h |   10 ++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)

Index: linux/drivers/md/dm-raid1.c
===================================================================
--- linux.orig/drivers/md/dm-raid1.c	2008-08-05 14:13:54.000000000 +0100
+++ linux/drivers/md/dm-raid1.c	2008-08-05 14:14:25.000000000 +0100
@@ -1157,6 +1157,9 @@ static void do_writes(struct mirror_set 
 	int state;
 	struct bio *bio;
 	struct bio_list sync, nosync, recover, *this_list = NULL;
+	struct bio_list requeue;
+	struct dm_dirty_log *log = ms-&gt;rh.log;
+	region_t region;
 
 	if (!writes-&gt;head)
 		return;
@@ -1167,9 +1170,18 @@ static void do_writes(struct mirror_set 
 	bio_list_init(&amp;sync);
 	bio_list_init(&amp;nosync);
 	bio_list_init(&amp;recover);
+	bio_list_init(&amp;requeue);
 
 	while ((bio = bio_list_pop(writes))) {
-		state = rh_state(&amp;ms-&gt;rh, bio_to_region(&amp;ms-&gt;rh, bio), 1);
+		region = bio_to_region(&amp;ms-&gt;rh, bio);
+
+		if (log-&gt;type-&gt;is_remote_recovering &amp;&amp;
+		    log-&gt;type-&gt;is_remote_recovering(log, region)) {
+			bio_list_add(&amp;requeue, bio);
+			continue;
+		}
+
+		state = rh_state(&amp;ms-&gt;rh, region, 1);
 		switch (state) {
 		case RH_CLEAN:
 		case RH_DIRTY:
@@ -1189,6 +1201,16 @@ static void do_writes(struct mirror_set 
 	}
 
 	/*
+	 * Add bios that are delayed due to remote recovery
+	 * back on to the write queue
+	 */
+	if (unlikely(requeue.head)) {
+		spin_lock_irq(&amp;ms-&gt;lock);
+		bio_list_merge(&amp;ms-&gt;writes, &amp;requeue);
+		spin_unlock_irq(&amp;ms-&gt;lock);
+	}
+
+	/*
 	 * Increment the pending counts for any regions that will
 	 * be written to (writes to recover regions are going to
 	 * be delayed).
Index: linux/include/linux/dm-dirty-log.h
===================================================================
--- linux.orig/include/linux/dm-dirty-log.h	2008-08-05 02:41:15.000000000 +0100
+++ linux/include/linux/dm-dirty-log.h	2008-08-05 14:14:25.000000000 +0100
@@ -113,6 +113,16 @@ struct dm_dirty_log_type {
 	 */
 	int (*status)(struct dm_dirty_log *log, status_type_t status_type,
 		      char *result, unsigned maxlen);
+
+	/*
+	 * is_remote_recovering 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).
+	 *
+	 * Returns: 0, 1
+	 */
+	int (*is_remote_recovering)(struct dm_dirty_log *log, region_t region);
 };
 
 int dm_dirty_log_type_register(struct dm_dirty_log_type *type);
</pre></body></html>