From bf3020b7494384f716d4b1a5a6aea48d3fbd420e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 11 Mar 2021 16:14:30 -0800 Subject: [PATCH] libsnapshot: Fix CowWriter::Finalize() not restoring footer correctly. Bug: 173432386 Test: cow_api_test Change-Id: If1b856fcdcd6b6ded5e00342037308c6b35d6fc0 --- fs_mgr/libsnapshot/cow_api_test.cpp | 24 ++++++++++++++++++++++++ fs_mgr/libsnapshot/cow_reader.cpp | 3 ++- fs_mgr/libsnapshot/cow_writer.cpp | 3 ++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/fs_mgr/libsnapshot/cow_api_test.cpp b/fs_mgr/libsnapshot/cow_api_test.cpp index a96352a2d..5d632206d 100644 --- a/fs_mgr/libsnapshot/cow_api_test.cpp +++ b/fs_mgr/libsnapshot/cow_api_test.cpp @@ -757,6 +757,30 @@ TEST_F(CowTest, ClusterAppendTest) { ASSERT_TRUE(iter->Done()); } +TEST_F(CowTest, AppendAfterFinalize) { + CowOptions options; + options.cluster_ops = 0; + auto writer = std::make_unique(options); + ASSERT_TRUE(writer->Initialize(cow_->fd)); + + std::string data = "This is some data, believe it"; + data.resize(options.block_size, '\0'); + ASSERT_TRUE(writer->AddRawBlocks(50, data.data(), data.size())); + ASSERT_TRUE(writer->AddLabel(3)); + ASSERT_TRUE(writer->Finalize()); + + std::string data2 = "More data!"; + data2.resize(options.block_size, '\0'); + ASSERT_TRUE(writer->AddRawBlocks(51, data2.data(), data2.size())); + ASSERT_TRUE(writer->Finalize()); + + ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0); + + // COW should be valid. + CowReader reader; + ASSERT_TRUE(reader.Parse(cow_->fd)); +} + } // namespace snapshot } // namespace android diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/cow_reader.cpp index 163e457e8..44a423cf7 100644 --- a/fs_mgr/libsnapshot/cow_reader.cpp +++ b/fs_mgr/libsnapshot/cow_reader.cpp @@ -229,7 +229,8 @@ bool CowReader::ParseOps(std::optional label) { if (footer_) { if (ops_buffer->size() != footer_->op.num_ops) { - LOG(ERROR) << "num ops does not match"; + LOG(ERROR) << "num ops does not match, expected " << footer_->op.num_ops << ", found " + << ops_buffer->size(); return false; } if (ops_buffer->size() * sizeof(CowOperation) != footer_->op.ops_size) { diff --git a/fs_mgr/libsnapshot/cow_writer.cpp b/fs_mgr/libsnapshot/cow_writer.cpp index 81edc793b..59f6d6f92 100644 --- a/fs_mgr/libsnapshot/cow_writer.cpp +++ b/fs_mgr/libsnapshot/cow_writer.cpp @@ -376,6 +376,7 @@ bool CowWriter::Finalize() { auto continue_data_pos = next_data_pos_; auto continue_op_pos = next_op_pos_; auto continue_size = ops_.size(); + auto continue_num_ops = footer_.op.num_ops; bool extra_cluster = false; // Footer should be at the end of a file, so if there is data after the current block, end it @@ -408,9 +409,9 @@ bool CowWriter::Finalize() { current_data_size_ = continue_data_size; next_data_pos_ = continue_data_pos; next_op_pos_ = continue_op_pos; + footer_.op.num_ops = continue_num_ops; ops_.resize(continue_size); } - return Sync(); }