Loading fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp +15 −10 Original line number Diff line number Diff line // Copyright (C) 2023 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, Loading @@ -15,6 +8,7 @@ #include <sys/stat.h> #include <cstdio> #include <limits> #include <memory> #include <android-base/file.h> Loading Loading @@ -513,19 +507,24 @@ TEST_F(CowTestV3, BufferMetadataSyncTest) { TEST_F(CowTestV3, SequenceTest) { CowOptions options; options.op_count_max = std::numeric_limits<uint32_t>::max(); constexpr int seq_len = std::numeric_limits<uint16_t>::max() / sizeof(uint32_t) + 1; options.op_count_max = seq_len; auto writer = CreateCowWriter(3, options, GetCowFd()); // sequence data. This just an arbitrary set of integers that specify the merge order. The // actual calculation is done by update_engine and passed to writer. All we care about here is // writing that data correctly const int seq_len = std::numeric_limits<uint16_t>::max() / sizeof(uint32_t) + 1; uint32_t sequence[seq_len]; for (int i = 0; i < seq_len; i++) { sequence[i] = i + 1; } ASSERT_TRUE(writer->AddSequenceData(seq_len, sequence)); ASSERT_TRUE(writer->AddZeroBlocks(1, seq_len)); ASSERT_TRUE(writer->AddZeroBlocks(1, seq_len - 1)); std::vector<uint8_t> data(writer->GetBlockSize()); for (size_t i = 0; i < data.size(); i++) { data[i] = static_cast<uint8_t>(i & 0xFF); } ASSERT_TRUE(writer->AddRawBlocks(seq_len, data.data(), data.size())); ASSERT_TRUE(writer->Finalize()); ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0); Loading @@ -539,6 +538,12 @@ TEST_F(CowTestV3, SequenceTest) { const auto& op = iter->Get(); ASSERT_EQ(op->new_block, seq_len - i); if (op->new_block == seq_len) { std::vector<uint8_t> read_back(writer->GetBlockSize()); ASSERT_EQ(reader.ReadData(op, read_back.data(), read_back.size()), static_cast<ssize_t>(read_back.size())); ASSERT_EQ(read_back, data); } iter->Next(); } Loading fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -382,7 +382,20 @@ bool CowWriterV3::EmitLabel(uint64_t label) { bool CowWriterV3::EmitSequenceData(size_t num_ops, const uint32_t* data) { // TODO: size sequence buffer based on options if (header_.op_count > 0) { LOG(ERROR) << "There's " << header_.op_count << " operations written to disk. Writing sequence data is only allowed before all " "operation writes."; return false; } header_.sequence_data_count = num_ops; // In COW format v3, data section is placed after op section and sequence // data section. Therefore, changing the sequence data count has the effect // of moving op section and data section. Therefore we need to reset the // value of |next_data_pos|. This is also the reason why writing sequence // data is only allowed if there's no operation written. next_data_pos_ = GetDataOffset(header_); if (!android::base::WriteFullyAtOffset(fd_, data, sizeof(data[0]) * num_ops, GetSequenceOffset(header_))) { PLOG(ERROR) << "writing sequence buffer failed"; Loading Loading
fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp +15 −10 Original line number Diff line number Diff line // Copyright (C) 2023 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, Loading @@ -15,6 +8,7 @@ #include <sys/stat.h> #include <cstdio> #include <limits> #include <memory> #include <android-base/file.h> Loading Loading @@ -513,19 +507,24 @@ TEST_F(CowTestV3, BufferMetadataSyncTest) { TEST_F(CowTestV3, SequenceTest) { CowOptions options; options.op_count_max = std::numeric_limits<uint32_t>::max(); constexpr int seq_len = std::numeric_limits<uint16_t>::max() / sizeof(uint32_t) + 1; options.op_count_max = seq_len; auto writer = CreateCowWriter(3, options, GetCowFd()); // sequence data. This just an arbitrary set of integers that specify the merge order. The // actual calculation is done by update_engine and passed to writer. All we care about here is // writing that data correctly const int seq_len = std::numeric_limits<uint16_t>::max() / sizeof(uint32_t) + 1; uint32_t sequence[seq_len]; for (int i = 0; i < seq_len; i++) { sequence[i] = i + 1; } ASSERT_TRUE(writer->AddSequenceData(seq_len, sequence)); ASSERT_TRUE(writer->AddZeroBlocks(1, seq_len)); ASSERT_TRUE(writer->AddZeroBlocks(1, seq_len - 1)); std::vector<uint8_t> data(writer->GetBlockSize()); for (size_t i = 0; i < data.size(); i++) { data[i] = static_cast<uint8_t>(i & 0xFF); } ASSERT_TRUE(writer->AddRawBlocks(seq_len, data.data(), data.size())); ASSERT_TRUE(writer->Finalize()); ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0); Loading @@ -539,6 +538,12 @@ TEST_F(CowTestV3, SequenceTest) { const auto& op = iter->Get(); ASSERT_EQ(op->new_block, seq_len - i); if (op->new_block == seq_len) { std::vector<uint8_t> read_back(writer->GetBlockSize()); ASSERT_EQ(reader.ReadData(op, read_back.data(), read_back.size()), static_cast<ssize_t>(read_back.size())); ASSERT_EQ(read_back, data); } iter->Next(); } Loading
fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -382,7 +382,20 @@ bool CowWriterV3::EmitLabel(uint64_t label) { bool CowWriterV3::EmitSequenceData(size_t num_ops, const uint32_t* data) { // TODO: size sequence buffer based on options if (header_.op_count > 0) { LOG(ERROR) << "There's " << header_.op_count << " operations written to disk. Writing sequence data is only allowed before all " "operation writes."; return false; } header_.sequence_data_count = num_ops; // In COW format v3, data section is placed after op section and sequence // data section. Therefore, changing the sequence data count has the effect // of moving op section and data section. Therefore we need to reset the // value of |next_data_pos|. This is also the reason why writing sequence // data is only allowed if there's no operation written. next_data_pos_ = GetDataOffset(header_); if (!android::base::WriteFullyAtOffset(fd_, data, sizeof(data[0]) * num_ops, GetSequenceOffset(header_))) { PLOG(ERROR) << "writing sequence buffer failed"; Loading