diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h index 69079cb23..6baf4beae 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h @@ -28,9 +28,6 @@ static constexpr uint32_t kCowVersionMinor = 0; static constexpr uint32_t kCowVersionManifest = 2; -static constexpr size_t BLOCK_SZ = 4096; -static constexpr size_t BLOCK_SHIFT = (__builtin_ffs(BLOCK_SZ) - 1); - // This header appears as the first sequence of bytes in the COW. All fields // in the layout are little-endian encoded. The on-disk layout is: // diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h index 73429e1c6..95a1270f9 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h @@ -63,7 +63,9 @@ class ICowReader { // // Partial reads are not possible unless |buffer_size| is less than the // operation block size. - virtual ssize_t ReadData(const CowOperation& op, void* buffer, size_t buffer_size, + // + // The operation pointer must derive from ICowOpIter::Get(). + virtual ssize_t ReadData(const CowOperation* op, void* buffer, size_t buffer_size, size_t ignore_bytes = 0) = 0; }; @@ -77,7 +79,7 @@ class ICowOpIter { virtual bool AtEnd() = 0; // Read the current operation. - virtual const CowOperation& Get() = 0; + virtual const CowOperation* Get() = 0; // Advance to the next item. virtual void Next() = 0; @@ -121,7 +123,7 @@ class CowReader final : public ICowReader { std::unique_ptr GetRevMergeOpIter(bool ignore_progress = false) override; std::unique_ptr GetMergeOpIter(bool ignore_progress = false) override; - ssize_t ReadData(const CowOperation& op, void* buffer, size_t buffer_size, + ssize_t ReadData(const CowOperation* op, void* buffer, size_t buffer_size, size_t ignore_bytes = 0) override; CowHeader& GetHeader() override { return header_; } diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp index 7d1b7ba85..edc9d65b2 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp @@ -46,7 +46,7 @@ class CowTest : public ::testing::Test { }; // Helper to check read sizes. -static inline bool ReadData(CowReader& reader, const CowOperation& op, void* buffer, size_t size) { +static inline bool ReadData(CowReader& reader, const CowOperation* op, void* buffer, size_t size) { return reader.ReadData(op, buffer, size) == size; } @@ -80,7 +80,7 @@ TEST_F(CowTest, CopyContiguous) { size_t i = 0; while (!iter->AtEnd()) { - auto op = &iter->Get(); + auto op = iter->Get(); ASSERT_EQ(op->type, kCowCopyOp); ASSERT_EQ(op->compression, kCowCompressNone); ASSERT_EQ(op->data_length, 0); @@ -126,7 +126,7 @@ TEST_F(CowTest, ReadWrite) { auto iter = reader.GetOpIter(); ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->AtEnd()); - auto op = &iter->Get(); + auto op = iter->Get(); ASSERT_EQ(op->type, kCowCopyOp); ASSERT_EQ(op->compression, kCowCompressNone); @@ -138,18 +138,18 @@ TEST_F(CowTest, ReadWrite) { iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowReplaceOp); ASSERT_EQ(op->compression, kCowCompressNone); ASSERT_EQ(op->data_length, 4096); ASSERT_EQ(op->new_block, 50); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); // Note: the zero operation gets split into two blocks. ASSERT_EQ(op->type, kCowZeroOp); @@ -160,7 +160,7 @@ TEST_F(CowTest, ReadWrite) { iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowZeroOp); ASSERT_EQ(op->compression, kCowCompressNone); @@ -205,7 +205,7 @@ TEST_F(CowTest, ReadWriteXor) { auto iter = reader.GetOpIter(); ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->AtEnd()); - auto op = &iter->Get(); + auto op = iter->Get(); ASSERT_EQ(op->type, kCowCopyOp); ASSERT_EQ(op->compression, kCowCompressNone); @@ -217,19 +217,19 @@ TEST_F(CowTest, ReadWriteXor) { iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowXorOp); ASSERT_EQ(op->compression, kCowCompressNone); ASSERT_EQ(op->data_length, 4096); ASSERT_EQ(op->new_block, 50); ASSERT_EQ(op->source, 98314); // 4096 * 24 + 10 - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); // Note: the zero operation gets split into two blocks. ASSERT_EQ(op->type, kCowZeroOp); @@ -240,7 +240,7 @@ TEST_F(CowTest, ReadWriteXor) { iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowZeroOp); ASSERT_EQ(op->compression, kCowCompressNone); @@ -274,7 +274,7 @@ TEST_F(CowTest, CompressGz) { auto iter = reader.GetOpIter(); ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->AtEnd()); - auto op = &iter->Get(); + auto op = iter->Get(); std::string sink(data.size(), '\0'); @@ -282,7 +282,7 @@ TEST_F(CowTest, CompressGz) { ASSERT_EQ(op->compression, kCowCompressGz); ASSERT_EQ(op->data_length, 56); // compressed! ASSERT_EQ(op->new_block, 50); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data); iter->Next(); @@ -329,14 +329,14 @@ TEST_P(CompressionTest, ThreadedBatchWrites) { int total_blocks = 0; while (!iter->AtEnd()) { - auto op = &iter->Get(); + auto op = iter->Get(); if (op->type == kCowXorOp) { total_blocks += 1; std::string sink(xor_data.size(), '\0'); ASSERT_EQ(op->new_block, 50); ASSERT_EQ(op->source, 98314); // 4096 * 24 + 10 - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, xor_data); } @@ -345,19 +345,19 @@ TEST_P(CompressionTest, ThreadedBatchWrites) { if (op->new_block == 100) { data.resize(options.block_size); std::string sink(data.size(), '\0'); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink.size(), data.size()); ASSERT_EQ(sink, data); } if (op->new_block == 6000) { data2.resize(options.block_size); std::string sink(data2.size(), '\0'); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data2); } if (op->new_block == 9000) { std::string sink(data3.size(), '\0'); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data3); } } @@ -403,25 +403,25 @@ TEST_P(CompressionTest, NoBatchWrites) { int total_blocks = 0; while (!iter->AtEnd()) { - auto op = &iter->Get(); + auto op = iter->Get(); if (op->type == kCowReplaceOp) { total_blocks += 1; if (op->new_block == 50) { data.resize(options.block_size); std::string sink(data.size(), '\0'); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data); } if (op->new_block == 3000) { data2.resize(options.block_size); std::string sink(data2.size(), '\0'); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data2); } if (op->new_block == 5000) { std::string sink(data3.size(), '\0'); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data3); } } @@ -519,7 +519,7 @@ TEST_F(CowTest, ClusterCompressGz) { auto iter = reader.GetOpIter(); ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->AtEnd()); - auto op = &iter->Get(); + auto op = iter->Get(); std::string sink(data.size(), '\0'); @@ -527,30 +527,30 @@ TEST_F(CowTest, ClusterCompressGz) { ASSERT_EQ(op->compression, kCowCompressGz); ASSERT_EQ(op->data_length, 56); // compressed! ASSERT_EQ(op->new_block, 50); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowClusterOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); sink = {}; sink.resize(data2.size(), '\0'); ASSERT_EQ(op->compression, kCowCompressGz); ASSERT_EQ(op->data_length, 41); // compressed! ASSERT_EQ(op->new_block, 51); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data2); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowClusterOp); @@ -585,11 +585,11 @@ TEST_F(CowTest, CompressTwoBlocks) { std::string sink(options.block_size, '\0'); - auto op = &iter->Get(); + auto op = iter->Get(); ASSERT_EQ(op->type, kCowReplaceOp); ASSERT_EQ(op->compression, kCowCompressGz); ASSERT_EQ(op->new_block, 51); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); } TEST_F(CowTest, GetSize) { @@ -659,9 +659,9 @@ TEST_F(CowTest, AppendLabelSmall) { ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->AtEnd()); - auto op = &iter->Get(); + auto op = iter->Get(); ASSERT_EQ(op->type, kCowReplaceOp); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data); iter->Next(); @@ -669,16 +669,16 @@ TEST_F(CowTest, AppendLabelSmall) { sink.resize(data2.size(), '\0'); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->source, 3); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowReplaceOp); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data2); iter->Next(); @@ -722,14 +722,14 @@ TEST_F(CowTest, AppendLabelMissing) { ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->AtEnd()); - auto op = &iter->Get(); + auto op = iter->Get(); ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->source, 0); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowZeroOp); iter->Next(); @@ -780,7 +780,7 @@ TEST_F(CowTest, AppendExtendedCorrupted) { ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->AtEnd()); - auto op = &iter->Get(); + auto op = iter->Get(); ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->source, 5); @@ -831,9 +831,9 @@ TEST_F(CowTest, AppendbyLabel) { ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->AtEnd()); - auto op = &iter->Get(); + auto op = iter->Get(); ASSERT_EQ(op->type, kCowReplaceOp); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data.substr(0, options.block_size)); iter->Next(); @@ -841,33 +841,33 @@ TEST_F(CowTest, AppendbyLabel) { sink.resize(options.block_size, '\0'); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowReplaceOp); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data.substr(options.block_size, 2 * options.block_size)); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->source, 4); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowZeroOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowZeroOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->source, 5); @@ -912,59 +912,59 @@ TEST_F(CowTest, ClusterTest) { ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->AtEnd()); - auto op = &iter->Get(); + auto op = iter->Get(); ASSERT_EQ(op->type, kCowReplaceOp); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data.substr(0, options.block_size)); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->source, 4); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowZeroOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowClusterOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowZeroOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->source, 5); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowCopyOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowClusterOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->source, 6); @@ -1011,22 +1011,22 @@ TEST_F(CowTest, ClusterAppendTest) { ASSERT_NE(iter, nullptr); ASSERT_FALSE(iter->AtEnd()); - auto op = &iter->Get(); + auto op = iter->Get(); ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->source, 50); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowReplaceOp); - ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); + ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data2); iter->Next(); ASSERT_FALSE(iter->AtEnd()); - op = &iter->Get(); + op = iter->Get(); ASSERT_EQ(op->type, kCowClusterOp); iter->Next(); @@ -1066,7 +1066,7 @@ AssertionResult WriteDataBlock(CowWriter* writer, uint64_t new_block, std::strin return AssertionSuccess(); } -AssertionResult CompareDataBlock(CowReader* reader, const CowOperation& op, +AssertionResult CompareDataBlock(CowReader* reader, const CowOperation* op, const std::string& data) { const auto& header = reader->GetHeader(); @@ -1124,12 +1124,12 @@ TEST_F(CowTest, ResumeMidCluster) { num_in_cluster++; max_in_cluster = std::max(max_in_cluster, num_in_cluster); - if (op.type == kCowReplaceOp) { + if (op->type == kCowReplaceOp) { num_replace++; - ASSERT_EQ(op.new_block, num_replace); + ASSERT_EQ(op->new_block, num_replace); ASSERT_TRUE(CompareDataBlock(&reader, op, "Block " + std::to_string(num_replace))); - } else if (op.type == kCowClusterOp) { + } else if (op->type == kCowClusterOp) { num_in_cluster = 0; num_clusters++; } @@ -1185,12 +1185,12 @@ TEST_F(CowTest, ResumeEndCluster) { num_in_cluster++; max_in_cluster = std::max(max_in_cluster, num_in_cluster); - if (op.type == kCowReplaceOp) { + if (op->type == kCowReplaceOp) { num_replace++; - ASSERT_EQ(op.new_block, num_replace); + ASSERT_EQ(op->new_block, num_replace); ASSERT_TRUE(CompareDataBlock(&reader, op, "Block " + std::to_string(num_replace))); - } else if (op.type == kCowClusterOp) { + } else if (op->type == kCowClusterOp) { num_in_cluster = 0; num_clusters++; } @@ -1236,12 +1236,12 @@ TEST_F(CowTest, DeleteMidCluster) { num_in_cluster++; max_in_cluster = std::max(max_in_cluster, num_in_cluster); - if (op.type == kCowReplaceOp) { + if (op->type == kCowReplaceOp) { num_replace++; - ASSERT_EQ(op.new_block, num_replace); + ASSERT_EQ(op->new_block, num_replace); ASSERT_TRUE(CompareDataBlock(&reader, op, "Block " + std::to_string(num_replace))); - } else if (op.type == kCowClusterOp) { + } else if (op->type == kCowClusterOp) { num_in_cluster = 0; num_clusters++; } @@ -1278,7 +1278,7 @@ TEST_F(CowTest, BigSeqOp) { ASSERT_TRUE(!iter->AtEnd()); const auto& op = iter->Get(); - ASSERT_EQ(op.new_block, seq_len - i); + ASSERT_EQ(op->new_block, seq_len - i); iter->Next(); } @@ -1345,7 +1345,7 @@ TEST_F(CowTest, ResumeSeqOp) { ASSERT_FALSE(iter->AtEnd()); const auto& op = iter->Get(); - ASSERT_EQ(op.new_block, expected_block); + ASSERT_EQ(op->new_block, expected_block); iter->Next(); expected_block--; @@ -1395,7 +1395,7 @@ TEST_F(CowTest, RevMergeOpItrTest) { while (!iter->AtEnd() && expected_new_block != revMergeOpSequence.end()) { const auto& op = iter->Get(); - ASSERT_EQ(op.new_block, *expected_new_block); + ASSERT_EQ(op->new_block, *expected_new_block); iter->Next(); expected_new_block++; @@ -1444,7 +1444,7 @@ TEST_F(CowTest, LegacyRevMergeOpItrTest) { while (!iter->AtEnd() && expected_new_block != revMergeOpSequence.end()) { const auto& op = iter->Get(); - ASSERT_EQ(op.new_block, *expected_new_block); + ASSERT_EQ(op->new_block, *expected_new_block); iter->Next(); expected_new_block++; diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp index 94c41093c..2157d0fa9 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp @@ -57,8 +57,6 @@ std::ostream& operator<<(std::ostream& os, CowOperation const& op) { os << "data_length:" << op.data_length << ",\t"; os << "new_block:" << op.new_block << ",\t"; os << "source:" << op.source; - if (op.type == kCowXorOp) - os << " (block:" << op.source / BLOCK_SZ << " offset:" << op.source % BLOCK_SZ << ")"; os << ")"; return os; } diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp index 893d95fc7..4c5a8bf5f 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp @@ -508,37 +508,37 @@ bool CowReader::PrepMergeOps() { bool CowReader::VerifyMergeOps() { auto itr = GetMergeOpIter(true); - std::unordered_map overwritten_blocks; + std::unordered_map overwritten_blocks; while (!itr->AtEnd()) { - CowOperation op = itr->Get(); + const auto& op = itr->Get(); uint64_t block; bool offset; - if (op.type == kCowCopyOp) { - block = op.source; + if (op->type == kCowCopyOp) { + block = op->source; offset = false; - } else if (op.type == kCowXorOp) { - block = op.source / BLOCK_SZ; - offset = (op.source % BLOCK_SZ) != 0; + } else if (op->type == kCowXorOp) { + block = op->source / header_.block_size; + offset = (op->source % header_.block_size) != 0; } else { itr->Next(); continue; } - CowOperation* overwrite = nullptr; + const CowOperation* overwrite = nullptr; if (overwritten_blocks.count(block)) { - overwrite = &overwritten_blocks[block]; + overwrite = overwritten_blocks[block]; LOG(ERROR) << "Invalid Sequence! Block needed for op:\n" << op << "\noverwritten by previously merged op:\n" << *overwrite; } if (offset && overwritten_blocks.count(block + 1)) { - overwrite = &overwritten_blocks[block + 1]; + overwrite = overwritten_blocks[block + 1]; LOG(ERROR) << "Invalid Sequence! Block needed for op:\n" << op << "\noverwritten by previously merged op:\n" << *overwrite; } if (overwrite != nullptr) return false; - overwritten_blocks[op.new_block] = op; + overwritten_blocks[op->new_block] = op; itr->Next(); } return true; @@ -561,7 +561,7 @@ class CowOpIter final : public ICowOpIter { CowOpIter(std::shared_ptr>& ops, uint64_t start); bool AtEnd() override; - const CowOperation& Get() override; + const CowOperation* Get() override; void Next() override; void Prev() override; @@ -595,9 +595,9 @@ void CowOpIter::Next() { op_iter_++; } -const CowOperation& CowOpIter::Get() { +const CowOperation* CowOpIter::Get() { CHECK(!AtEnd()); - return (*op_iter_); + return &(*op_iter_); } class CowRevMergeOpIter final : public ICowOpIter { @@ -606,7 +606,7 @@ class CowRevMergeOpIter final : public ICowOpIter { std::shared_ptr> block_pos_index, uint64_t start); bool AtEnd() override; - const CowOperation& Get() override; + const CowOperation* Get() override; void Next() override; void Prev() override; @@ -625,7 +625,7 @@ class CowMergeOpIter final : public ICowOpIter { std::shared_ptr> block_pos_index, uint64_t start); bool AtEnd() override; - const CowOperation& Get() override; + const CowOperation* Get() override; void Next() override; void Prev() override; @@ -664,9 +664,9 @@ void CowMergeOpIter::Next() { block_iter_++; } -const CowOperation& CowMergeOpIter::Get() { +const CowOperation* CowMergeOpIter::Get() { CHECK(!AtEnd()); - return ops_->data()[*block_iter_]; + return &ops_->data()[*block_iter_]; } CowRevMergeOpIter::CowRevMergeOpIter(std::shared_ptr> ops, @@ -696,9 +696,9 @@ void CowRevMergeOpIter::Next() { block_riter_++; } -const CowOperation& CowRevMergeOpIter::Get() { +const CowOperation* CowRevMergeOpIter::Get() { CHECK(!AtEnd()); - return ops_->data()[*block_riter_]; + return &ops_->data()[*block_riter_]; } std::unique_ptr CowReader::GetOpIter(bool merge_progress) { @@ -765,10 +765,10 @@ class CowDataStream final : public IByteStream { size_t remaining_; }; -ssize_t CowReader::ReadData(const CowOperation& op, void* buffer, size_t buffer_size, +ssize_t CowReader::ReadData(const CowOperation* op, void* buffer, size_t buffer_size, size_t ignore_bytes) { std::unique_ptr decompressor; - switch (op.compression) { + switch (op->compression) { case kCowCompressNone: break; case kCowCompressGz: @@ -778,28 +778,28 @@ ssize_t CowReader::ReadData(const CowOperation& op, void* buffer, size_t buffer_ decompressor = IDecompressor::Brotli(); break; case kCowCompressLz4: - if (header_.block_size != op.data_length) { + if (header_.block_size != op->data_length) { decompressor = IDecompressor::Lz4(); } break; default: - LOG(ERROR) << "Unknown compression type: " << op.compression; + LOG(ERROR) << "Unknown compression type: " << op->compression; return -1; } uint64_t offset; - if (op.type == kCowXorOp) { - offset = data_loc_->at(op.new_block); + if (op->type == kCowXorOp) { + offset = data_loc_->at(op->new_block); } else { - offset = op.source; + offset = op->source; } if (!decompressor) { - CowDataStream stream(this, offset + ignore_bytes, op.data_length - ignore_bytes); + CowDataStream stream(this, offset + ignore_bytes, op->data_length - ignore_bytes); return stream.ReadFully(buffer, buffer_size); } - CowDataStream stream(this, offset, op.data_length); + CowDataStream stream(this, offset, op->data_length); decompressor->set_stream(&stream); return decompressor->Decompress(buffer, buffer_size, header_.block_size, ignore_bytes); } diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp index cb20c6f51..0e1897947 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp @@ -407,7 +407,7 @@ bool CowWriter::OpenForAppend(uint64_t label) { auto iter = reader->GetOpIter(); while (!iter->AtEnd()) { - AddOperation(iter->Get()); + AddOperation(*iter->Get()); iter->Next(); } diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp index 40901621a..917cec424 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp @@ -64,19 +64,19 @@ struct Options { bool include_merged; }; -static void ShowBad(CowReader& reader, const struct CowOperation& op) { +static void ShowBad(CowReader& reader, const struct CowOperation* op) { size_t count; - auto buffer = std::make_unique(op.data_length); + auto buffer = std::make_unique(op->data_length); - if (!reader.GetRawBytes(op.source, buffer.get(), op.data_length, &count)) { + if (!reader.GetRawBytes(op->source, buffer.get(), op->data_length, &count)) { std::cerr << "Failed to read at all!\n"; } else { std::cout << "The Block data is:\n"; - for (int i = 0; i < op.data_length; i++) { + for (int i = 0; i < op->data_length; i++) { std::cout << std::hex << (int)buffer[i]; } std::cout << std::dec << "\n\n"; - if (op.data_length >= sizeof(CowOperation)) { + if (op->data_length >= sizeof(CowOperation)) { std::cout << "The start, as an op, would be " << *(CowOperation*)buffer.get() << "\n"; } } @@ -145,29 +145,29 @@ static bool Inspect(const std::string& path, Options opt) { bool success = true; uint64_t xor_ops = 0, copy_ops = 0, replace_ops = 0, zero_ops = 0; while (!iter->AtEnd()) { - const CowOperation& op = iter->Get(); + const CowOperation* op = iter->Get(); - if (!opt.silent && opt.show_ops) std::cout << op << "\n"; + if (!opt.silent && opt.show_ops) std::cout << *op << "\n"; - if (opt.decompress && op.type == kCowReplaceOp && op.compression != kCowCompressNone) { + if (opt.decompress && op->type == kCowReplaceOp && op->compression != kCowCompressNone) { if (reader.ReadData(op, buffer.data(), buffer.size()) < 0) { - std::cerr << "Failed to decompress for :" << op << "\n"; + std::cerr << "Failed to decompress for :" << *op << "\n"; success = false; if (opt.show_bad) ShowBad(reader, op); } } - if (op.type == kCowSequenceOp && opt.show_seq) { + if (op->type == kCowSequenceOp && opt.show_seq) { size_t read; std::vector merge_op_blocks; - size_t seq_len = op.data_length / sizeof(uint32_t); + size_t seq_len = op->data_length / sizeof(uint32_t); merge_op_blocks.resize(seq_len); - if (!reader.GetRawBytes(op.source, merge_op_blocks.data(), op.data_length, &read)) { + if (!reader.GetRawBytes(op->source, merge_op_blocks.data(), op->data_length, &read)) { PLOG(ERROR) << "Failed to read sequence op!"; return false; } if (!opt.silent) { - std::cout << "Sequence for " << op << " is :\n"; + std::cout << "Sequence for " << *op << " is :\n"; for (size_t i = 0; i < seq_len; i++) { std::cout << std::setfill('0') << std::setw(6) << merge_op_blocks[i] << ", "; if ((i + 1) % 10 == 0 || i + 1 == seq_len) std::cout << "\n"; @@ -175,13 +175,13 @@ static bool Inspect(const std::string& path, Options opt) { } } - if (op.type == kCowCopyOp) { + if (op->type == kCowCopyOp) { copy_ops++; - } else if (op.type == kCowReplaceOp) { + } else if (op->type == kCowReplaceOp) { replace_ops++; - } else if (op.type == kCowZeroOp) { + } else if (op->type == kCowZeroOp) { zero_ops++; - } else if (op.type == kCowXorOp) { + } else if (op->type == kCowXorOp) { xor_ops++; } diff --git a/fs_mgr/libsnapshot/snapshot_reader.cpp b/fs_mgr/libsnapshot/snapshot_reader.cpp index 48efae061..4e75ba754 100644 --- a/fs_mgr/libsnapshot/snapshot_reader.cpp +++ b/fs_mgr/libsnapshot/snapshot_reader.cpp @@ -86,7 +86,7 @@ bool CompressedSnapshotReader::SetCow(std::unique_ptr&& cow) { // Populate the operation map. op_iter_ = cow_->GetOpIter(); while (!op_iter_->AtEnd()) { - const CowOperation* op = &op_iter_->Get(); + const CowOperation* op = op_iter_->Get(); if (IsMetadataOp(*op)) { op_iter_->Next(); continue; @@ -205,7 +205,7 @@ ssize_t CompressedSnapshotReader::ReadBlock(uint64_t chunk, size_t start_offset, } else if (op->type == kCowZeroOp) { memset(buffer, 0, bytes_to_read); } else if (op->type == kCowReplaceOp) { - if (cow_->ReadData(*op, buffer, bytes_to_read, start_offset) < bytes_to_read) { + if (cow_->ReadData(op, buffer, bytes_to_read, start_offset) < bytes_to_read) { LOG(ERROR) << "CompressedSnapshotReader failed to read replace op"; errno = EIO; return -1; @@ -226,7 +226,7 @@ ssize_t CompressedSnapshotReader::ReadBlock(uint64_t chunk, size_t start_offset, return -1; } - if (cow_->ReadData(*op, buffer, bytes_to_read, start_offset) < bytes_to_read) { + if (cow_->ReadData(op, buffer, bytes_to_read, start_offset) < bytes_to_read) { LOG(ERROR) << "CompressedSnapshotReader failed to read xor op"; errno = EIO; return -1; diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp index 376e070ab..efa43b79d 100644 --- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp +++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp @@ -391,7 +391,7 @@ bool Snapuserd::ReadMetadata() { memset(de_ptr.get(), 0, (exceptions_per_area_ * sizeof(struct disk_exception))); while (!cowop_rm_iter->AtEnd()) { - const CowOperation* cow_op = &cowop_rm_iter->Get(); + const CowOperation* cow_op = cowop_rm_iter->Get(); struct disk_exception* de = reinterpret_cast((char*)de_ptr.get() + offset); @@ -459,7 +459,7 @@ bool Snapuserd::ReadMetadata() { while (!cowop_rm_iter->AtEnd()) { do { - const CowOperation* cow_op = &cowop_rm_iter->Get(); + const CowOperation* cow_op = cowop_rm_iter->Get(); // We have two cases specific cases: // diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp index 31a80a35c..922df3424 100644 --- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp +++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp @@ -100,7 +100,7 @@ bool WorkerThread::ProcessReplaceOp(const CowOperation* cow_op) { SNAP_LOG(ERROR) << "No space in buffer sink"; return false; } - ssize_t rv = reader_->ReadData(*cow_op, buffer, BLOCK_SZ); + ssize_t rv = reader_->ReadData(cow_op, buffer, BLOCK_SZ); if (rv != BLOCK_SZ) { SNAP_LOG(ERROR) << "ProcessReplaceOp failed for block " << cow_op->new_block << ", return = " << rv; diff --git a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_kernel.h b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_kernel.h index c592257ca..46952c4ed 100644 --- a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_kernel.h +++ b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_kernel.h @@ -41,6 +41,9 @@ static constexpr uint32_t SNAPSHOT_VALID = 1; */ static constexpr uint32_t SECTOR_SHIFT = 9; +static constexpr size_t BLOCK_SZ = 4096; +static constexpr size_t BLOCK_SHIFT = (__builtin_ffs(BLOCK_SZ) - 1); + typedef __u64 sector_t; typedef sector_t chunk_t; diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp index 9df8cf989..a51963985 100644 --- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp +++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp @@ -186,7 +186,7 @@ bool SnapshotHandler::ReadMetadata() { size_t copy_ops = 0, replace_ops = 0, zero_ops = 0, xor_ops = 0; while (!cowop_iter->AtEnd()) { - const CowOperation* cow_op = &cowop_iter->Get(); + const CowOperation* cow_op = cowop_iter->Get(); if (cow_op->type == kCowCopyOp) { copy_ops += 1; diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp index 3bc02d496..78582164f 100644 --- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp +++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp @@ -81,7 +81,7 @@ bool Worker::ProcessReplaceOp(const CowOperation* cow_op) { SNAP_LOG(ERROR) << "ProcessReplaceOp failed to allocate buffer"; return false; } - if (!reader_->ReadData(*cow_op, buffer, BLOCK_SZ)) { + if (!reader_->ReadData(cow_op, buffer, BLOCK_SZ)) { SNAP_LOG(ERROR) << "ProcessReplaceOp failed for block " << cow_op->new_block; return false; } @@ -139,7 +139,7 @@ bool Worker::ProcessXorOp(const CowOperation* cow_op) { << actual; return false; } - ssize_t size = reader_->ReadData(*cow_op, buffer, BLOCK_SZ); + ssize_t size = reader_->ReadData(cow_op, buffer, BLOCK_SZ); if (size != BLOCK_SZ) { SNAP_LOG(ERROR) << "ProcessXorOp failed for block " << cow_op->new_block << ", return value: " << size; diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.cpp index 4d91ff313..ce95b7659 100644 --- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.cpp +++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.cpp @@ -31,7 +31,7 @@ int Worker::PrepareMerge(uint64_t* source_offset, int* pending_ops, do { if (!cowop_iter_->AtEnd() && num_ops) { - const CowOperation* cow_op = &cowop_iter_->Get(); + const CowOperation* cow_op = cowop_iter_->Get(); if (checkOrderedOp && !IsOrderedOp(*cow_op)) { break; } @@ -46,7 +46,7 @@ int Worker::PrepareMerge(uint64_t* source_offset, int* pending_ops, nr_consecutive = 1; while (!cowop_iter_->AtEnd() && num_ops) { - const CowOperation* op = &cowop_iter_->Get(); + const CowOperation* op = cowop_iter_->Get(); if (checkOrderedOp && !IsOrderedOp(*op)) { break; } @@ -181,7 +181,7 @@ bool Worker::MergeOrderedOpsAsync() { SNAP_LOG(INFO) << "MergeOrderedOpsAsync started...."; while (!cowop_iter_->AtEnd()) { - const CowOperation* cow_op = &cowop_iter_->Get(); + const CowOperation* cow_op = cowop_iter_->Get(); if (!IsOrderedOp(*cow_op)) { break; } @@ -362,7 +362,7 @@ bool Worker::MergeOrderedOps() { SNAP_LOG(INFO) << "MergeOrderedOps started...."; while (!cowop_iter_->AtEnd()) { - const CowOperation* cow_op = &cowop_iter_->Get(); + const CowOperation* cow_op = cowop_iter_->Get(); if (!IsOrderedOp(*cow_op)) { break; } diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp index 4aad7a66b..17f1f0e27 100644 --- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp +++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp @@ -492,7 +492,7 @@ bool ReadAhead::ReadXorData(size_t block_index, size_t xor_op_index, << xor_op->new_block; return false; } - if (ssize_t rv = reader_->ReadData(*xor_op, buffer, BLOCK_SZ); rv != BLOCK_SZ) { + if (ssize_t rv = reader_->ReadData(xor_op, buffer, BLOCK_SZ); rv != BLOCK_SZ) { SNAP_LOG(ERROR) << " ReadAhead - XorOp Read failed for block: " << xor_op->new_block << ", return value: " << rv; @@ -592,7 +592,7 @@ bool ReadAhead::ReadAheadSyncIO() { SNAP_LOG(ERROR) << "ReadAhead - failed to allocate buffer"; return false; } - if (ssize_t rv = reader_->ReadData(*xor_op, buffer, BLOCK_SZ); rv != BLOCK_SZ) { + if (ssize_t rv = reader_->ReadData(xor_op, buffer, BLOCK_SZ); rv != BLOCK_SZ) { SNAP_LOG(ERROR) << " ReadAhead - XorOp Read failed for block: " << xor_op->new_block << ", return value: " << rv; @@ -834,8 +834,7 @@ void ReadAhead::RAResetIter(uint64_t num_blocks) { } const CowOperation* ReadAhead::GetRAOpIter() { - const CowOperation* cow_op = &cowop_iter_->Get(); - return cow_op; + return cowop_iter_->Get(); } void ReadAhead::InitializeBuffer() {