Merge changes I7ec850b5,I62aa8c7b am: c274088e5c am: f435ead883

Original change: https://android-review.googlesource.com/c/platform/system/core/+/2573073

Change-Id: I6ecdc6420ee07d4b1ba3801283fe242f06dbc55f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
David Anderson 2023-05-04 04:17:15 +00:00 committed by Automerger Merge Worker
commit eb32ea5f3f
15 changed files with 146 additions and 147 deletions

View file

@ -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:
//

View file

@ -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<ICowOpIter> GetRevMergeOpIter(bool ignore_progress = false) override;
std::unique_ptr<ICowOpIter> 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_; }

View file

@ -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++;

View file

@ -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;
}

View file

@ -508,37 +508,37 @@ bool CowReader::PrepMergeOps() {
bool CowReader::VerifyMergeOps() {
auto itr = GetMergeOpIter(true);
std::unordered_map<uint64_t, CowOperation> overwritten_blocks;
std::unordered_map<uint64_t, const CowOperation*> 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<std::vector<CowOperation>>& 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<std::vector<int>> 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<std::vector<int>> 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<std::vector<CowOperation>> 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<ICowOpIter> 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<IDecompressor> 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);
}

View file

@ -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();
}

View file

@ -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<uint8_t[]>(op.data_length);
auto buffer = std::make_unique<uint8_t[]>(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<uint32_t> 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++;
}

View file

@ -86,7 +86,7 @@ bool CompressedSnapshotReader::SetCow(std::unique_ptr<CowReader>&& 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;

View file

@ -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<struct disk_exception*>((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:
//

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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() {