From edf7c667dabb0c038c062fb7cfc1af378435907c Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Mon, 12 Jul 2021 21:41:23 -0700 Subject: [PATCH] snapuserd: Add XorSink We can compute the xor while decompessing by computing it within a buffer. This would allow us to use a smaller buffer than the full block size if we wish to cut down on the extra memory required. Bug: 177104308 Test: cow_snapuserd_test (Snapuserd_Test.xor_buffer) Change-Id: Id18505841c77340760cea2d20e83454f1142b9b5 --- .../snapuserd/cow_snapuserd_test.cpp | 29 ++++++++++++++++ fs_mgr/libsnapshot/snapuserd/snapuserd.h | 14 ++++++++ .../snapuserd/snapuserd_worker.cpp | 33 +++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/fs_mgr/libsnapshot/snapuserd/cow_snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/cow_snapuserd_test.cpp index a71832832..c663d86ef 100644 --- a/fs_mgr/libsnapshot/snapuserd/cow_snapuserd_test.cpp +++ b/fs_mgr/libsnapshot/snapuserd/cow_snapuserd_test.cpp @@ -1039,6 +1039,35 @@ void CowSnapuserdMetadataTest::ValidateMetadata() { } } +TEST(Snapuserd_Test, xor_buffer) { + std::string data = "Test String"; + std::string jumbled = {0x0C, 0x2A, 0x21, 0x54, 0x73, 0x27, 0x06, 0x1B, 0x07, 0x09, 0x46}; + std::string result = "XOR String!"; + + BufferSink sink; + XorSink xor_sink; + sink.Initialize(sizeof(struct dm_user_header) + 10); + int buffsize = 5; + xor_sink.Initialize(&sink, buffsize); + + void* buff = sink.GetPayloadBuffer(data.length()); + memcpy(buff, data.data(), data.length()); + + size_t actual; + size_t count = 0; + while (count < data.length()) { + void* xor_buff = xor_sink.GetBuffer(10, &actual); + ASSERT_EQ(actual, buffsize); + ASSERT_NE(xor_buff, nullptr); + memcpy(xor_buff, jumbled.data() + count, buffsize); + xor_sink.ReturnData(xor_buff, actual); + count += actual; + } + + std::string answer = reinterpret_cast(sink.GetPayloadBufPtr()); + ASSERT_EQ(answer, result); +} + TEST(Snapuserd_Test, Snapshot_Metadata) { CowSnapuserdMetadataTest harness; harness.Setup(); diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd.h b/fs_mgr/libsnapshot/snapuserd/snapuserd.h index 3cb5ee2a8..6814a983b 100644 --- a/fs_mgr/libsnapshot/snapuserd/snapuserd.h +++ b/fs_mgr/libsnapshot/snapuserd/snapuserd.h @@ -107,6 +107,20 @@ class BufferSink : public IByteSink { size_t buffer_size_; }; +class XorSink : public IByteSink { + public: + void Initialize(BufferSink* sink, size_t size); + void Reset(); + void* GetBuffer(size_t requested, size_t* actual) override; + bool ReturnData(void* buffer, size_t len) override; + + private: + BufferSink* bufsink_; + std::unique_ptr buffer_; + size_t buffer_size_; + size_t returned_; +}; + class Snapuserd; class ReadAheadThread { diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd_worker.cpp b/fs_mgr/libsnapshot/snapuserd/snapuserd_worker.cpp index d515f648a..ffb19b17b 100644 --- a/fs_mgr/libsnapshot/snapuserd/snapuserd_worker.cpp +++ b/fs_mgr/libsnapshot/snapuserd/snapuserd_worker.cpp @@ -71,6 +71,39 @@ void* BufferSink::GetPayloadBufPtr() { return msg->payload.buf; } +void XorSink::Initialize(BufferSink* sink, size_t size) { + bufsink_ = sink; + buffer_size_ = size; + returned_ = 0; + buffer_ = std::make_unique(size); +} + +void XorSink::Reset() { + returned_ = 0; +} + +void* XorSink::GetBuffer(size_t requested, size_t* actual) { + if (requested > buffer_size_) { + *actual = buffer_size_; + } else { + *actual = requested; + } + return buffer_.get(); +} + +bool XorSink::ReturnData(void* buffer, size_t len) { + uint8_t* xor_data = reinterpret_cast(buffer); + uint8_t* buff = reinterpret_cast(bufsink_->GetPayloadBuffer(len + returned_)); + if (buff == nullptr) { + return false; + } + for (size_t i = 0; i < len; i++) { + buff[returned_ + i] ^= xor_data[i]; + } + returned_ += len; + return true; +} + WorkerThread::WorkerThread(const std::string& cow_device, const std::string& backing_device, const std::string& control_device, const std::string& misc_name, std::shared_ptr snapuserd) {