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_DMTABLE_H_
18 #define _LIBDM_DMTABLE_H_
19 
20 #include <stdint.h>
21 
22 #include <memory>
23 #include <string>
24 #include <vector>
25 
26 #include "dm_target.h"
27 
28 namespace android {
29 namespace dm {
30 
31 class DmTable {
32   public:
DmTable()33     DmTable() : num_sectors_(0), readonly_(false) {}
34 
35     // Adds a target to the device mapper table for a range specified in the target object.
36     // The function will return 'true' if the target was successfully added and doesn't overlap with
37     // any of the existing targets in the table. Gaps are allowed. The final check, including
38     // overlaps and gaps are done before loading the table. Returns 'false' on failure.
39     bool AddTarget(std::unique_ptr<DmTarget>&& target);
40 
41     // Removes a target from the table for the range specified in the target object. Returns 'false'
42     // if the target name doesn't match with the one in the table. Returns 'true' if target is
43     // successfully removed.
44     bool RemoveTarget(std::unique_ptr<DmTarget>&& target);
45 
46     // Adds a target, constructing it in-place for convenience. For example,
47     //
48     //   table.Emplace<DmTargetZero>(0, num_sectors);
49     template <typename T, typename... Args>
Emplace(Args &&...args)50     bool Emplace(Args&&... args) {
51         return AddTarget(std::make_unique<T>(std::forward<Args>(args)...));
52     }
53 
54     // Checks the table to make sure it is valid. i.e. Checks for range overlaps, range gaps
55     // and returns 'true' if the table is ready to be loaded into kernel. Returns 'false' if the
56     // table is malformed.
57     bool valid() const;
58 
59     // Returns the total number of targets.
num_targets()60     size_t num_targets() const { return targets_.size(); }
61 
62     // Returns the total size represented by the table in terms of number of 512-byte sectors.
63     // NOTE: This function will overlook if there are any gaps in the targets added in the table.
64     uint64_t num_sectors() const;
65 
66     // Returns the string represntation of the table that is ready to be passed into the kernel
67     // as part of the DM_TABLE_LOAD ioctl.
68     std::string Serialize() const;
69 
set_readonly(bool readonly)70     void set_readonly(bool readonly) { readonly_ = readonly; }
readonly()71     bool readonly() const { return readonly_; }
72 
73     ~DmTable() = default;
74 
75   private:
76     // list of targets defined in this table sorted by
77     // their start and end sectors.
78     // Note: Overlapping targets MUST never be added in this list.
79     std::vector<std::unique_ptr<DmTarget>> targets_;
80 
81     // Total size in terms of # of sectors, as calculated by looking at the last and the first
82     // target in 'target_'.
83     uint64_t num_sectors_;
84 
85     // True if the device should be read-only; false otherwise.
86     bool readonly_;
87 };
88 
89 }  // namespace dm
90 }  // namespace android
91 
92 #endif /* _LIBDM_DMTABLE_H_ */
93