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

Commit 31e04264 authored by Akilesh Kailash's avatar Akilesh Kailash
Browse files

libsnapshot:snapuserd: mmap + msync header after merge



mmap the CowHeader and use msync to flush only the
first 4k page after merge is complete.

This cuts down ~30 seconds of merge completion time
on a 55M incremental OTA with 235k copy operations.

Although, this isn't a significant gain but this patch
creates a scaffolding for the next set of read-ahead patches.

Bug: 183863613
Test: Incremental and Full OTA
Signed-off-by: default avatarAkilesh Kailash <akailash@google.com>
Change-Id: I15bfec91ea1d5bdf4390670bcf406e1015b79299
parent acc1c5d1
Loading
Loading
Loading
Loading
+0 −24
Original line number Diff line number Diff line
@@ -139,12 +139,6 @@ bool CowWriter::SetFd(android::base::borrowed_fd fd) {
    return true;
}

void CowWriter::InitializeMerge(borrowed_fd fd, CowHeader* header) {
    fd_ = fd;
    memcpy(&header_, header, sizeof(CowHeader));
    merge_in_progress_ = true;
}

bool CowWriter::Initialize(unique_fd&& fd) {
    owned_fd_ = std::move(fd);
    return Initialize(borrowed_fd{owned_fd_});
@@ -517,24 +511,6 @@ bool CowWriter::Sync() {
    return true;
}

bool CowWriter::CommitMerge(int merged_ops) {
    CHECK(merge_in_progress_);
    header_.num_merge_ops += merged_ops;

    if (lseek(fd_.get(), 0, SEEK_SET) < 0) {
        PLOG(ERROR) << "lseek failed";
        return false;
    }

    if (!android::base::WriteFully(fd_, reinterpret_cast<const uint8_t*>(&header_),
                                   sizeof(header_))) {
        PLOG(ERROR) << "WriteFully failed";
        return false;
    }

    return Sync();
}

bool CowWriter::Truncate(off_t length) {
    if (is_dev_null_ || is_block_device_) {
        return true;
+0 −3
Original line number Diff line number Diff line
@@ -100,9 +100,6 @@ class CowWriter : public ICowWriter {
    bool InitializeAppend(android::base::unique_fd&&, uint64_t label);
    bool InitializeAppend(android::base::borrowed_fd fd, uint64_t label);

    void InitializeMerge(android::base::borrowed_fd fd, CowHeader* header);
    bool CommitMerge(int merged_ops);

    bool Finalize() override;

    uint64_t GetCowSize() override;
+40 −18
Original line number Diff line number Diff line
@@ -51,20 +51,17 @@ bool Snapuserd::InitializeWorkers() {
}

bool Snapuserd::CommitMerge(int num_merge_ops) {
    {
        std::lock_guard<std::mutex> lock(lock_);
        CowHeader header;
    struct CowHeader* ch = reinterpret_cast<struct CowHeader*>(mapped_addr_);
    ch->num_merge_ops += num_merge_ops;

        reader_->GetHeader(&header);
        header.num_merge_ops += num_merge_ops;
        reader_->UpdateMergeProgress(num_merge_ops);
        if (!writer_->CommitMerge(num_merge_ops)) {
            SNAP_LOG(ERROR) << "CommitMerge failed... merged_ops_cur_iter: " << num_merge_ops
                            << " Total-merged-ops: " << header.num_merge_ops;
    // Sync the first 4k block
    int ret = msync(mapped_addr_, BLOCK_SZ, MS_SYNC);
    if (ret < 0) {
        PLOG(ERROR) << "msync header failed: " << ret;
        return false;
    }

    merge_initiated_ = true;
    }

    return true;
}
@@ -93,9 +90,9 @@ void Snapuserd::CheckMergeCompletionStatus() {
        return;
    }

    CowHeader header;
    reader_->GetHeader(&header);
    SNAP_LOG(INFO) << "Merge-status: Total-Merged-ops: " << header.num_merge_ops
    struct CowHeader* ch = reinterpret_cast<struct CowHeader*>(mapped_addr_);

    SNAP_LOG(INFO) << "Merge-status: Total-Merged-ops: " << ch->num_merge_ops
                   << " Total-data-ops: " << reader_->total_data_ops();
}

@@ -175,8 +172,10 @@ bool Snapuserd::ReadMetadata() {
    reader_->InitializeMerge();
    SNAP_LOG(DEBUG) << "Merge-ops: " << header.num_merge_ops;

    writer_ = std::make_unique<CowWriter>(options);
    writer_->InitializeMerge(cow_fd_.get(), &header);
    if (!MmapMetadata()) {
        SNAP_LOG(ERROR) << "mmap failed";
        return false;
    }

    // Initialize the iterator for reading metadata
    cowop_riter_ = reader_->GetRevOpIter();
@@ -487,6 +486,29 @@ bool Snapuserd::ReadMetadata() {
    return true;
}

bool Snapuserd::MmapMetadata() {
    CowHeader header;
    reader_->GetHeader(&header);

    // mmap the first 4k page
    total_mapped_addr_length_ = BLOCK_SZ;
    mapped_addr_ = mmap(NULL, total_mapped_addr_length_, PROT_READ | PROT_WRITE, MAP_SHARED,
                        cow_fd_.get(), 0);
    if (mapped_addr_ == MAP_FAILED) {
        SNAP_LOG(ERROR) << "mmap metadata failed";
        return false;
    }

    return true;
}

void Snapuserd::UnmapBufferRegion() {
    int ret = munmap(mapped_addr_, total_mapped_addr_length_);
    if (ret < 0) {
        SNAP_PLOG(ERROR) << "munmap failed";
    }
}

void MyLogger(android::base::LogId, android::base::LogSeverity severity, const char*, const char*,
              unsigned int, const char* message) {
    if (severity == android::base::ERROR) {
+8 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/mman.h>

#include <bitset>
#include <csignal>
@@ -173,9 +174,10 @@ class Snapuserd : public std::enable_shared_from_this<Snapuserd> {
        return p1.first < p2.first;
    }

  private:
    std::vector<std::unique_ptr<WorkerThread>> worker_threads_;
    void UnmapBufferRegion();
    bool MmapMetadata();

  private:
    bool IsChunkIdMetadata(chunk_t chunk);
    chunk_t GetNextAllocatableChunkId(chunk_t chunk_id);

@@ -197,7 +199,6 @@ class Snapuserd : public std::enable_shared_from_this<Snapuserd> {
    std::unique_ptr<ICowOpIter> cowop_iter_;
    std::unique_ptr<ICowOpReverseIter> cowop_riter_;
    std::unique_ptr<CowReader> reader_;
    std::unique_ptr<CowWriter> writer_;

    // Vector of disk exception which is a
    // mapping of old-chunk to new-chunk
@@ -209,6 +210,10 @@ class Snapuserd : public std::enable_shared_from_this<Snapuserd> {

    std::mutex lock_;

    void* mapped_addr_;
    size_t total_mapped_addr_length_;

    std::vector<std::unique_ptr<WorkerThread>> worker_threads_;
    bool merge_initiated_ = false;
    bool attached_ = false;
};
+2 −1
Original line number Diff line number Diff line
@@ -209,10 +209,11 @@ void SnapuserdServer::RunThread(std::shared_ptr<DmUserHandler> handler) {
    }

    handler->snapuserd()->CloseFds();
    handler->snapuserd()->CheckMergeCompletionStatus();
    handler->snapuserd()->UnmapBufferRegion();

    auto misc_name = handler->misc_name();
    LOG(INFO) << "Handler thread about to exit: " << misc_name;
    handler->snapuserd()->CheckMergeCompletionStatus();

    {
        std::lock_guard<std::mutex> lock(lock_);
Loading