[lvm-devel] master - device: Skip read-modify-write if replacing whole block.

Alasdair Kergon agk at sourceware.org
Tue Dec 5 01:03:01 UTC 2017


Gitweb:        https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=7195df5acace29e77add6aa2f3df9c684e44694a
Commit:        7195df5acace29e77add6aa2f3df9c684e44694a
Parent:        e4805e48830c66e5fdcabf162a09cc27d6b73bc1
Author:        Alasdair G Kergon <agk at redhat.com>
AuthorDate:    Tue Dec 5 01:00:38 2017 +0000
Committer:     Alasdair G Kergon <agk at redhat.com>
CommitterDate: Tue Dec 5 01:00:38 2017 +0000

device: Skip read-modify-write if replacing whole block.

---
 WHATS_NEW           |    1 +
 lib/device/dev-io.c |   22 +++++++++++++---------
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/WHATS_NEW b/WHATS_NEW
index 541d764..674e7f1 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.02.177 -
 ====================================
+  Skip read-modify-write when entire block is replaced.
   Categorise I/O with reason annotations in debug messages.
   Command will lock memory only when suspending volumes.
   Merge segments when pvmove is finished.
diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c
index e108437..f77494f 100644
--- a/lib/device/dev-io.c
+++ b/lib/device/dev-io.c
@@ -231,6 +231,7 @@ static int _aligned_io(struct device_area *where, char *buffer,
 	char *bounce, *bounce_buf;
 	unsigned int physical_block_size = 0;
 	unsigned int block_size = 0;
+	unsigned buffer_was_widened = 0;
 	uintptr_t mask;
 	struct device_area widened;
 	int r = 0;
@@ -241,18 +242,19 @@ static int _aligned_io(struct device_area *where, char *buffer,
 
 	if (!block_size)
 		block_size = lvm_getpagesize();
+	mask = block_size - 1;
 
 	_widen_region(block_size, where, &widened);
 
-	/* Do we need to use a bounce buffer? */
-	mask = block_size - 1;
-	if (!memcmp(where, &widened, sizeof(widened)) &&
-	    !((uintptr_t) buffer & mask))
+	/* Did we widen the buffer?  When writing, this means means read-modify-write. */
+	if (where->size != widened.size || where->start != widened.start) {
+		buffer_was_widened = 1;
+		log_debug_io("Widening request for %" PRIu64 " bytes at %" PRIu64 " to %" PRIu64 " bytes at %" PRIu64 " on %s (for %s)",
+			     where->size, (uint64_t) where->start, widened.size, (uint64_t) widened.start, dev_name(where->dev), _reason_text(reason));
+	} else if (!((uintptr_t) buffer & mask))
+		/* Perform the I/O directly. */
 		return _io(where, buffer, should_write, reason);
 
-	log_debug_io("Widening request for %" PRIu64 " bytes at %" PRIu64 " to %" PRIu64 " bytes at %" PRIu64 " on %s (for %s)",
-		     where->size, (uint64_t) where->start, widened.size, (uint64_t) widened.start, dev_name(where->dev), _reason_text(reason));
-
 	/* Allocate a bounce buffer with an extra block */
 	if (!(bounce_buf = bounce = dm_malloc((size_t) widened.size + block_size))) {
 		log_error("Bounce buffer malloc failed");
@@ -265,10 +267,12 @@ static int _aligned_io(struct device_area *where, char *buffer,
 	if (((uintptr_t) bounce) & mask)
 		bounce = (char *) ((((uintptr_t) bounce) + mask) & ~mask);
 
-	/* channel the io through the bounce buffer */
-	if (!_io(&widened, bounce, 0, reason)) {
+	/* Do we need to read into the bounce buffer? */
+	if ((!should_write || buffer_was_widened) &&
+	    !_io(&widened, bounce, 0, reason)) {
 		if (!should_write)
 			goto_out;
+		/* FIXME Handle errors properly! */
 		/* FIXME pre-extend the file */
 		memset(bounce, '\n', widened.size);
 	}




More information about the lvm-devel mailing list