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 // Returns whether DisableImage() was called. 136 virtual bool IsImageDisabled(const std::string& name) = 0; 137 }; 138 139 class ImageManager final : public IImageManager { 140 public: 141 // Return an ImageManager for the given metadata and data directories. Both 142 // directories must already exist. 143 static std::unique_ptr<ImageManager> Open(const std::string& metadata_dir, 144 const std::string& data_dir, 145 const DeviceInfo& device_info = {}); 146 147 // Helper function that derives the metadata and data dirs given a single 148 // prefix. 149 static std::unique_ptr<ImageManager> Open(const std::string& dir_prefix, 150 const DeviceInfo& device_info = {}); 151 152 // Methods that must be implemented from IImageManager. 153 FiemapStatus CreateBackingImage(const std::string& name, uint64_t size, int flags, 154 std::function<bool(uint64_t, uint64_t)>&& on_progress) override; 155 bool DeleteBackingImage(const std::string& name) override; 156 bool MapImageDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms, 157 std::string* path) override; 158 bool UnmapImageDevice(const std::string& name) override; 159 bool BackingImageExists(const std::string& name) override; 160 bool IsImageMapped(const std::string& name) override; 161 bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name, 162 std::string* dev) override; 163 bool RemoveAllImages() override; 164 bool DisableImage(const std::string& name) override; 165 bool RemoveDisabledImages() override; 166 bool GetMappedImageDevice(const std::string& name, std::string* device) override; 167 bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) override; 168 bool IsImageDisabled(const std::string& name) override; 169 170 std::vector<std::string> GetAllBackingImages(); 171 172 // Validates that all images still have pinned extents. This will be removed 173 // once b/134588268 is fixed. 174 bool Validate(); 175 176 void set_partition_opener(std::unique_ptr<IPartitionOpener>&& opener); 177 178 // Writes |bytes| zeros at the beginning of the passed image 179 FiemapStatus ZeroFillNewImage(const std::string& name, uint64_t bytes); 180 181 // Validate that all images still have the same block map. 182 bool ValidateImageMaps(); 183 184 private: 185 ImageManager(const std::string& metadata_dir, const std::string& data_dir, 186 const DeviceInfo& device_info); 187 std::string GetImageHeaderPath(const std::string& name); 188 std::string GetStatusFilePath(const std::string& image_name); 189 bool MapWithLoopDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms, 190 std::string* path); 191 bool MapWithLoopDeviceList(const std::vector<std::string>& device_list, const std::string& name, 192 const std::chrono::milliseconds& timeout_ms, std::string* path); 193 bool MapWithDmLinear(const IPartitionOpener& opener, const std::string& name, 194 const std::chrono::milliseconds& timeout_ms, std::string* path); 195 bool UnmapImageDevice(const std::string& name, bool force); 196 bool IsUnreliablePinningAllowed() const; 197 bool MetadataDirIsTest() const; 198 199 ImageManager(const ImageManager&) = delete; 200 ImageManager& operator=(const ImageManager&) = delete; 201 ImageManager& operator=(ImageManager&&) = delete; 202 ImageManager(ImageManager&&) = delete; 203 204 std::string metadata_dir_; 205 std::string data_dir_; 206 std::unique_ptr<IPartitionOpener> partition_opener_; 207 DeviceInfo device_info_; 208 }; 209 210 // RAII helper class for mapping and opening devices with an ImageManager. 211 class MappedDevice final { 212 public: 213 static std::unique_ptr<MappedDevice> Open(IImageManager* manager, 214 const std::chrono::milliseconds& timeout_ms, 215 const std::string& name); 216 217 ~MappedDevice(); 218 fd()219 int fd() const { return fd_.get(); } path()220 const std::string& path() const { return path_; } 221 222 protected: 223 MappedDevice(IImageManager* manager, const std::string& name, const std::string& path); 224 225 IImageManager* manager_; 226 std::string name_; 227 std::string path_; 228 android::base::unique_fd fd_; 229 }; 230 231 } // namespace fiemap 232 } // namespace android 233