CreateSnapshot: reduce zero-filling for CoW images

Instead of zero-filling the whole image, only clean the dm-snapshot
metadata header of the CoW file.

Zero-filling a large image may take a long time, and this is a safe, but
not necessary operation if the operation is intended to prepare an
initial CoW file that will be used with a dm-snapshot device.
According to the Linux kernel code, only the first 32 bits of the CoW
file is used to detect if the dm-snapshot device under creation will be
at an initial state or the continuation of a previous dm-snapshot.
CREATE_IMAGE_RESET_SNAP is a flag that reduces the zeroing of the image
file to the first file chunk.

Change-Id: Ibc9fb3b6d19666a92125c988687ff8dacfad47be
Depends-On: I242e57a9a622fbb738bf82f8a260af1b13810069
Bug: 139378014
Test: manual, snapshot_test
Signed-off-by: Alessio Balsini <balsini@google.com>
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 588941a..75528ab 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -210,8 +210,27 @@
     }
 
     auto cow_name = GetCowName(name);
-    int cow_flags = IImageManager::CREATE_IMAGE_ZERO_FILL;
-    return images_->CreateBackingImage(cow_name, cow_size, cow_flags);
+    int cow_flags = IImageManager::CREATE_IMAGE_DEFAULT;
+    if (!images_->CreateBackingImage(cow_name, cow_size, cow_flags)) {
+        return false;
+    }
+
+    // when the kernel creates a persistent dm-snapshot, it requires a CoW file
+    // to store the modifications. The kernel interface does not specify how
+    // the CoW is used, and there is no standard associated.
+    // By looking at the current implementation, the CoW file is treated as:
+    // - a _NEW_ snapshot if its first 32 bits are zero, so the newly created
+    // dm-snapshot device will look like a perfect copy of the origin device;
+    // - an _EXISTING_ snapshot if the first 32 bits are equal to a
+    // kernel-specified magic number and the CoW file metadata is set as valid,
+    // so it can be used to resume the last state of a snapshot device;
+    // - an _INVALID_ snapshot otherwise.
+    // To avoid zero-filling the whole CoW file when a new dm-snapshot is
+    // created, here we zero-fill only the first 32 bits. This is a temporary
+    // workaround that will be discussed again when the kernel API gets
+    // consolidated.
+    ssize_t dm_snap_magic_size = 4;  // 32 bit
+    return images_->ZeroFillNewImage(cow_name, dm_snap_magic_size);
 }
 
 bool SnapshotManager::MapSnapshot(LockedFile* lock, const std::string& name,