Fix hard linking issue causing overlay fs copy-ups

This commit is contained in:
John Ericson 2023-07-25 10:28:11 -04:00
parent 83e703e7a8
commit 9ef0a9e8aa
4 changed files with 23 additions and 3 deletions

View file

@ -386,8 +386,9 @@ void LocalDerivationGoal::cleanupPostOutputsRegisteredModeNonCheck()
#if __linux__ #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) { if (link(from.c_str(), to.c_str()) == -1) {
/* Hard-linking fails if we exceed the maximum link count on a /* Hard-linking fails if we exceed the maximum link count on a
file (e.g. 32000 of ext3), which is quite possible after 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)) if (S_ISDIR(lstat(r).st_mode))
dirsInChroot.insert_or_assign(p, r); dirsInChroot.insert_or_assign(p, r);
else else
linkOrCopy(r, chrootRootDir + p); linkOrCopy(getLocalStore(), i, chrootRootDir + p);
} }
/* If we're repairing, checking or rebuilding part of a /* 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)); throw Error("could not add path '%s' to sandbox", worker.store.printStorePath(path));
} else } else
linkOrCopy(source, target); linkOrCopy(getLocalStore(), path, target);
#else #else
throw Error("don't know how to make path '%s' (produced by a recursive Nix call) appear in the sandbox", throw Error("don't know how to make path '%s' (produced by a recursive Nix call) appear in the sandbox",

View file

@ -73,6 +73,16 @@ public:
return getRealStoreDir() + "/" + std::string(storePath, storeDir.size() + 1); 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<std::string> getBuildLogExact(const StorePath & path) override; std::optional<std::string> getBuildLogExact(const StorePath & path) override;
}; };

View file

@ -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<LocalOverlayStore, LocalOverlayStoreConfig> regLocalOverlayStore; static RegisterStoreImplementation<LocalOverlayStore, LocalOverlayStoreConfig> regLocalOverlayStore;
} }

View file

@ -114,6 +114,8 @@ private:
void deleteGCPath(const Path & path, uint64_t & bytesFreed) override; void deleteGCPath(const Path & path, uint64_t & bytesFreed) override;
void optimiseStore() override; void optimiseStore() override;
Path toRealPathForHardLink(const StorePath & storePath) override;
}; };
} }