Merge "Pre-create userdata metadata encryption device." am: eb3182f040 am: af91a5ec2d am: a53bd16bc1

Original change: https://android-review.googlesource.com/c/platform/system/vold/+/1833056

Change-Id: I033738b64c71eb19c5f4aec5c01f8bd72cc82aaa
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index 2f11c8b..8b2b960 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -52,6 +52,7 @@
 using android::fscrypt::GetFirstApiLevel;
 using android::vold::KeyBuffer;
 using namespace android::dm;
+using namespace std::chrono_literals;
 
 // Parsed from metadata options
 struct CryptoOptions {
@@ -81,6 +82,17 @@
     return KeyGeneration{options.cipher.get_keysize(), true, options.use_hw_wrapped_key};
 }
 
+void defaultkey_precreate_dm_device() {
+    auto& dm = DeviceMapper::Instance();
+    if (dm.GetState(kDmNameUserdata) != DmDeviceState::INVALID) {
+        LOG(INFO) << "Not pre-creating userdata encryption device; device already exists";
+        return;
+    }
+    if (!dm.CreateEmptyDevice(kDmNameUserdata)) {
+        LOG(ERROR) << "Failed to pre-create userdata metadata encryption device";
+    }
+}
+
 static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
     // fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
     // partitions in the fsck domain.
@@ -173,8 +185,19 @@
     table.AddTarget(std::move(target));
 
     auto& dm = DeviceMapper::Instance();
-    if (!dm.CreateDevice(dm_name, table, crypto_blkdev, std::chrono::seconds(5))) {
-        PLOG(ERROR) << "Could not create default-key device " << dm_name;
+    if (dm_name == kDmNameUserdata && dm.GetState(dm_name) == DmDeviceState::SUSPENDED) {
+        // The device was created in advance, populate it now.
+        std::string path;
+        if (!dm.WaitForDevice(dm_name, 5s, crypto_blkdev)) {
+            LOG(ERROR) << "Failed to wait for default-key device " << dm_name;
+            return false;
+        }
+        if (!dm.LoadTableAndActivate(dm_name, table)) {
+            LOG(ERROR) << "Failed to populate default-key device " << dm_name;
+            return false;
+        }
+    } else if (!dm.CreateDevice(dm_name, table, crypto_blkdev, 5s)) {
+        LOG(ERROR) << "Could not create default-key device " << dm_name;
         return false;
     }
     return true;
diff --git a/MetadataCrypt.h b/MetadataCrypt.h
index e482765..06131ad 100644
--- a/MetadataCrypt.h
+++ b/MetadataCrypt.h
@@ -25,6 +25,7 @@
 namespace android {
 namespace vold {
 
+void defaultkey_precreate_dm_device();
 bool fscrypt_mount_metadata_encrypted(const std::string& block_device,
                                       const std::string& mount_point, bool needs_encrypt,
                                       bool should_format, const std::string& fs_type);
diff --git a/main.cpp b/main.cpp
index 1f85fb5..641d13a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -16,6 +16,7 @@
 
 #define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
 
+#include "MetadataCrypt.h"
 #include "NetlinkManager.h"
 #include "VoldNativeService.h"
 #include "VoldUtil.h"
@@ -247,6 +248,11 @@
             PLOG(FATAL) << "could not find logical partition " << entry.blk_device;
         }
 
+        if (entry.mount_point == "/data" && !entry.metadata_encryption.empty()) {
+            // Pre-populate userdata dm-devices since the uevents are asynchronous (b/198405417).
+            android::vold::defaultkey_precreate_dm_device();
+        }
+
         if (entry.fs_mgr_flags.vold_managed) {
             if (entry.fs_mgr_flags.nonremovable) {
                 LOG(WARNING) << "nonremovable no longer supported; ignoring volume";