libsnapshot: add CowSizeInfo struct

Adding a cow size info struct as writer will now need to know the op buffer
size at the time of initialization. The sequence of events is as follows
(same as estimate_cow_size but putting down here for clarity)

1. ota_from_target_files does dry run to determine cow size + ops buffer
   size
2. data is passed through delta archive manifest
3. snapshot.cpp parses these fields and confgiures cowoptions struct to
   pass to writer initialization
4. cow is initialized with correct sizing. Data is incrementally added
   at the ends of the cow ops buffer (which is why we need to know the
   sizing ahead of time)

Test: ota
Change-Id: I950e5ef82c9bd7e9bd9603b0599c930767ee3f0d
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
index 5b1e56c..ca0ebe1 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
@@ -33,7 +33,10 @@
 
 namespace android {
 namespace snapshot {
-
+struct CowSizeInfo {
+    uint64_t cow_size;
+    uint64_t op_count_max;
+};
 struct CowOptions {
     uint32_t block_size = 4096;
     std::string compression;
@@ -92,8 +95,9 @@
     // to ensure that the correct headers and footers are written.
     virtual bool Finalize() = 0;
 
-    // Return number of bytes the cow image occupies on disk.
-    virtual uint64_t GetCowSize() = 0;
+    // Return number of bytes the cow image occupies on disk + the size of sequence && ops buffer
+    // The latter two fields are used in v3 cow format and left as 0 for v2 cow format
+    virtual CowSizeInfo GetCowSizeInfo() const = 0;
 
     virtual uint32_t GetBlockSize() const = 0;
     virtual std::optional<uint32_t> GetMaxBlocks() const = 0;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_cow_writer.h
index c58c654..8491fb0 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_cow_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_cow_writer.h
@@ -24,8 +24,7 @@
     using FileDescriptor = chromeos_update_engine::FileDescriptor;
 
     MOCK_METHOD(bool, Finalize, (), (override));
-
-    MOCK_METHOD(uint64_t, GetCowSize, (), (override));
+    MOCK_METHOD(CowSizeInfo, GetCowSizeInfo, (), (const, override));
 
     MOCK_METHOD(bool, AddCopy, (uint64_t, uint64_t, uint64_t), (override));
     MOCK_METHOD(bool, AddRawBlocks, (uint64_t, const void*, size_t), (override));
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
index 49d86d8..1d1d24c 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
@@ -601,14 +601,14 @@
     ASSERT_TRUE(writer.AddCopy(10, 20));
     ASSERT_TRUE(writer.AddRawBlocks(50, data.data(), data.size()));
     ASSERT_TRUE(writer.AddZeroBlocks(51, 2));
-    auto size_before = writer.GetCowSize();
+    auto size_before = writer.GetCowSizeInfo().cow_size;
     ASSERT_TRUE(writer.Finalize());
-    auto size_after = writer.GetCowSize();
+    auto size_after = writer.GetCowSizeInfo().cow_size;
     ASSERT_EQ(size_before, size_after);
     struct stat buf;
 
     ASSERT_GE(fstat(cow_->fd, &buf), 0) << strerror(errno);
-    ASSERT_EQ(buf.st_size, writer.GetCowSize());
+    ASSERT_EQ(buf.st_size, writer.GetCowSizeInfo().cow_size);
 }
 
 TEST_F(CowTest, AppendLabelSmall) {
@@ -637,7 +637,7 @@
 
     struct stat buf;
     ASSERT_EQ(fstat(cow_->fd, &buf), 0);
-    ASSERT_EQ(buf.st_size, writer->GetCowSize());
+    ASSERT_EQ(buf.st_size, writer->GetCowSizeInfo().cow_size);
 
     // Read back both operations, and label.
     CowReader reader;
@@ -690,7 +690,7 @@
     ASSERT_TRUE(writer->AddRawBlocks(50, data.data(), data.size()));
     ASSERT_TRUE(writer->AddLabel(1));
     // Drop the tail end of the last op header, corrupting it.
-    ftruncate(cow_->fd, writer->GetCowSize() - sizeof(CowFooter) - 3);
+    ftruncate(cow_->fd, writer->GetCowSizeInfo().cow_size - sizeof(CowFooter) - 3);
 
     ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
 
@@ -705,7 +705,7 @@
 
     struct stat buf;
     ASSERT_EQ(fstat(cow_->fd, &buf), 0);
-    ASSERT_EQ(buf.st_size, writer->GetCowSize());
+    ASSERT_EQ(buf.st_size, writer->GetCowSizeInfo().cow_size);
 
     // Read back both operations.
     CowReader reader;
@@ -763,7 +763,7 @@
 
     struct stat buf;
     ASSERT_EQ(fstat(cow_->fd, &buf), 0);
-    ASSERT_EQ(buf.st_size, writer->GetCowSize());
+    ASSERT_EQ(buf.st_size, writer->GetCowSizeInfo().cow_size);
 
     // Read back all valid operations
     CowReader reader;
@@ -812,7 +812,7 @@
 
     struct stat buf;
     ASSERT_EQ(fstat(cow_->fd, &buf), 0);
-    ASSERT_EQ(buf.st_size, writer->GetCowSize());
+    ASSERT_EQ(buf.st_size, writer->GetCowSizeInfo().cow_size);
 
     // Read back all ops
     CowReader reader;
@@ -989,7 +989,7 @@
 
     struct stat buf;
     ASSERT_EQ(fstat(cow_->fd, &buf), 0);
-    ASSERT_EQ(buf.st_size, writer->GetCowSize());
+    ASSERT_EQ(buf.st_size, writer->GetCowSizeInfo().cow_size);
 
     // Read back both operations, plus cluster op at end
     CowReader reader;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
index 3383a58..8cf46f4 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
@@ -658,14 +658,14 @@
     options.compression = "none";
     auto estimator = android::snapshot::CreateCowEstimator(3, options);
     ASSERT_TRUE(estimator->AddZeroBlocks(0, 1024 * 1024));
-    const auto cow_size = estimator->GetCowSize();
+    const auto cow_size = estimator->GetCowSizeInfo().cow_size;
     options.op_count_max = 1024 * 1024;
     options.max_blocks = 1024 * 1024;
     CowWriterV3 writer(options, GetCowFd());
     ASSERT_TRUE(writer.Initialize());
     ASSERT_TRUE(writer.AddZeroBlocks(0, 1024 * 1024));
 
-    ASSERT_LE(writer.GetCowSize(), cow_size);
+    ASSERT_LE(writer.GetCowSizeInfo().cow_size, cow_size);
 }
 
 TEST_F(CowTestV3, CopyOpMany) {
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
index f9a4e47..75cd111 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
@@ -576,12 +576,14 @@
     return Sync();
 }
 
-uint64_t CowWriterV2::GetCowSize() {
+CowSizeInfo CowWriterV2::GetCowSizeInfo() const {
+    CowSizeInfo info;
     if (current_data_size_ > 0) {
-        return next_data_pos_ + sizeof(footer_);
+        info.cow_size = next_data_pos_ + sizeof(footer_);
     } else {
-        return next_op_pos_ + sizeof(footer_);
+        info.cow_size = next_op_pos_ + sizeof(footer_);
     }
+    return info;
 }
 
 bool CowWriterV2::GetDataPos(uint64_t* pos) {
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.h
index 50e635f..05de2ad 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.h
@@ -27,7 +27,7 @@
 
     bool Initialize(std::optional<uint64_t> label = {}) override;
     bool Finalize() override;
-    uint64_t GetCowSize() override;
+    CowSizeInfo GetCowSizeInfo() const override;
 
   protected:
     virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index d99e6e6..824fa39 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -491,8 +491,11 @@
     return Sync();
 }
 
-uint64_t CowWriterV3::GetCowSize() {
-    return next_data_pos_;
+CowSizeInfo CowWriterV3::GetCowSizeInfo() const {
+    CowSizeInfo info;
+    info.cow_size = next_data_pos_;
+    info.op_count_max = header_.op_count_max;
+    return info;
 }
 
 }  // namespace snapshot
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
index 3a7b877..73ac520 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
@@ -30,7 +30,7 @@
 
     bool Initialize(std::optional<uint64_t> label = {}) override;
     bool Finalize() override;
-    uint64_t GetCowSize() override;
+    CowSizeInfo GetCowSizeInfo() const override;
 
   protected:
     virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;