summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarin Petkov <petkov@chromium.org>2013-04-25 14:46:09 +0200
committerChromeBot <chrome-bot@google.com>2013-04-30 06:01:12 -0700
commit8a075a75a13a2b182c229f3095c20e69f8f8f999 (patch)
treea055c93def5a0cccf436a735ec25f436a27143ea
parentf413fe59759c73d6a5624c2158260b4302d01fe2 (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.cc37
-rw-r--r--delta_performer_unittest.cc31
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 && "