Loading fs_mgr/libsnapshot/Android.bp +12 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ cc_defaults { "liblog", ], static_libs: [ "libbrotli", "libdm", "libfstab", "libsnapshot_cow", Loading Loading @@ -109,6 +110,9 @@ cc_library_static { defaults: ["libsnapshot_defaults"], srcs: [":libsnapshot_sources"], recovery_available: true, cflags: [ "-DLIBSNAPSHOT_NO_COW_WRITE", ], static_libs: [ "libfs_mgr", ], Loading @@ -122,6 +126,9 @@ cc_library_static { ], srcs: [":libsnapshot_sources"], recovery_available: true, cflags: [ "-DLIBSNAPSHOT_NO_COW_WRITE", ], static_libs: [ "libfs_mgr", ], Loading Loading @@ -244,6 +251,7 @@ cc_defaults { static_libs: [ "android.hardware.boot@1.0", "android.hardware.boot@1.1", "libbrotli", "libfs_mgr", "libgsi", "libgmock", Loading Loading @@ -276,9 +284,11 @@ cc_binary { "snapshotctl.cpp", ], static_libs: [ "libbrotli", "libfstab", "libsnapshot", "libsnapshot_cow", "libz", "update_metadata-protos", ], shared_libs: [ Loading Loading @@ -332,6 +342,7 @@ cc_defaults { ], static_libs: [ "libbase", "libbrotli", "libcrypto_static", "libcutils", "libext2_uuid", Loading @@ -345,6 +356,7 @@ cc_defaults { "libsnapshot_cow", "libsnapshot_test_helpers", "libprotobuf-mutator", "libz", ], header_libs: [ "libchrome", Loading fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +5 −2 Original line number Diff line number Diff line Loading @@ -532,8 +532,8 @@ class SnapshotManager final : public ISnapshotManager { // Target/base device (eg system_b), always present. std::string target_device; // COW path (eg system_cow). Not present if no COW is needed. std::string cow_device; // COW name (eg system_cow). Not present if no COW is needed. std::string cow_device_name; // dm-snapshot instance. Not present in Update mode for VABC. std::string snapshot_device; Loading Loading @@ -626,6 +626,9 @@ class SnapshotManager final : public ISnapshotManager { bool GetMappedImageDeviceStringOrPath(const std::string& device_name, std::string* device_string_or_mapped_path); // Same as above, but for paths only (no major:minor device strings). bool GetMappedImageDevicePath(const std::string& device_name, std::string* device_path); std::string gsid_dir_; std::string metadata_dir_; std::unique_ptr<IDeviceInfo> device_; Loading fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h +24 −1 Original line number Diff line number Diff line Loading @@ -42,6 +42,29 @@ class ISnapshotWriter : public ICowWriter { android::base::unique_fd source_fd_; }; // Send writes to a COW or a raw device directly, based on a threshold. class CompressedSnapshotWriter : public ISnapshotWriter { public: CompressedSnapshotWriter(const CowOptions& options); // Sets the COW device, if needed. bool SetCowDevice(android::base::unique_fd&& cow_device); bool Flush() override; uint64_t GetCowSize() override; std::unique_ptr<FileDescriptor> OpenReader() override; protected: bool EmitCopy(uint64_t new_block, uint64_t old_block) override; bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override; private: android::base::unique_fd cow_device_; std::unique_ptr<CowWriter> cow_; }; // Write directly to a dm-snapshot device. class OnlineKernelSnapshotWriter : public ISnapshotWriter { public: Loading @@ -52,7 +75,7 @@ class OnlineKernelSnapshotWriter : public ISnapshotWriter { bool Flush() override; uint64_t GetCowSize() override { return cow_size_; } virtual std::unique_ptr<FileDescriptor> OpenReader() override; std::unique_ptr<FileDescriptor> OpenReader() override; protected: bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; Loading fs_mgr/libsnapshot/snapshot.cpp +67 −6 Original line number Diff line number Diff line Loading @@ -271,7 +271,7 @@ bool SnapshotManager::FinishedSnapshotWrites(bool wipe) { return false; } if (!EnsureNoOverflowSnapshot(lock.get())) { if (!IsCompressionEnabled() && !EnsureNoOverflowSnapshot(lock.get())) { LOG(ERROR) << "Cannot ensure there are no overflow snapshots."; return false; } Loading Loading @@ -1716,7 +1716,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, return false; } if (paths) { paths->cow_device = cow_device; paths->cow_device_name = cow_name; } remaining_time = GetRemainingTime(params.timeout_ms, begin); Loading @@ -1724,6 +1724,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, if (context == SnapshotContext::Update && IsCompressionEnabled()) { // Stop here, we can't run dm-user yet, the COW isn't built. created_devices.Release(); return true; } Loading Loading @@ -2471,6 +2472,12 @@ bool SnapshotManager::MapUpdateSnapshot(const CreateLogicalPartitionParams& para std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) { #if defined(LIBSNAPSHOT_NO_COW_WRITE) (void)params; LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery"; return nullptr; #else // First unmap any existing mapping. auto lock = LockShared(); if (!lock) return nullptr; Loading @@ -2486,7 +2493,7 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( } SnapshotStatus status; if (!paths.cow_device.empty()) { if (!paths.cow_device_name.empty()) { if (!ReadSnapshotStatus(lock.get(), params.GetPartitionName(), &status)) { return nullptr; } Loading @@ -2504,14 +2511,51 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( return OpenCompressedSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths); } return OpenKernelSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths); #endif } #if !defined(LIBSNAPSHOT_NO_COW_WRITE) std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter( LockedFile*, const std::string&, const SnapshotStatus&, const SnapshotPaths&) { LOG(ERROR) << "OpenSnapshotWriter not yet implemented for compression"; LockedFile* lock, [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths) { CHECK(lock); CowOptions cow_options; cow_options.compression = "gz"; cow_options.max_blocks = {status.device_size() / cow_options.block_size}; // Currently we don't support partial snapshots, since partition_cow_creator // never creates this scenario. CHECK(status.snapshot_size() == status.device_size()); auto writer = std::make_unique<CompressedSnapshotWriter>(cow_options); unique_fd base_fd(open(paths.target_device.c_str(), O_RDWR | O_CLOEXEC)); if (base_fd < 0) { PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << paths.target_device; return nullptr; } writer->SetSourceDevice(std::move(base_fd)); std::string cow_path; if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) { LOG(ERROR) << "Could not determine path for " << paths.cow_device_name; return nullptr; } unique_fd cow_fd(open(cow_path.c_str(), O_RDWR | O_CLOEXEC)); if (cow_fd < 0) { PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << cow_path; return nullptr; } if (!writer->SetCowDevice(std::move(cow_fd))) { LOG(ERROR) << "Could not create COW writer from " << cow_path; return nullptr; } return writer; } std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter( LockedFile* lock, [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths) { Loading @@ -2534,6 +2578,7 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter( return writer; } #endif // !defined(LIBSNAPSHOT_NO_COW_WRITE) bool SnapshotManager::UnmapUpdateSnapshot(const std::string& target_partition_name) { auto lock = LockShared(); Loading Loading @@ -2872,6 +2917,22 @@ ISnapshotMergeStats* SnapshotManager::GetSnapshotMergeStatsInstance() { return SnapshotMergeStats::GetInstance(*this); } // This is only to be used in recovery or normal Android (not first-stage init). // We don't guarantee dm paths are available in first-stage init, because ueventd // isn't running yet. bool SnapshotManager::GetMappedImageDevicePath(const std::string& device_name, std::string* device_path) { auto& dm = DeviceMapper::Instance(); // Try getting the device string if it is a device mapper device. if (dm.GetState(device_name) != DmDeviceState::INVALID) { return dm.GetDmDevicePathByName(device_name, device_path); } // Otherwise, get path from IImageManager. return images_->GetMappedImageDevice(device_name, device_path); } bool SnapshotManager::GetMappedImageDeviceStringOrPath(const std::string& device_name, std::string* device_string_or_mapped_path) { auto& dm = DeviceMapper::Instance(); Loading fs_mgr/libsnapshot/snapshot_writer.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,40 @@ void ISnapshotWriter::SetSourceDevice(android::base::unique_fd&& source_fd) { source_fd_ = std::move(source_fd); } CompressedSnapshotWriter::CompressedSnapshotWriter(const CowOptions& options) : ISnapshotWriter(options) {} bool CompressedSnapshotWriter::SetCowDevice(android::base::unique_fd&& cow_device) { cow_device_ = std::move(cow_device); cow_ = std::make_unique<CowWriter>(options_); return cow_->Initialize(cow_device_); } bool CompressedSnapshotWriter::Flush() { return cow_->Flush(); } uint64_t CompressedSnapshotWriter::GetCowSize() { return cow_->GetCowSize(); } std::unique_ptr<FileDescriptor> CompressedSnapshotWriter::OpenReader() { return nullptr; } bool CompressedSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block) { return cow_->AddCopy(new_block, old_block); } bool CompressedSnapshotWriter::EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) { return cow_->AddRawBlocks(new_block_start, data, size); } bool CompressedSnapshotWriter::EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) { return cow_->AddZeroBlocks(new_block_start, num_blocks); } OnlineKernelSnapshotWriter::OnlineKernelSnapshotWriter(const CowOptions& options) : ISnapshotWriter(options) {} Loading Loading
fs_mgr/libsnapshot/Android.bp +12 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ cc_defaults { "liblog", ], static_libs: [ "libbrotli", "libdm", "libfstab", "libsnapshot_cow", Loading Loading @@ -109,6 +110,9 @@ cc_library_static { defaults: ["libsnapshot_defaults"], srcs: [":libsnapshot_sources"], recovery_available: true, cflags: [ "-DLIBSNAPSHOT_NO_COW_WRITE", ], static_libs: [ "libfs_mgr", ], Loading @@ -122,6 +126,9 @@ cc_library_static { ], srcs: [":libsnapshot_sources"], recovery_available: true, cflags: [ "-DLIBSNAPSHOT_NO_COW_WRITE", ], static_libs: [ "libfs_mgr", ], Loading Loading @@ -244,6 +251,7 @@ cc_defaults { static_libs: [ "android.hardware.boot@1.0", "android.hardware.boot@1.1", "libbrotli", "libfs_mgr", "libgsi", "libgmock", Loading Loading @@ -276,9 +284,11 @@ cc_binary { "snapshotctl.cpp", ], static_libs: [ "libbrotli", "libfstab", "libsnapshot", "libsnapshot_cow", "libz", "update_metadata-protos", ], shared_libs: [ Loading Loading @@ -332,6 +342,7 @@ cc_defaults { ], static_libs: [ "libbase", "libbrotli", "libcrypto_static", "libcutils", "libext2_uuid", Loading @@ -345,6 +356,7 @@ cc_defaults { "libsnapshot_cow", "libsnapshot_test_helpers", "libprotobuf-mutator", "libz", ], header_libs: [ "libchrome", Loading
fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +5 −2 Original line number Diff line number Diff line Loading @@ -532,8 +532,8 @@ class SnapshotManager final : public ISnapshotManager { // Target/base device (eg system_b), always present. std::string target_device; // COW path (eg system_cow). Not present if no COW is needed. std::string cow_device; // COW name (eg system_cow). Not present if no COW is needed. std::string cow_device_name; // dm-snapshot instance. Not present in Update mode for VABC. std::string snapshot_device; Loading Loading @@ -626,6 +626,9 @@ class SnapshotManager final : public ISnapshotManager { bool GetMappedImageDeviceStringOrPath(const std::string& device_name, std::string* device_string_or_mapped_path); // Same as above, but for paths only (no major:minor device strings). bool GetMappedImageDevicePath(const std::string& device_name, std::string* device_path); std::string gsid_dir_; std::string metadata_dir_; std::unique_ptr<IDeviceInfo> device_; Loading
fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h +24 −1 Original line number Diff line number Diff line Loading @@ -42,6 +42,29 @@ class ISnapshotWriter : public ICowWriter { android::base::unique_fd source_fd_; }; // Send writes to a COW or a raw device directly, based on a threshold. class CompressedSnapshotWriter : public ISnapshotWriter { public: CompressedSnapshotWriter(const CowOptions& options); // Sets the COW device, if needed. bool SetCowDevice(android::base::unique_fd&& cow_device); bool Flush() override; uint64_t GetCowSize() override; std::unique_ptr<FileDescriptor> OpenReader() override; protected: bool EmitCopy(uint64_t new_block, uint64_t old_block) override; bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override; private: android::base::unique_fd cow_device_; std::unique_ptr<CowWriter> cow_; }; // Write directly to a dm-snapshot device. class OnlineKernelSnapshotWriter : public ISnapshotWriter { public: Loading @@ -52,7 +75,7 @@ class OnlineKernelSnapshotWriter : public ISnapshotWriter { bool Flush() override; uint64_t GetCowSize() override { return cow_size_; } virtual std::unique_ptr<FileDescriptor> OpenReader() override; std::unique_ptr<FileDescriptor> OpenReader() override; protected: bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; Loading
fs_mgr/libsnapshot/snapshot.cpp +67 −6 Original line number Diff line number Diff line Loading @@ -271,7 +271,7 @@ bool SnapshotManager::FinishedSnapshotWrites(bool wipe) { return false; } if (!EnsureNoOverflowSnapshot(lock.get())) { if (!IsCompressionEnabled() && !EnsureNoOverflowSnapshot(lock.get())) { LOG(ERROR) << "Cannot ensure there are no overflow snapshots."; return false; } Loading Loading @@ -1716,7 +1716,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, return false; } if (paths) { paths->cow_device = cow_device; paths->cow_device_name = cow_name; } remaining_time = GetRemainingTime(params.timeout_ms, begin); Loading @@ -1724,6 +1724,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, if (context == SnapshotContext::Update && IsCompressionEnabled()) { // Stop here, we can't run dm-user yet, the COW isn't built. created_devices.Release(); return true; } Loading Loading @@ -2471,6 +2472,12 @@ bool SnapshotManager::MapUpdateSnapshot(const CreateLogicalPartitionParams& para std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) { #if defined(LIBSNAPSHOT_NO_COW_WRITE) (void)params; LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery"; return nullptr; #else // First unmap any existing mapping. auto lock = LockShared(); if (!lock) return nullptr; Loading @@ -2486,7 +2493,7 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( } SnapshotStatus status; if (!paths.cow_device.empty()) { if (!paths.cow_device_name.empty()) { if (!ReadSnapshotStatus(lock.get(), params.GetPartitionName(), &status)) { return nullptr; } Loading @@ -2504,14 +2511,51 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( return OpenCompressedSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths); } return OpenKernelSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths); #endif } #if !defined(LIBSNAPSHOT_NO_COW_WRITE) std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter( LockedFile*, const std::string&, const SnapshotStatus&, const SnapshotPaths&) { LOG(ERROR) << "OpenSnapshotWriter not yet implemented for compression"; LockedFile* lock, [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths) { CHECK(lock); CowOptions cow_options; cow_options.compression = "gz"; cow_options.max_blocks = {status.device_size() / cow_options.block_size}; // Currently we don't support partial snapshots, since partition_cow_creator // never creates this scenario. CHECK(status.snapshot_size() == status.device_size()); auto writer = std::make_unique<CompressedSnapshotWriter>(cow_options); unique_fd base_fd(open(paths.target_device.c_str(), O_RDWR | O_CLOEXEC)); if (base_fd < 0) { PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << paths.target_device; return nullptr; } writer->SetSourceDevice(std::move(base_fd)); std::string cow_path; if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) { LOG(ERROR) << "Could not determine path for " << paths.cow_device_name; return nullptr; } unique_fd cow_fd(open(cow_path.c_str(), O_RDWR | O_CLOEXEC)); if (cow_fd < 0) { PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << cow_path; return nullptr; } if (!writer->SetCowDevice(std::move(cow_fd))) { LOG(ERROR) << "Could not create COW writer from " << cow_path; return nullptr; } return writer; } std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter( LockedFile* lock, [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths) { Loading @@ -2534,6 +2578,7 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter( return writer; } #endif // !defined(LIBSNAPSHOT_NO_COW_WRITE) bool SnapshotManager::UnmapUpdateSnapshot(const std::string& target_partition_name) { auto lock = LockShared(); Loading Loading @@ -2872,6 +2917,22 @@ ISnapshotMergeStats* SnapshotManager::GetSnapshotMergeStatsInstance() { return SnapshotMergeStats::GetInstance(*this); } // This is only to be used in recovery or normal Android (not first-stage init). // We don't guarantee dm paths are available in first-stage init, because ueventd // isn't running yet. bool SnapshotManager::GetMappedImageDevicePath(const std::string& device_name, std::string* device_path) { auto& dm = DeviceMapper::Instance(); // Try getting the device string if it is a device mapper device. if (dm.GetState(device_name) != DmDeviceState::INVALID) { return dm.GetDmDevicePathByName(device_name, device_path); } // Otherwise, get path from IImageManager. return images_->GetMappedImageDevice(device_name, device_path); } bool SnapshotManager::GetMappedImageDeviceStringOrPath(const std::string& device_name, std::string* device_string_or_mapped_path) { auto& dm = DeviceMapper::Instance(); Loading
fs_mgr/libsnapshot/snapshot_writer.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,40 @@ void ISnapshotWriter::SetSourceDevice(android::base::unique_fd&& source_fd) { source_fd_ = std::move(source_fd); } CompressedSnapshotWriter::CompressedSnapshotWriter(const CowOptions& options) : ISnapshotWriter(options) {} bool CompressedSnapshotWriter::SetCowDevice(android::base::unique_fd&& cow_device) { cow_device_ = std::move(cow_device); cow_ = std::make_unique<CowWriter>(options_); return cow_->Initialize(cow_device_); } bool CompressedSnapshotWriter::Flush() { return cow_->Flush(); } uint64_t CompressedSnapshotWriter::GetCowSize() { return cow_->GetCowSize(); } std::unique_ptr<FileDescriptor> CompressedSnapshotWriter::OpenReader() { return nullptr; } bool CompressedSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block) { return cow_->AddCopy(new_block, old_block); } bool CompressedSnapshotWriter::EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) { return cow_->AddRawBlocks(new_block_start, data, size); } bool CompressedSnapshotWriter::EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) { return cow_->AddZeroBlocks(new_block_start, num_blocks); } OnlineKernelSnapshotWriter::OnlineKernelSnapshotWriter(const CowOptions& options) : ISnapshotWriter(options) {} Loading