Loading fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,9 @@ class MockSnapshotManager : public ISnapshotManager { std::string* snapshot_path), std::string* snapshot_path), (override)); (override)); MOCK_METHOD(std::unique_ptr<ISnapshotWriter>, OpenSnapshotWriter, MOCK_METHOD(std::unique_ptr<ISnapshotWriter>, OpenSnapshotWriter, (const android::fs_mgr::CreateLogicalPartitionParams& params), (override)); (const android::fs_mgr::CreateLogicalPartitionParams& params, const std::optional<std::string>&), (override)); MOCK_METHOD(bool, UnmapUpdateSnapshot, (const std::string& target_partition_name), (override)); MOCK_METHOD(bool, UnmapUpdateSnapshot, (const std::string& target_partition_name), (override)); MOCK_METHOD(bool, NeedSnapshotsInFirstStageMount, (), (override)); MOCK_METHOD(bool, NeedSnapshotsInFirstStageMount, (), (override)); MOCK_METHOD(bool, CreateLogicalAndSnapshotPartitions, MOCK_METHOD(bool, CreateLogicalAndSnapshotPartitions, Loading fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +15 −11 Original line number Original line Diff line number Diff line Loading @@ -182,9 +182,12 @@ class ISnapshotManager { std::string* snapshot_path) = 0; std::string* snapshot_path) = 0; // Create an ISnapshotWriter to build a snapshot against a target partition. The partition name // Create an ISnapshotWriter to build a snapshot against a target partition. The partition name // must be suffixed. // must be suffixed. If a source partition exists, it must be specified as well. The source // partition will only be used if raw bytes are needed. The source partition should be an // absolute path to the device, not a partition name. virtual std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( virtual std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) = 0; const android::fs_mgr::CreateLogicalPartitionParams& params, const std::optional<std::string>& source_device) = 0; // Unmap a snapshot device or CowWriter that was previously opened with MapUpdateSnapshot, // Unmap a snapshot device or CowWriter that was previously opened with MapUpdateSnapshot, // OpenSnapshotWriter. All outstanding open descriptors, writers, or // OpenSnapshotWriter. All outstanding open descriptors, writers, or Loading Loading @@ -300,7 +303,8 @@ class SnapshotManager final : public ISnapshotManager { bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params, bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params, std::string* snapshot_path) override; std::string* snapshot_path) override; std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) override; const android::fs_mgr::CreateLogicalPartitionParams& params, const std::optional<std::string>& source_device) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool NeedSnapshotsInFirstStageMount() override; bool NeedSnapshotsInFirstStageMount() override; bool CreateLogicalAndSnapshotPartitions( bool CreateLogicalAndSnapshotPartitions( Loading Loading @@ -540,13 +544,13 @@ class SnapshotManager final : public ISnapshotManager { }; }; // Helpers for OpenSnapshotWriter. // Helpers for OpenSnapshotWriter. std::unique_ptr<ISnapshotWriter> OpenCompressedSnapshotWriter(LockedFile* lock, std::unique_ptr<ISnapshotWriter> OpenCompressedSnapshotWriter( const std::string& partition_name, LockedFile* lock, const std::optional<std::string>& source_device, const SnapshotStatus& status, const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths); const SnapshotPaths& paths); std::unique_ptr<ISnapshotWriter> OpenKernelSnapshotWriter(LockedFile* lock, std::unique_ptr<ISnapshotWriter> OpenKernelSnapshotWriter( const std::string& partition_name, LockedFile* lock, const std::optional<std::string>& source_device, const SnapshotStatus& status, const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths); const SnapshotPaths& paths); // Map the base device, COW devices, and snapshot device. // Map the base device, COW devices, and snapshot device. Loading fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h +2 −1 Original line number Original line Diff line number Diff line Loading @@ -37,7 +37,8 @@ class SnapshotManagerStub : public ISnapshotManager { bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params, bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params, std::string* snapshot_path) override; std::string* snapshot_path) override; std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) override; const android::fs_mgr::CreateLogicalPartitionParams& params, const std::optional<std::string>& source_device) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool NeedSnapshotsInFirstStageMount() override; bool NeedSnapshotsInFirstStageMount() override; bool CreateLogicalAndSnapshotPartitions( bool CreateLogicalAndSnapshotPartitions( Loading fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h +7 −2 Original line number Original line Diff line number Diff line Loading @@ -33,13 +33,18 @@ class ISnapshotWriter : public ICowWriter { // Set the source device. This is used for AddCopy() operations, if the // Set the source device. This is used for AddCopy() operations, if the // underlying writer needs the original bytes (for example if backed by // underlying writer needs the original bytes (for example if backed by // dm-snapshot or if writing directly to an unsnapshotted region). // dm-snapshot or if writing directly to an unsnapshotted region). The void SetSourceDevice(android::base::unique_fd&& source_fd); // device is only opened on the first operation that requires it. void SetSourceDevice(const std::string& source_device); virtual std::unique_ptr<FileDescriptor> OpenReader() = 0; virtual std::unique_ptr<FileDescriptor> OpenReader() = 0; protected: protected: android::base::borrowed_fd GetSourceFd(); private: android::base::unique_fd source_fd_; android::base::unique_fd source_fd_; std::optional<std::string> source_device_; }; }; // Send writes to a COW or a raw device directly, based on a threshold. // Send writes to a COW or a raw device directly, based on a threshold. Loading fs_mgr/libsnapshot/snapshot.cpp +19 −13 Original line number Original line Diff line number Diff line Loading @@ -2471,9 +2471,11 @@ bool SnapshotManager::MapUpdateSnapshot(const CreateLogicalPartitionParams& para } } std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) { const android::fs_mgr::CreateLogicalPartitionParams& params, const std::optional<std::string>& source_device) { #if defined(LIBSNAPSHOT_NO_COW_WRITE) #if defined(LIBSNAPSHOT_NO_COW_WRITE) (void)params; (void)params; (void)source_device; LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery"; LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery"; return nullptr; return nullptr; Loading Loading @@ -2508,16 +2510,19 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( } } if (IsCompressionEnabled()) { if (IsCompressionEnabled()) { return OpenCompressedSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths); return OpenCompressedSnapshotWriter(lock.get(), source_device, params.GetPartitionName(), status, paths); } } return OpenKernelSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths); return OpenKernelSnapshotWriter(lock.get(), source_device, params.GetPartitionName(), status, paths); #endif #endif } } #if !defined(LIBSNAPSHOT_NO_COW_WRITE) #if !defined(LIBSNAPSHOT_NO_COW_WRITE) std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter( std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter( LockedFile* lock, [[maybe_unused]] const std::string& partition_name, LockedFile* lock, const std::optional<std::string>& source_device, const SnapshotStatus& status, const SnapshotPaths& paths) { [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths) { CHECK(lock); CHECK(lock); CowOptions cow_options; CowOptions cow_options; Loading @@ -2529,13 +2534,9 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter( CHECK(status.snapshot_size() == status.device_size()); CHECK(status.snapshot_size() == status.device_size()); auto writer = std::make_unique<CompressedSnapshotWriter>(cow_options); auto writer = std::make_unique<CompressedSnapshotWriter>(cow_options); if (source_device) { unique_fd base_fd(open(paths.target_device.c_str(), O_RDWR | O_CLOEXEC)); writer->SetSourceDevice(*source_device); if (base_fd < 0) { PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << paths.target_device; return nullptr; } } writer->SetSourceDevice(std::move(base_fd)); std::string cow_path; std::string cow_path; if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) { if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) { Loading @@ -2557,8 +2558,9 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter( } } std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter( std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter( LockedFile* lock, [[maybe_unused]] const std::string& partition_name, LockedFile* lock, const std::optional<std::string>& source_device, const SnapshotStatus& status, const SnapshotPaths& paths) { [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths) { CHECK(lock); CHECK(lock); CowOptions cow_options; CowOptions cow_options; Loading @@ -2573,6 +2575,10 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter( return nullptr; return nullptr; } } if (source_device) { writer->SetSourceDevice(*source_device); } uint64_t cow_size = status.cow_partition_size() + status.cow_file_size(); uint64_t cow_size = status.cow_partition_size() + status.cow_file_size(); writer->SetSnapshotDevice(std::move(fd), cow_size); writer->SetSnapshotDevice(std::move(fd), cow_size); Loading Loading
fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,9 @@ class MockSnapshotManager : public ISnapshotManager { std::string* snapshot_path), std::string* snapshot_path), (override)); (override)); MOCK_METHOD(std::unique_ptr<ISnapshotWriter>, OpenSnapshotWriter, MOCK_METHOD(std::unique_ptr<ISnapshotWriter>, OpenSnapshotWriter, (const android::fs_mgr::CreateLogicalPartitionParams& params), (override)); (const android::fs_mgr::CreateLogicalPartitionParams& params, const std::optional<std::string>&), (override)); MOCK_METHOD(bool, UnmapUpdateSnapshot, (const std::string& target_partition_name), (override)); MOCK_METHOD(bool, UnmapUpdateSnapshot, (const std::string& target_partition_name), (override)); MOCK_METHOD(bool, NeedSnapshotsInFirstStageMount, (), (override)); MOCK_METHOD(bool, NeedSnapshotsInFirstStageMount, (), (override)); MOCK_METHOD(bool, CreateLogicalAndSnapshotPartitions, MOCK_METHOD(bool, CreateLogicalAndSnapshotPartitions, Loading
fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +15 −11 Original line number Original line Diff line number Diff line Loading @@ -182,9 +182,12 @@ class ISnapshotManager { std::string* snapshot_path) = 0; std::string* snapshot_path) = 0; // Create an ISnapshotWriter to build a snapshot against a target partition. The partition name // Create an ISnapshotWriter to build a snapshot against a target partition. The partition name // must be suffixed. // must be suffixed. If a source partition exists, it must be specified as well. The source // partition will only be used if raw bytes are needed. The source partition should be an // absolute path to the device, not a partition name. virtual std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( virtual std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) = 0; const android::fs_mgr::CreateLogicalPartitionParams& params, const std::optional<std::string>& source_device) = 0; // Unmap a snapshot device or CowWriter that was previously opened with MapUpdateSnapshot, // Unmap a snapshot device or CowWriter that was previously opened with MapUpdateSnapshot, // OpenSnapshotWriter. All outstanding open descriptors, writers, or // OpenSnapshotWriter. All outstanding open descriptors, writers, or Loading Loading @@ -300,7 +303,8 @@ class SnapshotManager final : public ISnapshotManager { bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params, bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params, std::string* snapshot_path) override; std::string* snapshot_path) override; std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) override; const android::fs_mgr::CreateLogicalPartitionParams& params, const std::optional<std::string>& source_device) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool NeedSnapshotsInFirstStageMount() override; bool NeedSnapshotsInFirstStageMount() override; bool CreateLogicalAndSnapshotPartitions( bool CreateLogicalAndSnapshotPartitions( Loading Loading @@ -540,13 +544,13 @@ class SnapshotManager final : public ISnapshotManager { }; }; // Helpers for OpenSnapshotWriter. // Helpers for OpenSnapshotWriter. std::unique_ptr<ISnapshotWriter> OpenCompressedSnapshotWriter(LockedFile* lock, std::unique_ptr<ISnapshotWriter> OpenCompressedSnapshotWriter( const std::string& partition_name, LockedFile* lock, const std::optional<std::string>& source_device, const SnapshotStatus& status, const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths); const SnapshotPaths& paths); std::unique_ptr<ISnapshotWriter> OpenKernelSnapshotWriter(LockedFile* lock, std::unique_ptr<ISnapshotWriter> OpenKernelSnapshotWriter( const std::string& partition_name, LockedFile* lock, const std::optional<std::string>& source_device, const SnapshotStatus& status, const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths); const SnapshotPaths& paths); // Map the base device, COW devices, and snapshot device. // Map the base device, COW devices, and snapshot device. Loading
fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h +2 −1 Original line number Original line Diff line number Diff line Loading @@ -37,7 +37,8 @@ class SnapshotManagerStub : public ISnapshotManager { bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params, bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params, std::string* snapshot_path) override; std::string* snapshot_path) override; std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) override; const android::fs_mgr::CreateLogicalPartitionParams& params, const std::optional<std::string>& source_device) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool NeedSnapshotsInFirstStageMount() override; bool NeedSnapshotsInFirstStageMount() override; bool CreateLogicalAndSnapshotPartitions( bool CreateLogicalAndSnapshotPartitions( Loading
fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h +7 −2 Original line number Original line Diff line number Diff line Loading @@ -33,13 +33,18 @@ class ISnapshotWriter : public ICowWriter { // Set the source device. This is used for AddCopy() operations, if the // Set the source device. This is used for AddCopy() operations, if the // underlying writer needs the original bytes (for example if backed by // underlying writer needs the original bytes (for example if backed by // dm-snapshot or if writing directly to an unsnapshotted region). // dm-snapshot or if writing directly to an unsnapshotted region). The void SetSourceDevice(android::base::unique_fd&& source_fd); // device is only opened on the first operation that requires it. void SetSourceDevice(const std::string& source_device); virtual std::unique_ptr<FileDescriptor> OpenReader() = 0; virtual std::unique_ptr<FileDescriptor> OpenReader() = 0; protected: protected: android::base::borrowed_fd GetSourceFd(); private: android::base::unique_fd source_fd_; android::base::unique_fd source_fd_; std::optional<std::string> source_device_; }; }; // Send writes to a COW or a raw device directly, based on a threshold. // Send writes to a COW or a raw device directly, based on a threshold. Loading
fs_mgr/libsnapshot/snapshot.cpp +19 −13 Original line number Original line Diff line number Diff line Loading @@ -2471,9 +2471,11 @@ bool SnapshotManager::MapUpdateSnapshot(const CreateLogicalPartitionParams& para } } std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) { const android::fs_mgr::CreateLogicalPartitionParams& params, const std::optional<std::string>& source_device) { #if defined(LIBSNAPSHOT_NO_COW_WRITE) #if defined(LIBSNAPSHOT_NO_COW_WRITE) (void)params; (void)params; (void)source_device; LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery"; LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery"; return nullptr; return nullptr; Loading Loading @@ -2508,16 +2510,19 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( } } if (IsCompressionEnabled()) { if (IsCompressionEnabled()) { return OpenCompressedSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths); return OpenCompressedSnapshotWriter(lock.get(), source_device, params.GetPartitionName(), status, paths); } } return OpenKernelSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths); return OpenKernelSnapshotWriter(lock.get(), source_device, params.GetPartitionName(), status, paths); #endif #endif } } #if !defined(LIBSNAPSHOT_NO_COW_WRITE) #if !defined(LIBSNAPSHOT_NO_COW_WRITE) std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter( std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter( LockedFile* lock, [[maybe_unused]] const std::string& partition_name, LockedFile* lock, const std::optional<std::string>& source_device, const SnapshotStatus& status, const SnapshotPaths& paths) { [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths) { CHECK(lock); CHECK(lock); CowOptions cow_options; CowOptions cow_options; Loading @@ -2529,13 +2534,9 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter( CHECK(status.snapshot_size() == status.device_size()); CHECK(status.snapshot_size() == status.device_size()); auto writer = std::make_unique<CompressedSnapshotWriter>(cow_options); auto writer = std::make_unique<CompressedSnapshotWriter>(cow_options); if (source_device) { unique_fd base_fd(open(paths.target_device.c_str(), O_RDWR | O_CLOEXEC)); writer->SetSourceDevice(*source_device); if (base_fd < 0) { PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << paths.target_device; return nullptr; } } writer->SetSourceDevice(std::move(base_fd)); std::string cow_path; std::string cow_path; if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) { if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) { Loading @@ -2557,8 +2558,9 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter( } } std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter( std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter( LockedFile* lock, [[maybe_unused]] const std::string& partition_name, LockedFile* lock, const std::optional<std::string>& source_device, const SnapshotStatus& status, const SnapshotPaths& paths) { [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status, const SnapshotPaths& paths) { CHECK(lock); CHECK(lock); CowOptions cow_options; CowOptions cow_options; Loading @@ -2573,6 +2575,10 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter( return nullptr; return nullptr; } } if (source_device) { writer->SetSourceDevice(*source_device); } uint64_t cow_size = status.cow_partition_size() + status.cow_file_size(); uint64_t cow_size = status.cow_partition_size() + status.cow_file_size(); writer->SetSnapshotDevice(std::move(fd), cow_size); writer->SetSnapshotDevice(std::move(fd), cow_size); Loading