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

Commit 3b7f64d3 authored by David Anderson's avatar David Anderson Committed by android-build-merger
Browse files

Merge "fiemap_writer: Add a progress notification."

am: dec43643

Change-Id: I580c5f8efd0e3fe8147f782fa0bfdc5c895153bb
parents c6b683e1 dec43643
Loading
Loading
Loading
Loading
+18 −3
Original line number Diff line number Diff line
@@ -220,7 +220,7 @@ static bool PerformFileChecks(const std::string& file_path, uint64_t file_size,
}

static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz,
                         uint64_t file_size) {
                         uint64_t file_size, std::function<bool(uint64_t, uint64_t)> on_progress) {
    // Reserve space for the file on the file system and write it out to make sure the extents
    // don't come back unwritten. Return from this function with the kernel file offset set to 0.
    // If the filesystem is f2fs, then we also PIN the file on disk to make sure the blocks
@@ -245,12 +245,22 @@ static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blo
        return false;
    }

    int permille = -1;
    for (; offset < file_size; offset += blocksz) {
        if (!::android::base::WriteFully(file_fd, buffer.get(), blocksz)) {
            PLOG(ERROR) << "Failed to write" << blocksz << " bytes at offset" << offset
                        << " in file " << file_path;
            return false;
        }
        // Don't invoke the callback every iteration - wait until a significant
        // chunk (here, 1/1000th) of the data has been processed.
        int new_permille = (static_cast<uint64_t>(offset) * 1000) / file_size;
        if (new_permille != permille) {
            if (on_progress && !on_progress(offset, file_size)) {
                return false;
            }
            permille = new_permille;
        }
    }

    if (lseek64(file_fd, 0, SEEK_SET) < 0) {
@@ -264,6 +274,10 @@ static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blo
        return false;
    }

    // Send one last progress notification.
    if (on_progress && !on_progress(file_size, file_size)) {
        return false;
    }
    return true;
}

@@ -412,7 +426,8 @@ static bool ReadFiemap(int file_fd, const std::string& file_path,
    return last_extent_seen;
}

FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create) {
FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create,
                                   std::function<bool(uint64_t, uint64_t)> progress) {
    // if 'create' is false, open an existing file and do not truncate.
    int open_flags = O_RDWR | O_CLOEXEC;
    if (create) {
@@ -474,7 +489,7 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s
    }

    if (create) {
        if (!AllocateFile(file_fd, abs_path, blocksz, file_size)) {
        if (!AllocateFile(file_fd, abs_path, blocksz, file_size, std::move(progress))) {
            LOG(ERROR) << "Failed to allocate file: " << abs_path << " of size: " << file_size
                       << " bytes";
            cleanup(abs_path, create);
+19 −0
Original line number Diff line number Diff line
@@ -83,6 +83,25 @@ TEST_F(FiemapWriterTest, CheckFilePath) {
    EXPECT_EQ(access(testfile.c_str(), F_OK), 0);
}

TEST_F(FiemapWriterTest, CheckProgress) {
    std::vector<uint64_t> expected{
            0,
            4096,
    };
    size_t invocations = 0;
    auto callback = [&](uint64_t done, uint64_t total) -> bool {
        EXPECT_LT(invocations, expected.size());
        EXPECT_EQ(done, expected[invocations]);
        EXPECT_EQ(total, 4096);
        invocations++;
        return true;
    };

    auto ptr = FiemapWriter::Open(testfile, 4096, true, std::move(callback));
    EXPECT_NE(ptr, nullptr);
    EXPECT_EQ(invocations, 2);
}

TEST_F(FiemapWriterTest, CheckBlockDevicePath) {
    FiemapUniquePtr fptr = FiemapWriter::Open(testfile, 4096);
    EXPECT_EQ(fptr->size(), 4096);
+7 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <unistd.h>

#include <functional>
#include <string>
#include <vector>

@@ -36,9 +37,13 @@ class FiemapWriter final {
  public:
    // Factory method for FiemapWriter.
    // The method returns FiemapUniquePtr that contains all the data necessary to be able to write
    // to the given file directly using raw block i/o.
    // to the given file directly using raw block i/o. The optional progress callback will be
    // invoked, if create is true, while the file is being initialized. It receives the bytes
    // written and the number of total bytes. If the callback returns false, the operation will
    // fail.
    static FiemapUniquePtr Open(const std::string& file_path, uint64_t file_size,
                                bool create = true);
                                bool create = true,
                                std::function<bool(uint64_t, uint64_t)> progress = {});

    // Syncs block device writes.
    bool Flush() const;