Loading fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h +5 −4 Original line number Diff line number Diff line Loading @@ -52,8 +52,9 @@ class ICowWriter { virtual ~ICowWriter() {} // Encode an operation that copies the contents of |old_block| to the // location of |new_block|. bool AddCopy(uint64_t new_block, uint64_t old_block); // location of |new_block|. 'num_blocks' is the number of contiguous // COPY operations from |old_block| to |new_block|. bool AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1); // Encode a sequence of raw blocks. |size| must be a multiple of the block size. bool AddRawBlocks(uint64_t new_block_start, const void* data, size_t size); Loading Loading @@ -84,7 +85,7 @@ class ICowWriter { const CowOptions& options() { return options_; } protected: virtual bool EmitCopy(uint64_t new_block, uint64_t old_block) = 0; virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) = 0; virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) = 0; virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, uint16_t offset) = 0; Loading Loading @@ -122,7 +123,7 @@ class CowWriter : public ICowWriter { uint32_t GetCowVersion() { return header_.major_version; } protected: virtual bool EmitCopy(uint64_t new_block, uint64_t old_block) override; virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override; virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, uint16_t offset) override; Loading fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ class MockSnapshotWriter : public ISnapshotWriter { // Returns true if AddCopy() operations are supported. MOCK_METHOD(bool, SupportsCopyOperation, (), (const override)); MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t), (override)); MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t, uint64_t), (override)); MOCK_METHOD(bool, EmitRawBlocks, (uint64_t, const void*, size_t), (override)); MOCK_METHOD(bool, EmitXorBlocks, (uint32_t, const void*, size_t, uint32_t, uint16_t), (override)); Loading fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h +2 −2 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ class CompressedSnapshotWriter final : public ISnapshotWriter { bool VerifyMergeOps() const noexcept; protected: bool EmitCopy(uint64_t new_block, uint64_t old_block) override; bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override; bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, uint16_t offset) override; Loading Loading @@ -113,7 +113,7 @@ class OnlineKernelSnapshotWriter final : public ISnapshotWriter { bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override; bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, uint16_t offset) override; bool EmitCopy(uint64_t new_block, uint64_t old_block) override; bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override; bool EmitLabel(uint64_t label) override; bool EmitSequenceData(size_t num_ops, const uint32_t* data) override; Loading fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp +42 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,48 @@ class StringSink : public IByteSink { std::string stream_; }; TEST_F(CowTest, CopyContiguous) { CowOptions options; options.cluster_ops = 0; CowWriter writer(options); ASSERT_TRUE(writer.Initialize(cow_->fd)); ASSERT_TRUE(writer.AddCopy(10, 1000, 100)); ASSERT_TRUE(writer.Finalize()); ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0); CowReader reader; CowHeader header; CowFooter footer; ASSERT_TRUE(reader.Parse(cow_->fd)); ASSERT_TRUE(reader.GetHeader(&header)); ASSERT_TRUE(reader.GetFooter(&footer)); ASSERT_EQ(header.magic, kCowMagicNumber); ASSERT_EQ(header.major_version, kCowVersionMajor); ASSERT_EQ(header.minor_version, kCowVersionMinor); ASSERT_EQ(header.block_size, options.block_size); ASSERT_EQ(footer.op.num_ops, 100); auto iter = reader.GetOpIter(); ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->Done()); size_t i = 0; while (!iter->Done()) { auto op = &iter->Get(); ASSERT_EQ(op->type, kCowCopyOp); ASSERT_EQ(op->compression, kCowCompressNone); ASSERT_EQ(op->data_length, 0); ASSERT_EQ(op->new_block, 10 + i); ASSERT_EQ(op->source, 1000 + i); iter->Next(); i += 1; } ASSERT_EQ(i, 100); } TEST_F(CowTest, ReadWrite) { CowOptions options; options.cluster_ops = 0; Loading fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp +22 −10 Original line number Diff line number Diff line Loading @@ -38,11 +38,16 @@ static_assert(sizeof(off_t) == sizeof(uint64_t)); using android::base::borrowed_fd; using android::base::unique_fd; bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block) { if (!ValidateNewBlock(new_block)) { bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) { CHECK(num_blocks != 0); for (size_t i = 0; i < num_blocks; i++) { if (!ValidateNewBlock(new_block + i)) { return false; } return EmitCopy(new_block, old_block); } return EmitCopy(new_block, old_block, num_blocks); } bool ICowWriter::AddRawBlocks(uint64_t new_block_start, const void* data, size_t size) { Loading Loading @@ -286,13 +291,20 @@ bool CowWriter::OpenForAppend(uint64_t label) { return EmitClusterIfNeeded(); } bool CowWriter::EmitCopy(uint64_t new_block, uint64_t old_block) { bool CowWriter::EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) { CHECK(!merge_in_progress_); for (size_t i = 0; i < num_blocks; i++) { CowOperation op = {}; op.type = kCowCopyOp; op.new_block = new_block; op.source = old_block; return WriteOperation(op); op.new_block = new_block + i; op.source = old_block + i; if (!WriteOperation(op)) { return false; } } return true; } bool CowWriter::EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) { Loading Loading
fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h +5 −4 Original line number Diff line number Diff line Loading @@ -52,8 +52,9 @@ class ICowWriter { virtual ~ICowWriter() {} // Encode an operation that copies the contents of |old_block| to the // location of |new_block|. bool AddCopy(uint64_t new_block, uint64_t old_block); // location of |new_block|. 'num_blocks' is the number of contiguous // COPY operations from |old_block| to |new_block|. bool AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1); // Encode a sequence of raw blocks. |size| must be a multiple of the block size. bool AddRawBlocks(uint64_t new_block_start, const void* data, size_t size); Loading Loading @@ -84,7 +85,7 @@ class ICowWriter { const CowOptions& options() { return options_; } protected: virtual bool EmitCopy(uint64_t new_block, uint64_t old_block) = 0; virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) = 0; virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) = 0; virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, uint16_t offset) = 0; Loading Loading @@ -122,7 +123,7 @@ class CowWriter : public ICowWriter { uint32_t GetCowVersion() { return header_.major_version; } protected: virtual bool EmitCopy(uint64_t new_block, uint64_t old_block) override; virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override; virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, uint16_t offset) override; Loading
fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ class MockSnapshotWriter : public ISnapshotWriter { // Returns true if AddCopy() operations are supported. MOCK_METHOD(bool, SupportsCopyOperation, (), (const override)); MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t), (override)); MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t, uint64_t), (override)); MOCK_METHOD(bool, EmitRawBlocks, (uint64_t, const void*, size_t), (override)); MOCK_METHOD(bool, EmitXorBlocks, (uint32_t, const void*, size_t, uint32_t, uint16_t), (override)); Loading
fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h +2 −2 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ class CompressedSnapshotWriter final : public ISnapshotWriter { bool VerifyMergeOps() const noexcept; protected: bool EmitCopy(uint64_t new_block, uint64_t old_block) override; bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override; bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, uint16_t offset) override; Loading Loading @@ -113,7 +113,7 @@ class OnlineKernelSnapshotWriter final : public ISnapshotWriter { bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override; bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, uint16_t offset) override; bool EmitCopy(uint64_t new_block, uint64_t old_block) override; bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override; bool EmitLabel(uint64_t label) override; bool EmitSequenceData(size_t num_ops, const uint32_t* data) override; Loading
fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp +42 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,48 @@ class StringSink : public IByteSink { std::string stream_; }; TEST_F(CowTest, CopyContiguous) { CowOptions options; options.cluster_ops = 0; CowWriter writer(options); ASSERT_TRUE(writer.Initialize(cow_->fd)); ASSERT_TRUE(writer.AddCopy(10, 1000, 100)); ASSERT_TRUE(writer.Finalize()); ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0); CowReader reader; CowHeader header; CowFooter footer; ASSERT_TRUE(reader.Parse(cow_->fd)); ASSERT_TRUE(reader.GetHeader(&header)); ASSERT_TRUE(reader.GetFooter(&footer)); ASSERT_EQ(header.magic, kCowMagicNumber); ASSERT_EQ(header.major_version, kCowVersionMajor); ASSERT_EQ(header.minor_version, kCowVersionMinor); ASSERT_EQ(header.block_size, options.block_size); ASSERT_EQ(footer.op.num_ops, 100); auto iter = reader.GetOpIter(); ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->Done()); size_t i = 0; while (!iter->Done()) { auto op = &iter->Get(); ASSERT_EQ(op->type, kCowCopyOp); ASSERT_EQ(op->compression, kCowCompressNone); ASSERT_EQ(op->data_length, 0); ASSERT_EQ(op->new_block, 10 + i); ASSERT_EQ(op->source, 1000 + i); iter->Next(); i += 1; } ASSERT_EQ(i, 100); } TEST_F(CowTest, ReadWrite) { CowOptions options; options.cluster_ops = 0; Loading
fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp +22 −10 Original line number Diff line number Diff line Loading @@ -38,11 +38,16 @@ static_assert(sizeof(off_t) == sizeof(uint64_t)); using android::base::borrowed_fd; using android::base::unique_fd; bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block) { if (!ValidateNewBlock(new_block)) { bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) { CHECK(num_blocks != 0); for (size_t i = 0; i < num_blocks; i++) { if (!ValidateNewBlock(new_block + i)) { return false; } return EmitCopy(new_block, old_block); } return EmitCopy(new_block, old_block, num_blocks); } bool ICowWriter::AddRawBlocks(uint64_t new_block_start, const void* data, size_t size) { Loading Loading @@ -286,13 +291,20 @@ bool CowWriter::OpenForAppend(uint64_t label) { return EmitClusterIfNeeded(); } bool CowWriter::EmitCopy(uint64_t new_block, uint64_t old_block) { bool CowWriter::EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) { CHECK(!merge_in_progress_); for (size_t i = 0; i < num_blocks; i++) { CowOperation op = {}; op.type = kCowCopyOp; op.new_block = new_block; op.source = old_block; return WriteOperation(op); op.new_block = new_block + i; op.source = old_block + i; if (!WriteOperation(op)) { return false; } } return true; } bool CowWriter::EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) { Loading