From 5eae2cb4508282b1ae8f7f376a07645c650557d0 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 9 May 2023 13:27:22 -0700 Subject: [PATCH] libsnapshot: Remove ISnapshotWriter. This only added one real method to ICowWriter, so let's just fold it into ICowWriter. CompressedSnapshotWriter goes away as well. CompressedSnapshotReader is now part of libsnapshot_cow. Bug: 280529365 Test: m otapackage apply ota Change-Id: I55358c3c9be111d5aee1a0c22c29cb1539d05494 --- fs_mgr/libsnapshot/Android.bp | 9 +- .../include/libsnapshot/cow_reader.h | 9 +- .../include/libsnapshot/cow_writer.h | 13 ++ ...ck_snapshot_writer.h => mock_cow_writer.h} | 16 +- .../include/libsnapshot/mock_snapshot.h | 4 +- .../include/libsnapshot/snapshot.h | 28 ++- .../include/libsnapshot/snapshot_stub.h | 4 +- .../include/libsnapshot/snapshot_writer.h | 93 --------- .../include_test/libsnapshot/test_helpers.h | 2 +- .../{ => libsnapshot_cow}/snapshot_reader.cpp | 88 +++------ .../{ => libsnapshot_cow}/snapshot_reader.h | 32 +--- .../snapshot_reader_test.cpp | 19 +- .../libsnapshot_cow/writer_base.cpp | 32 ++++ .../libsnapshot/libsnapshot_cow/writer_base.h | 3 + fs_mgr/libsnapshot/snapshot.cpp | 40 ++-- fs_mgr/libsnapshot/snapshot_stub.cpp | 4 +- fs_mgr/libsnapshot/snapshot_test.cpp | 28 +-- fs_mgr/libsnapshot/snapshot_writer.cpp | 179 ------------------ fs_mgr/libsnapshot/snapshot_writer_test.cpp | 62 ------ fs_mgr/libsnapshot/snapshotctl.cpp | 7 +- fs_mgr/libsnapshot/test_helpers.cpp | 7 +- 21 files changed, 159 insertions(+), 520 deletions(-) rename fs_mgr/libsnapshot/include/libsnapshot/{mock_snapshot_writer.h => mock_cow_writer.h} (75%) delete mode 100644 fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h rename fs_mgr/libsnapshot/{ => libsnapshot_cow}/snapshot_reader.cpp (83%) rename fs_mgr/libsnapshot/{ => libsnapshot_cow}/snapshot_reader.h (69%) rename fs_mgr/libsnapshot/{ => libsnapshot_cow}/snapshot_reader_test.cpp (92%) delete mode 100644 fs_mgr/libsnapshot/snapshot_writer.cpp delete mode 100644 fs_mgr/libsnapshot/snapshot_writer_test.cpp diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp index e931bec39..046d30cc9 100644 --- a/fs_mgr/libsnapshot/Android.bp +++ b/fs_mgr/libsnapshot/Android.bp @@ -85,11 +85,9 @@ filegroup { "android/snapshot/snapshot.proto", "device_info.cpp", "snapshot.cpp", - "snapshot_reader.cpp", "snapshot_stats.cpp", "snapshot_stub.cpp", "snapshot_metadata_updater.cpp", - "snapshot_writer.cpp", "partition_cow_creator.cpp", "return.cpp", "utility.cpp", @@ -165,6 +163,9 @@ cc_defaults { "liblz4", "libzstd", ], + header_libs: [ + "libupdate_engine_headers", + ], export_include_dirs: ["include"], } @@ -179,6 +180,7 @@ cc_library_static { "libsnapshot_cow/cow_format.cpp", "libsnapshot_cow/cow_reader.cpp", "libsnapshot_cow/parser_v2.cpp", + "libsnapshot_cow/snapshot_reader.cpp", "libsnapshot_cow/writer_base.cpp", "libsnapshot_cow/writer_v2.cpp", ], @@ -224,9 +226,7 @@ cc_defaults { srcs: [ "partition_cow_creator_test.cpp", "snapshot_metadata_updater_test.cpp", - "snapshot_reader_test.cpp", "snapshot_test.cpp", - "snapshot_writer_test.cpp", ], shared_libs: [ "libbinder", @@ -372,6 +372,7 @@ cc_test { "libsnapshot_cow_defaults", ], srcs: [ + "libsnapshot_cow/snapshot_reader_test.cpp", "libsnapshot_cow/test_v2.cpp", ], cflags: [ diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h index 95a1270f9..3890b1754 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h @@ -24,6 +24,10 @@ #include #include +namespace chromeos_update_engine { +class FileDescriptor; +} // namespace chromeos_update_engine + namespace android { namespace snapshot { @@ -32,6 +36,8 @@ class ICowOpIter; // Interface for reading from a snapuserd COW. class ICowReader { public: + using FileDescriptor = chromeos_update_engine::FileDescriptor; + virtual ~ICowReader() {} // Return the file header. @@ -109,10 +115,9 @@ class CowReader final : public ICowReader { bool Parse(android::base::borrowed_fd fd, std::optional label = {}); bool InitForMerge(android::base::unique_fd&& fd); + bool VerifyMergeOps() override; - bool GetFooter(CowFooter* footer) override; - bool GetLastLabel(uint64_t* label) override; // Create a CowOpIter object which contains footer_.num_ops diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h index af2d3efc5..d6194eb93 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h @@ -61,6 +61,8 @@ struct CowOptions { // will occur in the sequence they were added to the COW. class ICowWriter { public: + using FileDescriptor = chromeos_update_engine::FileDescriptor; + virtual ~ICowWriter() {} // Encode an operation that copies the contents of |old_block| to the @@ -93,6 +95,17 @@ class ICowWriter { virtual uint32_t GetBlockSize() const = 0; virtual std::optional GetMaxBlocks() const = 0; + + // Open an ICowReader for this writer. The reader will be a snapshot of the + // current operations in the writer; new writes after OpenReader() will not + // be reflected. + virtual std::unique_ptr OpenReader() = 0; + + // Open a file descriptor. This allows reading and seeing through the cow + // as if it were a normal file. The optional source_device must be a valid + // path if the CowReader contains any copy or xor operations. + virtual std::unique_ptr OpenFileDescriptor( + const std::optional& source_device) = 0; }; class CompressWorker { diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_cow_writer.h similarity index 75% rename from fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h rename to fs_mgr/libsnapshot/include/libsnapshot/mock_cow_writer.h index 52e3a9c4e..c58c6542a 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_cow_writer.h @@ -15,17 +15,16 @@ // #include -#include +#include namespace android::snapshot { -class MockSnapshotWriter : public ISnapshotWriter { +class MockCowWriter : public ICowWriter { public: - using FileDescriptor = ISnapshotWriter::FileDescriptor; + using FileDescriptor = chromeos_update_engine::FileDescriptor; MOCK_METHOD(bool, Finalize, (), (override)); - // Return number of bytes the cow image occupies on disk. MOCK_METHOD(uint64_t, GetCowSize, (), (override)); MOCK_METHOD(bool, AddCopy, (uint64_t, uint64_t, uint64_t), (override)); @@ -35,11 +34,12 @@ class MockSnapshotWriter : public ISnapshotWriter { MOCK_METHOD(bool, AddZeroBlocks, (uint64_t, uint64_t), (override)); MOCK_METHOD(bool, AddLabel, (uint64_t), (override)); MOCK_METHOD(bool, AddSequenceData, (size_t, const uint32_t*), (override)); - MOCK_METHOD(bool, Initialize, (), (override)); - MOCK_METHOD(bool, InitializeAppend, (uint64_t), (override)); - MOCK_METHOD(bool, VerifyMergeOps, (), (override, const, noexcept)); - MOCK_METHOD(std::unique_ptr, OpenReader, (), (override)); MOCK_METHOD(uint32_t, GetBlockSize, (), (override, const)); MOCK_METHOD(std::optional, GetMaxBlocks, (), (override, const)); + + MOCK_METHOD(std::unique_ptr, OpenReader, (), (override)); + MOCK_METHOD(std::unique_ptr, OpenFileDescriptor, + (const std::optional&), (override)); }; + } // namespace android::snapshot diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h index d458b8718..ca45d2fad 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h @@ -42,9 +42,9 @@ class MockSnapshotManager : public ISnapshotManager { (const android::fs_mgr::CreateLogicalPartitionParams& params, std::string* snapshot_path), (override)); - MOCK_METHOD(std::unique_ptr, OpenSnapshotWriter, + MOCK_METHOD(std::unique_ptr, OpenSnapshotWriter, (const android::fs_mgr::CreateLogicalPartitionParams& params, - const std::optional&), + std::optional), (override)); MOCK_METHOD(bool, UnmapUpdateSnapshot, (const std::string& target_partition_name), (override)); MOCK_METHOD(bool, NeedSnapshotsInFirstStageMount, (), (override)); diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h index ecf1d1531..df532ee21 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h @@ -33,12 +33,11 @@ #include #include #include -#include - #include +#include #include -#include #include +#include #ifndef FRIEND_TEST #define FRIEND_TEST(test_set_name, individual_test) \ @@ -211,16 +210,13 @@ class ISnapshotManager { virtual bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params, std::string* snapshot_path) = 0; - // Create an ISnapshotWriter to build a snapshot against a target partition. The partition name + // Create an ICowWriter to build a snapshot against a target partition. The partition name // 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. - // - // After calling OpenSnapshotWriter, the caller must invoke Initialize or InitializeForAppend - // before invoking write operations. - virtual std::unique_ptr OpenSnapshotWriter( + virtual std::unique_ptr OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params, - const std::optional& source_device) = 0; + std::optional label = {}) = 0; // Unmap a snapshot device or CowWriter that was previously opened with MapUpdateSnapshot, // OpenSnapshotWriter. All outstanding open descriptors, writers, or @@ -362,9 +358,9 @@ class SnapshotManager final : public ISnapshotManager { Return CreateUpdateSnapshots(const DeltaArchiveManifest& manifest) override; bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params, std::string* snapshot_path) override; - std::unique_ptr OpenSnapshotWriter( + std::unique_ptr OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params, - const std::optional& source_device) override; + std::optional label) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool NeedSnapshotsInFirstStageMount() override; bool CreateLogicalAndSnapshotPartitions( @@ -693,10 +689,10 @@ class SnapshotManager final : public ISnapshotManager { }; // Helpers for OpenSnapshotWriter. - std::unique_ptr OpenCompressedSnapshotWriter( - LockedFile* lock, const std::optional& source_device, - const std::string& partition_name, const SnapshotStatus& status, - const SnapshotPaths& paths); + std::unique_ptr OpenCompressedSnapshotWriter(LockedFile* lock, + const SnapshotStatus& status, + const SnapshotPaths& paths, + std::optional label); // Map the base device, COW devices, and snapshot device. bool MapPartitionWithSnapshot(LockedFile* lock, CreateLogicalPartitionParams params, @@ -743,7 +739,7 @@ class SnapshotManager final : public ISnapshotManager { // Initialize snapshots so that they can be mapped later. // Map the COW partition and zero-initialize the header. Return InitializeUpdateSnapshots( - LockedFile* lock, MetadataBuilder* target_metadata, + LockedFile* lock, uint32_t cow_version, MetadataBuilder* target_metadata, const LpMetadata* exported_target_metadata, const std::string& target_suffix, const std::map& all_snapshot_status); diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h index 171c7c6f9..1c9b40368 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h @@ -40,9 +40,9 @@ class SnapshotManagerStub : public ISnapshotManager { const chromeos_update_engine::DeltaArchiveManifest& manifest) override; bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params, std::string* snapshot_path) override; - std::unique_ptr OpenSnapshotWriter( + std::unique_ptr OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params, - const std::optional& source_device) override; + std::optional label) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool NeedSnapshotsInFirstStageMount() override; bool CreateLogicalAndSnapshotPartitions( diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h deleted file mode 100644 index 2653a6053..000000000 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (C) 2020 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 - -namespace chromeos_update_engine { -class FileDescriptor; -} // namespace chromeos_update_engine - -namespace android { -namespace snapshot { - -class ISnapshotWriter : public ICowWriter { - public: - using FileDescriptor = chromeos_update_engine::FileDescriptor; - - virtual ~ISnapshotWriter() {} - - // Open the writer in write mode (no append). - virtual bool Initialize() = 0; - - // Open the writer in append mode, with the last label to resume - // from. See CowWriter::InitializeAppend. - virtual bool InitializeAppend(uint64_t label) = 0; - - virtual std::unique_ptr OpenReader() = 0; - - virtual bool VerifyMergeOps() const noexcept = 0; -}; - -// Send writes to a COW or a raw device directly, based on a threshold. -class CompressedSnapshotWriter final : public ISnapshotWriter { - public: - CompressedSnapshotWriter(const CowOptions& options); - - void SetSourceDevice(const std::string& source_device); - - // Sets the COW device; this is required. - bool SetCowDevice(android::base::unique_fd&& cow_device); - - bool Initialize() override; - bool InitializeAppend(uint64_t label) override; - bool Finalize() override; - uint64_t GetCowSize() override; - uint32_t GetBlockSize() const override; - std::optional GetMaxBlocks() const override; - std::unique_ptr OpenReader() override; - bool VerifyMergeOps() const noexcept; - - bool AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override; - bool AddRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; - bool AddXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, - uint16_t offset) override; - bool AddZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override; - bool AddLabel(uint64_t label) override; - bool AddSequenceData(size_t num_ops, const uint32_t* data) override; - - private: - std::unique_ptr OpenCowReader() const; - android::base::borrowed_fd GetSourceFd(); - - CowOptions options_; - - // Set the source device. This is used for AddCopy() operations, if the - // underlying writer needs the original bytes (for example if backed by - // dm-snapshot or if writing directly to an unsnapshotted region). The - // device is only opened on the first operation that requires it. - std::optional source_device_; - android::base::unique_fd source_fd_; - - android::base::unique_fd cow_device_; - std::unique_ptr cow_; -}; - -} // namespace snapshot -} // namespace android diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h index f45d4ed2a..5e9f049d1 100644 --- a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h +++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h @@ -198,7 +198,7 @@ void DeleteBackingImage(android::fiemap::IImageManager* manager, const std::stri // Expect space of |path| is multiple of 4K. bool WriteRandomData(const std::string& path, std::optional expect_size = std::nullopt, std::string* hash = nullptr); -std::string HashSnapshot(ISnapshotWriter* writer); +std::string HashSnapshot(ICowWriter::FileDescriptor* writer); std::string ToHexString(const uint8_t* buf, size_t len); diff --git a/fs_mgr/libsnapshot/snapshot_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp similarity index 83% rename from fs_mgr/libsnapshot/snapshot_reader.cpp rename to fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp index 4e75ba754..f9cdbc0fe 100644 --- a/fs_mgr/libsnapshot/snapshot_reader.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp @@ -18,73 +18,24 @@ #include #include -#include namespace android { namespace snapshot { using android::base::borrowed_fd; -// Not supported. -bool ReadOnlyFileDescriptor::Open(const char*, int, mode_t) { - errno = EINVAL; - return false; -} - -bool ReadOnlyFileDescriptor::Open(const char*, int) { - errno = EINVAL; - return false; -} - -ssize_t ReadOnlyFileDescriptor::Write(const void*, size_t) { - errno = EINVAL; - return false; -} - -bool ReadOnlyFileDescriptor::BlkIoctl(int, uint64_t, uint64_t, int*) { - errno = EINVAL; - return false; -} - -ReadFdFileDescriptor::ReadFdFileDescriptor(android::base::unique_fd&& fd) : fd_(std::move(fd)) {} - -ssize_t ReadFdFileDescriptor::Read(void* buf, size_t count) { - return read(fd_.get(), buf, count); -} - -off64_t ReadFdFileDescriptor::Seek(off64_t offset, int whence) { - return lseek(fd_.get(), offset, whence); -} - -uint64_t ReadFdFileDescriptor::BlockDevSize() { - return get_block_device_size(fd_.get()); -} - -bool ReadFdFileDescriptor::Close() { - fd_ = {}; - return true; -} - -bool ReadFdFileDescriptor::IsSettingErrno() { - return true; -} - -bool ReadFdFileDescriptor::IsOpen() { - return fd_ >= 0; -} - -bool ReadFdFileDescriptor::Flush() { - return true; -} - -bool CompressedSnapshotReader::SetCow(std::unique_ptr&& cow) { - cow_ = std::move(cow); - +CompressedSnapshotReader::CompressedSnapshotReader(std::unique_ptr&& cow, + const std::optional& source_device, + std::optional block_dev_size) + : cow_(std::move(cow)), + block_size_(cow_->GetHeader().block_size), + source_device_(source_device), + block_device_size_(block_dev_size.value_or(0)) { const auto& header = cow_->GetHeader(); block_size_ = header.block_size; // Populate the operation map. - op_iter_ = cow_->GetOpIter(); + op_iter_ = cow_->GetOpIter(false); while (!op_iter_->AtEnd()) { const CowOperation* op = op_iter_->Get(); if (IsMetadataOp(*op)) { @@ -97,16 +48,27 @@ bool CompressedSnapshotReader::SetCow(std::unique_ptr&& cow) { ops_[op->new_block] = op; op_iter_->Next(); } - - return true; } -void CompressedSnapshotReader::SetSourceDevice(const std::string& source_device) { - source_device_ = {source_device}; +// Not supported. +bool CompressedSnapshotReader::Open(const char*, int, mode_t) { + errno = EINVAL; + return false; } -void CompressedSnapshotReader::SetBlockDeviceSize(uint64_t block_device_size) { - block_device_size_ = block_device_size; +bool CompressedSnapshotReader::Open(const char*, int) { + errno = EINVAL; + return false; +} + +ssize_t CompressedSnapshotReader::Write(const void*, size_t) { + errno = EINVAL; + return false; +} + +bool CompressedSnapshotReader::BlkIoctl(int, uint64_t, uint64_t, int*) { + errno = EINVAL; + return false; } borrowed_fd CompressedSnapshotReader::GetSourceFd() { diff --git a/fs_mgr/libsnapshot/snapshot_reader.h b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.h similarity index 69% rename from fs_mgr/libsnapshot/snapshot_reader.h rename to fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.h index 5e19c62ce..3de63ed19 100644 --- a/fs_mgr/libsnapshot/snapshot_reader.h +++ b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.h @@ -26,36 +26,16 @@ namespace android { namespace snapshot { -class ReadOnlyFileDescriptor : public chromeos_update_engine::FileDescriptor { +class CompressedSnapshotReader : public chromeos_update_engine::FileDescriptor { public: + CompressedSnapshotReader(std::unique_ptr&& cow, + const std::optional& source_device, + std::optional block_dev_size); + bool Open(const char* path, int flags, mode_t mode) override; bool Open(const char* path, int flags) override; ssize_t Write(const void* buf, size_t count) override; bool BlkIoctl(int request, uint64_t start, uint64_t length, int* result) override; -}; - -class ReadFdFileDescriptor : public ReadOnlyFileDescriptor { - public: - explicit ReadFdFileDescriptor(android::base::unique_fd&& fd); - - ssize_t Read(void* buf, size_t count) override; - off64_t Seek(off64_t offset, int whence) override; - uint64_t BlockDevSize() override; - bool Close() override; - bool IsSettingErrno() override; - bool IsOpen() override; - bool Flush() override; - - private: - android::base::unique_fd fd_; -}; - -class CompressedSnapshotReader : public ReadOnlyFileDescriptor { - public: - bool SetCow(std::unique_ptr&& cow); - void SetSourceDevice(const std::string& source_device); - void SetBlockDeviceSize(uint64_t block_device_size); - ssize_t Read(void* buf, size_t count) override; off64_t Seek(off64_t offset, int whence) override; uint64_t BlockDevSize() override; @@ -68,7 +48,7 @@ class CompressedSnapshotReader : public ReadOnlyFileDescriptor { ssize_t ReadBlock(uint64_t chunk, size_t start_offset, void* buffer, size_t size); android::base::borrowed_fd GetSourceFd(); - std::unique_ptr cow_; + std::unique_ptr cow_; std::unique_ptr op_iter_; uint32_t block_size_ = 0; diff --git a/fs_mgr/libsnapshot/snapshot_reader_test.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader_test.cpp similarity index 92% rename from fs_mgr/libsnapshot/snapshot_reader_test.cpp rename to fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader_test.cpp index f25023d81..10cb06d7e 100644 --- a/fs_mgr/libsnapshot/snapshot_reader_test.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader_test.cpp @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include - #include #include @@ -61,7 +59,7 @@ class OfflineSnapshotTest : public ::testing::Test { ASSERT_EQ(fsync(base_->fd), 0); } - void WriteCow(ISnapshotWriter* writer) { + void WriteCow(ICowWriter* writer) { std::string new_block = MakeNewBlockString(); std::string xor_block = MakeXorBlockString(); @@ -72,8 +70,8 @@ class OfflineSnapshotTest : public ::testing::Test { ASSERT_TRUE(writer->Finalize()); } - void TestBlockReads(ISnapshotWriter* writer) { - auto reader = writer->OpenReader(); + void TestBlockReads(ICowWriter* writer) { + auto reader = writer->OpenFileDescriptor(base_->path); ASSERT_NE(reader, nullptr); // Test that unchanged blocks are not modified. @@ -117,8 +115,8 @@ class OfflineSnapshotTest : public ::testing::Test { ASSERT_EQ(two_blocks, zeroes); } - void TestByteReads(ISnapshotWriter* writer) { - auto reader = writer->OpenReader(); + void TestByteReads(ICowWriter* writer) { + auto reader = writer->OpenFileDescriptor(base_->path); ASSERT_NE(reader, nullptr); std::string blob(kBlockSize * 3, 'x'); @@ -154,7 +152,7 @@ class OfflineSnapshotTest : public ::testing::Test { ASSERT_EQ(got, expected); } - void TestReads(ISnapshotWriter* writer) { + void TestReads(ICowWriter* writer) { ASSERT_NO_FATAL_FAILURE(TestBlockReads(writer)); ASSERT_NO_FATAL_FAILURE(TestByteReads(writer)); } @@ -186,10 +184,7 @@ TEST_F(OfflineSnapshotTest, CompressedSnapshot) { unique_fd cow_fd(dup(cow_->fd)); ASSERT_GE(cow_fd, 0); - auto writer = std::make_unique(options); - writer->SetSourceDevice(base_->path); - ASSERT_TRUE(writer->SetCowDevice(std::move(cow_fd))); - ASSERT_TRUE(writer->Initialize()); + auto writer = CreateCowWriter(kDefaultCowVersion, options, std::move(cow_fd)); ASSERT_NO_FATAL_FAILURE(WriteCow(writer.get())); ASSERT_NO_FATAL_FAILURE(TestReads(writer.get())); } diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.cpp index 22e63d0a3..ff34c597b 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.cpp @@ -21,6 +21,7 @@ #include #include +#include "snapshot_reader.h" // The info messages here are spammy, but as useful for update_engine. Disable // them when running on the host. @@ -159,5 +160,36 @@ bool CowWriterBase::ValidateNewBlock(uint64_t new_block) { return true; } +std::unique_ptr CowWriterBase::OpenReader() { + unique_fd cow_fd(fcntl(fd_.get(), F_DUPFD | F_DUPFD_CLOEXEC, 0)); + if (cow_fd < 0) { + PLOG(ERROR) << "CowWriterV2::OpenReander: dup COW device"; + return nullptr; + } + + auto cow = std::make_unique(); + if (!cow->Parse(std::move(cow_fd))) { + LOG(ERROR) << "CowWriterV2::OpenReader: unable to read COW"; + return nullptr; + } + return cow; +} + +std::unique_ptr CowWriterBase::OpenFileDescriptor( + const std::optional& source_device) { + auto reader = OpenReader(); + if (!reader) { + return nullptr; + } + + std::optional block_dev_size; + if (options_.max_blocks) { + block_dev_size = {*options_.max_blocks * options_.block_size}; + } + + return std::make_unique(std::move(reader), source_device, + block_dev_size); +} + } // namespace snapshot } // namespace android diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.h index 8fa90656f..c8b477275 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.h +++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.h @@ -43,6 +43,9 @@ class CowWriterBase : public ICowWriter { bool AddSequenceData(size_t num_ops, const uint32_t* data) override; uint32_t GetBlockSize() const override { return options_.block_size; } std::optional GetMaxBlocks() const override { return options_.max_blocks; } + std::unique_ptr OpenReader() override; + std::unique_ptr OpenFileDescriptor( + const std::optional& source_device) override; const CowOptions& options() const { return options_; } diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp index 5920bc22f..fbea79b4a 100644 --- a/fs_mgr/libsnapshot/snapshot.cpp +++ b/fs_mgr/libsnapshot/snapshot.cpp @@ -45,10 +45,9 @@ #include #include #include "device_info.h" -#include "libsnapshot_cow/writer_v2.h" +#include "libsnapshot_cow/parser_v2.h" #include "partition_cow_creator.h" #include "snapshot_metadata_updater.h" -#include "snapshot_reader.h" #include "utility.h" namespace android { @@ -3288,7 +3287,7 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife return Return::Error(); } - ret = InitializeUpdateSnapshots(lock.get(), target_metadata.get(), + ret = InitializeUpdateSnapshots(lock.get(), dap_metadata.cow_version(), target_metadata.get(), exported_target_metadata.get(), target_suffix, all_snapshot_status); if (!ret.is_ok()) return ret; @@ -3510,7 +3509,7 @@ Return SnapshotManager::CreateUpdateSnapshotsInternal( } Return SnapshotManager::InitializeUpdateSnapshots( - LockedFile* lock, MetadataBuilder* target_metadata, + LockedFile* lock, uint32_t cow_version, MetadataBuilder* target_metadata, const LpMetadata* exported_target_metadata, const std::string& target_suffix, const std::map& all_snapshot_status) { CHECK(lock); @@ -3558,8 +3557,8 @@ Return SnapshotManager::InitializeUpdateSnapshots( } options.compression = it->second.compression_algorithm(); - CowWriterV2 writer(options, std::move(fd)); - if (!writer.Initialize(std::nullopt) || !writer.Finalize()) { + auto writer = CreateCowWriter(cow_version, options, std::move(fd)); + if (!writer->Finalize()) { LOG(ERROR) << "Could not initialize COW device for " << target_partition->name(); return Return::Error(); } @@ -3609,12 +3608,12 @@ bool SnapshotManager::MapUpdateSnapshot(const CreateLogicalPartitionParams& para return true; } -std::unique_ptr SnapshotManager::OpenSnapshotWriter( +std::unique_ptr SnapshotManager::OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params, - const std::optional& source_device) { + std::optional label) { #if defined(LIBSNAPSHOT_NO_COW_WRITE) (void)params; - (void)source_device; + (void)label; LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery"; return nullptr; @@ -3653,16 +3652,14 @@ std::unique_ptr SnapshotManager::OpenSnapshotWriter( return nullptr; } - return OpenCompressedSnapshotWriter(lock.get(), source_device, params.GetPartitionName(), - status, paths); + return OpenCompressedSnapshotWriter(lock.get(), status, paths, label); #endif } #if !defined(LIBSNAPSHOT_NO_COW_WRITE) -std::unique_ptr SnapshotManager::OpenCompressedSnapshotWriter( - LockedFile* lock, const std::optional& source_device, - [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status, - const SnapshotPaths& paths) { +std::unique_ptr SnapshotManager::OpenCompressedSnapshotWriter( + LockedFile* lock, const SnapshotStatus& status, const SnapshotPaths& paths, + std::optional label) { CHECK(lock); CowOptions cow_options; @@ -3679,11 +3676,6 @@ std::unique_ptr SnapshotManager::OpenCompressedSnapshotWriter( // never creates this scenario. CHECK(status.snapshot_size() == status.device_size()); - auto writer = std::make_unique(cow_options); - if (source_device) { - writer->SetSourceDevice(*source_device); - } - std::string cow_path; if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) { LOG(ERROR) << "Could not determine path for " << paths.cow_device_name; @@ -3695,12 +3687,14 @@ std::unique_ptr SnapshotManager::OpenCompressedSnapshotWriter( 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; + + CowHeader header; + if (!ReadCowHeader(cow_fd, &header)) { + LOG(ERROR) << "OpenCompressedSnapshotWriter: read header failed"; return nullptr; } - return writer; + return CreateCowWriter(header.prefix.major_version, cow_options, std::move(cow_fd), label); } #endif // !defined(LIBSNAPSHOT_NO_COW_WRITE) diff --git a/fs_mgr/libsnapshot/snapshot_stub.cpp b/fs_mgr/libsnapshot/snapshot_stub.cpp index 84e2226fa..93541020e 100644 --- a/fs_mgr/libsnapshot/snapshot_stub.cpp +++ b/fs_mgr/libsnapshot/snapshot_stub.cpp @@ -154,8 +154,8 @@ ISnapshotMergeStats* SnapshotManagerStub::GetSnapshotMergeStatsInstance() { return &snapshot_merge_stats; } -std::unique_ptr SnapshotManagerStub::OpenSnapshotWriter( - const CreateLogicalPartitionParams&, const std::optional&) { +std::unique_ptr SnapshotManagerStub::OpenSnapshotWriter( + const CreateLogicalPartitionParams&, std::optional) { LOG(ERROR) << __FUNCTION__ << " should never be called."; return nullptr; } diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp index dac1b771b..0a85489bd 100644 --- a/fs_mgr/libsnapshot/snapshot_test.cpp +++ b/fs_mgr/libsnapshot/snapshot_test.cpp @@ -345,7 +345,7 @@ class SnapshotTest : public ::testing::Test { } AssertionResult MapUpdateSnapshot(const std::string& name, - std::unique_ptr* writer) { + std::unique_ptr* writer) { TestPartitionOpener opener(fake_super); CreateLogicalPartitionParams params{ .block_device = fake_super, @@ -355,14 +355,10 @@ class SnapshotTest : public ::testing::Test { .partition_opener = &opener, }; - auto old_partition = "/dev/block/mapper/" + GetOtherPartitionName(name); - auto result = sm->OpenSnapshotWriter(params, {old_partition}); + auto result = sm->OpenSnapshotWriter(params, {}); if (!result) { return AssertionFailure() << "Cannot open snapshot for writing: " << name; } - if (!result->Initialize()) { - return AssertionFailure() << "Cannot initialize snapshot for writing: " << name; - } if (writer) { *writer = std::move(result); @@ -440,7 +436,7 @@ class SnapshotTest : public ::testing::Test { // Prepare A/B slot for a partition named "test_partition". AssertionResult PrepareOneSnapshot(uint64_t device_size, - std::unique_ptr* writer = nullptr) { + std::unique_ptr* writer = nullptr) { lock_ = nullptr; DeltaArchiveManifest manifest; @@ -651,7 +647,7 @@ TEST_F(SnapshotTest, Merge) { bool userspace_snapshots = false; if (snapuserd_required_) { - std::unique_ptr writer; + std::unique_ptr writer; ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize, &writer)); userspace_snapshots = sm->UpdateUsesUserSnapshots(lock_.get()); @@ -1160,7 +1156,7 @@ class SnapshotUpdateTest : public SnapshotTest { AssertionResult MapOneUpdateSnapshot(const std::string& name) { if (snapuserd_required_) { - std::unique_ptr writer; + std::unique_ptr writer; return MapUpdateSnapshot(name, &writer); } else { std::string path; @@ -1181,7 +1177,7 @@ class SnapshotUpdateTest : public SnapshotTest { AssertionResult WriteSnapshotAndHash(PartitionUpdate* partition) { std::string name = partition->partition_name() + "_b"; if (snapuserd_required_) { - std::unique_ptr writer; + std::unique_ptr writer; auto res = MapUpdateSnapshot(name, &writer); if (!res) { return res; @@ -1250,7 +1246,7 @@ class SnapshotUpdateTest : public SnapshotTest { // It doesn't really matter the order, we just want copies that reference // blocks that won't exist if the partition shrinks. AssertionResult ShiftAllSnapshotBlocks(const std::string& name, uint64_t old_size) { - std::unique_ptr writer; + std::unique_ptr writer; if (auto res = MapUpdateSnapshot(name, &writer); !res) { return res; } @@ -1273,7 +1269,13 @@ class SnapshotUpdateTest : public SnapshotTest { return AssertionFailure() << "Unable to finalize writer for " << name; } - auto hash = HashSnapshot(writer.get()); + auto old_partition = "/dev/block/mapper/" + GetOtherPartitionName(name); + auto reader = writer->OpenFileDescriptor(old_partition); + if (!reader) { + return AssertionFailure() << "Could not open file descriptor for " << name; + } + + auto hash = HashSnapshot(reader.get()); if (hash.empty()) { return AssertionFailure() << "Unable to hash snapshot writer for " << name; } @@ -1428,7 +1430,7 @@ TEST_F(SnapshotUpdateTest, DuplicateOps) { for (auto* partition : partitions) { AddOperation(partition); - std::unique_ptr writer; + std::unique_ptr writer; auto res = MapUpdateSnapshot(partition->partition_name() + "_b", &writer); ASSERT_TRUE(res); ASSERT_TRUE(writer->AddZeroBlocks(0, 1)); diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp deleted file mode 100644 index 0ea424c7e..000000000 --- a/fs_mgr/libsnapshot/snapshot_writer.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (C) 2020 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. -// - -#include - -#include -#include -#include -#include "libsnapshot_cow/writer_v2.h" -#include "snapshot_reader.h" - -namespace android { -namespace snapshot { - -using android::base::borrowed_fd; -using android::base::unique_fd; -using chromeos_update_engine::FileDescriptor; - -void CompressedSnapshotWriter::SetSourceDevice(const std::string& source_device) { - source_device_ = {source_device}; -} - -borrowed_fd CompressedSnapshotWriter::GetSourceFd() { - if (!source_device_) { - LOG(ERROR) << "Attempted to read from source device but none was set"; - return borrowed_fd{-1}; - } - - if (source_fd_ < 0) { - source_fd_.reset(open(source_device_->c_str(), O_RDONLY | O_CLOEXEC)); - if (source_fd_ < 0) { - PLOG(ERROR) << "open " << *source_device_; - return borrowed_fd{-1}; - } - } - return source_fd_; -} - -CompressedSnapshotWriter::CompressedSnapshotWriter(const CowOptions& options) : options_(options) {} - -bool CompressedSnapshotWriter::SetCowDevice(android::base::unique_fd&& cow_device) { - cow_device_ = std::move(cow_device); - return true; -} - -bool CompressedSnapshotWriter::Finalize() { - return cow_->Finalize(); -} - -uint64_t CompressedSnapshotWriter::GetCowSize() { - return cow_->GetCowSize(); -} - -std::unique_ptr CompressedSnapshotWriter::OpenCowReader() const { - unique_fd cow_fd(dup(cow_device_.get())); - if (cow_fd < 0) { - PLOG(ERROR) << "dup COW device"; - return nullptr; - } - - auto cow = std::make_unique(); - if (!cow->Parse(std::move(cow_fd))) { - LOG(ERROR) << "Unable to read COW"; - return nullptr; - } - return cow; -} - -bool CompressedSnapshotWriter::VerifyMergeOps() const noexcept { - auto cow_reader = OpenCowReader(); - if (cow_reader == nullptr) { - LOG(ERROR) << "Couldn't open CowReader"; - return false; - } - return cow_reader->VerifyMergeOps(); -} - -std::unique_ptr CompressedSnapshotWriter::OpenReader() { - auto cow = OpenCowReader(); - if (cow == nullptr) { - return nullptr; - } - - auto reader = std::make_unique(); - if (!reader->SetCow(std::move(cow))) { - LOG(ERROR) << "Unable to initialize COW reader"; - return nullptr; - } - if (source_device_) { - reader->SetSourceDevice(*source_device_); - } - - if (options_.max_blocks) { - reader->SetBlockDeviceSize(*options_.max_blocks * options_.block_size); - } - - return reader; -} - -bool CompressedSnapshotWriter::AddCopy(uint64_t new_block, uint64_t old_block, - uint64_t num_blocks) { - return cow_->AddCopy(new_block, old_block, num_blocks); -} - -bool CompressedSnapshotWriter::AddRawBlocks(uint64_t new_block_start, const void* data, - size_t size) { - return cow_->AddRawBlocks(new_block_start, data, size); -} - -bool CompressedSnapshotWriter::AddXorBlocks(uint32_t new_block_start, const void* data, size_t size, - uint32_t old_block, uint16_t offset) { - return cow_->AddXorBlocks(new_block_start, data, size, old_block, offset); -} - -bool CompressedSnapshotWriter::AddZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) { - return cow_->AddZeroBlocks(new_block_start, num_blocks); -} - -bool CompressedSnapshotWriter::AddLabel(uint64_t label) { - return cow_->AddLabel(label); -} - -bool CompressedSnapshotWriter::AddSequenceData(size_t num_ops, const uint32_t* data) { - return cow_->AddSequenceData(num_ops, data); -} - -bool CompressedSnapshotWriter::Initialize() { - unique_fd cow_fd(dup(cow_device_.get())); - if (cow_fd < 0) { - PLOG(ERROR) << "dup COW device"; - return false; - } - - auto cow = std::make_unique(options_, std::move(cow_fd)); - if (!cow->Initialize(std::nullopt)) { - return false; - } - cow_ = std::move(cow); - return true; -} - -bool CompressedSnapshotWriter::InitializeAppend(uint64_t label) { - unique_fd cow_fd(dup(cow_device_.get())); - if (cow_fd < 0) { - PLOG(ERROR) << "dup COW device"; - return false; - } - - auto cow = std::make_unique(options_, std::move(cow_fd)); - if (!cow->Initialize(label)) { - return false; - } - cow_ = std::move(cow); - return true; -} - -uint32_t CompressedSnapshotWriter::GetBlockSize() const { - return cow_->GetBlockSize(); -} - -std::optional CompressedSnapshotWriter::GetMaxBlocks() const { - return cow_->GetMaxBlocks(); -} - -} // namespace snapshot -} // namespace android diff --git a/fs_mgr/libsnapshot/snapshot_writer_test.cpp b/fs_mgr/libsnapshot/snapshot_writer_test.cpp deleted file mode 100644 index a03632b46..000000000 --- a/fs_mgr/libsnapshot/snapshot_writer_test.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (C) 2021 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. -// - -#include - -#include - -#include -#include -#include -#include - -namespace android::snapshot { -class CompressedSnapshotWriterTest : public ::testing::Test { - public: - static constexpr size_t BLOCK_SIZE = 4096; -}; - -TEST_F(CompressedSnapshotWriterTest, ReadAfterWrite) { - TemporaryFile cow_device_file{}; - android::snapshot::CowOptions options{.block_size = BLOCK_SIZE}; - android::snapshot::CompressedSnapshotWriter snapshot_writer{options}; - ASSERT_TRUE(snapshot_writer.SetCowDevice(android::base::unique_fd{cow_device_file.fd})); - ASSERT_TRUE(snapshot_writer.Initialize()); - std::vector buffer; - buffer.resize(BLOCK_SIZE); - std::fill(buffer.begin(), buffer.end(), 123); - - ASSERT_TRUE(snapshot_writer.AddRawBlocks(0, buffer.data(), buffer.size())); - ASSERT_TRUE(snapshot_writer.Finalize()); - auto cow_reader = snapshot_writer.OpenReader(); - ASSERT_NE(cow_reader, nullptr); - ASSERT_TRUE(snapshot_writer.AddRawBlocks(1, buffer.data(), buffer.size())); - ASSERT_TRUE(snapshot_writer.AddRawBlocks(2, buffer.data(), buffer.size())); - ASSERT_TRUE(snapshot_writer.Finalize()); - // After wrigin some data, if we call OpenReader() again, writes should - // be visible to the newly opened reader. update_engine relies on this - // behavior for verity writes. - cow_reader = snapshot_writer.OpenReader(); - ASSERT_NE(cow_reader, nullptr); - std::vector read_back; - read_back.resize(buffer.size()); - cow_reader->Seek(BLOCK_SIZE, SEEK_SET); - const auto bytes_read = cow_reader->Read(read_back.data(), read_back.size()); - ASSERT_EQ((size_t)(bytes_read), BLOCK_SIZE); - ASSERT_EQ(read_back, buffer); -} - -} // namespace android::snapshot diff --git a/fs_mgr/libsnapshot/snapshotctl.cpp b/fs_mgr/libsnapshot/snapshotctl.cpp index ad3f83cba..38eb719fd 100644 --- a/fs_mgr/libsnapshot/snapshotctl.cpp +++ b/fs_mgr/libsnapshot/snapshotctl.cpp @@ -133,7 +133,6 @@ bool CreateTestUpdate(SnapshotManager* sm) { // Write the "new" system partition. auto system_target_name = "system" + target_slot; - auto source_device = "/dev/block/mapper/" + system_source_name; CreateLogicalPartitionParams clpp = { .block_device = fs_mgr_get_super_partition_name(target_slot_number), .metadata_slot = {target_slot_number}, @@ -141,15 +140,11 @@ bool CreateTestUpdate(SnapshotManager* sm) { .partition_opener = &opener, .timeout_ms = 10s, }; - auto writer = sm->OpenSnapshotWriter(clpp, {source_device}); + auto writer = sm->OpenSnapshotWriter(clpp, std::nullopt); if (!writer) { std::cerr << "Could not open snapshot writer.\n"; return false; } - if (!writer->Initialize()) { - std::cerr << "Could not initialize snapshot for writing.\n"; - return false; - } for (uint64_t block = 0; block < system_source_size / 4096; block++) { if (!writer->AddCopy(block, block)) { diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp index a224f6b58..2eac34749 100644 --- a/fs_mgr/libsnapshot/test_helpers.cpp +++ b/fs_mgr/libsnapshot/test_helpers.cpp @@ -130,12 +130,7 @@ bool WriteRandomData(const std::string& path, std::optional expect_size, return true; } -std::string HashSnapshot(ISnapshotWriter* writer) { - auto reader = writer->OpenReader(); - if (!reader) { - return {}; - } - +std::string HashSnapshot(ICowWriter::FileDescriptor* reader) { SHA256_CTX ctx; SHA256_Init(&ctx);