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
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index 8917116..2079609 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;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp
index 695913a..778ba62 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::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);
 }
 
@@ -96,7 +96,7 @@
 
 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 @@
     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 7fe7b41..e8dad92 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;
@@ -296,12 +297,13 @@
             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 8a2bd2c..e928d35 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
@@ -52,12 +52,12 @@
     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; }