diff --git a/src/libstore/local-overlay-store.cc b/src/libstore/local-overlay-store.cc index 47d09dc75..38c40fbad 100644 --- a/src/libstore/local-overlay-store.cc +++ b/src/libstore/local-overlay-store.cc @@ -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 regLocalOverlayStore; } diff --git a/src/libstore/local-overlay-store.hh b/src/libstore/local-overlay-store.hh index f489c6ed6..ffb310b7b 100644 --- a/src/libstore/local-overlay-store.hh +++ b/src/libstore/local-overlay-store.hh @@ -123,6 +123,8 @@ private: void optimiseStore() override; Path toRealPathForHardLink(const StorePath & storePath) override; + + bool _remountRequired = false; }; } diff --git a/tests/overlay-local-store/delete-inner.sh b/tests/overlay-local-store/delete-inner.sh index 20b39c7fa..051b59d5f 100644 --- a/tests/overlay-local-store/delete-inner.sh +++ b/tests/overlay-local-store/delete-inner.sh @@ -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/}"