Loading services/incremental/IncrementalService.cpp +43 −11 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -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 Loading services/incremental/ServiceWrappers.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -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); Loading services/incremental/ServiceWrappers.h +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading services/incremental/test/IncrementalServiceTest.cpp +6 −1 Original line number Diff line number Diff line Loading @@ -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)); Loading @@ -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)); } Loading Loading
services/incremental/IncrementalService.cpp +43 −11 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -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 Loading
services/incremental/ServiceWrappers.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
services/incremental/ServiceWrappers.h +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
services/incremental/test/IncrementalServiceTest.cpp +6 −1 Original line number Diff line number Diff line Loading @@ -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)); Loading @@ -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)); } Loading