From 9ef0a9e8aa2e27991434c104ad73b1b95b241f08 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 25 Jul 2023 10:28:11 -0400 Subject: [PATCH] Fix hard linking issue causing overlay fs copy-ups --- src/libstore/build/local-derivation-goal.cc | 7 ++++--- src/libstore/local-fs-store.hh | 10 ++++++++++ src/libstore/local-overlay-store.cc | 7 +++++++ src/libstore/local-overlay-store.hh | 2 ++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index b7a27490c..3bc88ee86 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -386,8 +386,9 @@ void LocalDerivationGoal::cleanupPostOutputsRegisteredModeNonCheck() #if __linux__ -static void linkOrCopy(const Path & from, const Path & to) +static void linkOrCopy(LocalFSStore & store, const StorePath & from_, const Path & to) { + auto from = store.toRealPathForHardLink(from_); if (link(from.c_str(), to.c_str()) == -1) { /* Hard-linking fails if we exceed the maximum link count on a file (e.g. 32000 of ext3), which is quite possible after a @@ -712,7 +713,7 @@ void LocalDerivationGoal::startBuilder() if (S_ISDIR(lstat(r).st_mode)) dirsInChroot.insert_or_assign(p, r); else - linkOrCopy(r, chrootRootDir + p); + linkOrCopy(getLocalStore(), i, chrootRootDir + p); } /* If we're repairing, checking or rebuilding part of a @@ -1574,7 +1575,7 @@ void LocalDerivationGoal::addDependency(const StorePath & path) throw Error("could not add path '%s' to sandbox", worker.store.printStorePath(path)); } else - linkOrCopy(source, target); + linkOrCopy(getLocalStore(), path, target); #else throw Error("don't know how to make path '%s' (produced by a recursive Nix call) appear in the sandbox", diff --git a/src/libstore/local-fs-store.hh b/src/libstore/local-fs-store.hh index 488109501..19858f5c8 100644 --- a/src/libstore/local-fs-store.hh +++ b/src/libstore/local-fs-store.hh @@ -73,6 +73,16 @@ public: return getRealStoreDir() + "/" + std::string(storePath, storeDir.size() + 1); } + /** + * If the real path is hardlinked with something else, we might + * prefer to refer to the other path instead. This is the case with + * overlayfs, for example. + */ + virtual Path toRealPathForHardLink(const StorePath & storePath) + { + return Store::toRealPath(storePath); + } + std::optional getBuildLogExact(const StorePath & path) override; }; diff --git a/src/libstore/local-overlay-store.cc b/src/libstore/local-overlay-store.cc index 700a5227b..47d09dc75 100644 --- a/src/libstore/local-overlay-store.cc +++ b/src/libstore/local-overlay-store.cc @@ -209,6 +209,13 @@ void LocalOverlayStore::optimiseStore() } } +Path LocalOverlayStore::toRealPathForHardLink(const StorePath & path) +{ + return lowerStore->isValidPath(path) + ? lowerStore->Store::toRealPath(path) + : Store::toRealPath(path); +} + static RegisterStoreImplementation regLocalOverlayStore; } diff --git a/src/libstore/local-overlay-store.hh b/src/libstore/local-overlay-store.hh index 349d9e6ed..64e2ef488 100644 --- a/src/libstore/local-overlay-store.hh +++ b/src/libstore/local-overlay-store.hh @@ -114,6 +114,8 @@ private: void deleteGCPath(const Path & path, uint64_t & bytesFreed) override; void optimiseStore() override; + + Path toRealPathForHardLink(const StorePath & storePath) override; }; }