diff options
author | Darin Petkov <petkov@chromium.org> | 2013-04-25 14:46:09 +0200 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-04-30 06:01:12 -0700 |
commit | 8a075a75a13a2b182c229f3095c20e69f8f8f999 (patch) | |
tree | a055c93def5a0cccf436a735ec25f436a27143ea | |
parent | f413fe59759c73d6a5624c2158260b4302d01fe2 (diff) |
AU: Handle moving of sparse block extents correctly in DeltaPerformer.
Rather than reading from sparse holes, just reset the buffer with zeros. Drop
writes to sparse holes (and DCHECK that the data to be written is all zeros).
This patch also adds the following tests:
- Move a file of zeros into a sparse file.
- Move a sparse file into a file of zeros.
- Move a partially sparse file.
BUG=chromium:196378
TEST=unit tests
Change-Id: Idab8d44b391fbe7714c7fd53f7f383c9bf81edc1
Reviewed-on: https://gerrit.chromium.org/gerrit/49172
Commit-Queue: Darin Petkov <petkov@chromium.org>
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Darin Petkov <petkov@chromium.org>
-rw-r--r-- | delta_performer.cc | 37 | ||||
-rw-r--r-- | delta_performer_unittest.cc | 31 |
2 files changed, 55 insertions, 13 deletions
diff --git a/delta_performer.cc b/delta_performer.cc index 0a2a9432..ae1f7e5e 100644 --- a/delta_performer.cc +++ b/delta_performer.cc @@ -580,14 +580,19 @@ bool DeltaPerformer::PerformMoveOperation( for (int i = 0; i < operation.src_extents_size(); i++) { ssize_t bytes_read_this_iteration = 0; const Extent& extent = operation.src_extents(i); - TEST_AND_RETURN_FALSE(utils::PReadAll(fd, - &buf[bytes_read], - extent.num_blocks() * block_size_, - extent.start_block() * block_size_, - &bytes_read_this_iteration)); + const size_t bytes = extent.num_blocks() * block_size_; + if (extent.start_block() == kSparseHole) { + bytes_read_this_iteration = bytes; + memset(&buf[bytes_read], 0, bytes); + } else { + TEST_AND_RETURN_FALSE(utils::PReadAll(fd, + &buf[bytes_read], + bytes, + extent.start_block() * block_size_, + &bytes_read_this_iteration)); + } TEST_AND_RETURN_FALSE( - bytes_read_this_iteration == - static_cast<ssize_t>(extent.num_blocks() * block_size_)); + bytes_read_this_iteration == static_cast<ssize_t>(bytes)); bytes_read += bytes_read_this_iteration; } @@ -603,11 +608,19 @@ bool DeltaPerformer::PerformMoveOperation( ssize_t bytes_written = 0; for (int i = 0; i < operation.dst_extents_size(); i++) { const Extent& extent = operation.dst_extents(i); - TEST_AND_RETURN_FALSE(utils::PWriteAll(fd, - &buf[bytes_written], - extent.num_blocks() * block_size_, - extent.start_block() * block_size_)); - bytes_written += extent.num_blocks() * block_size_; + const size_t bytes = extent.num_blocks() * block_size_; + if (extent.start_block() == kSparseHole) { + DCHECK_EQ(&buf[bytes_written], + std::search_n(&buf[bytes_written], &buf[bytes_written + bytes], + bytes, 0)); + } else { + TEST_AND_RETURN_FALSE( + utils::PWriteAll(fd, + &buf[bytes_written], + bytes, + extent.start_block() * block_size_)); + } + bytes_written += bytes; } DCHECK_EQ(bytes_written, bytes_read); DCHECK_EQ(bytes_written, static_cast<ssize_t>(buf.size())); diff --git a/delta_performer_unittest.cc b/delta_performer_unittest.cc index 0c2c5885..83f3863a 100644 --- a/delta_performer_unittest.cc +++ b/delta_performer_unittest.cc @@ -285,6 +285,20 @@ static void GenerateDeltaFile(bool full_kernel, &hardtocompress[0], hardtocompress.size())); + vector<char> zeros(16 * 1024, 0); + EXPECT_EQ(zeros.size(), + file_util::WriteFile( + FilePath(StringPrintf("%s/move-to-sparse", a_mnt.c_str())), + &zeros[0], zeros.size())); + + EXPECT_TRUE( + WriteSparseFile(StringPrintf("%s/move-from-sparse", a_mnt.c_str()), + 16 * 1024)); + + EXPECT_EQ(0, system(StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse " + "bs=1 seek=4096 count=1", + a_mnt.c_str()).c_str())); + // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff // patch fails to zero out the final block. vector<char> ones(1024 * 1024, 0xff); @@ -320,7 +334,22 @@ static void GenerateDeltaFile(bool full_kernel, b_mnt.c_str()).c_str())); EXPECT_TRUE(WriteSparseFile(StringPrintf("%s/fullsparse", b_mnt.c_str()), 1024 * 1024)); - EXPECT_EQ(0, system(StringPrintf("dd if=/dev/zero of=%s/partsparese bs=1 " + + EXPECT_TRUE( + WriteSparseFile(StringPrintf("%s/move-to-sparse", b_mnt.c_str()), + 16 * 1024)); + + vector<char> zeros(16 * 1024, 0); + EXPECT_EQ(zeros.size(), + file_util::WriteFile( + FilePath(StringPrintf("%s/move-from-sparse", b_mnt.c_str())), + &zeros[0], zeros.size())); + + EXPECT_EQ(0, system(StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse " + "bs=1 seek=4096 count=1", + b_mnt.c_str()).c_str())); + + EXPECT_EQ(0, system(StringPrintf("dd if=/dev/zero of=%s/partsparse bs=1 " "seek=4096 count=1", b_mnt.c_str()).c_str())); EXPECT_EQ(0, system(StringPrintf("cp %s/srchardlink0 %s/tmp && " |