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

When processing the second part of a split bio resubmitted to the same
device we should skip the bookkeeping and avoid requesting io_lock
recursively.  Also fix a possible deadlock if the wait loop gets
interrupted.

Signed-off-by: Milan Broz &lt;mbroz@redhat.com&gt;
Signed-off-by: Alasdair G Kergon &lt;agk@redhat.com&gt;
---
 drivers/md/dm.c |   25 +++++++++++++++++++++----
 1 files changed, 21 insertions(+), 4 deletions(-)

Index: current-quilt/drivers/md/dm.c
===================================================================
--- current-quilt.orig/drivers/md/dm.c	2007-07-25 21:04:54.000000000 +0100
+++ current-quilt/drivers/md/dm.c	2007-07-25 21:04:55.000000000 +0100
@@ -564,6 +564,12 @@ static int clone2_endio(struct bio *bio,
 	return error;
 }
 
+static int is_clone2(struct mapped_device *md, struct bio *bio)
+{
+	return (bio-&gt;bi_end_io == clone2_endio &amp;&amp;
+		bio-&gt;bi_private == md);
+}
+
 static sector_t max_io_len(struct mapped_device *md,
 			   sector_t sector, struct dm_target *ti)
 {
@@ -817,6 +823,15 @@ static int dm_request(request_queue_t *q
 		return 0;
 	}
 
+	/*
+	 * If this is the second part of a split bio,
+	 * always map it immediately.
+	 */
+	if (is_clone2(md, bio)) {
+		r = __split_bio(md, bio);
+		goto out_req;
+	}
+
 	down_read(&amp;md-&gt;io_lock);
 
 	disk_stat_inc(dm_disk(md), ios[rw]);
@@ -1265,10 +1280,11 @@ EXPORT_SYMBOL_GPL(dm_put);
 /*
  * Process the deferred bios
  */
-static void __flush_deferred_io(struct mapped_device *md, struct bio *c)
+static void flush_deferred_io(struct mapped_device *md, struct bio *c)
 {
 	struct bio *n;
 
+	down_read(&amp;md-&gt;io_lock);
 	while (c) {
 		n = c-&gt;bi_next;
 		c-&gt;bi_next = NULL;
@@ -1276,6 +1292,7 @@ static void __flush_deferred_io(struct m
 			bio_io_error(c, c-&gt;bi_size);
 		c = n;
 	}
+	up_read(&amp;md-&gt;io_lock);
 }
 
 /*
@@ -1436,8 +1453,8 @@ int dm_suspend(struct mapped_device *md,
 	if (atomic_read(&amp;md-&gt;pending)) {
 		clear_bit(DMF_BLOCK_IO, &amp;md-&gt;flags);
 		def = bio_list_get(&amp;md-&gt;deferred);
-		__flush_deferred_io(md, def);
 		up_write(&amp;md-&gt;io_lock);
+		flush_deferred_io(md, def);
 		unlock_fs(md);
 		goto out; /* pushback list is already flushed, so skip flush */
 	}
@@ -1464,8 +1481,8 @@ flush_and_out:
 		spin_unlock_irqrestore(&amp;md-&gt;pushback_lock, flags);
 
 		def = bio_list_get(&amp;md-&gt;deferred);
-		__flush_deferred_io(md, def);
 		up_write(&amp;md-&gt;io_lock);
+		flush_deferred_io(md, def);
 	}
 
 out:
@@ -1503,8 +1520,8 @@ int dm_resume(struct mapped_device *md)
 	clear_bit(DMF_BLOCK_IO, &amp;md-&gt;flags);
 
 	def = bio_list_get(&amp;md-&gt;deferred);
-	__flush_deferred_io(md, def);
 	up_write(&amp;md-&gt;io_lock);
+	flush_deferred_io(md, def);
 
 	unlock_fs(md);
 
</pre></body></html>