1 /* 2 * Copyright 2018 Google, Inc 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _LIBDM_DM_H_ 18 #define _LIBDM_DM_H_ 19 20 #include <fcntl.h> 21 #include <linux/dm-ioctl.h> 22 #include <linux/kdev_t.h> 23 #include <stdint.h> 24 #include <sys/sysmacros.h> 25 #include <unistd.h> 26 27 #include <memory> 28 #include <string> 29 #include <utility> 30 #include <vector> 31 32 #include "dm_table.h" 33 34 // The minimum expected device mapper major.minor version 35 #define DM_VERSION0 (4) 36 #define DM_VERSION1 (0) 37 #define DM_VERSION2 (0) 38 39 #define DM_ALIGN_MASK (7) 40 #define DM_ALIGN(x) ((x + DM_ALIGN_MASK) & ~DM_ALIGN_MASK) 41 42 namespace android { 43 namespace dm { 44 45 enum class DmDeviceState { INVALID, SUSPENDED, ACTIVE }; 46 47 class DeviceMapper final { 48 public: 49 class DmBlockDevice final { 50 public: 51 // only allow creating this with dm_name_list 52 DmBlockDevice() = delete; 53 DmBlockDevice(struct dm_name_list * d)54 explicit DmBlockDevice(struct dm_name_list* d) : name_(d->name), dev_(d->dev){}; 55 56 // Returs device mapper name associated with the block device name()57 const std::string& name() const { return name_; } 58 59 // Return major number for the block device Major()60 uint32_t Major() const { return major(dev_); } 61 62 // Return minor number for the block device Minor()63 uint32_t Minor() const { return minor(dev_); } 64 ~DmBlockDevice() = default; 65 66 private: 67 std::string name_; 68 uint64_t dev_; 69 }; 70 71 // Removes a device mapper device with the given name. 72 // Returns 'true' on success, false otherwise. 73 bool DeleteDevice(const std::string& name); 74 75 // Reads the device mapper table from the device with given anme and 76 // returns it in a DmTable object. 77 const std::unique_ptr<DmTable> table(const std::string& name) const; 78 79 // Returns the current state of the underlying device mapper device 80 // with given name. 81 // One of INVALID, SUSPENDED or ACTIVE. 82 DmDeviceState GetState(const std::string& name) const; 83 84 // Creates a device, loads the given table, and activates it. If the device 85 // is not able to be activated, it is destroyed, and false is returned. 86 bool CreateDevice(const std::string& name, const DmTable& table); 87 88 // Loads the device mapper table from parameter into the underlying device 89 // mapper device with given name and activate / resumes the device in the 90 // process. A device with the given name must already exist. 91 // 92 // Returns 'true' on success, false otherwise. 93 bool LoadTableAndActivate(const std::string& name, const DmTable& table); 94 95 // Returns true if a list of available device mapper targets registered in the kernel was 96 // successfully read and stored in 'targets'. Returns 'false' otherwise. 97 bool GetAvailableTargets(std::vector<DmTargetTypeInfo>* targets); 98 99 // Return 'true' if it can successfully read the list of device mapper block devices 100 // currently created. 'devices' will be empty if the kernel interactions 101 // were successful and there are no block devices at the moment. Returns 102 // 'false' in case of any failure along the way. 103 bool GetAvailableDevices(std::vector<DmBlockDevice>* devices); 104 105 // Returns the path to the device mapper device node in '/dev' corresponding to 106 // 'name'. If the device does not exist, false is returned, and the path 107 // parameter is not set. 108 bool GetDmDevicePathByName(const std::string& name, std::string* path); 109 110 // The only way to create a DeviceMapper object. 111 static DeviceMapper& Instance(); 112 ~DeviceMapper()113 ~DeviceMapper() { 114 if (fd_ != -1) { 115 ::close(fd_); 116 } 117 } 118 119 // Query the status of a table, given a device name. The output vector will 120 // contain one TargetInfo for each target in the table. If the device does 121 // not exist, or there were too many targets, the call will fail and return 122 // false. 123 struct TargetInfo { 124 struct dm_target_spec spec; 125 std::string data; TargetInfoTargetInfo126 TargetInfo(const struct dm_target_spec& spec, const std::string& data) 127 : spec(spec), data(data) {} 128 }; 129 bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table); 130 131 // Identical to GetTableStatus, except also retrives the active table for the device 132 // mapper device from the kernel. 133 bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table); 134 135 private: 136 // Maximum possible device mapper targets registered in the kernel. 137 // This is only used to read the list of targets from kernel so we allocate 138 // a finite amount of memory. This limit is in no way enforced by the kernel. 139 static constexpr uint32_t kMaxPossibleDmTargets = 256; 140 141 // Maximum possible device mapper created block devices. Note that this is restricted by 142 // the minor numbers (that used to be 8 bits) that can be range from 0 to 2^20-1 in newer 143 // kernels. In Android systems however, we never expect these to grow beyond the artificial 144 // limit we are imposing here of 256. 145 static constexpr uint32_t kMaxPossibleDmDevices = 256; 146 147 bool GetTable(const std::string& name, uint32_t flags, std::vector<TargetInfo>* table); 148 149 void InitIo(struct dm_ioctl* io, const std::string& name = std::string()) const; 150 151 DeviceMapper(); 152 153 // Creates a device mapper device with given name. 154 // Return 'true' on success and 'false' on failure to 155 // create OR if a device mapper device with the same name already 156 // exists. 157 bool CreateDevice(const std::string& name); 158 159 int fd_; 160 // Non-copyable & Non-movable 161 DeviceMapper(const DeviceMapper&) = delete; 162 DeviceMapper& operator=(const DeviceMapper&) = delete; 163 DeviceMapper& operator=(DeviceMapper&&) = delete; 164 DeviceMapper(DeviceMapper&&) = delete; 165 }; 166 167 } // namespace dm 168 } // namespace android 169 170 #endif /* _LIBDM_DM_H_ */ 171