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

Commit d0c3a04c authored by Daniel Zheng's avatar Daniel Zheng
Browse files

libsnapshot: add CowSizeInfo struct

Adding a cow size info struct as writer will now need to know the op buffer
size at the time of initialization. The sequence of events is as follows
(same as estimate_cow_size but putting down here for clarity)

1. ota_from_target_files does dry run to determine cow size + ops buffer
   size
2. data is passed through delta archive manifest
3. snapshot.cpp parses these fields and confgiures cowoptions struct to
   pass to writer initialization
4. cow is initialized with correct sizing. Data is incrementally added
   at the ends of the cow ops buffer (which is why we need to know the
   sizing ahead of time)

Test: ota
Change-Id: I950e5ef82c9bd7e9bd9603b0599c930767ee3f0d
parent 75d3663d
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -33,7 +33,10 @@

namespace android {
namespace snapshot {

struct CowSizeInfo {
    uint64_t cow_size;
    uint64_t op_count_max;
};
struct CowOptions {
    uint32_t block_size = 4096;
    std::string compression;
@@ -92,8 +95,9 @@ class ICowWriter {
    // to ensure that the correct headers and footers are written.
    virtual bool Finalize() = 0;

    // Return number of bytes the cow image occupies on disk.
    virtual uint64_t GetCowSize() = 0;
    // Return number of bytes the cow image occupies on disk + the size of sequence && ops buffer
    // The latter two fields are used in v3 cow format and left as 0 for v2 cow format
    virtual CowSizeInfo GetCowSizeInfo() const = 0;

    virtual uint32_t GetBlockSize() const = 0;
    virtual std::optional<uint32_t> GetMaxBlocks() const = 0;
+1 −2
Original line number Diff line number Diff line
@@ -24,8 +24,7 @@ class MockCowWriter : public ICowWriter {
    using FileDescriptor = chromeos_update_engine::FileDescriptor;

    MOCK_METHOD(bool, Finalize, (), (override));

    MOCK_METHOD(uint64_t, GetCowSize, (), (override));
    MOCK_METHOD(CowSizeInfo, GetCowSizeInfo, (), (const, override));

    MOCK_METHOD(bool, AddCopy, (uint64_t, uint64_t, uint64_t), (override));
    MOCK_METHOD(bool, AddRawBlocks, (uint64_t, const void*, size_t), (override));
+9 −9
Original line number Diff line number Diff line
@@ -601,14 +601,14 @@ TEST_F(CowTest, GetSize) {
    ASSERT_TRUE(writer.AddCopy(10, 20));
    ASSERT_TRUE(writer.AddRawBlocks(50, data.data(), data.size()));
    ASSERT_TRUE(writer.AddZeroBlocks(51, 2));
    auto size_before = writer.GetCowSize();
    auto size_before = writer.GetCowSizeInfo().cow_size;
    ASSERT_TRUE(writer.Finalize());
    auto size_after = writer.GetCowSize();
    auto size_after = writer.GetCowSizeInfo().cow_size;
    ASSERT_EQ(size_before, size_after);
    struct stat buf;

    ASSERT_GE(fstat(cow_->fd, &buf), 0) << strerror(errno);
    ASSERT_EQ(buf.st_size, writer.GetCowSize());
    ASSERT_EQ(buf.st_size, writer.GetCowSizeInfo().cow_size);
}

TEST_F(CowTest, AppendLabelSmall) {
@@ -637,7 +637,7 @@ TEST_F(CowTest, AppendLabelSmall) {

    struct stat buf;
    ASSERT_EQ(fstat(cow_->fd, &buf), 0);
    ASSERT_EQ(buf.st_size, writer->GetCowSize());
    ASSERT_EQ(buf.st_size, writer->GetCowSizeInfo().cow_size);

    // Read back both operations, and label.
    CowReader reader;
@@ -690,7 +690,7 @@ TEST_F(CowTest, AppendLabelMissing) {
    ASSERT_TRUE(writer->AddRawBlocks(50, data.data(), data.size()));
    ASSERT_TRUE(writer->AddLabel(1));
    // Drop the tail end of the last op header, corrupting it.
    ftruncate(cow_->fd, writer->GetCowSize() - sizeof(CowFooter) - 3);
    ftruncate(cow_->fd, writer->GetCowSizeInfo().cow_size - sizeof(CowFooter) - 3);

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

@@ -705,7 +705,7 @@ TEST_F(CowTest, AppendLabelMissing) {

    struct stat buf;
    ASSERT_EQ(fstat(cow_->fd, &buf), 0);
    ASSERT_EQ(buf.st_size, writer->GetCowSize());
    ASSERT_EQ(buf.st_size, writer->GetCowSizeInfo().cow_size);

    // Read back both operations.
    CowReader reader;
@@ -763,7 +763,7 @@ TEST_F(CowTest, AppendExtendedCorrupted) {

    struct stat buf;
    ASSERT_EQ(fstat(cow_->fd, &buf), 0);
    ASSERT_EQ(buf.st_size, writer->GetCowSize());
    ASSERT_EQ(buf.st_size, writer->GetCowSizeInfo().cow_size);

    // Read back all valid operations
    CowReader reader;
@@ -812,7 +812,7 @@ TEST_F(CowTest, AppendbyLabel) {

    struct stat buf;
    ASSERT_EQ(fstat(cow_->fd, &buf), 0);
    ASSERT_EQ(buf.st_size, writer->GetCowSize());
    ASSERT_EQ(buf.st_size, writer->GetCowSizeInfo().cow_size);

    // Read back all ops
    CowReader reader;
@@ -989,7 +989,7 @@ TEST_F(CowTest, ClusterAppendTest) {

    struct stat buf;
    ASSERT_EQ(fstat(cow_->fd, &buf), 0);
    ASSERT_EQ(buf.st_size, writer->GetCowSize());
    ASSERT_EQ(buf.st_size, writer->GetCowSizeInfo().cow_size);

    // Read back both operations, plus cluster op at end
    CowReader reader;
+2 −2
Original line number Diff line number Diff line
@@ -658,14 +658,14 @@ TEST_F(CowTestV3, CowSizeEstimate) {
    options.compression = "none";
    auto estimator = android::snapshot::CreateCowEstimator(3, options);
    ASSERT_TRUE(estimator->AddZeroBlocks(0, 1024 * 1024));
    const auto cow_size = estimator->GetCowSize();
    const auto cow_size = estimator->GetCowSizeInfo().cow_size;
    options.op_count_max = 1024 * 1024;
    options.max_blocks = 1024 * 1024;
    CowWriterV3 writer(options, GetCowFd());
    ASSERT_TRUE(writer.Initialize());
    ASSERT_TRUE(writer.AddZeroBlocks(0, 1024 * 1024));

    ASSERT_LE(writer.GetCowSize(), cow_size);
    ASSERT_LE(writer.GetCowSizeInfo().cow_size, cow_size);
}

TEST_F(CowTestV3, CopyOpMany) {
+5 −3
Original line number Diff line number Diff line
@@ -576,12 +576,14 @@ bool CowWriterV2::Finalize() {
    return Sync();
}

uint64_t CowWriterV2::GetCowSize() {
CowSizeInfo CowWriterV2::GetCowSizeInfo() const {
    CowSizeInfo info;
    if (current_data_size_ > 0) {
        return next_data_pos_ + sizeof(footer_);
        info.cow_size = next_data_pos_ + sizeof(footer_);
    } else {
        return next_op_pos_ + sizeof(footer_);
        info.cow_size = next_op_pos_ + sizeof(footer_);
    }
    return info;
}

bool CowWriterV2::GetDataPos(uint64_t* pos) {
Loading