diff options
author | Nikita Ioffe <ioffe@google.com> | 2020-01-02 02:44:44 +0000 |
---|---|---|
committer | Nikita Ioffe <ioffe@google.com> | 2020-01-02 03:16:54 +0000 |
commit | db8fdbb02b7aa45dc05261a57a05c3e9432017fb (patch) | |
tree | 1f209b260bf2f7c635feda1a2db058f829b4820a /apexd/apex_database.cpp | |
parent | 2b1c19a07463a65ea49f3b0bdf514f195e62e194 (diff) |
Add hashtree_loop_name to MountedApexData
And also fill in hashtree_loop_name inside
MountedApexDatabase::PopulateFromMounts.
This is a prerequisite for freeing a loop device when an apex is
deactivated (e.g. during userspace reboot). Actual logic to free a loop
device will be implemented in a follow up CL.
Since I was there, added tests for
MountedApexDatabase::PopulateFromMounts function.
Test: atest apex_database_test
Test: atest apexservice_test
Test: atest --test-mapping system/apex:presubmit
Bug: 135984674
Bug: 145670581
Change-Id: Ib2a4ef30073f26931d7e2e326b589b929166e223
Diffstat (limited to 'apexd/apex_database.cpp')
-rw-r--r-- | apexd/apex_database.cpp | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/apexd/apex_database.cpp b/apexd/apex_database.cpp index 096c56f..99fdbe8 100644 --- a/apexd/apex_database.cpp +++ b/apexd/apex_database.cpp @@ -125,6 +125,50 @@ bool isActiveMountPoint(const std::string& mountPoint) { return (mountPoint.find('@') == std::string::npos); } +Result<void> PopulateLoopInfo(const BlockDevice& top_device, + MountedApexData* apex_data) { + std::vector<BlockDevice> slaves = top_device.GetSlaves(); + if (slaves.size() != 1 && slaves.size() != 2) { + return Error() << "dm device " << top_device.DevPath() + << " has unexpected number of slaves : " << slaves.size(); + } + std::vector<std::string> backing_files; + backing_files.reserve(slaves.size()); + for (const auto& dev : slaves) { + if (dev.GetType() != LoopDevice) { + return Error() << dev.DevPath() << " is not a loop device"; + } + auto backing_file = dev.GetProperty("loop/backing_file"); + if (!backing_file) { + return backing_file.error(); + } + backing_files.push_back(std::move(*backing_file)); + } + // Enforce following invariant: + // * slaves[0] always represents a data loop device + // * if size = 2 then slaves[1] represents an external hashtree loop device + if (slaves.size() == 2) { + if (!StartsWith(backing_files[0], kActiveApexPackagesDataDir)) { + std::swap(slaves[0], slaves[1]); + std::swap(backing_files[0], backing_files[1]); + } + } + if (!StartsWith(backing_files[0], kActiveApexPackagesDataDir)) { + return Error() << "Data loop device " << slaves[0].DevPath() + << " has unexpected backing file " << backing_files[0]; + } + if (slaves.size() == 2) { + if (!StartsWith(backing_files[1], kApexHashTreeDir)) { + return Error() << "Hashtree loop device " << slaves[1].DevPath() + << " has unexpected backing file " << backing_files[1]; + } + apex_data->hashtree_loop_name = slaves[1].DevPath(); + } + apex_data->loop_name = slaves[0].DevPath(); + apex_data->full_path = backing_files[0]; + return {}; +} + Result<MountedApexData> resolveMountInfo(const BlockDevice& block, const std::string& mountPoint) { // Now, see if it is dm-verity or loop mounted @@ -134,25 +178,22 @@ Result<MountedApexData> resolveMountInfo(const BlockDevice& block, if (!backingFile) { return backingFile.error(); } - return MountedApexData(block.DevPath(), *backingFile, mountPoint, ""); + return MountedApexData(block.DevPath(), *backingFile, mountPoint, + /* device_name= */ "", + /* hashtree_loop_name= */ ""); } case DeviceMapperDevice: { auto name = block.GetProperty("dm/name"); if (!name) { return name.error(); } - auto slaves = block.GetSlaves(); - if (slaves.empty() || slaves[0].GetType() != LoopDevice) { - return Errorf("DeviceMapper device with no loop devices"); - } - // TODO(jooyung): handle multiple loop devices when hash tree is - // externalized - auto slave = slaves[0]; - auto backingFile = slave.GetProperty("loop/backing_file"); - if (!backingFile) { - return backingFile.error(); + MountedApexData result; + result.mount_point = mountPoint; + result.device_name = *name; + if (auto status = PopulateLoopInfo(block, &result); !status) { + return status.error(); } - return MountedApexData(slave.DevPath(), *backingFile, mountPoint, *name); + return result; } case UnknownDevice: { return Errorf("Can't resolve {}", block.DevPath().string()); |