From 156d9d2293780c7b5331915fec4bc4727252c838 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 21 Sep 2021 17:21:57 -0700 Subject: [PATCH] Pre-create userdata metadata encryption device. CreateDevice() implicitly calls WaitForDevice(), which can impact boot time if there are many uevents waiting to be processed. To alleviate this, create an empty "userdata" device when vold starts (if metada encryption is enabled). When it comes time to actually enable metadata encryption, the device can be re-used and the subsequent Wait should be much faster. Bug: 198405417 Test: manual test; device boots Change-Id: Iaacd10858272f17353475e25075ea1dda13f8fc4 --- MetadataCrypt.cpp | 27 +++++++++++++++++++++++++-- MetadataCrypt.h | 1 + main.cpp | 6 ++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp index 277a908..ef4c41e 100644 --- a/MetadataCrypt.cpp +++ b/MetadataCrypt.cpp @@ -52,6 +52,7 @@ using android::fs_mgr::GetEntryForMountPoint; 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 @@ const KeyGeneration makeGen(const CryptoOptions& options) { 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. @@ -171,8 +183,19 @@ static bool create_crypto_blk_dev(const std::string& dm_name, const std::string& 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 @@ static int process_config(VolumeManager* vm, VoldConfigs* configs) { 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";