libsnapshot: op_count_max default to max blocks

In the case that op_count_max is read in as zero, we should use the
upper bound of max blocks as the estimation. One case in which this
error can happen is if a v2 cow estimator is used, we should still be
able to run an OTA if we upper bound our ops buffer size estimation.

Test: th
Change-Id: I97ca66368d6631bf43c8911ed66f99c9e8096e2d
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
index 8cf46f4..de60213 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
@@ -72,6 +72,7 @@
 
 TEST_F(CowTestV3, Header) {
     CowOptions options;
+    options.op_count_max = 15;
     auto writer = CreateCowWriter(3, options, GetCowFd());
     ASSERT_TRUE(writer->Finalize());
 
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index 0e13197..051b2fb 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -129,6 +129,18 @@
     header_.compression_algorithm = *algorithm;
     header_.op_count_max = options_.op_count_max;
 
+    if (!IsEstimating() && header_.op_count_max == 0) {
+        if (!options_.max_blocks.has_value()) {
+            LOG(ERROR) << "can't size op buffer size since op_count_max is 0 and max_blocks is not "
+                          "set.";
+            return false;
+        }
+        LOG(INFO) << "op count max is read in as 0. Setting to "
+                     "num blocks in partition "
+                  << options_.max_blocks.value();
+        header_.op_count_max = options_.max_blocks.value();
+    }
+
     if (parts.size() > 1) {
         if (!android::base::ParseUint(parts[1], &compression_.compression_level)) {
             LOG(ERROR) << "failed to parse compression level invalid type: " << parts[1];
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index c12a9e2..9ce00e5 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -1142,8 +1142,8 @@
     return result;
 }
 
-auto SnapshotManager::CheckMergeState(LockedFile* lock, const std::function<bool()>& before_cancel)
-        -> MergeResult {
+auto SnapshotManager::CheckMergeState(LockedFile* lock,
+                                      const std::function<bool()>& before_cancel) -> MergeResult {
     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
     switch (update_status.state()) {
         case UpdateState::None:
@@ -1218,8 +1218,8 @@
                 wrong_phase = true;
                 break;
             default:
-                LOG(ERROR) << "Unknown merge status for \"" << snapshot << "\": "
-                           << "\"" << result.state << "\"";
+                LOG(ERROR) << "Unknown merge status for \"" << snapshot << "\": " << "\""
+                           << result.state << "\"";
                 if (failure_code == MergeFailureCode::Ok) {
                     failure_code = MergeFailureCode::UnexpectedMergeState;
                 }
@@ -2797,8 +2797,8 @@
     return true;
 }
 
-auto SnapshotManager::OpenFile(const std::string& file, int lock_flags)
-        -> std::unique_ptr<LockedFile> {
+auto SnapshotManager::OpenFile(const std::string& file,
+                               int lock_flags) -> std::unique_ptr<LockedFile> {
     unique_fd fd(open(file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
     if (fd < 0) {
         PLOG(ERROR) << "Open failed: " << file;
@@ -3558,6 +3558,7 @@
             options.compression = it->second.compression_algorithm();
             if (cow_version >= 3) {
                 options.op_count_max = it->second.estimated_ops_buffer_size();
+                options.max_blocks = {it->second.device_size() / options.block_size};
             }
 
             auto writer = CreateCowWriter(cow_version, options, std::move(fd));
@@ -4343,8 +4344,7 @@
         }
     }
 
-    LOG(ERROR) << "Device-mapper device " << name << "(" << full_path << ")"
-               << " still in use."
+    LOG(ERROR) << "Device-mapper device " << name << "(" << full_path << ")" << " still in use."
                << "  Probably a file descriptor was leaked or held open, or a loop device is"
                << " attached.";
     return false;