1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

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

This commit is contained in:
Alasdair G Kergon 2017-12-05 01:00:38 +00:00
parent e4805e4883
commit 7195df5aca
2 changed files with 14 additions and 9 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.177 - Version 2.02.177 -
==================================== ====================================
Skip read-modify-write when entire block is replaced.
Categorise I/O with reason annotations in debug messages. Categorise I/O with reason annotations in debug messages.
Command will lock memory only when suspending volumes. Command will lock memory only when suspending volumes.
Merge segments when pvmove is finished. Merge segments when pvmove is finished.

View File

@ -231,6 +231,7 @@ static int _aligned_io(struct device_area *where, char *buffer,
char *bounce, *bounce_buf; char *bounce, *bounce_buf;
unsigned int physical_block_size = 0; unsigned int physical_block_size = 0;
unsigned int block_size = 0; unsigned int block_size = 0;
unsigned buffer_was_widened = 0;
uintptr_t mask; uintptr_t mask;
struct device_area widened; struct device_area widened;
int r = 0; int r = 0;
@ -241,18 +242,19 @@ static int _aligned_io(struct device_area *where, char *buffer,
if (!block_size) if (!block_size)
block_size = lvm_getpagesize(); block_size = lvm_getpagesize();
mask = block_size - 1;
_widen_region(block_size, where, &widened); _widen_region(block_size, where, &widened);
/* Do we need to use a bounce buffer? */ /* Did we widen the buffer? When writing, this means means read-modify-write. */
mask = block_size - 1; if (where->size != widened.size || where->start != widened.start) {
if (!memcmp(where, &widened, sizeof(widened)) && buffer_was_widened = 1;
!((uintptr_t) buffer & mask)) 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); 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 */ /* Allocate a bounce buffer with an extra block */
if (!(bounce_buf = bounce = dm_malloc((size_t) widened.size + block_size))) { if (!(bounce_buf = bounce = dm_malloc((size_t) widened.size + block_size))) {
log_error("Bounce buffer malloc failed"); 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) if (((uintptr_t) bounce) & mask)
bounce = (char *) ((((uintptr_t) bounce) + mask) & ~mask); bounce = (char *) ((((uintptr_t) bounce) + mask) & ~mask);
/* channel the io through the bounce buffer */ /* Do we need to read into the bounce buffer? */
if (!_io(&widened, bounce, 0, reason)) { if ((!should_write || buffer_was_widened) &&
!_io(&widened, bounce, 0, reason)) {
if (!should_write) if (!should_write)
goto_out; goto_out;
/* FIXME Handle errors properly! */
/* FIXME pre-extend the file */ /* FIXME pre-extend the file */
memset(bounce, '\n', widened.size); memset(bounce, '\n', widened.size);
} }