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

Commit 324d2e39 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[incfs] Preallocate space for IncFS files" into sc-dev

parents 1e21b23a 65fc38a0
Loading
Loading
Loading
Loading
+43 −11
Original line number Diff line number Diff line
@@ -96,6 +96,10 @@ static const Constants& constants() {
    return c;
}

static bool isPageAligned(IncFsSize s) {
    return (s & (Constants::blockSize - 1)) == 0;
}

template <base::LogSeverity level = base::ERROR>
bool mkdirOrLog(std::string_view name, int mode = 0770, bool allowExisting = true) {
    auto cstr = path::c_str(name);
@@ -1001,25 +1005,53 @@ std::string IncrementalService::normalizePathToStorage(const IncFsMount& ifs, St

int IncrementalService::makeFile(StorageId storage, std::string_view path, int mode, FileId id,
                                 incfs::NewFileParams params, std::span<const uint8_t> data) {
    if (auto ifs = getIfs(storage)) {
        std::string normPath = normalizePathToStorage(*ifs, storage, path);
    const auto ifs = getIfs(storage);
    if (!ifs) {
        return -EINVAL;
    }
    if (data.size() > params.size) {
        LOG(ERROR) << "Bad data size - bigger than file size";
        return -EINVAL;
    }
    if (!data.empty() && data.size() != params.size) {
        // Writing a page is an irreversible operation, and it can't be updated with additional
        // data later. Check that the last written page is complete, or we may break the file.
        if (!isPageAligned(data.size())) {
            LOG(ERROR) << "Bad data size - tried to write half a page?";
            return -EINVAL;
        }
    }
    const std::string normPath = normalizePathToStorage(*ifs, storage, path);
    if (normPath.empty()) {
            LOG(ERROR) << "Internal error: storageId " << storage
                       << " failed to normalize: " << path;
        LOG(ERROR) << "Internal error: storageId " << storage << " failed to normalize: " << path;
        return -EINVAL;
    }
    if (auto err = mIncFs->makeFile(ifs->control, normPath, mode, id, params); err) {
        LOG(ERROR) << "Internal error: storageId " << storage << " failed to makeFile: " << err;
        return err;
    }
    if (params.size > 0) {
        // Only v2+ incfs supports automatically trimming file over-reserved sizes
        if (mIncFs->features() & incfs::Features::v2) {
            if (auto err = mIncFs->reserveSpace(ifs->control, normPath, params.size)) {
                if (err != -EOPNOTSUPP) {
                    LOG(ERROR) << "Failed to reserve space for a new file: " << err;
                    (void)mIncFs->unlink(ifs->control, normPath);
                    return err;
                } else {
                    LOG(WARNING) << "Reserving space for backing file isn't supported, "
                                    "may run out of disk later";
                }
            }
        }
        if (!data.empty()) {
            if (auto err = setFileContent(ifs, id, path, data); err) {
                (void)mIncFs->unlink(ifs->control, normPath);
                return err;
            }
        }
        return 0;
    }
    return -EINVAL;
    return 0;
}

int IncrementalService::makeDir(StorageId storageId, std::string_view path, int mode) {
@@ -1708,7 +1740,7 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
        }

        const auto entryUncompressed = entry.method == kCompressStored;
        const auto entryPageAligned = (entry.offset & (constants().blockSize - 1)) == 0;
        const auto entryPageAligned = isPageAligned(entry.offset);

        if (!extractNativeLibs) {
            // ensure the file is properly aligned and unpacked
+4 −0
Original line number Diff line number Diff line
@@ -209,6 +209,10 @@ public:
    ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final {
        return incfs::writeBlocks({blocks.data(), size_t(blocks.size())});
    }
    ErrorCode reserveSpace(const Control& control, std::string_view path,
                           IncFsSize size) const final {
        return incfs::reserveSpace(control, path, size);
    }
    WaitResult waitForPendingReads(const Control& control, std::chrono::milliseconds timeout,
                                   std::vector<incfs::ReadInfo>* pendingReadsBuffer) const final {
        return incfs::waitForPendingReads(control, timeout, pendingReadsBuffer);
+2 −0
Original line number Diff line number Diff line
@@ -107,6 +107,8 @@ public:
    virtual ErrorCode unlink(const Control& control, std::string_view path) const = 0;
    virtual UniqueFd openForSpecialOps(const Control& control, FileId id) const = 0;
    virtual ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const = 0;
    virtual ErrorCode reserveSpace(const Control& control, std::string_view path,
                                   IncFsSize size) const = 0;
    virtual WaitResult waitForPendingReads(
            const Control& control, std::chrono::milliseconds timeout,
            std::vector<incfs::ReadInfo>* pendingReadsBuffer) const = 0;
+6 −1
Original line number Diff line number Diff line
@@ -372,6 +372,8 @@ public:
    MOCK_CONST_METHOD2(unlink, ErrorCode(const Control& control, std::string_view path));
    MOCK_CONST_METHOD2(openForSpecialOps, UniqueFd(const Control& control, FileId id));
    MOCK_CONST_METHOD1(writeBlocks, ErrorCode(std::span<const DataBlock> blocks));
    MOCK_CONST_METHOD3(reserveSpace,
                       ErrorCode(const Control& control, std::string_view path, IncFsSize size));
    MOCK_CONST_METHOD3(waitForPendingReads,
                       WaitResult(const Control& control, std::chrono::milliseconds timeout,
                                  std::vector<incfs::ReadInfo>* pendingReadsBuffer));
@@ -379,7 +381,10 @@ public:
                       ErrorCode(const Control& control,
                                 const std::vector<PerUidReadTimeouts>& perUidReadTimeouts));

    MockIncFs() { ON_CALL(*this, listExistingMounts(_)).WillByDefault(Return()); }
    MockIncFs() {
        ON_CALL(*this, listExistingMounts(_)).WillByDefault(Return());
        ON_CALL(*this, reserveSpace(_, _, _)).WillByDefault(Return(0));
    }

    void makeFileFails() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(-1)); }
    void makeFileSuccess() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(0)); }