diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/cow_reader.cpp index e8f01532a..5306b2843 100644 --- a/fs_mgr/libsnapshot/cow_reader.cpp +++ b/fs_mgr/libsnapshot/cow_reader.cpp @@ -231,7 +231,7 @@ bool CowReader::ParseOps(std::optional label) { memcpy(&footer_->op, ¤t_op, sizeof(footer->op)); off_t offs = lseek(fd_.get(), pos, SEEK_SET); if (offs < 0 || pos != static_cast(offs)) { - PLOG(ERROR) << "lseek next op failed"; + PLOG(ERROR) << "lseek next op failed " << offs; return false; } if (!android::base::ReadFully(fd_, &footer->data, sizeof(footer->data))) { @@ -251,7 +251,7 @@ bool CowReader::ParseOps(std::optional label) { // Position for next cluster read off_t offs = lseek(fd_.get(), pos, SEEK_SET); if (offs < 0 || pos != static_cast(offs)) { - PLOG(ERROR) << "lseek next op failed"; + PLOG(ERROR) << "lseek next op failed " << offs; return false; } ops_buffer->resize(current_op_num); diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h index 3655c01d0..b0be5a594 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h @@ -44,6 +44,7 @@ class MockSnapshotWriter : public ISnapshotWriter { // Open the writer in write mode (no append). MOCK_METHOD(bool, Initialize, (), (override)); + MOCK_METHOD(bool, VerifyMergeOps, (), (override, const, noexcept)); // Open the writer in append mode, with the last label to resume // from. See CowWriter::InitializeAppend. diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h index b09e1ae82..545f1171d 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h @@ -47,6 +47,7 @@ class ISnapshotWriter : public ICowWriter { virtual bool InitializeAppend(uint64_t label) = 0; virtual std::unique_ptr OpenReader() = 0; + virtual bool VerifyMergeOps() const noexcept = 0; protected: android::base::borrowed_fd GetSourceFd(); @@ -58,7 +59,7 @@ class ISnapshotWriter : public ICowWriter { }; // Send writes to a COW or a raw device directly, based on a threshold. -class CompressedSnapshotWriter : public ISnapshotWriter { +class CompressedSnapshotWriter final : public ISnapshotWriter { public: CompressedSnapshotWriter(const CowOptions& options); @@ -70,6 +71,7 @@ class CompressedSnapshotWriter : public ISnapshotWriter { bool Finalize() override; uint64_t GetCowSize() override; std::unique_ptr OpenReader() override; + bool VerifyMergeOps() const noexcept; protected: bool EmitCopy(uint64_t new_block, uint64_t old_block) override; @@ -81,13 +83,14 @@ class CompressedSnapshotWriter : public ISnapshotWriter { bool EmitSequenceData(size_t num_ops, const uint32_t* data) override; private: + std::unique_ptr OpenCowReader() const; android::base::unique_fd cow_device_; std::unique_ptr cow_; }; // Write directly to a dm-snapshot device. -class OnlineKernelSnapshotWriter : public ISnapshotWriter { +class OnlineKernelSnapshotWriter final : public ISnapshotWriter { public: OnlineKernelSnapshotWriter(const CowOptions& options); @@ -101,6 +104,10 @@ class OnlineKernelSnapshotWriter : public ISnapshotWriter { uint64_t GetCowSize() override { return cow_size_; } std::unique_ptr OpenReader() override; + // Online kernel snapshot writer doesn't care about merge sequences. + // So ignore. + bool VerifyMergeOps() const noexcept override { return true; } + protected: 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; diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp index 3eda08e5c..48b7d80f7 100644 --- a/fs_mgr/libsnapshot/snapshot_writer.cpp +++ b/fs_mgr/libsnapshot/snapshot_writer.cpp @@ -67,7 +67,7 @@ uint64_t CompressedSnapshotWriter::GetCowSize() { return cow_->GetCowSize(); } -std::unique_ptr CompressedSnapshotWriter::OpenReader() { +std::unique_ptr CompressedSnapshotWriter::OpenCowReader() const { unique_fd cow_fd(dup(cow_device_.get())); if (cow_fd < 0) { PLOG(ERROR) << "dup COW device"; @@ -79,6 +79,20 @@ std::unique_ptr CompressedSnapshotWriter::OpenReader() { 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(); auto reader = std::make_unique(); if (!reader->SetCow(std::move(cow))) {