David Anderson | 62e5b20 | 2018-05-01 17:09:17 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2018 The Android Open Source Project |
| 3 | * |
| 4 | * Permission is hereby granted, free of charge, to any person |
| 5 | * obtaining a copy of this software and associated documentation |
| 6 | * files (the "Software"), to deal in the Software without |
| 7 | * restriction, including without limitation the rights to use, copy, |
| 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies |
| 9 | * of the Software, and to permit persons to whom the Software is |
| 10 | * furnished to do so, subject to the following conditions: |
| 11 | * |
| 12 | * The above copyright notice and this permission notice shall be |
| 13 | * included in all copies or substantial portions of the Software. |
| 14 | * |
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 22 | * SOFTWARE. |
| 23 | */ |
| 24 | |
| 25 | #include "fs_mgr_dm_linear.h" |
| 26 | |
| 27 | #include <inttypes.h> |
| 28 | #include <linux/dm-ioctl.h> |
| 29 | #include <string.h> |
| 30 | #include <sys/ioctl.h> |
| 31 | #include <sys/stat.h> |
| 32 | #include <unistd.h> |
| 33 | |
| 34 | #include <sstream> |
| 35 | |
| 36 | #include <android-base/logging.h> |
| 37 | #include <android-base/stringprintf.h> |
| 38 | #include <android-base/strings.h> |
| 39 | #include <android-base/unique_fd.h> |
David Anderson | 6590df2 | 2018-06-14 15:03:53 -0700 | [diff] [blame] | 40 | #include <liblp/reader.h> |
David Anderson | 62e5b20 | 2018-05-01 17:09:17 -0700 | [diff] [blame] | 41 | |
| 42 | #include "fs_mgr_priv.h" |
David Anderson | 62e5b20 | 2018-05-01 17:09:17 -0700 | [diff] [blame] | 43 | |
| 44 | namespace android { |
| 45 | namespace fs_mgr { |
| 46 | |
David Anderson | 4b52440 | 2018-06-21 16:19:48 -0700 | [diff] [blame] | 47 | using DeviceMapper = android::dm::DeviceMapper; |
| 48 | using DmTable = android::dm::DmTable; |
| 49 | using DmTarget = android::dm::DmTarget; |
| 50 | using DmTargetZero = android::dm::DmTargetZero; |
| 51 | using DmTargetLinear = android::dm::DmTargetLinear; |
David Anderson | 62e5b20 | 2018-05-01 17:09:17 -0700 | [diff] [blame] | 52 | |
David Anderson | 4b52440 | 2018-06-21 16:19:48 -0700 | [diff] [blame] | 53 | static bool CreateDmTable(const std::string& block_device, const LpMetadata& metadata, |
| 54 | const LpMetadataPartition& partition, DmTable* table) { |
| 55 | uint64_t sector = 0; |
| 56 | for (size_t i = 0; i < partition.num_extents; i++) { |
| 57 | const auto& extent = metadata.extents[partition.first_extent_index + i]; |
| 58 | std::unique_ptr<DmTarget> target; |
| 59 | switch (extent.target_type) { |
| 60 | case LP_TARGET_TYPE_ZERO: |
| 61 | target = std::make_unique<DmTargetZero>(sector, extent.num_sectors); |
| 62 | break; |
| 63 | case LP_TARGET_TYPE_LINEAR: |
| 64 | target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, block_device, |
| 65 | extent.target_data); |
| 66 | break; |
| 67 | default: |
| 68 | LOG(ERROR) << "Unknown target type in metadata: " << extent.target_type; |
| 69 | return false; |
| 70 | } |
| 71 | if (!table->AddTarget(std::move(target))) { |
| 72 | return false; |
| 73 | } |
| 74 | sector += extent.num_sectors; |
| 75 | } |
| 76 | if (partition.attributes & LP_PARTITION_ATTR_READONLY) { |
| 77 | table->set_readonly(true); |
| 78 | } |
| 79 | return true; |
| 80 | } |
| 81 | |
David Anderson | 23de22d | 2018-07-20 16:28:04 -0700 | [diff] [blame] | 82 | static bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata, |
| 83 | const LpMetadataPartition& partition, std::string* path) { |
| 84 | DeviceMapper& dm = DeviceMapper::Instance(); |
| 85 | |
| 86 | DmTable table; |
| 87 | if (!CreateDmTable(block_device, metadata, partition, &table)) { |
| 88 | return false; |
| 89 | } |
| 90 | std::string name = GetPartitionName(partition); |
| 91 | if (!dm.CreateDevice(name, table)) { |
| 92 | return false; |
| 93 | } |
| 94 | if (!dm.GetDmDevicePathByName(name, path)) { |
| 95 | return false; |
| 96 | } |
| 97 | LINFO << "Created logical partition " << name << " on device " << *path; |
| 98 | return true; |
| 99 | } |
| 100 | |
David Anderson | 6590df2 | 2018-06-14 15:03:53 -0700 | [diff] [blame] | 101 | bool CreateLogicalPartitions(const std::string& block_device) { |
| 102 | uint32_t slot = SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix()); |
| 103 | auto metadata = ReadMetadata(block_device.c_str(), slot); |
| 104 | if (!metadata) { |
| 105 | LOG(ERROR) << "Could not read partition table."; |
| 106 | return true; |
| 107 | } |
David Anderson | 6590df2 | 2018-06-14 15:03:53 -0700 | [diff] [blame] | 108 | for (const auto& partition : metadata->partitions) { |
David Anderson | 4b52440 | 2018-06-21 16:19:48 -0700 | [diff] [blame] | 109 | std::string path; |
David Anderson | 23de22d | 2018-07-20 16:28:04 -0700 | [diff] [blame] | 110 | if (!CreateLogicalPartition(block_device, *metadata.get(), partition, &path)) { |
| 111 | LERROR << "Could not create logical partition: " << GetPartitionName(partition); |
| 112 | return false; |
| 113 | } |
David Anderson | 6590df2 | 2018-06-14 15:03:53 -0700 | [diff] [blame] | 114 | } |
David Anderson | 4b52440 | 2018-06-21 16:19:48 -0700 | [diff] [blame] | 115 | return true; |
David Anderson | 6590df2 | 2018-06-14 15:03:53 -0700 | [diff] [blame] | 116 | } |
| 117 | |
David Anderson | 23de22d | 2018-07-20 16:28:04 -0700 | [diff] [blame] | 118 | bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot, |
| 119 | const std::string& partition_name, std::string* path) { |
| 120 | auto metadata = ReadMetadata(block_device.c_str(), metadata_slot); |
| 121 | if (!metadata) { |
| 122 | LOG(ERROR) << "Could not read partition table."; |
| 123 | return true; |
| 124 | } |
| 125 | for (const auto& partition : metadata->partitions) { |
| 126 | if (GetPartitionName(partition) == partition_name) { |
| 127 | return CreateLogicalPartition(block_device, *metadata.get(), partition, path); |
| 128 | } |
| 129 | } |
| 130 | LERROR << "Could not find any partition with name: " << partition_name; |
| 131 | return false; |
| 132 | } |
| 133 | |
| 134 | bool DestroyLogicalPartition(const std::string& name) { |
| 135 | DeviceMapper& dm = DeviceMapper::Instance(); |
David Anderson | b9f734c | 2018-08-03 10:12:16 -0700 | [diff] [blame^] | 136 | if (!dm.DeleteDevice(name)) { |
| 137 | return false; |
| 138 | } |
| 139 | LINFO << "Unmapped logical partition " << name; |
| 140 | return true; |
David Anderson | 23de22d | 2018-07-20 16:28:04 -0700 | [diff] [blame] | 141 | } |
| 142 | |
David Anderson | 62e5b20 | 2018-05-01 17:09:17 -0700 | [diff] [blame] | 143 | } // namespace fs_mgr |
| 144 | } // namespace android |