From ed70dacf2fe5558603590627e3c49fa04d665e50 Mon Sep 17 00:00:00 2001 From: Alex Young Date: Tue, 20 Nov 2012 17:24:19 +0000 Subject: [PATCH] Don't skip parts of a file when calling fiemap A mis-incremented offset in the fiemap-processing code meant that non-sparse portions of files were missed. --- src/client.c | 7 +++++-- src/ioutil.c | 2 +- tests/acceptance/environment.rb | 4 ++++ tests/acceptance/test_happy_path.rb | 27 +++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/client.c b/src/client.c index d23f303..79bfb0b 100644 --- a/src/client.c +++ b/src/client.c @@ -140,8 +140,11 @@ void write_not_zeroes(struct client* client, uint64_t from, int len) * and memcpy being fast, rather than try to * hand-optimized something specific. */ - if (zerobuffer[0] != 0 || - memcmp(zerobuffer, zerobuffer + 1, blockrun - 1)) { + + int all_zeros = (zerobuffer[0] == 0) && + (0 == memcmp( zerobuffer, zerobuffer+1, blockrun-1 )); + + if ( !all_zeros ) { memcpy(client->mapped+from, zerobuffer, blockrun); bitset_set_range(map, from, blockrun); server_dirty(client->serve, from, blockrun); diff --git a/src/ioutil.c b/src/ioutil.c index 0c2bf90..e6a61f9 100644 --- a/src/ioutil.c +++ b/src/ioutil.c @@ -64,7 +64,7 @@ int build_allocation_map(struct bitset_mapping* allocation_map, int fd) struct fiemap_extent *last = &fiemap->fm_extents[ fiemap->fm_mapped_extents-1 ]; - offset += last->fe_logical + last->fe_length; + offset = last->fe_logical + last->fe_length; } else { offset += fiemap->fm_length; diff --git a/tests/acceptance/environment.rb b/tests/acceptance/environment.rb index 5b80cd2..e1efb0c 100644 --- a/tests/acceptance/environment.rb +++ b/tests/acceptance/environment.rb @@ -78,6 +78,10 @@ class Environment end + def write1( data ) + @nbd1.write( 0, data ) + end + def writefile1(data) @file1 = FileWriter.new(@filename1, @blocksize).write(data) end diff --git a/tests/acceptance/test_happy_path.rb b/tests/acceptance/test_happy_path.rb index c93a770..0819074 100644 --- a/tests/acceptance/test_happy_path.rb +++ b/tests/acceptance/test_happy_path.rb @@ -129,5 +129,32 @@ class TestHappyPath < Test::Unit::TestCase assert_no_match( /^(F|E):/, stderr ) end + + def test_write_more_than_one_run + one_mb = 2**20 + data = "\0" * 256 * one_mb + + File.open(@env.filename1, "wb") do |f| f.write( "1" * 256 * one_mb ) end + + @env.serve1 + sleep 5 + @env.write1( data ) + @env.nbd1.can_die(0) + @env.nbd1.kill + + i = 0 + File.open(@env.filename1, "rb") do |f| + while mb = f.read( one_mb ) + unless "\0"*one_mb == mb + msg = "Read non-zeros after offset %x:\n"%(i * one_mb) + msg += `hexdump #{@env.filename1} | head -n5` + fail msg + end + i += 1 + end + end + p i + end + end