From 6433d165438540be6702063b19a585dde4ca5170 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 14 Dec 2022 21:55:34 -0800 Subject: [PATCH] libdm: Add a helper function for creating placeholder devices. Bug: 259328366 Test: device boots and mounts userdata Change-Id: I7aced2eeca984e8ec69633c25d44cd411d0a0583 --- fs_mgr/libdm/dm.cpp | 24 ++++++++++++++++++++++++ fs_mgr/libdm/include/libdm/dm.h | 6 ++++++ 2 files changed, 30 insertions(+) diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp index 0624fe0fc..deffae1ad 100644 --- a/fs_mgr/libdm/dm.cpp +++ b/fs_mgr/libdm/dm.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -711,5 +712,28 @@ std::map DeviceMapper::FindDmPartitions() { return dm_block_devices; } +bool DeviceMapper::CreatePlaceholderDevice(const std::string& name) { + if (!CreateEmptyDevice(name)) { + return false; + } + + struct utsname uts; + unsigned int major, minor; + if (uname(&uts) != 0 || sscanf(uts.release, "%u.%u", &major, &minor) != 2) { + LOG(ERROR) << "Could not parse the kernel version from uname"; + return true; + } + + // On Linux 5.15+, there is no uevent until DM_TABLE_LOAD. + if (major > 5 || (major == 5 && minor >= 15)) { + DmTable table; + table.Emplace(0, 1); + if (!LoadTable(name, table)) { + return false; + } + } + return true; +} + } // namespace dm } // namespace android diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h index f17ae1338..dbef8f902 100644 --- a/fs_mgr/libdm/include/libdm/dm.h +++ b/fs_mgr/libdm/include/libdm/dm.h @@ -292,6 +292,12 @@ class DeviceMapper final : public IDeviceMapper { // Returns mapping std::map FindDmPartitions(); + // Create a placeholder device. This is useful for ensuring that a uevent is in the pipeline, + // to reduce the amount of time a future WaitForDevice will block. On kernels < 5.15, this + // simply calls CreateEmptyDevice. On 5.15 and higher, it also loads (but does not activate) + // a placeholder table containing dm-error. + bool CreatePlaceholderDevice(const std::string& name); + private: // Maximum possible device mapper targets registered in the kernel. // This is only used to read the list of targets from kernel so we allocate