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