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

Commit d021544d authored by Daniel Rosenberg's avatar Daniel Rosenberg Committed by Gerrit Code Review
Browse files

Merge "libsnapshot: Remove Initialize(fd, APPEND)"

parents f7c47f81 dd6cb0d2
Loading
Loading
Loading
Loading
+23 −51
Original line number Diff line number Diff line
@@ -271,7 +271,7 @@ TEST_F(CowTest, GetSize) {
    ASSERT_EQ(buf.st_size, writer.GetCowSize());
}

TEST_F(CowTest, Append) {
TEST_F(CowTest, AppendLabelSmall) {
    CowOptions options;
    auto writer = std::make_unique<CowWriter>(options);
    ASSERT_TRUE(writer->Initialize(cow_->fd));
@@ -279,12 +279,13 @@ TEST_F(CowTest, Append) {
    std::string data = "This is some data, believe it";
    data.resize(options.block_size, '\0');
    ASSERT_TRUE(writer->AddRawBlocks(50, data.data(), data.size()));
    ASSERT_TRUE(writer->AddLabel(3));
    ASSERT_TRUE(writer->Finalize());

    ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);

    writer = std::make_unique<CowWriter>(options);
    ASSERT_TRUE(writer->Initialize(cow_->fd, CowWriter::OpenMode::APPEND));
    ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 3));

    std::string data2 = "More data!";
    data2.resize(options.block_size, '\0');
@@ -297,11 +298,12 @@ TEST_F(CowTest, Append) {
    ASSERT_EQ(fstat(cow_->fd, &buf), 0);
    ASSERT_EQ(buf.st_size, writer->GetCowSize());

    // Read back both operations.
    // Read back both operations, and label.
    CowReader reader;
    uint64_t label;
    ASSERT_TRUE(reader.Parse(cow_->fd));
    ASSERT_FALSE(reader.GetLastLabel(&label));
    ASSERT_TRUE(reader.GetLastLabel(&label));
    ASSERT_EQ(label, 3);

    StringSink sink;

@@ -317,6 +319,13 @@ TEST_F(CowTest, Append) {
    iter->Next();
    sink.Reset();

    ASSERT_FALSE(iter->Done());
    op = &iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 3);

    iter->Next();

    ASSERT_FALSE(iter->Done());
    op = &iter->Get();
    ASSERT_EQ(op->type, kCowReplaceOp);
@@ -327,33 +336,26 @@ TEST_F(CowTest, Append) {
    ASSERT_TRUE(iter->Done());
}

TEST_F(CowTest, AppendCorrupted) {
TEST_F(CowTest, AppendLabelMissing) {
    CowOptions options;
    auto writer = std::make_unique<CowWriter>(options);
    ASSERT_TRUE(writer->Initialize(cow_->fd));

    ASSERT_TRUE(writer->AddLabel(0));
    std::string data = "This is some data, believe it";
    data.resize(options.block_size, '\0');
    ASSERT_TRUE(writer->AddRawBlocks(50, data.data(), data.size()));
    ASSERT_TRUE(writer->AddLabel(0));
    ASSERT_TRUE(writer->AddZeroBlocks(50, 1));
    ASSERT_TRUE(writer->Finalize());
    // Drop the tail end of the header. Last entry may be corrupted.
    ftruncate(cow_->fd, writer->GetCowSize() - 5);
    ASSERT_TRUE(writer->AddLabel(1));
    // Drop the tail end of the last op header, corrupting it.
    ftruncate(cow_->fd, writer->GetCowSize() - sizeof(CowFooter) - 3);

    ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);

    writer = std::make_unique<CowWriter>(options);
    ASSERT_TRUE(writer->Initialize(cow_->fd, CowWriter::OpenMode::APPEND));
    ASSERT_FALSE(writer->InitializeAppend(cow_->fd, 1));
    ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 0));

    ASSERT_TRUE(writer->AddZeroBlocks(51, 1));
    ASSERT_TRUE(writer->AddLabel(1));

    std::string data2 = "More data!";
    data2.resize(options.block_size, '\0');
    ASSERT_TRUE(writer->AddRawBlocks(52, data2.data(), data2.size()));
    ASSERT_TRUE(writer->AddLabel(2));

    ASSERT_TRUE(writer->Finalize());

    ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
@@ -362,7 +364,7 @@ TEST_F(CowTest, AppendCorrupted) {
    ASSERT_EQ(fstat(cow_->fd, &buf), 0);
    ASSERT_EQ(buf.st_size, writer->GetCowSize());

    // Read back all three operations.
    // Read back both operations.
    CowReader reader;
    ASSERT_TRUE(reader.Parse(cow_->fd));

@@ -373,15 +375,6 @@ TEST_F(CowTest, AppendCorrupted) {

    ASSERT_FALSE(iter->Done());
    auto op = &iter->Get();
    ASSERT_EQ(op->type, kCowReplaceOp);
    ASSERT_TRUE(reader.ReadData(*op, &sink));
    ASSERT_EQ(sink.stream(), data);

    iter->Next();
    sink.Reset();

    ASSERT_FALSE(iter->Done());
    op = &iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 0);

@@ -393,27 +386,6 @@ TEST_F(CowTest, AppendCorrupted) {

    iter->Next();

    ASSERT_FALSE(iter->Done());
    op = &iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 1);

    iter->Next();

    ASSERT_FALSE(iter->Done());
    op = &iter->Get();
    ASSERT_EQ(op->type, kCowReplaceOp);
    ASSERT_TRUE(reader.ReadData(*op, &sink));
    ASSERT_EQ(sink.stream(), data2);

    iter->Next();

    ASSERT_FALSE(iter->Done());
    op = &iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 2);
    iter->Next();

    ASSERT_TRUE(iter->Done());
}

@@ -429,7 +401,7 @@ TEST_F(CowTest, AppendExtendedCorrupted) {
    ASSERT_TRUE(writer->AddRawBlocks(50, data.data(), data.size()));
    ASSERT_TRUE(writer->AddLabel(6));

    // fail to write the footer
    // fail to write the footer. Cow Format does not know if Label 6 is valid

    ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);

@@ -443,7 +415,7 @@ TEST_F(CowTest, AppendExtendedCorrupted) {
    ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);

    writer = std::make_unique<CowWriter>(options);
    ASSERT_TRUE(writer->Initialize(cow_->fd, CowWriter::OpenMode::APPEND));
    ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 5));

    ASSERT_TRUE(writer->Finalize());

+12 −42
Original line number Diff line number Diff line
@@ -125,25 +125,17 @@ bool CowWriter::SetFd(android::base::borrowed_fd fd) {
    return true;
}

bool CowWriter::Initialize(unique_fd&& fd, OpenMode mode) {
bool CowWriter::Initialize(unique_fd&& fd) {
    owned_fd_ = std::move(fd);
    return Initialize(borrowed_fd{owned_fd_}, mode);
    return Initialize(borrowed_fd{owned_fd_});
}

bool CowWriter::Initialize(borrowed_fd fd, OpenMode mode) {
bool CowWriter::Initialize(borrowed_fd fd) {
    if (!SetFd(fd) || !ParseOptions()) {
        return false;
    }

    switch (mode) {
        case OpenMode::WRITE:
    return OpenForWrite();
        case OpenMode::APPEND:
            return OpenForAppend();
        default:
            LOG(ERROR) << "Unknown open mode in CowWriter";
            return false;
    }
}

bool CowWriter::InitializeAppend(android::base::unique_fd&& fd, uint64_t label) {
@@ -182,17 +174,15 @@ bool CowWriter::OpenForWrite() {
    return true;
}

bool CowWriter::OpenForAppend(std::optional<uint64_t> label) {
bool CowWriter::OpenForAppend(uint64_t label) {
    auto reader = std::make_unique<CowReader>();
    bool incomplete = false;
    bool add_next = false;
    std::queue<CowOperation> toAdd;
    bool found_label = false;

    if (!reader->Parse(fd_) || !reader->GetHeader(&header_)) {
        return false;
    }
    incomplete = !reader->GetFooter(&footer_);
    reader->GetFooter(&footer_);

    options_.block_size = header_.block_size;

@@ -203,36 +193,16 @@ bool CowWriter::OpenForAppend(std::optional<uint64_t> label) {

    auto iter = reader->GetOpIter();
    while (!iter->Done() && !found_label) {
        CowOperation op = iter->Get();
        if (op.type == kCowFooterOp) break;
        if (label.has_value()) {
        const CowOperation& op = iter->Get();

        if (op.type == kCowFooterOp) break;
            if (op.type == kCowLabelOp) {
                if (op.source == label) found_label = true;
            }
        if (op.type == kCowLabelOp && op.source == label) found_label = true;
        AddOperation(op);
        } else {
            if (incomplete) {
                // Last set of labeled operations may be corrupt. Wait to add it.
                // We always sync after a label. If we see ops after a label, we
                // can infer that sync must have completed.
                if (add_next) {
                    add_next = false;
                    while (!toAdd.empty()) {
                        AddOperation(toAdd.front());
                        toAdd.pop();
                    }
                }
                toAdd.push(op);
                if (op.type == kCowLabelOp) add_next = true;
            } else {
                AddOperation(op);
            }
        }

        iter->Next();
    }

    if (label.has_value() && !found_label) {
    if (!found_label) {
        LOG(ERROR) << "Failed to find last label";
        return false;
    }
+4 −8
Original line number Diff line number Diff line
@@ -82,19 +82,15 @@ class ICowWriter {

class CowWriter : public ICowWriter {
  public:
    enum class OpenMode { WRITE, APPEND };

    explicit CowWriter(const CowOptions& options);

    // Set up the writer.
    // If opening for write, the file starts from the beginning.
    // If opening for append, if the file has a footer, we start appending to the last op.
    // If the footer isn't found, the last label is considered corrupt, and dropped.
    // The file starts from the beginning.
    //
    // If fd is < 0, the CowWriter will be opened against /dev/null. This is for
    // computing COW sizes without using storage space.
    bool Initialize(android::base::unique_fd&& fd, OpenMode mode = OpenMode::WRITE);
    bool Initialize(android::base::borrowed_fd fd, OpenMode mode = OpenMode::WRITE);
    bool Initialize(android::base::unique_fd&& fd);
    bool Initialize(android::base::borrowed_fd fd);
    // Set up a writer, assuming that the given label is the last valid label.
    // This will result in dropping any labels that occur after the given on, and will fail
    // if the given label does not appear.
@@ -115,7 +111,7 @@ class CowWriter : public ICowWriter {
    void SetupHeaders();
    bool ParseOptions();
    bool OpenForWrite();
    bool OpenForAppend(std::optional<uint64_t> label = std::nullopt);
    bool OpenForAppend(uint64_t label);
    bool GetDataPos(uint64_t* pos);
    bool WriteRawData(const void* data, size_t size);
    bool WriteOperation(const CowOperation& op, const void* data = nullptr, size_t size = 0);
+4 −4
Original line number Diff line number Diff line
@@ -42,9 +42,9 @@ class ISnapshotWriter : public ICowWriter {
    // Open the writer in write mode (no append).
    virtual bool Initialize() = 0;

    // Open the writer in append mode, optionally with the last label to resume
    // Open the writer in append mode, with the last label to resume
    // from. See CowWriter::InitializeAppend.
    virtual bool InitializeAppend(std::optional<uint64_t> label = {}) = 0;
    virtual bool InitializeAppend(uint64_t label) = 0;

    virtual std::unique_ptr<FileDescriptor> OpenReader() = 0;

@@ -66,7 +66,7 @@ class CompressedSnapshotWriter : public ISnapshotWriter {
    bool SetCowDevice(android::base::unique_fd&& cow_device);

    bool Initialize() override;
    bool InitializeAppend(std::optional<uint64_t> label = {}) override;
    bool InitializeAppend(uint64_t label) override;
    bool Finalize() override;
    uint64_t GetCowSize() override;
    std::unique_ptr<FileDescriptor> OpenReader() override;
@@ -92,7 +92,7 @@ class OnlineKernelSnapshotWriter : public ISnapshotWriter {
    void SetSnapshotDevice(android::base::unique_fd&& snapshot_fd, uint64_t cow_size);

    bool Initialize() override { return true; }
    bool InitializeAppend(std::optional<uint64_t>) override { return true; }
    bool InitializeAppend(uint64_t) override { return true; }

    bool Finalize() override;
    uint64_t GetCowSize() override { return cow_size_; }
+3 −6
Original line number Diff line number Diff line
@@ -113,14 +113,11 @@ bool CompressedSnapshotWriter::EmitLabel(uint64_t label) {
}

bool CompressedSnapshotWriter::Initialize() {
    return cow_->Initialize(cow_device_, CowWriter::OpenMode::WRITE);
    return cow_->Initialize(cow_device_);
}

bool CompressedSnapshotWriter::InitializeAppend(std::optional<uint64_t> label) {
    if (label) {
        return cow_->InitializeAppend(cow_device_, *label);
    }
    return cow_->Initialize(cow_device_, CowWriter::OpenMode::APPEND);
bool CompressedSnapshotWriter::InitializeAppend(uint64_t label) {
    return cow_->InitializeAppend(cow_device_, label);
}

OnlineKernelSnapshotWriter::OnlineKernelSnapshotWriter(const CowOptions& options)