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

Commit 7a9e007a authored by Daniel Zheng's avatar Daniel Zheng
Browse files

Refactor off COW header v3

Cow reader will store header v3 in memory. ReadCowHeader can remain
mostly unchanged since the cow prefix is the same.
header->prefix.header_size will then tell us if we're reading a v3 or v2
header. v3 header is strictly a superset of v2 header so we can read a
v2 header into a v3 struct.

Added a test case to test_v3 where we write a header using v2_writer and
ensure CowReader is able to read it.

Test: cow_api_test
Change-Id: I142f18d871322930b7dc341c342c8b63a481341c
parent f2270d2b
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -172,7 +172,7 @@ class CowReader final : public ICowReader {

    android::base::unique_fd owned_fd_;
    android::base::borrowed_fd fd_;
    CowHeader header_;
    CowHeaderV3 header_;
    std::optional<CowFooter> footer_;
    uint64_t fd_size_;
    std::optional<uint64_t> last_label_;
@@ -188,7 +188,10 @@ class CowReader final : public ICowReader {
    uint8_t compression_type_ = kCowCompressNone;
};

bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header);
// Though this function takes in a CowHeaderV3, the struct could be populated as a v1/v2 CowHeader.
// The extra fields will just be filled as 0. V3 header is strictly a superset of v1/v2 header and
// contains all of the latter's field
bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header);

}  // namespace snapshot
}  // namespace android
+4 −3
Original line number Diff line number Diff line
@@ -28,12 +28,13 @@
#include <zlib.h>

#include "cow_decompress.h"
#include "libsnapshot/cow_format.h"
#include "parser_v2.h"

namespace android {
namespace snapshot {

bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header) {
bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header) {
    if (lseek(fd.get(), 0, SEEK_SET) < 0) {
        PLOG(ERROR) << "lseek header failed";
        return false;
@@ -49,9 +50,9 @@ bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header) {
                   << "Expected: " << kCowMagicNumber;
        return false;
    }
    if (header->prefix.header_size > sizeof(CowHeader)) {
    if (header->prefix.header_size > sizeof(CowHeaderV3)) {
        LOG(ERROR) << "Unknown CowHeader size (got " << header->prefix.header_size
                   << " bytes, expected at most " << sizeof(CowHeader) << " bytes)";
                   << " bytes, expected at most " << sizeof(CowHeaderV3) << " bytes)";
        return false;
    }

+1 −1
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeader& header) {
}

static bool ShowRawOpStream(borrowed_fd fd) {
    CowHeader header;
    CowHeaderV3 header;
    if (!ReadCowHeader(fd, &header)) {
        LOG(ERROR) << "parse header failed";
        return false;
+24 −0
Original line number Diff line number Diff line
@@ -26,7 +26,9 @@
#include <libsnapshot/cow_writer.h>
#include "cow_decompress.h"
#include "libsnapshot/cow_format.h"
#include "writer_v2.h"
#include "writer_v3.h"

using android::base::unique_fd;
using testing::AssertionFailure;
using testing::AssertionResult;
@@ -49,5 +51,27 @@ class CowOperationV3Test : public ::testing::Test {
    std::unique_ptr<TemporaryFile> cow_;
};

TEST_F(CowOperationV3Test, CowHeaderV2Test) {
    CowOptions options;
    options.cluster_ops = 5;
    options.num_merge_ops = 1;
    options.block_size = 4096;
    std::string data = "This is some data, believe it";
    data.resize(options.block_size, '\0');
    auto writer_v2 = std::make_unique<CowWriterV2>(options, GetCowFd());
    ASSERT_TRUE(writer_v2->Initialize());
    ASSERT_TRUE(writer_v2->Finalize());

    CowReader reader;
    ASSERT_TRUE(reader.Parse(cow_->fd));

    const auto& header = reader.GetHeader();
    ASSERT_EQ(header.prefix.magic, kCowMagicNumber);
    ASSERT_EQ(header.prefix.major_version, kCowVersionMajor);
    ASSERT_EQ(header.prefix.minor_version, kCowVersionMinor);
    ASSERT_EQ(header.block_size, options.block_size);
    ASSERT_EQ(header.cluster_ops, options.cluster_ops);
}

}  // namespace snapshot
}  // namespace android
 No newline at end of file
+3 −1
Original line number Diff line number Diff line
@@ -269,9 +269,11 @@ bool CowWriterV2::OpenForWrite() {
}

bool CowWriterV2::OpenForAppend(uint64_t label) {
    if (!ReadCowHeader(fd_, &header_)) {
    CowHeaderV3 header_v3;
    if (!ReadCowHeader(fd_, &header_v3)) {
        return false;
    }
    header_ = header_v3;

    CowParserV2 parser;
    if (!parser.Parse(fd_, header_, {label})) {
Loading