From c7def6849aac0a47eca22ab5a24621d70276e8bf Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 20 Jun 2018 13:15:31 -0700 Subject: [PATCH] libdm: Add DmTargetTypeInfo and a unit test. This change refactors DmTarget. It was satisfying two separate use cases that have no overlap: (1) as a container for informational queries, and (2) for specifying table targets. The kernel's nomenclature for the former is a "target type," so the new class is named DmTargetTypeInfo. In addition, this change adds a unit test for DeviceMapper::GetAvailableTargets that ensures the device has at least a linear target type (with more TBD). Bug: 110035986 Test: libdm_test gtest Change-Id: Icb87976801e8a1e6ec79e48b1d58c308d36279e5 --- fs_mgr/libdm/Android.bp | 14 ++++++++ fs_mgr/libdm/dm.cpp | 4 +-- fs_mgr/libdm/dm_test.cpp | 37 +++++++++++++++++++ fs_mgr/libdm/include/libdm/dm.h | 2 +- fs_mgr/libdm/include/libdm/dm_target.h | 50 ++++++++++++++------------ fs_mgr/tools/dmctl.cpp | 3 +- 6 files changed, 83 insertions(+), 27 deletions(-) create mode 100644 fs_mgr/libdm/dm_test.cpp diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp index 672d401cd..f1b18ddaf 100644 --- a/fs_mgr/libdm/Android.bp +++ b/fs_mgr/libdm/Android.bp @@ -16,6 +16,7 @@ cc_library_static { name: "libdm", + defaults: ["fs_mgr_defaults"], recovery_available: true, export_include_dirs: ["include"], @@ -35,3 +36,16 @@ cc_library_static { "liblog_headers", ], } + +cc_test { + name: "libdm_test", + defaults: ["fs_mgr_defaults"], + static_libs: [ + "libdm", + "libbase", + "liblog", + ], + srcs: [ + "dm_test.cpp", + ] +} diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp index 5a2dfc67a..9a53fe9af 100644 --- a/fs_mgr/libdm/dm.cpp +++ b/fs_mgr/libdm/dm.cpp @@ -129,7 +129,7 @@ bool DeviceMapper::LoadTableAndActivate(const std::string& name, const DmTable& // Reads all the available device mapper targets and their corresponding // versions from the kernel and returns in a vector -bool DeviceMapper::GetAvailableTargets(std::vector* targets) { +bool DeviceMapper::GetAvailableTargets(std::vector* targets) { targets->clear(); // calculate the space needed to read a maximum of kMaxPossibleDmTargets @@ -178,7 +178,7 @@ bool DeviceMapper::GetAvailableTargets(std::vector* targets) { struct dm_target_versions* vers = reinterpret_cast(static_cast(buffer.get()) + next); while (next && data_size) { - targets->emplace_back((vers)); + targets->emplace_back(vers); if (vers->next == 0) { break; } diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp new file mode 100644 index 000000000..adbe82088 --- /dev/null +++ b/fs_mgr/libdm/dm_test.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +using namespace std; +using namespace android::dm; + +TEST(libdm, HasMinimumTargets) { + DeviceMapper& dm = DeviceMapper::Instance(); + vector targets; + ASSERT_TRUE(dm.GetAvailableTargets(&targets)); + + map by_name; + for (const auto& target : targets) { + by_name[target.name()] = target; + } + + auto iter = by_name.find("linear"); + EXPECT_NE(iter, by_name.end()); +} diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h index 840777499..8d23b2cf0 100644 --- a/fs_mgr/libdm/include/libdm/dm.h +++ b/fs_mgr/libdm/include/libdm/dm.h @@ -95,7 +95,7 @@ class DeviceMapper final { // Returns true if a list of available device mapper targets registered in the kernel was // successfully read and stored in 'targets'. Returns 'false' otherwise. - bool GetAvailableTargets(std::vector* targets); + bool GetAvailableTargets(std::vector* targets); // Return 'true' if it can successfully read the list of device mapper block devices // currently created. 'devices' will be empty if the kernel interactions diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h index e3058a87d..50902f249 100644 --- a/fs_mgr/libdm/include/libdm/dm_target.h +++ b/fs_mgr/libdm/include/libdm/dm_target.h @@ -27,45 +27,49 @@ namespace android { namespace dm { +class DmTargetTypeInfo { + public: + DmTargetTypeInfo() : major_(0), minor_(0), patch_(0) {} + DmTargetTypeInfo(const struct dm_target_versions* info) + : name_(info->name), + major_(info->version[0]), + minor_(info->version[1]), + patch_(info->version[2]) {} + + const std::string& name() const { return name_; } + std::string version() const { + return std::to_string(major_) + "." + std::to_string(minor_) + "." + std::to_string(patch_); + } + + private: + std::string name_; + uint32_t major_; + uint32_t minor_; + uint32_t patch_; +}; + class DmTarget { public: - DmTarget(const std::string& name, uint64_t start = 0, uint64_t length = 0) - : name_(name), v0_(0), v1_(0), v2_(0), start_(start), length_(length){}; - - // Creates a DmTarget object from dm_target_version as read from kernel - // with DM_LIST_VERSION ioctl. - DmTarget(const struct dm_target_versions* vers) : start_(0), length_(0) { - CHECK(vers != nullptr) << "Can't create DmTarget with dm_target_versions set to nullptr"; - v0_ = vers->version[0]; - v1_ = vers->version[1]; - v2_ = vers->version[2]; - name_ = vers->name; - } + DmTarget(uint64_t start, uint64_t length) : start_(start), length_(length) {} virtual ~DmTarget() = default; // Returns name of the target. - const std::string& name() const { return name_; } + virtual const std::string& name() const = 0; + + // Return the first logical sector represented by this target. + uint64_t start() const { return start_; } // Returns size in number of sectors when this target is part of // a DmTable, return 0 otherwise. uint64_t size() const { return length_; } - // Return string representation of the device mapper target version. - std::string version() const { - return std::to_string(v0_) + "." + std::to_string(v1_) + "." + std::to_string(v2_); - } - // Function that converts this object to a string of arguments that can // be passed to the kernel for adding this target in a table. Each target (e.g. verity, linear) // must implement this, for it to be used on a device. - virtual std::string Serialize() const { return ""; } + virtual std::string Serialize() const = 0; private: - // Name of the target. - std::string name_; - // Target version. - uint32_t v0_, v1_, v2_; // logical sector number start and total length (in terms of 512-byte sectors) represented // by this target within a DmTable. uint64_t start_, length_; diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp index d637dc67c..0478867ca 100644 --- a/fs_mgr/tools/dmctl.cpp +++ b/fs_mgr/tools/dmctl.cpp @@ -36,6 +36,7 @@ using DeviceMapper = ::android::dm::DeviceMapper; using DmTable = ::android::dm::DmTable; using DmTarget = ::android::dm::DmTarget; +using DmTargetTypeInfo = ::android::dm::DmTargetTypeInfo; using DmBlockDevice = ::android::dm::DeviceMapper::DmBlockDevice; static int Usage(void) { @@ -89,7 +90,7 @@ static int DmDeleteCmdHandler(int argc, char** argv) { } static int DmListTargets(DeviceMapper& dm) { - std::vector targets; + std::vector targets; if (!dm.GetAvailableTargets(&targets)) { std::cerr << "Failed to read available device mapper targets" << std::endl; return -errno;