• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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