// Copyright (C) 2019 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace android { namespace snapshot { // Unit is sectors, this is a 4K chunk. static constexpr uint32_t kSnapshotChunkSize = 8; // A list of devices we created along the way. // - Whenever a device is created that is subject to GC'ed at the end of // this function, add it to this list. // - If any error has occurred, the list is destroyed, and all these devices // are cleaned up. // - Upon success, Release() should be called so that the created devices // are kept. struct AutoDeviceList { ~AutoDeviceList(); template void EmplaceBack(Args&&... args) { devices_.emplace_back(std::make_unique(std::forward(args)...)); } void Release(); private: std::vector> devices_; }; // Automatically unmap a device upon deletion. struct AutoUnmapDevice : AutoDevice { // On destruct, delete |name| from device mapper. AutoUnmapDevice(android::dm::DeviceMapper* dm, const std::string& name) : AutoDevice(name), dm_(dm) {} AutoUnmapDevice(AutoUnmapDevice&& other) = default; ~AutoUnmapDevice(); private: DISALLOW_COPY_AND_ASSIGN(AutoUnmapDevice); android::dm::DeviceMapper* dm_ = nullptr; }; // Automatically unmap an image upon deletion. struct AutoUnmapImage : AutoDevice { // On destruct, delete |name| from image manager. AutoUnmapImage(android::fiemap::IImageManager* images, const std::string& name) : AutoDevice(name), images_(images) {} AutoUnmapImage(AutoUnmapImage&& other) = default; ~AutoUnmapImage(); private: DISALLOW_COPY_AND_ASSIGN(AutoUnmapImage); android::fiemap::IImageManager* images_ = nullptr; }; // Automatically deletes a snapshot. |name| should be the name of the partition, e.g. "system_a". // Client is responsible for maintaining the lifetime of |manager| and |lock|. struct AutoDeleteSnapshot : AutoDevice { AutoDeleteSnapshot(SnapshotManager* manager, SnapshotManager::LockedFile* lock, const std::string& name) : AutoDevice(name), manager_(manager), lock_(lock) {} AutoDeleteSnapshot(AutoDeleteSnapshot&& other); ~AutoDeleteSnapshot(); private: DISALLOW_COPY_AND_ASSIGN(AutoDeleteSnapshot); SnapshotManager* manager_ = nullptr; SnapshotManager::LockedFile* lock_ = nullptr; }; struct AutoUnmountDevice : AutoDevice { // Empty object that does nothing. AutoUnmountDevice() : AutoDevice("") {} static std::unique_ptr New(const std::string& path); ~AutoUnmountDevice(); private: AutoUnmountDevice(const std::string& path, android::fs_mgr::Fstab&& fstab) : AutoDevice(path), fstab_(std::move(fstab)) {} android::fs_mgr::Fstab fstab_; }; // Return a list of partitions in |builder| with the name ending in |suffix|. std::vector ListPartitionsWithSuffix( android::fs_mgr::MetadataBuilder* builder, const std::string& suffix); // Initialize a device before using it as the COW device for a dm-snapshot device. Return InitializeKernelCow(const std::string& device); // "Atomically" write string to file. This is done by a series of actions: // 1. Write to path + ".tmp" // 2. Move temporary file to path using rename() // Note that rename() is an atomic operation. This function may not work properly if there // is an open fd to |path|, because that fd has an old view of the file. bool WriteStringToFileAtomic(const std::string& content, const std::string& path); // Writes current time to a given stream. struct Now {}; std::ostream& operator<<(std::ostream& os, const Now&); // Append to |extents|. Merged into the last element if possible. void AppendExtent(google::protobuf::RepeatedPtrField* extents, uint64_t start_block, uint64_t num_blocks); bool IsCompressionEnabled(); // Swap the suffix of a partition name. std::string GetOtherPartitionName(const std::string& name); } // namespace snapshot } // namespace android