Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit edf7c667 authored by Daniel Rosenberg's avatar Daniel Rosenberg
Browse files

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
parent d091522d
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -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<char*>(sink.GetPayloadBufPtr());
    ASSERT_EQ(answer, result);
}

TEST(Snapuserd_Test, Snapshot_Metadata) {
    CowSnapuserdMetadataTest harness;
    harness.Setup();
+14 −0
Original line number Diff line number Diff line
@@ -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<uint8_t[]> buffer_;
    size_t buffer_size_;
    size_t returned_;
};

class Snapuserd;

class ReadAheadThread {
+33 −0
Original line number Diff line number Diff line
@@ -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<uint8_t[]>(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<uint8_t*>(buffer);
    uint8_t* buff = reinterpret_cast<uint8_t*>(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> snapuserd) {