diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h index 2beeb9f62..bfa8f6bea 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h @@ -149,9 +149,6 @@ struct CowOperationV2 { // The on disk format of cow (currently == CowOperation) struct CowOperationV3 { - // The operation code (see the constants and structures below). - uint8_t type; - // If this operation reads from the data section of the COW, this contains // the length. uint16_t data_length; @@ -159,6 +156,10 @@ struct CowOperationV3 { // The block of data in the new image that this operation modifies. uint32_t new_block; + // source_info with have the following layout + // |---4 bits ---| ---12 bits---| --- 48 bits ---| + // |--- type --- | -- unused -- | --- source --- | + // // The value of |source| depends on the operation code. // // CopyOp: a 32-bit block location in the source image. @@ -167,8 +168,6 @@ struct CowOperationV3 { // ZeroOp: unused // LabelOp: a 64-bit opaque identifier. // - // For ops other than Label: - // Bits 47-62 are reserved and must be zero. // A block is compressed if it’s data is < block_sz uint64_t source_info; } __attribute__((packed)); @@ -200,9 +199,21 @@ static constexpr uint8_t kCowReadAheadNotStarted = 0; static constexpr uint8_t kCowReadAheadInProgress = 1; static constexpr uint8_t kCowReadAheadDone = 2; -static constexpr uint64_t kCowOpSourceInfoDataMask = (1ULL << 48) - 1; +// this is a mask to grab the last 48 bits of a 64 bit integer +static constexpr uint64_t kCowOpSourceInfoDataMask = (0x1ULL << 48) - 1; +// this is a mask to grab the first 4 bits of a 64 bit integer +static constexpr uint64_t kCowOpSourceInfoTypeBit = 60; +static constexpr uint64_t kCowOpSourceInfoTypeNumBits = 4; +static constexpr uint64_t kCowOpSourceInfoTypeMask = (1 << kCowOpSourceInfoTypeNumBits) - 1; -static inline uint64_t GetCowOpSourceInfoData(const CowOperation& op) { +static constexpr void SetCowOpSourceInfoType(CowOperation* op, const uint8_t type) { + op->source_info |= uint64_t(type) << kCowOpSourceInfoTypeBit; +} +static constexpr uint64_t GetCowOpSourceInfoType(const CowOperation& op) { + return (op.source_info >> kCowOpSourceInfoTypeBit) & kCowOpSourceInfoTypeMask; +} + +static constexpr uint64_t GetCowOpSourceInfoData(const CowOperation& op) { return op.source_info & kCowOpSourceInfoDataMask; } diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp index 5ab4f7a52..1be592d21 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp @@ -81,16 +81,19 @@ std::ostream& operator<<(std::ostream& os, CowOperationV2 const& op) { std::ostream& operator<<(std::ostream& os, CowOperation const& op) { os << "CowOperation("; - EmitCowTypeString(os, op.type); - if (op.type == kCowReplaceOp || op.type == kCowXorOp || op.type == kCowSequenceOp) { + EmitCowTypeString(os, GetCowOpSourceInfoType(op)); + if (GetCowOpSourceInfoType(op) == kCowReplaceOp || GetCowOpSourceInfoType(op) == kCowXorOp || + GetCowOpSourceInfoType(op) == kCowSequenceOp) { os << ", data_length:" << op.data_length; } - if (op.type != kCowClusterOp && op.type != kCowSequenceOp && op.type != kCowLabelOp) { + if (GetCowOpSourceInfoType(op) != kCowClusterOp && + GetCowOpSourceInfoType(op) != kCowSequenceOp && GetCowOpSourceInfoType(op) != kCowLabelOp) { os << ", new_block:" << op.new_block; } - if (op.type == kCowXorOp || op.type == kCowReplaceOp || op.type == kCowCopyOp) { + if (GetCowOpSourceInfoType(op) == kCowXorOp || GetCowOpSourceInfoType(op) == kCowReplaceOp || + GetCowOpSourceInfoType(op) == kCowCopyOp) { os << ", source:" << (op.source_info & kCowOpSourceInfoDataMask); - } else if (op.type == kCowClusterOp) { + } else if (GetCowOpSourceInfoType(op) == kCowClusterOp) { os << ", cluster_data:" << (op.source_info & kCowOpSourceInfoDataMask); } else { os << ", label:0x" << android::base::StringPrintf("%" PRIx64, op.source_info); @@ -120,7 +123,7 @@ int64_t GetNextDataOffset(const CowOperationV2& op, uint32_t cluster_ops) { } bool IsMetadataOp(const CowOperation& op) { - switch (op.type) { + switch (GetCowOpSourceInfoType(op)) { case kCowLabelOp: case kCowClusterOp: case kCowFooterOp: @@ -132,7 +135,7 @@ bool IsMetadataOp(const CowOperation& op) { } bool IsOrderedOp(const CowOperation& op) { - switch (op.type) { + switch (GetCowOpSourceInfoType(op)) { case kCowCopyOp: case kCowXorOp: return true; diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp index 85fd4c37b..c52705ca8 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -110,7 +111,7 @@ bool CowReader::Parse(android::base::borrowed_fd fd, std::optional lab const auto& v2_op = parser.ops()->at(i); auto& new_op = ops_->at(i); - new_op.type = v2_op.type; + SetCowOpSourceInfoType(&new_op, v2_op.type); new_op.data_length = v2_op.data_length; if (v2_op.new_block > std::numeric_limits::max()) { @@ -120,7 +121,7 @@ bool CowReader::Parse(android::base::borrowed_fd fd, std::optional lab new_op.new_block = v2_op.new_block; uint64_t source_info = v2_op.source; - if (new_op.type != kCowLabelOp) { + if (GetCowOpSourceInfoType(new_op) != kCowLabelOp) { source_info &= kCowOpSourceInfoDataMask; if (source_info != v2_op.source) { LOG(ERROR) << "Out-of-range source value in COW op: " << v2_op; @@ -137,7 +138,7 @@ bool CowReader::Parse(android::base::borrowed_fd fd, std::optional lab return false; } } - new_op.source_info = source_info; + new_op.source_info |= source_info; } // If we're resuming a write, we're not ready to merge @@ -260,7 +261,7 @@ bool CowReader::PrepMergeOps() { for (size_t i = 0; i < ops_->size(); i++) { auto& current_op = ops_->data()[i]; - if (current_op.type == kCowSequenceOp) { + if (GetCowOpSourceInfoType(current_op) == kCowSequenceOp) { size_t seq_len = current_op.data_length / sizeof(uint32_t); merge_op_blocks->resize(merge_op_blocks->size() + seq_len); @@ -572,7 +573,7 @@ std::unique_ptr CowReader::GetMergeOpIter(bool ignore_progress) { } bool CowReader::GetRawBytes(const CowOperation* op, void* buffer, size_t len, size_t* read) { - switch (op->type) { + switch (GetCowOpSourceInfoType(*op)) { case kCowSequenceOp: case kCowReplaceOp: case kCowXorOp: @@ -665,7 +666,7 @@ ssize_t CowReader::ReadData(const CowOperation* op, void* buffer, size_t buffer_ } uint64_t offset; - if (op->type == kCowXorOp) { + if (GetCowOpSourceInfoType(*op) == kCowXorOp) { offset = data_loc_->at(op->new_block); } else { offset = GetCowOpSourceInfoData(*op); @@ -682,7 +683,7 @@ ssize_t CowReader::ReadData(const CowOperation* op, void* buffer, size_t buffer_ } bool CowReader::GetSourceOffset(const CowOperation* op, uint64_t* source_offset) { - switch (op->type) { + switch (GetCowOpSourceInfoType(*op)) { case kCowCopyOp: *source_offset = GetCowOpSourceInfoData(*op) * header_.block_size; return true; diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp index 83b5a1295..aaaf20c2f 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "parser_v2.h" @@ -198,7 +199,7 @@ static bool Inspect(const std::string& path) { if (!FLAGS_silent && FLAGS_show_ops) std::cout << *op << "\n"; - if ((FLAGS_decompress || extract_to >= 0) && op->type == kCowReplaceOp) { + if ((FLAGS_decompress || extract_to >= 0) && GetCowOpSourceInfoType(*op) == kCowReplaceOp) { if (reader.ReadData(op, buffer.data(), buffer.size()) < 0) { std::cerr << "Failed to decompress for :" << *op << "\n"; success = false; @@ -212,12 +213,13 @@ static bool Inspect(const std::string& path) { return false; } } - } else if (extract_to >= 0 && !IsMetadataOp(*op) && op->type != kCowZeroOp) { + } else if (extract_to >= 0 && !IsMetadataOp(*op) && + GetCowOpSourceInfoType(*op) != kCowZeroOp) { PLOG(ERROR) << "Cannot extract op yet: " << *op; return false; } - if (op->type == kCowSequenceOp && FLAGS_show_merge_sequence) { + if (GetCowOpSourceInfoType(*op) == kCowSequenceOp && FLAGS_show_merge_sequence) { size_t read; std::vector merge_op_blocks; size_t seq_len = op->data_length / sizeof(uint32_t); @@ -235,13 +237,13 @@ static bool Inspect(const std::string& path) { } } - if (op->type == kCowCopyOp) { + if (GetCowOpSourceInfoType(*op) == kCowCopyOp) { copy_ops++; - } else if (op->type == kCowReplaceOp) { + } else if (GetCowOpSourceInfoType(*op) == kCowReplaceOp) { replace_ops++; - } else if (op->type == kCowZeroOp) { + } else if (GetCowOpSourceInfoType(*op) == kCowZeroOp) { zero_ops++; - } else if (op->type == kCowXorOp) { + } else if (GetCowOpSourceInfoType(*op) == kCowXorOp) { xor_ops++; } diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp index a3e40d962..d7ee432f4 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp @@ -147,7 +147,7 @@ ssize_t CompressedSnapshotReader::ReadBlock(uint64_t chunk, size_t start_offset, op = ops_[chunk]; } - if (!op || op->type == kCowCopyOp) { + if (!op || GetCowOpSourceInfoType(*op) == kCowCopyOp) { borrowed_fd fd = GetSourceFd(); if (fd < 0) { // GetSourceFd sets errno. @@ -169,15 +169,15 @@ ssize_t CompressedSnapshotReader::ReadBlock(uint64_t chunk, size_t start_offset, // ReadFullyAtOffset sets errno. return -1; } - } else if (op->type == kCowZeroOp) { + } else if (GetCowOpSourceInfoType(*op) == kCowZeroOp) { memset(buffer, 0, bytes_to_read); - } else if (op->type == kCowReplaceOp) { + } else if (GetCowOpSourceInfoType(*op) == kCowReplaceOp) { 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; } - } else if (op->type == kCowXorOp) { + } else if (GetCowOpSourceInfoType(*op) == kCowXorOp) { borrowed_fd fd = GetSourceFd(); if (fd < 0) { // GetSourceFd sets errno. @@ -208,7 +208,8 @@ ssize_t CompressedSnapshotReader::ReadBlock(uint64_t chunk, size_t start_offset, ((char*)buffer)[i] ^= data[i]; } } else { - LOG(ERROR) << "CompressedSnapshotReader unknown op type: " << uint32_t(op->type); + LOG(ERROR) << "CompressedSnapshotReader unknown op type: " + << uint32_t(GetCowOpSourceInfoType(*op)); errno = EINVAL; return -1; } diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp index 35d74bac0..d9628758e 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp @@ -25,6 +25,7 @@ #include #include #include "cow_decompress.h" +#include "libsnapshot/cow_format.h" #include "writer_v2.h" using android::base::unique_fd; @@ -85,7 +86,7 @@ TEST_F(CowTest, CopyContiguous) { size_t i = 0; while (!iter->AtEnd()) { auto op = iter->Get(); - ASSERT_EQ(op->type, kCowCopyOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowCopyOp); ASSERT_EQ(op->data_length, 0); ASSERT_EQ(op->new_block, 10 + i); ASSERT_EQ(GetCowOpSourceInfoData(*op), 1000 + i); @@ -131,7 +132,7 @@ TEST_F(CowTest, ReadWrite) { ASSERT_FALSE(iter->AtEnd()); auto op = iter->Get(); - ASSERT_EQ(op->type, kCowCopyOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowCopyOp); ASSERT_EQ(op->data_length, 0); ASSERT_EQ(op->new_block, 10); ASSERT_EQ(GetCowOpSourceInfoData(*op), 20); @@ -142,7 +143,7 @@ TEST_F(CowTest, ReadWrite) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowReplaceOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowReplaceOp); ASSERT_EQ(op->data_length, 4096); ASSERT_EQ(op->new_block, 50); ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); @@ -153,7 +154,7 @@ TEST_F(CowTest, ReadWrite) { op = iter->Get(); // Note: the zero operation gets split into two blocks. - ASSERT_EQ(op->type, kCowZeroOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowZeroOp); ASSERT_EQ(op->data_length, 0); ASSERT_EQ(op->new_block, 51); ASSERT_EQ(GetCowOpSourceInfoData(*op), 0); @@ -162,7 +163,7 @@ TEST_F(CowTest, ReadWrite) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowZeroOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowZeroOp); ASSERT_EQ(op->data_length, 0); ASSERT_EQ(op->new_block, 52); ASSERT_EQ(GetCowOpSourceInfoData(*op), 0); @@ -206,7 +207,7 @@ TEST_F(CowTest, ReadWriteXor) { ASSERT_FALSE(iter->AtEnd()); auto op = iter->Get(); - ASSERT_EQ(op->type, kCowCopyOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowCopyOp); ASSERT_EQ(op->data_length, 0); ASSERT_EQ(op->new_block, 10); ASSERT_EQ(GetCowOpSourceInfoData(*op), 20); @@ -217,7 +218,7 @@ TEST_F(CowTest, ReadWriteXor) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowXorOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowXorOp); ASSERT_EQ(op->data_length, 4096); ASSERT_EQ(op->new_block, 50); ASSERT_EQ(GetCowOpSourceInfoData(*op), 98314); // 4096 * 24 + 10 @@ -229,7 +230,7 @@ TEST_F(CowTest, ReadWriteXor) { op = iter->Get(); // Note: the zero operation gets split into two blocks. - ASSERT_EQ(op->type, kCowZeroOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowZeroOp); ASSERT_EQ(op->data_length, 0); ASSERT_EQ(op->new_block, 51); ASSERT_EQ(GetCowOpSourceInfoData(*op), 0); @@ -238,7 +239,7 @@ TEST_F(CowTest, ReadWriteXor) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowZeroOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowZeroOp); ASSERT_EQ(op->data_length, 0); ASSERT_EQ(op->new_block, 52); ASSERT_EQ(GetCowOpSourceInfoData(*op), 0); @@ -273,7 +274,7 @@ TEST_F(CowTest, CompressGz) { std::string sink(data.size(), '\0'); - ASSERT_EQ(op->type, kCowReplaceOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowReplaceOp); ASSERT_EQ(op->data_length, 56); // compressed! ASSERT_EQ(op->new_block, 50); ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); @@ -325,7 +326,7 @@ TEST_P(CompressionTest, ThreadedBatchWrites) { while (!iter->AtEnd()) { auto op = iter->Get(); - if (op->type == kCowXorOp) { + if (GetCowOpSourceInfoType(*op) == kCowXorOp) { total_blocks += 1; std::string sink(xor_data.size(), '\0'); ASSERT_EQ(op->new_block, 50); @@ -334,7 +335,7 @@ TEST_P(CompressionTest, ThreadedBatchWrites) { ASSERT_EQ(sink, xor_data); } - if (op->type == kCowReplaceOp) { + if (GetCowOpSourceInfoType(*op) == kCowReplaceOp) { total_blocks += 1; if (op->new_block == 100) { data.resize(options.block_size); @@ -399,7 +400,7 @@ TEST_P(CompressionTest, NoBatchWrites) { while (!iter->AtEnd()) { auto op = iter->Get(); - if (op->type == kCowReplaceOp) { + if (GetCowOpSourceInfoType(*op) == kCowReplaceOp) { total_blocks += 1; if (op->new_block == 50) { data.resize(options.block_size); @@ -519,7 +520,7 @@ TEST_F(CowTest, ClusterCompressGz) { std::string sink(data.size(), '\0'); - ASSERT_EQ(op->type, kCowReplaceOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowReplaceOp); ASSERT_EQ(op->data_length, 56); // compressed! ASSERT_EQ(op->new_block, 50); ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); @@ -529,7 +530,7 @@ TEST_F(CowTest, ClusterCompressGz) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowClusterOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowClusterOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); @@ -546,7 +547,7 @@ TEST_F(CowTest, ClusterCompressGz) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowClusterOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowClusterOp); iter->Next(); ASSERT_TRUE(iter->AtEnd()); @@ -580,7 +581,7 @@ TEST_F(CowTest, CompressTwoBlocks) { std::string sink(options.block_size, '\0'); auto op = iter->Get(); - ASSERT_EQ(op->type, kCowReplaceOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowReplaceOp); ASSERT_EQ(op->new_block, 51); ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); } @@ -653,7 +654,7 @@ TEST_F(CowTest, AppendLabelSmall) { ASSERT_FALSE(iter->AtEnd()); auto op = iter->Get(); - ASSERT_EQ(op->type, kCowReplaceOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowReplaceOp); ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data); @@ -663,14 +664,14 @@ TEST_F(CowTest, AppendLabelSmall) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowLabelOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowLabelOp); ASSERT_EQ(GetCowOpSourceInfoData(*op), 3); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowReplaceOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowReplaceOp); ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data2); @@ -716,14 +717,14 @@ TEST_F(CowTest, AppendLabelMissing) { ASSERT_FALSE(iter->AtEnd()); auto op = iter->Get(); - ASSERT_EQ(op->type, kCowLabelOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowLabelOp); ASSERT_EQ(GetCowOpSourceInfoData(*op), 0); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowZeroOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowZeroOp); iter->Next(); @@ -774,7 +775,7 @@ TEST_F(CowTest, AppendExtendedCorrupted) { ASSERT_FALSE(iter->AtEnd()); auto op = iter->Get(); - ASSERT_EQ(op->type, kCowLabelOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowLabelOp); ASSERT_EQ(GetCowOpSourceInfoData(*op), 5); iter->Next(); @@ -825,7 +826,7 @@ TEST_F(CowTest, AppendbyLabel) { ASSERT_FALSE(iter->AtEnd()); auto op = iter->Get(); - ASSERT_EQ(op->type, kCowReplaceOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowReplaceOp); ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data.substr(0, options.block_size)); @@ -835,7 +836,7 @@ TEST_F(CowTest, AppendbyLabel) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowReplaceOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowReplaceOp); ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data.substr(options.block_size, 2 * options.block_size)); @@ -843,25 +844,25 @@ TEST_F(CowTest, AppendbyLabel) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowLabelOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowLabelOp); ASSERT_EQ(GetCowOpSourceInfoData(*op), 4); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowZeroOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowZeroOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowZeroOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowZeroOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowLabelOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowLabelOp); ASSERT_EQ(GetCowOpSourceInfoData(*op), 5); iter->Next(); @@ -906,7 +907,7 @@ TEST_F(CowTest, ClusterTest) { ASSERT_FALSE(iter->AtEnd()); auto op = iter->Get(); - ASSERT_EQ(op->type, kCowReplaceOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowReplaceOp); ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data.substr(0, options.block_size)); @@ -914,51 +915,51 @@ TEST_F(CowTest, ClusterTest) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowLabelOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowLabelOp); ASSERT_EQ(GetCowOpSourceInfoData(*op), 4); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowZeroOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowZeroOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowClusterOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowClusterOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowZeroOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowZeroOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowLabelOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowLabelOp); ASSERT_EQ(GetCowOpSourceInfoData(*op), 5); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowCopyOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowCopyOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowClusterOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowClusterOp); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowLabelOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowLabelOp); ASSERT_EQ(GetCowOpSourceInfoData(*op), 6); iter->Next(); @@ -1005,14 +1006,14 @@ TEST_F(CowTest, ClusterAppendTest) { ASSERT_FALSE(iter->AtEnd()); auto op = iter->Get(); - ASSERT_EQ(op->type, kCowLabelOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowLabelOp); ASSERT_EQ(GetCowOpSourceInfoData(*op), 50); iter->Next(); ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowReplaceOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowReplaceOp); ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size())); ASSERT_EQ(sink, data2); @@ -1020,7 +1021,7 @@ TEST_F(CowTest, ClusterAppendTest) { ASSERT_FALSE(iter->AtEnd()); op = iter->Get(); - ASSERT_EQ(op->type, kCowClusterOp); + ASSERT_EQ(GetCowOpSourceInfoType(*op), kCowClusterOp); iter->Next(); @@ -1117,12 +1118,12 @@ TEST_F(CowTest, ResumeMidCluster) { num_in_cluster++; max_in_cluster = std::max(max_in_cluster, num_in_cluster); - if (op->type == kCowReplaceOp) { + if (GetCowOpSourceInfoType(*op) == kCowReplaceOp) { 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 (GetCowOpSourceInfoType(*op) == kCowClusterOp) { num_in_cluster = 0; num_clusters++; } @@ -1178,12 +1179,12 @@ TEST_F(CowTest, ResumeEndCluster) { num_in_cluster++; max_in_cluster = std::max(max_in_cluster, num_in_cluster); - if (op->type == kCowReplaceOp) { + if (GetCowOpSourceInfoType(*op) == kCowReplaceOp) { 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 (GetCowOpSourceInfoType(*op) == kCowClusterOp) { num_in_cluster = 0; num_clusters++; } @@ -1229,12 +1230,12 @@ TEST_F(CowTest, DeleteMidCluster) { num_in_cluster++; max_in_cluster = std::max(max_in_cluster, num_in_cluster); - if (op->type == kCowReplaceOp) { + if (GetCowOpSourceInfoType(*op) == kCowReplaceOp) { 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 (GetCowOpSourceInfoType(*op) == kCowClusterOp) { num_in_cluster = 0; num_clusters++; } diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp index 2373d4df5..a4d617f26 100644 --- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp +++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp @@ -49,5 +49,14 @@ class CowOperationV3Test : public ::testing::Test { std::unique_ptr cow_; }; +TEST_F(CowOperationV3Test, CowTypeTest) { + CowOperationV3 new_op; + CowOperationV2 old_op; + old_op.type = kCowReplaceOp; + ASSERT_NE(GetCowOpSourceInfoType(new_op), old_op.type); + SetCowOpSourceInfoType(&new_op, old_op.type); + ASSERT_EQ(GetCowOpSourceInfoType(new_op), old_op.type); +} + } // namespace snapshot } // namespace android \ No newline at end of file diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp index 6dc082e86..0be6ff518 100644 --- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp +++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp @@ -25,6 +25,7 @@ #include #include #include +#include "libsnapshot/cow_format.h" #include #include @@ -406,9 +407,9 @@ bool Snapuserd::ReadMetadata() { break; } - if (cow_op->type == kCowReplaceOp) { + if (GetCowOpSourceInfoType(*cow_op) == kCowReplaceOp) { replace_ops++; - } else if (cow_op->type == kCowZeroOp) { + } else if (GetCowOpSourceInfoType(*cow_op) == kCowZeroOp) { zero_ops++; } @@ -540,7 +541,7 @@ bool Snapuserd::ReadMetadata() { chunk_vec_.push_back(std::make_pair(ChunkToSector(data_chunk_id), cow_op)); offset += sizeof(struct disk_exception); num_ops += 1; - if (cow_op->type == kCowCopyOp) { + if (GetCowOpSourceInfoType(*cow_op) == kCowCopyOp) { copy_ops++; } diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp index ab0b3094b..b2a4f2c8f 100644 --- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp +++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "libsnapshot/cow_format.h" #include "snapuserd.h" #include @@ -192,7 +193,7 @@ void ReadAheadThread::PrepareReadAhead(uint64_t* source_offset, int* pending_ops const CowOperation* cow_op = GetRAOpIter(); CHECK_NE(cow_op, nullptr); *source_offset = GetCowOpSourceInfoData(*cow_op); - if (cow_op->type == kCowCopyOp) { + if (GetCowOpSourceInfoData(*cow_op) == kCowCopyOp) { *source_offset *= BLOCK_SZ; } RAIterNext(); @@ -211,7 +212,7 @@ void ReadAheadThread::PrepareReadAhead(uint64_t* source_offset, int* pending_ops const CowOperation* op = GetRAOpIter(); CHECK_NE(op, nullptr); uint64_t next_offset = GetCowOpSourceInfoData(*op); - if (op->type == kCowCopyOp) { + if (GetCowOpSourceInfoData(*op) == kCowCopyOp) { next_offset *= BLOCK_SZ; } if (next_offset + nr_consecutive * BLOCK_SZ != *source_offset) { 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 571b35238..0930a5d9c 100644 --- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp +++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "libsnapshot/cow_format.h" #include "snapuserd.h" #include @@ -177,7 +178,7 @@ bool WorkerThread::ProcessCowOp(const CowOperation* cow_op) { return false; } - switch (cow_op->type) { + switch (GetCowOpSourceInfoType(*cow_op)) { case kCowReplaceOp: { return ProcessReplaceOp(cow_op); } @@ -191,7 +192,8 @@ bool WorkerThread::ProcessCowOp(const CowOperation* cow_op) { } default: { - SNAP_LOG(ERROR) << "Unsupported operation-type found: " << cow_op->type; + SNAP_LOG(ERROR) << "Unsupported operation-type found: " + << GetCowOpSourceInfoType(*cow_op); } } return false; diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp index 11b8d7c92..d06ba588f 100644 --- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp +++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp @@ -17,6 +17,7 @@ #include +#include "libsnapshot/cow_format.h" #include "snapuserd_core.h" #include "utility.h" @@ -114,13 +115,13 @@ bool MergeWorker::MergeReplaceZeroOps() { SNAP_LOG(ERROR) << "AcquireBuffer failed in MergeReplaceOps"; return false; } - if (cow_op->type == kCowReplaceOp) { + if (GetCowOpSourceInfoType(*cow_op) == kCowReplaceOp) { if (!reader_->ReadData(cow_op, buffer, BLOCK_SZ)) { SNAP_LOG(ERROR) << "Failed to read COW in merge"; return false; } } else { - CHECK(cow_op->type == kCowZeroOp); + CHECK(GetCowOpSourceInfoType(*cow_op) == kCowZeroOp); memset(buffer, 0, BLOCK_SZ); } } diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/read_worker.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/read_worker.cpp index 5cb13e8bc..ffa23ead4 100644 --- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/read_worker.cpp +++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/read_worker.cpp @@ -18,6 +18,7 @@ #include +#include "libsnapshot/cow_format.h" #include "snapuserd_core.h" #include "utility.h" @@ -63,7 +64,7 @@ bool ReadWorker::ReadFromSourceDevice(const CowOperation* cow_op, void* buffer) << " Op: " << *cow_op; if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SZ, offset)) { std::string op; - if (cow_op->type == kCowCopyOp) + if (GetCowOpSourceInfoType(*cow_op) == kCowCopyOp) op = "Copy-op"; else { op = "Xor-op"; @@ -133,7 +134,7 @@ bool ReadWorker::ProcessOrderedOp(const CowOperation* cow_op, void* buffer) { } case MERGE_GROUP_STATE::GROUP_MERGE_PENDING: { bool ret; - if (cow_op->type == kCowCopyOp) { + if (GetCowOpSourceInfoType(*cow_op) == kCowCopyOp) { ret = ProcessCopyOp(cow_op, buffer); } else { ret = ProcessXorOp(cow_op, buffer); @@ -167,7 +168,7 @@ bool ReadWorker::ProcessCowOp(const CowOperation* cow_op, void* buffer) { return false; } - switch (cow_op->type) { + switch (GetCowOpSourceInfoType(*cow_op)) { case kCowReplaceOp: { return ProcessReplaceOp(cow_op, buffer); } @@ -183,7 +184,7 @@ bool ReadWorker::ProcessCowOp(const CowOperation* cow_op, void* buffer) { } default: { - SNAP_LOG(ERROR) << "Unknown operation-type found: " << cow_op->type; + SNAP_LOG(ERROR) << "Unknown operation-type found: " << GetCowOpSourceInfoType(*cow_op); } } return false; 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 e886ec399..536ff2f63 100644 --- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp +++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp @@ -24,6 +24,7 @@ #include #include +#include "libsnapshot/cow_format.h" #include "merge_worker.h" #include "read_worker.h" @@ -196,13 +197,13 @@ bool SnapshotHandler::ReadMetadata() { while (!cowop_iter->AtEnd()) { const CowOperation* cow_op = cowop_iter->Get(); - if (cow_op->type == kCowCopyOp) { + if (GetCowOpSourceInfoType(*cow_op) == kCowCopyOp) { copy_ops += 1; - } else if (cow_op->type == kCowReplaceOp) { + } else if (GetCowOpSourceInfoType(*cow_op) == kCowReplaceOp) { replace_ops += 1; - } else if (cow_op->type == kCowZeroOp) { + } else if (GetCowOpSourceInfoType(*cow_op) == kCowZeroOp) { zero_ops += 1; - } else if (cow_op->type == kCowXorOp) { + } else if (GetCowOpSourceInfoType(*cow_op) == kCowXorOp) { xor_ops += 1; } 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 998d233d5..d7d43a6a0 100644 --- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp +++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp @@ -18,6 +18,7 @@ #include +#include "libsnapshot/cow_format.h" #include "snapuserd_core.h" #include "utility.h" @@ -77,7 +78,7 @@ int ReadAhead::PrepareNextReadAhead(uint64_t* source_offset, int* pending_ops, SNAP_LOG(ERROR) << "PrepareNextReadAhead operation has no source offset: " << *cow_op; return nr_consecutive; } - if (cow_op->type == kCowXorOp) { + if (GetCowOpSourceInfoType(*cow_op) == kCowXorOp) { xor_op_vec.push_back(cow_op); } @@ -106,7 +107,7 @@ int ReadAhead::PrepareNextReadAhead(uint64_t* source_offset, int* pending_ops, break; } - if (op->type == kCowXorOp) { + if (GetCowOpSourceInfoType(*op) == kCowXorOp) { xor_op_vec.push_back(op); }