Merge changes Ia35a4541,Iaf13450d
* changes:
fs_mgr: remove fs_mgr_dm_ioctl
fs_mgr: replace DM_TABLE_STATUS use with libdm.
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index b0b4839..a3ce879 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -38,7 +38,6 @@
include_dirs: ["system/vold"],
srcs: [
"fs_mgr.cpp",
- "fs_mgr_dm_ioctl.cpp",
"fs_mgr_format.cpp",
"fs_mgr_verity.cpp",
"fs_mgr_avb.cpp",
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 9856126..6417a5c 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -50,6 +50,7 @@
#include <ext4_utils/ext4_sb.h>
#include <ext4_utils/ext4_utils.h>
#include <ext4_utils/wipe.h>
+#include <libdm/dm.h>
#include <linux/fs.h>
#include <linux/loop.h>
#include <linux/magic.h>
@@ -59,7 +60,6 @@
#include "fs_mgr.h"
#include "fs_mgr_avb.h"
#include "fs_mgr_priv.h"
-#include "fs_mgr_priv_dm_ioctl.h"
#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
#define KEY_IN_FOOTER "footer"
@@ -76,6 +76,8 @@
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+using DeviceMapper = android::dm::DeviceMapper;
+
// record fs stat
enum FsStatFlags {
FS_STAT_IS_EXT4 = 0x0001,
@@ -802,14 +804,9 @@
return true;
}
- android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDONLY));
- if (dm_fd < 0) {
- PLOG(ERROR) << "open /dev/device-mapper failed";
- return false;
- }
- struct dm_ioctl io;
+ DeviceMapper& dm = DeviceMapper::Instance();
std::string device_name;
- if (!fs_mgr_dm_get_device_name(&io, rec->blk_device, dm_fd, &device_name)) {
+ if (!dm.GetDmDevicePathByName(rec->blk_device, &device_name)) {
return false;
}
free(rec->blk_device);
@@ -1369,12 +1366,6 @@
return false;
}
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)));
- if (fd == -1) {
- PERROR << "Error opening device mapper";
- return false;
- }
-
std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
fs_mgr_free_fstab);
if (!fstab) {
@@ -1382,8 +1373,8 @@
return false;
}
- alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
- struct dm_ioctl* io = (struct dm_ioctl*)buffer;
+ DeviceMapper& dm = DeviceMapper::Instance();
+
bool system_root = android::base::GetProperty("ro.build.system_root_image", "") == "true";
for (int i = 0; i < fstab->num_entries; i++) {
@@ -1399,20 +1390,20 @@
mount_point = basename(fstab->recs[i].mount_point);
}
- fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, mount_point);
+ const char* status = nullptr;
- const char* status;
- if (ioctl(fd, DM_TABLE_STATUS, io)) {
+ std::vector<DeviceMapper::TargetInfo> table;
+ if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) {
if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
status = "V";
} else {
PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point.c_str();
continue;
}
+ } else {
+ status = table[0].data.c_str();
}
- status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
-
// To be consistent in vboot 1.0 and vboot 2.0 (AVB), change the mount_point
// back to 'system' for the callback. So it has property [partition.system.verified]
// instead of [partition.vroot.verified].
diff --git a/fs_mgr/fs_mgr_dm_ioctl.cpp b/fs_mgr/fs_mgr_dm_ioctl.cpp
deleted file mode 100644
index 3a7fae4..0000000
--- a/fs_mgr/fs_mgr_dm_ioctl.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2016 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 <errno.h>
-#include <string.h>
-
-#include <android-base/logging.h>
-#include <sys/ioctl.h>
-
-#include "fs_mgr_priv.h"
-#include "fs_mgr_priv_dm_ioctl.h"
-
-void fs_mgr_dm_ioctl_init(struct dm_ioctl* io, size_t size, const std::string& name) {
- memset(io, 0, size);
- io->data_size = size;
- io->data_start = sizeof(struct dm_ioctl);
- io->version[0] = 4;
- io->version[1] = 0;
- io->version[2] = 0;
- if (!name.empty()) {
- strlcpy(io->name, name.c_str(), sizeof(io->name));
- }
-}
-
-bool fs_mgr_dm_create_device(struct dm_ioctl* io, const std::string& name, int fd) {
- fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
- if (ioctl(fd, DM_DEV_CREATE, io)) {
- PERROR << "Error creating device mapping";
- return false;
- }
- return true;
-}
-
-bool fs_mgr_dm_destroy_device(struct dm_ioctl* io, const std::string& name, int fd) {
- fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
- if (ioctl(fd, DM_DEV_REMOVE, io)) {
- PERROR << "Error removing device mapping";
- return false;
- }
- return true;
-}
-
-bool fs_mgr_dm_get_device_name(struct dm_ioctl* io, const std::string& name, int fd,
- std::string* out_dev_name) {
- FS_MGR_CHECK(out_dev_name != nullptr);
-
- fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
- if (ioctl(fd, DM_DEV_STATUS, io)) {
- PERROR << "Error fetching device-mapper device number";
- return false;
- }
-
- int dev_num = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
- *out_dev_name = "/dev/block/dm-" + std::to_string(dev_num);
-
- return true;
-}
-
-bool fs_mgr_dm_resume_table(struct dm_ioctl* io, const std::string& name, int fd) {
- fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
- if (ioctl(fd, DM_DEV_SUSPEND, io)) {
- PERROR << "Error activating device table";
- return false;
- }
- return true;
-}
diff --git a/fs_mgr/fs_mgr_priv_dm_ioctl.h b/fs_mgr/fs_mgr_priv_dm_ioctl.h
deleted file mode 100644
index 792475d..0000000
--- a/fs_mgr/fs_mgr_priv_dm_ioctl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef __CORE_FS_MGR_PRIV_DM_IOCTL_H
-#define __CORE_FS_MGR_PRIV_DM_IOCTL_H
-
-#include <linux/dm-ioctl.h>
-#include <string>
-
-void fs_mgr_dm_ioctl_init(struct dm_ioctl* io, size_t size, const std::string& name);
-
-bool fs_mgr_dm_create_device(struct dm_ioctl* io, const std::string& name, int fd);
-
-bool fs_mgr_dm_destroy_device(struct dm_ioctl* io, const std::string& name, int fd);
-
-bool fs_mgr_dm_get_device_name(struct dm_ioctl* io, const std::string& name, int fd,
- std::string* out_dev_name);
-
-bool fs_mgr_dm_resume_table(struct dm_ioctl* io, const std::string& name, int fd);
-
-#endif /* __CORE_FS_MGR_PRIV_DM_IOCTL_H */
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index b96f4c1..ad3b6f4 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -272,6 +272,46 @@
return true;
}
+bool DeviceMapper::GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) {
+ char buffer[4096];
+ struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer);
+
+ InitIo(io, name);
+ io->data_size = sizeof(buffer);
+ io->data_start = sizeof(*io);
+ if (ioctl(fd_, DM_TABLE_STATUS, io) < 0) {
+ PLOG(ERROR) << "DM_TABLE_STATUS failed for " << name;
+ return false;
+ }
+ if (io->flags & DM_BUFFER_FULL_FLAG) {
+ PLOG(ERROR) << "DM_TABLE_STATUS result for " << name << " was too large";
+ return false;
+ }
+
+ uint32_t cursor = io->data_start;
+ uint32_t data_end = std::min(io->data_size, uint32_t(sizeof(buffer)));
+ for (uint32_t i = 0; i < io->target_count; i++) {
+ if (cursor + sizeof(struct dm_target_spec) > data_end) {
+ break;
+ }
+ // After each dm_target_spec is a status string. spec->next is an
+ // offset from |io->data_start|, and we clamp it to the size of our
+ // buffer.
+ struct dm_target_spec* spec = reinterpret_cast<struct dm_target_spec*>(buffer + cursor);
+ uint32_t data_offset = cursor + sizeof(dm_target_spec);
+ uint32_t next_cursor = std::min(io->data_start + spec->next, data_end);
+
+ std::string data;
+ if (next_cursor > data_offset) {
+ // Note: we use c_str() to eliminate any extra trailing 0s.
+ data = std::string(buffer + data_offset, next_cursor - data_offset).c_str();
+ }
+ table->emplace_back(*spec, data);
+ cursor = next_cursor;
+ }
+ return true;
+}
+
// private methods of DeviceMapper
void DeviceMapper::InitIo(struct dm_ioctl* io, const std::string& name) const {
CHECK(io != nullptr) << "nullptr passed to dm_ioctl initialization";
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index 85f8e4a..cc61917 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -160,6 +160,20 @@
ASSERT_EQ(strncmp(sector, message2, sizeof(message2)), 0);
}
+ // Test GetTableStatus.
+ DeviceMapper& dm = DeviceMapper::Instance();
+ vector<DeviceMapper::TargetInfo> targets;
+ ASSERT_TRUE(dm.GetTableStatus(dev.name(), &targets));
+ ASSERT_EQ(targets.size(), 2);
+ EXPECT_EQ(strcmp(targets[0].spec.target_type, "linear"), 0);
+ EXPECT_TRUE(targets[0].data.empty());
+ EXPECT_EQ(targets[0].spec.sector_start, 0);
+ EXPECT_EQ(targets[0].spec.length, 1);
+ EXPECT_EQ(strcmp(targets[1].spec.target_type, "linear"), 0);
+ EXPECT_TRUE(targets[1].data.empty());
+ EXPECT_EQ(targets[1].spec.sector_start, 1);
+ EXPECT_EQ(targets[1].spec.length, 1);
+
// Normally the TestDevice destructor would delete this, but at least one
// test should ensure that device deletion works.
ASSERT_TRUE(dev.Destroy());
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 60bceed..e2bc729 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -26,6 +26,7 @@
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include <android-base/logging.h>
@@ -117,6 +118,18 @@
}
}
+ // Query the status of a table, given a device name. The output vector will
+ // contain one TargetInfo for each target in the table. If the device does
+ // not exist, or there were too many targets, the call will fail and return
+ // false.
+ struct TargetInfo {
+ struct dm_target_spec spec;
+ std::string data;
+ TargetInfo(const struct dm_target_spec& spec, const std::string& data)
+ : spec(spec), data(data) {}
+ };
+ bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table);
+
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
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 9d48b8c..5e11c84 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -50,6 +50,7 @@
std::cerr << " delete <dm-name>" << std::endl;
std::cerr << " list <devices | targets>" << std::endl;
std::cerr << " getpath <dm-name>" << std::endl;
+ std::cerr << " table <dm-name>" << std::endl;
std::cerr << " help" << std::endl;
std::cerr << std::endl;
std::cerr << "Target syntax:" << std::endl;
@@ -258,6 +259,31 @@
return 0;
}
+static int TableCmdHandler(int argc, char** argv) {
+ if (argc != 1) {
+ std::cerr << "Invalid arguments, see \'dmctl help\'" << std::endl;
+ return -EINVAL;
+ }
+
+ DeviceMapper& dm = DeviceMapper::Instance();
+ std::vector<DeviceMapper::TargetInfo> table;
+ if (!dm.GetTableStatus(argv[0], &table)) {
+ std::cerr << "Could not query table status of device \"" << argv[0] << "\"." << std::endl;
+ return -EINVAL;
+ }
+ std::cout << "Targets in the device-mapper table for " << argv[0] << ":" << std::endl;
+ for (const auto& target : table) {
+ std::cout << target.spec.sector_start << "-"
+ << (target.spec.sector_start + target.spec.length) << ": "
+ << target.spec.target_type;
+ if (!target.data.empty()) {
+ std::cout << ", " << target.data;
+ }
+ std::cout << std::endl;
+ }
+ return 0;
+}
+
static std::map<std::string, std::function<int(int, char**)>> cmdmap = {
// clang-format off
{"create", DmCreateCmdHandler},
@@ -265,6 +291,7 @@
{"list", DmListCmdHandler},
{"help", HelpCmdHandler},
{"getpath", GetPathCmdHandler},
+ {"table", TableCmdHandler},
// clang-format on
};