[incremental] Use file range mapping for .so if available
Bug: 180535478 Test: IncrementalService unit tests Change-Id: I663dcdce337c289cacc5dc7224dedf5a55605c86
This commit is contained in:
@@ -1617,7 +1617,7 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
|
||||
// Need a shared pointer: will be passing it into all unpacking jobs.
|
||||
std::shared_ptr<ZipArchive> zipFile(zipFileHandle, [](ZipArchiveHandle h) { CloseArchive(h); });
|
||||
void* cookie = nullptr;
|
||||
const auto libFilePrefix = path::join(constants().libDir, abi) + "/";
|
||||
const auto libFilePrefix = path::join(constants().libDir, abi) += "/";
|
||||
if (StartIteration(zipFile.get(), &cookie, libFilePrefix, constants().libSuffix)) {
|
||||
LOG(ERROR) << "Failed to start zip iteration for " << apkFullPath;
|
||||
return false;
|
||||
@@ -1627,6 +1627,17 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
|
||||
|
||||
auto openZipTs = Clock::now();
|
||||
|
||||
auto mapFiles = (mIncFs->features() & incfs::Features::v2);
|
||||
incfs::FileId sourceId;
|
||||
if (mapFiles) {
|
||||
sourceId = mIncFs->getFileId(ifs->control, apkFullPath);
|
||||
if (!incfs::isValidFileId(sourceId)) {
|
||||
LOG(WARNING) << "Error getting IncFS file ID for apk path '" << apkFullPath
|
||||
<< "', mapping disabled";
|
||||
mapFiles = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Job> jobQueue;
|
||||
ZipEntry entry;
|
||||
std::string_view fileName;
|
||||
@@ -1635,13 +1646,16 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto entryUncompressed = entry.method == kCompressStored;
|
||||
const auto entryPageAligned = (entry.offset & (constants().blockSize - 1)) == 0;
|
||||
|
||||
if (!extractNativeLibs) {
|
||||
// ensure the file is properly aligned and unpacked
|
||||
if (entry.method != kCompressStored) {
|
||||
if (!entryUncompressed) {
|
||||
LOG(WARNING) << "Library " << fileName << " must be uncompressed to mmap it";
|
||||
return false;
|
||||
}
|
||||
if ((entry.offset & (constants().blockSize - 1)) != 0) {
|
||||
if (!entryPageAligned) {
|
||||
LOG(WARNING) << "Library " << fileName
|
||||
<< " must be page-aligned to mmap it, offset = 0x" << std::hex
|
||||
<< entry.offset;
|
||||
@@ -1665,6 +1679,28 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mapFiles && entryUncompressed && entryPageAligned && entry.uncompressed_length > 0) {
|
||||
incfs::NewMappedFileParams mappedFileParams = {
|
||||
.sourceId = sourceId,
|
||||
.sourceOffset = entry.offset,
|
||||
.size = entry.uncompressed_length,
|
||||
};
|
||||
|
||||
if (auto res = mIncFs->makeMappedFile(ifs->control, targetLibPathAbsolute, 0755,
|
||||
mappedFileParams);
|
||||
res == 0) {
|
||||
if (perfLoggingEnabled()) {
|
||||
auto doneTs = Clock::now();
|
||||
LOG(INFO) << "incfs: Mapped " << libName << ": "
|
||||
<< elapsedMcs(startFileTs, doneTs) << "mcs";
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
LOG(WARNING) << "Failed to map file for: '" << targetLibPath << "' errno: " << res
|
||||
<< "; falling back to full extraction";
|
||||
}
|
||||
}
|
||||
|
||||
// Create new lib file without signature info
|
||||
incfs::NewFileParams libFileParams = {
|
||||
.size = entry.uncompressed_length,
|
||||
@@ -1673,7 +1709,7 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
|
||||
.metadata = {targetLibPath.c_str(), (IncFsSize)targetLibPath.size()},
|
||||
};
|
||||
incfs::FileId libFileId = idFromMetadata(targetLibPath);
|
||||
if (auto res = mIncFs->makeFile(ifs->control, targetLibPathAbsolute, 0777, libFileId,
|
||||
if (auto res = mIncFs->makeFile(ifs->control, targetLibPathAbsolute, 0755, libFileId,
|
||||
libFileParams)) {
|
||||
LOG(ERROR) << "Failed to make file for: " << targetLibPath << " errno: " << res;
|
||||
// If one lib file fails to be created, abort others as well
|
||||
|
||||
@@ -134,10 +134,11 @@ private:
|
||||
} mLooper;
|
||||
};
|
||||
|
||||
class RealIncFs : public IncFsWrapper {
|
||||
class RealIncFs final : public IncFsWrapper {
|
||||
public:
|
||||
RealIncFs() = default;
|
||||
~RealIncFs() final = default;
|
||||
Features features() const final { return incfs::features(); }
|
||||
void listExistingMounts(const ExistingMountCallback& cb) const final {
|
||||
for (auto mount : incfs::defaultMountRegistry().copyMounts()) {
|
||||
auto binds = mount.binds(); // span() doesn't like rvalue containers, needs to save it.
|
||||
@@ -153,6 +154,10 @@ public:
|
||||
incfs::NewFileParams params) const final {
|
||||
return incfs::makeFile(control, path, mode, id, params);
|
||||
}
|
||||
ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
|
||||
incfs::NewMappedFileParams params) const final {
|
||||
return incfs::makeMappedFile(control, path, mode, params);
|
||||
}
|
||||
ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
|
||||
return incfs::makeDir(control, path, mode);
|
||||
}
|
||||
|
||||
@@ -77,18 +77,22 @@ public:
|
||||
using ErrorCode = incfs::ErrorCode;
|
||||
using UniqueFd = incfs::UniqueFd;
|
||||
using WaitResult = incfs::WaitResult;
|
||||
using Features = incfs::Features;
|
||||
|
||||
using ExistingMountCallback =
|
||||
std::function<void(std::string_view root, std::string_view backingDir,
|
||||
std::span<std::pair<std::string_view, std::string_view>> binds)>;
|
||||
|
||||
virtual ~IncFsWrapper() = default;
|
||||
virtual Features features() const = 0;
|
||||
virtual void listExistingMounts(const ExistingMountCallback& cb) const = 0;
|
||||
virtual Control openMount(std::string_view path) const = 0;
|
||||
virtual Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs,
|
||||
IncFsFd blocksWritten) const = 0;
|
||||
virtual ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
|
||||
incfs::NewFileParams params) const = 0;
|
||||
virtual ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
|
||||
incfs::NewMappedFileParams params) const = 0;
|
||||
virtual ErrorCode makeDir(const Control& control, std::string_view path, int mode) const = 0;
|
||||
virtual ErrorCode makeDirs(const Control& control, std::string_view path, int mode) const = 0;
|
||||
virtual incfs::RawMetadata getMetadata(const Control& control, FileId fileid) const = 0;
|
||||
|
||||
@@ -322,6 +322,7 @@ private:
|
||||
|
||||
class MockIncFs : public IncFsWrapper {
|
||||
public:
|
||||
MOCK_CONST_METHOD0(features, Features());
|
||||
MOCK_CONST_METHOD1(listExistingMounts, void(const ExistingMountCallback& cb));
|
||||
MOCK_CONST_METHOD1(openMount, Control(std::string_view path));
|
||||
MOCK_CONST_METHOD4(createControl,
|
||||
@@ -330,6 +331,9 @@ public:
|
||||
MOCK_CONST_METHOD5(makeFile,
|
||||
ErrorCode(const Control& control, std::string_view path, int mode, FileId id,
|
||||
NewFileParams params));
|
||||
MOCK_CONST_METHOD4(makeMappedFile,
|
||||
ErrorCode(const Control& control, std::string_view path, int mode,
|
||||
NewMappedFileParams params));
|
||||
MOCK_CONST_METHOD3(makeDir, ErrorCode(const Control& control, std::string_view path, int mode));
|
||||
MOCK_CONST_METHOD3(makeDirs,
|
||||
ErrorCode(const Control& control, std::string_view path, int mode));
|
||||
|
||||
Reference in New Issue
Block a user