Avoid creating whiteout for duplicate store paths.

This commit is contained in:
Ben Radford 2023-07-26 13:21:38 +01:00 committed by Ben Radford
parent cc6f8aa91a
commit 11c493f8fa
3 changed files with 23 additions and 2 deletions

View file

@ -183,11 +183,27 @@ void LocalOverlayStore::deleteGCPath(const Path & path, uint64_t & bytesFreed)
warn("local-overlay: unexpected gc path '%s' ", path);
return;
}
if (pathExists(toUpperPath({path.substr(mergedDir.length())}))) {
LocalStore::deleteGCPath(path, bytesFreed);
StorePath storePath = {path.substr(mergedDir.length())};
auto upperPath = toUpperPath(storePath);
if (pathExists(upperPath)) {
std::cerr << " upper exists" << std::endl;
if (lowerStore->isValidPath(storePath)) {
std::cerr << " lower exists" << std::endl;
// Path also exists in lower store.
// We must delete via upper layer to avoid creating a whiteout.
deletePath(upperPath, bytesFreed);
_remountRequired = true;
} else {
// Path does not exist in lower store.
// So we can delete via overlayfs and not need to remount.
LocalStore::deleteGCPath(path, bytesFreed);
}
}
}
void LocalOverlayStore::optimiseStore()
{
Activity act(*logger, actOptimiseStore);
@ -209,6 +225,7 @@ void LocalOverlayStore::optimiseStore()
}
}
Path LocalOverlayStore::toRealPathForHardLink(const StorePath & path)
{
return lowerStore->isValidPath(path)
@ -216,6 +233,7 @@ Path LocalOverlayStore::toRealPathForHardLink(const StorePath & path)
: Store::toRealPath(path);
}
static RegisterStoreImplementation<LocalOverlayStore, LocalOverlayStoreConfig> regLocalOverlayStore;
}

View file

@ -123,6 +123,8 @@ private:
void optimiseStore() override;
Path toRealPathForHardLink(const StorePath & storePath) override;
bool _remountRequired = false;
};
}

View file

@ -28,6 +28,7 @@ lowerInode=$(stat -c %i "$storeA/$lowerPath")
# Now delete file via the overlay store
nix-store --store "$storeB" --delete "$upperPath"
remountOverlayfs
# Check there is no longer a file in upper layer
expect 1 stat "$storeBTop/${upperPath##/nix/store/}"