Merge "Disable partition verification when device boots on snapshot" into main
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 87c4cd2..a6d8226 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -2825,7 +2825,8 @@
     }
 
     prev_file = match[1];
-    unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(prev_file, 0).release());
+    auto elf_memory = unwindstack::Memory::CreateFileMemory(prev_file, 0);
+    unwindstack::Elf elf(elf_memory);
     if (!elf.Init() || !elf.valid()) {
       // Skipping invalid elf files.
       continue;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index 8917116..75467cb 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
@@ -107,8 +107,10 @@
 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;
@@ -230,6 +232,19 @@
     return op.source_info & kCowOpSourceInfoDataMask;
 }
 
+static constexpr off_t GetOpOffset(uint32_t op_index, const CowHeaderV3 header) {
+    return header.prefix.header_size + header.buffer_size +
+           (header.resume_point_max * sizeof(ResumePoint)) + (op_index * sizeof(CowOperationV3));
+}
+static constexpr off_t GetDataOffset(const CowHeaderV3 header) {
+    return header.prefix.header_size + header.buffer_size +
+           (header.resume_point_max * sizeof(ResumePoint)) +
+           header.op_count_max * sizeof(CowOperation);
+}
+static constexpr off_t GetResumeOffset(const CowHeaderV3 header) {
+    return header.prefix.header_size + header.buffer_size;
+}
+
 struct CowFooter {
     CowFooterOperation op;
     uint8_t unused[64];
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp
index d411ab9..52c6348 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp
@@ -75,14 +75,14 @@
 }
 
 bool CowParserV3::ReadResumeBuffer(borrowed_fd fd) {
-    resume_points_ = std::make_shared<std::vector<ResumePoint>>(header_.resume_buffer_size);
+    resume_points_ = std::make_shared<std::vector<ResumePoint>>(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);
 }
 
-std::optional<uint32_t> CowParserV3::FindResumeOp(const uint32_t label) {
+std::optional<uint32_t> CowParserV3::FindResumeOp(const uint64_t label) {
     for (auto& resume_point : *resume_points_) {
         if (resume_point.label == label) {
             return resume_point.op_index;
@@ -94,18 +94,12 @@
     return std::nullopt;
 }
 
-off_t CowParserV3::GetDataOffset() const {
-    return sizeof(CowHeaderV3) + header_.buffer_size +
-           header_.resume_buffer_size * sizeof(ResumePoint) +
-           header_.op_count_max * sizeof(CowOperation);
-}
-
 bool CowParserV3::ParseOps(borrowed_fd fd, const uint32_t op_index) {
     ops_ = std::make_shared<std::vector<CowOperationV3>>();
     ops_->resize(op_index);
 
-    const off_t offset = header_.prefix.header_size + header_.buffer_size +
-                         header_.resume_buffer_size * sizeof(ResumePoint);
+    // read beginning of operation buffer -> so op_index = 0
+    const off_t offset = GetOpOffset(0, header_);
     if (!android::base::ReadFullyAtOffset(fd, ops_->data(), ops_->size() * sizeof(CowOperationV3),
                                           offset)) {
         PLOG(ERROR) << "read ops failed";
@@ -113,7 +107,7 @@
     }
 
     // fill out mapping of XOR op data location
-    uint64_t data_pos = GetDataOffset();
+    uint64_t data_pos = GetDataOffset(header_);
 
     xor_data_loc_ = std::make_shared<std::unordered_map<uint64_t, uint64_t>>();
 
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h
index dceb815..afc01af 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h
@@ -49,8 +49,7 @@
 
   private:
     bool ParseOps(android::base::borrowed_fd fd, const uint32_t op_index);
-    std::optional<uint32_t> FindResumeOp(const uint32_t label);
-    off_t GetDataOffset() const;
+    std::optional<uint32_t> FindResumeOp(const uint64_t label);
     CowHeaderV3 header_ = {};
     std::shared_ptr<std::vector<CowOperationV3>> ops_;
     bool ReadResumeBuffer(android::base::borrowed_fd fd);
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index 89fd903..6883c5e 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -78,7 +78,8 @@
     // 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;
@@ -169,7 +170,7 @@
         LOG(ERROR) << "Header sync failed";
         return false;
     }
-    next_data_pos_ = GetDataOffset();
+    next_data_pos_ = GetDataOffset(header_);
     return true;
 }
 
@@ -191,7 +192,7 @@
 
     resume_points_ = parser.resume_points();
     options_.block_size = header_.block_size;
-    next_data_pos_ = GetDataOffset();
+    next_data_pos_ = GetDataOffset(header_);
 
     TranslatedCowOps ops;
     parser.Translate(&ops);
@@ -296,16 +297,17 @@
             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),
-                                           GetResumeOffset())) {
+                                           GetResumeOffset(header_))) {
         PLOG(ERROR) << "writing resume buffer failed";
         return false;
     }
@@ -331,7 +333,7 @@
         return false;
     }
 
-    const off_t offset = GetOpOffset(header_.op_count);
+    const off_t offset = GetOpOffset(header_.op_count, header_);
     if (!android::base::WriteFullyAtOffset(fd_, &op, sizeof(op), offset)) {
         PLOG(ERROR) << "write failed for " << op << " at " << offset;
         return false;
@@ -360,9 +362,7 @@
 }
 
 uint64_t CowWriterV3::GetCowSize() {
-    LOG(ERROR) << __LINE__ << " " << __FILE__
-               << " <- Get Cow Size function here should never be called";
-    return 0;
+    return next_data_pos_;
 }
 
 }  // namespace snapshot
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
index 8a2bd2c..3dfc33c 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
@@ -49,19 +49,6 @@
                     uint16_t offset, uint8_t type);
     bool CompressBlocks(size_t num_blocks, const void* data);
 
-    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)) +
-               (op_index * sizeof(CowOperationV3));
-    }
-    off_t GetDataOffset() const {
-        return sizeof(CowHeaderV3) + header_.buffer_size +
-               (header_.resume_buffer_size * sizeof(ResumePoint)) +
-               header_.op_count_max * sizeof(CowOperation);
-    }
-    off_t GetResumeOffset() const { return sizeof(CowHeaderV3) + header_.buffer_size; }
-
   private:
     CowHeaderV3 header_{};
     CowCompression compression_;