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 // 116 // This is not available in binder, since it is intended for recovery. 117 // When binder is available, images can simply be removed. 118 virtual bool DisableImage(const std::string& name) = 0; 119 120 // Remove all images that been marked as disabled. 121 virtual bool RemoveDisabledImages() = 0; 122 123 // Get all backing image names. 124 virtual std::vector<std::string> GetAllBackingImages() = 0; 125 126 // Writes |bytes| zeros to |name| file. If |bytes| is 0, then the 127 // whole file if filled with zeros. 128 virtual FiemapStatus ZeroFillNewImage(const std::string& name, uint64_t bytes) = 0; 129 130 // Find and remove all images and metadata for this manager. 131 virtual bool RemoveAllImages() = 0; 132 133 virtual bool UnmapImageIfExists(const std::string& name); 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 166 std::vector<std::string> GetAllBackingImages(); 167 168 // Validates that all images still have pinned extents. This will be removed 169 // once b/134588268 is fixed. 170 bool Validate(); 171 172 void set_partition_opener(std::unique_ptr<IPartitionOpener>&& opener); 173 174 // Writes |bytes| zeros at the beginning of the passed image 175 FiemapStatus ZeroFillNewImage(const std::string& name, uint64_t bytes); 176 177 private: 178 ImageManager(const std::string& metadata_dir, const std::string& data_dir, 179 const DeviceInfo& device_info); 180 std::string GetImageHeaderPath(const std::string& name); 181 std::string GetStatusFilePath(const std::string& image_name); 182 bool MapWithLoopDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms, 183 std::string* path); 184 bool MapWithLoopDeviceList(const std::vector<std::string>& device_list, const std::string& name, 185 const std::chrono::milliseconds& timeout_ms, std::string* path); 186 bool MapWithDmLinear(const IPartitionOpener& opener, const std::string& name, 187 const std::chrono::milliseconds& timeout_ms, std::string* path); 188 bool UnmapImageDevice(const std::string& name, bool force); 189 bool IsUnreliablePinningAllowed() const; 190 bool MetadataDirIsTest() const; 191 192 ImageManager(const ImageManager&) = delete; 193 ImageManager& operator=(const ImageManager&) = delete; 194 ImageManager& operator=(ImageManager&&) = delete; 195 ImageManager(ImageManager&&) = delete; 196 197 std::string metadata_dir_; 198 std::string data_dir_; 199 std::unique_ptr<IPartitionOpener> partition_opener_; 200 DeviceInfo device_info_; 201 }; 202 203 // RAII helper class for mapping and opening devices with an ImageManager. 204 class MappedDevice final { 205 public: 206 static std::unique_ptr<MappedDevice> Open(IImageManager* manager, 207 const std::chrono::milliseconds& timeout_ms, 208 const std::string& name); 209 210 ~MappedDevice(); 211 fd()212 int fd() const { return fd_.get(); } path()213 const std::string& path() const { return path_; } 214 215 protected: 216 MappedDevice(IImageManager* manager, const std::string& name, const std::string& path); 217 218 IImageManager* manager_; 219 std::string name_; 220 std::string path_; 221 android::base::unique_fd fd_; 222 }; 223 224 } // namespace fiemap 225 } // namespace android 226