Merge "libsnapshot: Changes to AddCopy() API" am: ad5cc05ca2

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

Change-Id: I3a87da1b2828615261137bea2190b950f00f22ce
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Akilesh Kailash 2022-10-19 21:30:49 +00:00 committed by Automerger Merge Worker
commit d3c48d800c
6 changed files with 92 additions and 26 deletions

View file

@ -52,8 +52,9 @@ class ICowWriter {
virtual ~ICowWriter() {} virtual ~ICowWriter() {}
// Encode an operation that copies the contents of |old_block| to the // Encode an operation that copies the contents of |old_block| to the
// location of |new_block|. // location of |new_block|. 'num_blocks' is the number of contiguous
bool AddCopy(uint64_t new_block, uint64_t old_block); // COPY operations from |old_block| to |new_block|.
bool AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1);
// Encode a sequence of raw blocks. |size| must be a multiple of the block size. // Encode a sequence of raw blocks. |size| must be a multiple of the block size.
bool AddRawBlocks(uint64_t new_block_start, const void* data, size_t size); bool AddRawBlocks(uint64_t new_block_start, const void* data, size_t size);
@ -84,7 +85,7 @@ class ICowWriter {
const CowOptions& options() { return options_; } const CowOptions& options() { return options_; }
protected: protected:
virtual bool EmitCopy(uint64_t new_block, uint64_t old_block) = 0; virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) = 0;
virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) = 0; virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) = 0;
virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
uint32_t old_block, uint16_t offset) = 0; uint32_t old_block, uint16_t offset) = 0;
@ -122,7 +123,7 @@ class CowWriter : public ICowWriter {
uint32_t GetCowVersion() { return header_.major_version; } uint32_t GetCowVersion() { return header_.major_version; }
protected: protected:
virtual bool EmitCopy(uint64_t new_block, uint64_t old_block) override; virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
uint32_t old_block, uint16_t offset) override; uint32_t old_block, uint16_t offset) override;

View file

@ -34,7 +34,7 @@ class MockSnapshotWriter : public ISnapshotWriter {
// Returns true if AddCopy() operations are supported. // Returns true if AddCopy() operations are supported.
MOCK_METHOD(bool, SupportsCopyOperation, (), (const override)); MOCK_METHOD(bool, SupportsCopyOperation, (), (const override));
MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t), (override)); MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t, uint64_t), (override));
MOCK_METHOD(bool, EmitRawBlocks, (uint64_t, const void*, size_t), (override)); MOCK_METHOD(bool, EmitRawBlocks, (uint64_t, const void*, size_t), (override));
MOCK_METHOD(bool, EmitXorBlocks, (uint32_t, const void*, size_t, uint32_t, uint16_t), MOCK_METHOD(bool, EmitXorBlocks, (uint32_t, const void*, size_t, uint32_t, uint16_t),
(override)); (override));

View file

@ -74,7 +74,7 @@ class CompressedSnapshotWriter final : public ISnapshotWriter {
bool VerifyMergeOps() const noexcept; bool VerifyMergeOps() const noexcept;
protected: protected:
bool EmitCopy(uint64_t new_block, uint64_t old_block) override; bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override; bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
uint16_t offset) override; uint16_t offset) override;
@ -113,7 +113,7 @@ class OnlineKernelSnapshotWriter final : public ISnapshotWriter {
bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override; bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block, bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
uint16_t offset) override; uint16_t offset) override;
bool EmitCopy(uint64_t new_block, uint64_t old_block) override; bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
bool EmitLabel(uint64_t label) override; bool EmitLabel(uint64_t label) override;
bool EmitSequenceData(size_t num_ops, const uint32_t* data) override; bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;

View file

@ -62,6 +62,48 @@ class StringSink : public IByteSink {
std::string stream_; std::string stream_;
}; };
TEST_F(CowTest, CopyContiguous) {
CowOptions options;
options.cluster_ops = 0;
CowWriter writer(options);
ASSERT_TRUE(writer.Initialize(cow_->fd));
ASSERT_TRUE(writer.AddCopy(10, 1000, 100));
ASSERT_TRUE(writer.Finalize());
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
CowReader reader;
CowHeader header;
CowFooter footer;
ASSERT_TRUE(reader.Parse(cow_->fd));
ASSERT_TRUE(reader.GetHeader(&header));
ASSERT_TRUE(reader.GetFooter(&footer));
ASSERT_EQ(header.magic, kCowMagicNumber);
ASSERT_EQ(header.major_version, kCowVersionMajor);
ASSERT_EQ(header.minor_version, kCowVersionMinor);
ASSERT_EQ(header.block_size, options.block_size);
ASSERT_EQ(footer.op.num_ops, 100);
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
size_t i = 0;
while (!iter->Done()) {
auto op = &iter->Get();
ASSERT_EQ(op->type, kCowCopyOp);
ASSERT_EQ(op->compression, kCowCompressNone);
ASSERT_EQ(op->data_length, 0);
ASSERT_EQ(op->new_block, 10 + i);
ASSERT_EQ(op->source, 1000 + i);
iter->Next();
i += 1;
}
ASSERT_EQ(i, 100);
}
TEST_F(CowTest, ReadWrite) { TEST_F(CowTest, ReadWrite) {
CowOptions options; CowOptions options;
options.cluster_ops = 0; options.cluster_ops = 0;

View file

@ -38,11 +38,16 @@ static_assert(sizeof(off_t) == sizeof(uint64_t));
using android::base::borrowed_fd; using android::base::borrowed_fd;
using android::base::unique_fd; using android::base::unique_fd;
bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block) { bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
if (!ValidateNewBlock(new_block)) { CHECK(num_blocks != 0);
return false;
for (size_t i = 0; i < num_blocks; i++) {
if (!ValidateNewBlock(new_block + i)) {
return false;
}
} }
return EmitCopy(new_block, old_block);
return EmitCopy(new_block, old_block, num_blocks);
} }
bool ICowWriter::AddRawBlocks(uint64_t new_block_start, const void* data, size_t size) { bool ICowWriter::AddRawBlocks(uint64_t new_block_start, const void* data, size_t size) {
@ -286,13 +291,20 @@ bool CowWriter::OpenForAppend(uint64_t label) {
return EmitClusterIfNeeded(); return EmitClusterIfNeeded();
} }
bool CowWriter::EmitCopy(uint64_t new_block, uint64_t old_block) { bool CowWriter::EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
CHECK(!merge_in_progress_); CHECK(!merge_in_progress_);
CowOperation op = {};
op.type = kCowCopyOp; for (size_t i = 0; i < num_blocks; i++) {
op.new_block = new_block; CowOperation op = {};
op.source = old_block; op.type = kCowCopyOp;
return WriteOperation(op); op.new_block = new_block + i;
op.source = old_block + i;
if (!WriteOperation(op)) {
return false;
}
}
return true;
} }
bool CowWriter::EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) { bool CowWriter::EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) {

View file

@ -111,8 +111,9 @@ std::unique_ptr<FileDescriptor> CompressedSnapshotWriter::OpenReader() {
return reader; return reader;
} }
bool CompressedSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block) { bool CompressedSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block,
return cow_->AddCopy(new_block, old_block); uint64_t num_blocks) {
return cow_->AddCopy(new_block, old_block, num_blocks);
} }
bool CompressedSnapshotWriter::EmitRawBlocks(uint64_t new_block_start, const void* data, bool CompressedSnapshotWriter::EmitRawBlocks(uint64_t new_block_start, const void* data,
@ -191,19 +192,29 @@ bool OnlineKernelSnapshotWriter::EmitZeroBlocks(uint64_t new_block_start, uint64
return true; return true;
} }
bool OnlineKernelSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block) { bool OnlineKernelSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block,
uint64_t num_blocks) {
auto source_fd = GetSourceFd(); auto source_fd = GetSourceFd();
if (source_fd < 0) { if (source_fd < 0) {
return false; return false;
} }
std::string buffer(options_.block_size, 0); CHECK(num_blocks != 0);
uint64_t offset = old_block * options_.block_size;
if (!android::base::ReadFullyAtOffset(source_fd, buffer.data(), buffer.size(), offset)) { for (size_t i = 0; i < num_blocks; i++) {
PLOG(ERROR) << "EmitCopy read"; std::string buffer(options_.block_size, 0);
return false; uint64_t offset = (old_block + i) * options_.block_size;
if (!android::base::ReadFullyAtOffset(source_fd, buffer.data(), buffer.size(), offset)) {
PLOG(ERROR) << "EmitCopy read";
return false;
}
if (!EmitRawBlocks(new_block + i, buffer.data(), buffer.size())) {
PLOG(ERROR) << "EmitRawBlocks failed";
return false;
}
} }
return EmitRawBlocks(new_block, buffer.data(), buffer.size());
return true;
} }
bool OnlineKernelSnapshotWriter::EmitLabel(uint64_t) { bool OnlineKernelSnapshotWriter::EmitLabel(uint64_t) {