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