1 //
2 // Copyright (C) 2019 The Android Open Source Project
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 #pragma once
18 
19 #include <stdint.h>
20 
21 #include <chrono>
22 #include <functional>
23 #include <memory>
24 #include <optional>
25 #include <set>
26 #include <string>
27 
28 #include <android-base/unique_fd.h>
29 #include <libfiemap/fiemap_status.h>
30 #include <liblp/partition_opener.h>
31 
32 namespace android {
33 namespace fiemap {
34 
35 class IImageManager {
36   public:
37     using IPartitionOpener = android::fs_mgr::IPartitionOpener;
38 
~IImageManager()39     virtual ~IImageManager() {}
40 
41     // Helper for dependency injection.
42     struct DeviceInfo {
43         std::optional<bool> is_recovery;
44     };
45 
46     // When linking to libfiemap_binder, the Open() call will use binder.
47     // Otherwise, the Open() call will use the ImageManager implementation
48     // below. In binder mode, device_info is ignored.
49     static std::unique_ptr<IImageManager> Open(const std::string& dir_prefix,
50                                                const std::chrono::milliseconds& timeout_ms,
51                                                const DeviceInfo& device_info = {});
52 
53     // Flags for CreateBackingImage().
54     static constexpr int CREATE_IMAGE_DEFAULT = 0x0;
55     static constexpr int CREATE_IMAGE_READONLY = 0x1;
56     static constexpr int CREATE_IMAGE_ZERO_FILL = 0x2;
57 
58     // Create an image that can be mapped as a block-device. If |force_zero_fill|
59     // is true, the image will be zero-filled. Otherwise, the initial content
60     // of the image is undefined. If zero-fill is requested, and the operation
61     // cannot be completed, the image will be deleted and this function will
62     // return false.
63     virtual FiemapStatus CreateBackingImage(
64             const std::string& name, uint64_t size, int flags,
65             std::function<bool(uint64_t, uint64_t)>&& on_progress = nullptr) = 0;
66 
67     // Delete an image created with CreateBackingImage. Its entry will be
68     // removed from the associated lp_metadata file.
69     virtual bool DeleteBackingImage(const std::string& name) = 0;
70 
71     // Create a block device for an image previously created with
72     // CreateBackingImage. This will wait for at most |timeout_ms| milliseconds
73     // for |path| to be available, and will return false if not available in
74     // the requested time. If |timeout_ms| is zero, this is NOT guaranteed to
75     // return true. A timeout of 10s is recommended.
76     //
77     // Note that snapshots created with a readonly flag are always mapped
78     // writable. The flag is persisted in the lp_metadata file however, so if
79     // fs_mgr::CreateLogicalPartition(s) is used, the flag will be respected.
80     virtual bool MapImageDevice(const std::string& name,
81                                 const std::chrono::milliseconds& timeout_ms, std::string* path) = 0;
82 
83     // Unmap a block device previously mapped with mapBackingImage.
84     virtual bool UnmapImageDevice(const std::string& name) = 0;
85 
86     // Returns true whether the named backing image exists. This does not check
87     // consistency with the /data partition, so that it can return true in
88     // recovery.
89     virtual bool BackingImageExists(const std::string& name) = 0;
90 
91     // Returns true if the specified image is mapped to a device.
92     virtual bool IsImageMapped(const std::string& name) = 0;
93 
94     // Map an image using device-mapper. This is not available over binder, and
95     // is intended only for first-stage init. The returned device is a major:minor
96     // device string.
97     virtual bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
98                                           std::string* dev) = 0;
99 
100     // If an image was mapped, return the path to its device. Otherwise, return
101     // false. Errors are not reported in this case, calling IsImageMapped is
102     // not necessary.
103     virtual bool GetMappedImageDevice(const std::string& name, std::string* device) = 0;
104 
105     // Map all images owned by this manager. This is only intended to be used
106     // during first-stage init, and as such, it does not provide a timeout
107     // (meaning libdm races can't be resolved, as ueventd is not available),
108     // and is not available over binder.
109     //
110     // The callback provided is given the list of dependent block devices.
111     virtual bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) = 0;
112 
113     // Mark an image as disabled. This is useful for marking an image as
114     // will-be-deleted in recovery, since recovery cannot mount /data.
115     virtual bool DisableImage(const std::string& name) = 0;
116 
117     // Remove all images that been marked as disabled.
118     virtual bool RemoveDisabledImages() = 0;
119 
120     // Get all backing image names.
121     virtual std::vector<std::string> GetAllBackingImages() = 0;
122 
123     // Writes |bytes| zeros to |name| file. If |bytes| is 0, then the
124     // whole file if filled with zeros.
125     virtual FiemapStatus ZeroFillNewImage(const std::string& name, uint64_t bytes) = 0;
126 
127     // Find and remove all images and metadata for this manager.
128     virtual bool RemoveAllImages() = 0;
129 
130     virtual bool UnmapImageIfExists(const std::string& name);
131 
132     // Returns whether DisableImage() was called.
133     virtual bool IsImageDisabled(const std::string& name) = 0;
134 };
135 
136 class ImageManager final : public IImageManager {
137   public:
138     // Return an ImageManager for the given metadata and data directories. Both
139     // directories must already exist.
140     static std::unique_ptr<ImageManager> Open(const std::string& metadata_dir,
141                                               const std::string& data_dir,
142                                               const DeviceInfo& device_info = {});
143 
144     // Helper function that derives the metadata and data dirs given a single
145     // prefix.
146     static std::unique_ptr<ImageManager> Open(const std::string& dir_prefix,
147                                               const DeviceInfo& device_info = {});
148 
149     // Methods that must be implemented from IImageManager.
150     FiemapStatus CreateBackingImage(const std::string& name, uint64_t size, int flags,
151                                     std::function<bool(uint64_t, uint64_t)>&& on_progress) override;
152     bool DeleteBackingImage(const std::string& name) override;
153     bool MapImageDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
154                         std::string* path) override;
155     bool UnmapImageDevice(const std::string& name) override;
156     bool BackingImageExists(const std::string& name) override;
157     bool IsImageMapped(const std::string& name) override;
158     bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
159                                   std::string* dev) override;
160     bool RemoveAllImages() override;
161     bool DisableImage(const std::string& name) override;
162     bool RemoveDisabledImages() override;
163     bool GetMappedImageDevice(const std::string& name, std::string* device) override;
164     bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) override;
165     bool IsImageDisabled(const std::string& name) override;
166 
167     std::vector<std::string> GetAllBackingImages();
168 
169     // Validates that all images still have pinned extents. This will be removed
170     // once b/134588268 is fixed.
171     bool Validate();
172 
173     void set_partition_opener(std::unique_ptr<IPartitionOpener>&& opener);
174 
175     // Writes |bytes| zeros at the beginning of the passed image
176     FiemapStatus ZeroFillNewImage(const std::string& name, uint64_t bytes);
177 
178     // Validate that all images still have the same block map.
179     bool ValidateImageMaps();
180 
181   private:
182     ImageManager(const std::string& metadata_dir, const std::string& data_dir,
183                  const DeviceInfo& device_info);
184     std::string GetImageHeaderPath(const std::string& name);
185     std::string GetStatusFilePath(const std::string& image_name);
186     bool MapWithLoopDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
187                            std::string* path);
188     bool MapWithLoopDeviceList(const std::vector<std::string>& device_list, const std::string& name,
189                                const std::chrono::milliseconds& timeout_ms, std::string* path);
190     bool MapWithDmLinear(const IPartitionOpener& opener, const std::string& name,
191                          const std::chrono::milliseconds& timeout_ms, std::string* path);
192     bool UnmapImageDevice(const std::string& name, bool force);
193     bool IsUnreliablePinningAllowed() const;
194     bool MetadataDirIsTest() const;
195 
196     ImageManager(const ImageManager&) = delete;
197     ImageManager& operator=(const ImageManager&) = delete;
198     ImageManager& operator=(ImageManager&&) = delete;
199     ImageManager(ImageManager&&) = delete;
200 
201     std::string metadata_dir_;
202     std::string data_dir_;
203     std::unique_ptr<IPartitionOpener> partition_opener_;
204     DeviceInfo device_info_;
205 };
206 
207 // RAII helper class for mapping and opening devices with an ImageManager.
208 class MappedDevice final {
209   public:
210     static std::unique_ptr<MappedDevice> Open(IImageManager* manager,
211                                               const std::chrono::milliseconds& timeout_ms,
212                                               const std::string& name);
213 
214     ~MappedDevice();
215 
fd()216     int fd() const { return fd_.get(); }
path()217     const std::string& path() const { return path_; }
218 
219   protected:
220     MappedDevice(IImageManager* manager, const std::string& name, const std::string& path);
221 
222     IImageManager* manager_;
223     std::string name_;
224     std::string path_;
225     android::base::unique_fd fd_;
226 };
227 
228 }  // namespace fiemap
229 }  // namespace android
230