From f897650f6ef61db2e1ccb850527362aa9cbb5fa7 Mon Sep 17 00:00:00 2001 From: Daniel Zheng Date: Mon, 13 Nov 2023 11:05:35 -0800 Subject: [PATCH] libsnapshot: resume_point_count We want to add a resume_point_count in the header to represent how many resume points we've written. In the case that we've written less than resume_buffer_size, we only want to read the valid resume points. without these changes incremental OTA runs into segfault or have faulty data when trying to FindResumeOp() as our resume points contain invalid entries Test: full ota followed by inc ota on cuttlefish Change-Id: I0a8971955439639f2d0f39d9d518c1145ae15c3d --- fs_mgr/libsnapshot/include/libsnapshot/cow_format.h | 4 +++- fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp | 8 ++++---- fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp | 8 +++++--- fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h | 4 ++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h index 8917116d0..2079609c0 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h @@ -107,8 +107,10 @@ static constexpr uint8_t kNumResumePoints = 4; struct CowHeaderV3 : public CowHeader { // Location of sequence buffer in COW. uint64_t sequence_buffer_offset; + // number of currently written resume points + uint32_t resume_point_count; // Size, in bytes, of the CowResumePoint buffer. - uint32_t resume_buffer_size; + uint32_t resume_point_max; // Number of CowOperationV3 structs in the operation buffer, currently and total // region size. uint32_t op_count; diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp index 695913a32..778ba6270 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp @@ -75,10 +75,10 @@ bool CowParserV3::Parse(borrowed_fd fd, const CowHeaderV3& header, std::optional } bool CowParserV3::ReadResumeBuffer(borrowed_fd fd) { - resume_points_ = std::make_shared>(header_.resume_buffer_size); + resume_points_ = std::make_shared>(header_.resume_point_count); return android::base::ReadFullyAtOffset(fd, resume_points_->data(), - header_.resume_buffer_size * sizeof(ResumePoint), + header_.resume_point_count * sizeof(ResumePoint), header_.prefix.header_size + header_.buffer_size); } @@ -96,7 +96,7 @@ std::optional CowParserV3::FindResumeOp(const uint64_t label) { off_t CowParserV3::GetDataOffset() const { return sizeof(CowHeaderV3) + header_.buffer_size + - header_.resume_buffer_size * sizeof(ResumePoint) + + header_.resume_point_max * sizeof(ResumePoint) + header_.op_count_max * sizeof(CowOperation); } @@ -105,7 +105,7 @@ bool CowParserV3::ParseOps(borrowed_fd fd, const uint32_t op_index) { ops_->resize(op_index); const off_t offset = header_.prefix.header_size + header_.buffer_size + - header_.resume_buffer_size * sizeof(ResumePoint); + header_.resume_point_max * sizeof(ResumePoint); if (!android::base::ReadFullyAtOffset(fd, ops_->data(), ops_->size() * sizeof(CowOperationV3), offset)) { PLOG(ERROR) << "read ops failed"; diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp index 7fe7b4157..e8dad922a 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp @@ -78,7 +78,8 @@ void CowWriterV3::SetupHeaders() { // WIP: not quite sure how some of these are calculated yet, assuming buffer_size is determined // during COW size estimation header_.sequence_buffer_offset = 0; - header_.resume_buffer_size = kNumResumePoints; + header_.resume_point_count = 0; + header_.resume_point_max = kNumResumePoints; header_.op_count = 0; header_.op_count_max = 0; header_.compression_algorithm = kCowCompressNone; @@ -296,12 +297,13 @@ bool CowWriterV3::EmitLabel(uint64_t label) { resume_points_->end()); resume_points_->push_back({label, header_.op_count}); + header_.resume_point_count++; // remove the oldest resume point if resume_buffer is full - while (resume_points_->size() > header_.resume_buffer_size) { + while (resume_points_->size() > header_.resume_point_max) { resume_points_->erase(resume_points_->begin()); } - CHECK_LE(resume_points_->size(), header_.resume_buffer_size); + CHECK_LE(resume_points_->size(), header_.resume_point_max); if (!android::base::WriteFullyAtOffset(fd_, resume_points_->data(), resume_points_->size() * sizeof(ResumePoint), diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h index 8a2bd2c6d..e928d3557 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h +++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h @@ -52,12 +52,12 @@ class CowWriterV3 : public CowWriterBase { off_t GetOpOffset(uint32_t op_index) const { CHECK_LT(op_index, header_.op_count_max); return header_.prefix.header_size + header_.buffer_size + - (header_.resume_buffer_size * sizeof(ResumePoint)) + + (header_.resume_point_max * sizeof(ResumePoint)) + (op_index * sizeof(CowOperationV3)); } off_t GetDataOffset() const { return sizeof(CowHeaderV3) + header_.buffer_size + - (header_.resume_buffer_size * sizeof(ResumePoint)) + + (header_.resume_point_max * sizeof(ResumePoint)) + header_.op_count_max * sizeof(CowOperation); } off_t GetResumeOffset() const { return sizeof(CowHeaderV3) + header_.buffer_size; }