From 1df702d34733e69599a6ae21cb366348a2534b7d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 1 Aug 2012 19:01:50 -0400 Subject: removeUnusedLinks(): Print stats on disk space saved by hard linking --- src/libstore/gc.cc | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/libstore/gc.cc') diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 874efe4d32d9..a7547d079b31 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -581,6 +581,8 @@ void LocalStore::removeUnusedLinks() AutoCloseDir dir = opendir(linksDir.c_str()); if (!dir) throw SysError(format("opening directory `%1%'") % linksDir); + unsigned long long actualSize = 0, unsharedSize = 0; + struct dirent * dirent; while (errno = 0, dirent = readdir(dir)) { checkInterrupt(); @@ -592,13 +594,26 @@ void LocalStore::removeUnusedLinks() if (lstat(path.c_str(), &st) == -1) throw SysError(format("statting `%1%'") % path); - if (st.st_nlink != 1) continue; + if (st.st_nlink != 1) { + unsigned long long size = st.st_blocks * 512ULL; + actualSize += size; + unsharedSize += (st.st_nlink - 1) * size; + continue; + } printMsg(lvlTalkative, format("deleting unused link `%1%'") % path); if (unlink(path.c_str()) == -1) throw SysError(format("deleting `%1%'") % path); } + + struct stat st; + if (stat(linksDir.c_str(), &st) == -1) + throw SysError(format("statting `%1%'") % linksDir); + unsigned long long overhead = st.st_blocks * 512ULL; + + printMsg(lvlInfo, format("note: currently hard linking saves %.2f MiB") + % ((unsharedSize - actualSize - overhead) / (1024.0 * 1024.0))); } -- cgit 1.4.1 From 967d066d8e452e59507ebae7585d6f34a4edf687 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 1 Aug 2012 19:14:30 -0400 Subject: nix-store --gc: Make ‘--max-freed 0’ do the right thing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is, delete almost nothing (it will still remove unused links from /nix/store/.links). --- src/libstore/gc.cc | 4 ++-- src/libstore/store-api.cc | 4 ++-- src/libstore/store-api.hh | 3 +-- src/nix-store/nix-store.cc | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) (limited to 'src/libstore/gc.cc') diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index a7547d079b31..7753b3fe20c0 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -550,7 +550,7 @@ bool LocalStore::tryToDelete(GCState & state, const Path & path) } else deleteGarbage(state, path); - if (state.options.maxFreed && state.results.bytesFreed + state.bytesInvalidated > state.options.maxFreed) { + if (state.results.bytesFreed + state.bytesInvalidated > state.options.maxFreed) { printMsg(lvlInfo, format("deleted or invalidated more than %1% bytes; stopping") % state.options.maxFreed); throw GCLimitReached(); } @@ -675,7 +675,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) throw Error(format("cannot delete path `%1%' since it is still alive") % *i); } - } else { + } else if (options.maxFreed > 0) { if (shouldDelete(state.options.action)) printMsg(lvlError, format("deleting garbage...")); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index b64988268cdb..dac581e14e9e 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -2,7 +2,7 @@ #include "globals.hh" #include "util.hh" -#include +#include namespace nix { @@ -12,7 +12,7 @@ GCOptions::GCOptions() { action = gcDeleteDead; ignoreLiveness = false; - maxFreed = 0; + maxFreed = ULLONG_MAX; } diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 9ba67852efec..c0fb50f23dd2 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -48,8 +48,7 @@ struct GCOptions /* For `gcDeleteSpecific', the paths to delete. */ PathSet pathsToDelete; - /* Stop after at least `maxFreed' bytes have been freed. 0 means - no limit. */ + /* Stop after at least `maxFreed' bytes have been freed. */ unsigned long long maxFreed; GCOptions(); diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 82e08fecf22a..9a675fcd576a 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -583,7 +583,7 @@ static void opGC(Strings opFlags, Strings opArgs) else if (*i == "--delete") options.action = GCOptions::gcDeleteDead; else if (*i == "--max-freed") { long long maxFreed = getIntArg(*i, i, opFlags.end()); - options.maxFreed = maxFreed >= 1 ? maxFreed : 1; + options.maxFreed = maxFreed >= 0 ? maxFreed : 0; } else throw UsageError(format("bad sub-operation `%1%' in GC") % *i); -- cgit 1.4.1 From 01d56c1eeca497de247413a64a544605c53d9d41 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 1 Aug 2012 22:34:46 -0400 Subject: Drop the block count in the garbage collector --- src/libstore/build.cc | 11 +++++------ src/libstore/gc.cc | 5 ++--- src/libstore/local-store.hh | 3 +-- src/libstore/remote-store.cc | 2 +- src/libstore/store-api.hh | 4 ---- src/libutil/util.cc | 21 ++++++++------------- src/libutil/util.hh | 3 +-- src/nix-store/nix-store.cc | 9 ++++----- src/nix-worker/nix-worker.cc | 2 +- 9 files changed, 23 insertions(+), 37 deletions(-) (limited to 'src/libstore/gc.cc') diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 290635695e05..91f235b7ab10 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -606,18 +606,17 @@ void getOwnership(const Path & path) } -void deletePathWrapped(const Path & path, - unsigned long long & bytesFreed, unsigned long long & blocksFreed) +void deletePathWrapped(const Path & path, unsigned long long & bytesFreed) { try { /* First try to delete it ourselves. */ - deletePath(path, bytesFreed, blocksFreed); + deletePath(path, bytesFreed); } catch (SysError & e) { /* If this failed due to a permission error, then try it with the setuid helper. */ if (haveBuildUsers() && !amPrivileged()) { getOwnership(path); - deletePath(path, bytesFreed, blocksFreed); + deletePath(path, bytesFreed); } else throw; } @@ -626,8 +625,8 @@ void deletePathWrapped(const Path & path, void deletePathWrapped(const Path & path) { - unsigned long long dummy1, dummy2; - deletePathWrapped(path, dummy1, dummy2); + unsigned long long dummy1; + deletePathWrapped(path, dummy1); } diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 7753b3fe20c0..a1bb4051cd1b 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -425,10 +425,9 @@ bool LocalStore::isActiveTempFile(const GCState & state, void LocalStore::deleteGarbage(GCState & state, const Path & path) { printMsg(lvlInfo, format("deleting `%1%'") % path); - unsigned long long bytesFreed, blocksFreed; - deletePathWrapped(path, bytesFreed, blocksFreed); + unsigned long long bytesFreed; + deletePathWrapped(path, bytesFreed); state.results.bytesFreed += bytesFreed; - state.results.blocksFreed += blocksFreed; } diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 50910f353ad1..721cc6afbed5 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -304,8 +304,7 @@ void getOwnership(const Path & path); /* Like deletePath(), but changes the ownership of `path' using the setuid wrapper if necessary (and possible). */ -void deletePathWrapped(const Path & path, - unsigned long long & bytesFreed, unsigned long long & blocksFreed); +void deletePathWrapped(const Path & path, unsigned long long & bytesFreed); void deletePathWrapped(const Path & path); diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index cbb70b2fd726..5e7f02749135 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -494,7 +494,7 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results) results.paths = readStrings(from); results.bytesFreed = readLongLong(from); - results.blocksFreed = readLongLong(from); + readLongLong(from); // obsolete } diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index c0fb50f23dd2..79ae0170d700 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -65,13 +65,9 @@ struct GCResults number of bytes that would be or was freed. */ unsigned long long bytesFreed; - /* The number of file system blocks that would be or was freed. */ - unsigned long long blocksFreed; - GCResults() { bytesFreed = 0; - blocksFreed = 0; } }; diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 689fc543af31..9d8e4afed37d 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -297,8 +297,7 @@ void computePathSize(const Path & path, } -static void _deletePath(const Path & path, unsigned long long & bytesFreed, - unsigned long long & blocksFreed) +static void _deletePath(const Path & path, unsigned long long & bytesFreed) { checkInterrupt(); @@ -308,10 +307,8 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed, if (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode)) makeMutable(path); - if (!S_ISDIR(st.st_mode) && st.st_nlink == 1) { - bytesFreed += st.st_size; - blocksFreed += st.st_blocks; - } + if (!S_ISDIR(st.st_mode) && st.st_nlink == 1) + bytesFreed += st.st_blocks * 512; if (S_ISDIR(st.st_mode)) { Strings names = readDirectory(path); @@ -323,7 +320,7 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed, } for (Strings::iterator i = names.begin(); i != names.end(); ++i) - _deletePath(path + "/" + *i, bytesFreed, blocksFreed); + _deletePath(path + "/" + *i, bytesFreed); } if (remove(path.c_str()) == -1) @@ -333,19 +330,17 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed, void deletePath(const Path & path) { - unsigned long long dummy1, dummy2; - deletePath(path, dummy1, dummy2); + unsigned long long dummy; + deletePath(path, dummy); } -void deletePath(const Path & path, unsigned long long & bytesFreed, - unsigned long long & blocksFreed) +void deletePath(const Path & path, unsigned long long & bytesFreed) { startNest(nest, lvlDebug, format("recursively deleting path `%1%'") % path); bytesFreed = 0; - blocksFreed = 0; - _deletePath(path, bytesFreed, blocksFreed); + _deletePath(path, bytesFreed); } diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 9b8656f70485..edb7c0fa6c60 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -80,8 +80,7 @@ void computePathSize(const Path & path, returns the number of bytes and blocks freed. */ void deletePath(const Path & path); -void deletePath(const Path & path, unsigned long long & bytesFreed, - unsigned long long & blocksFreed); +void deletePath(const Path & path, unsigned long long & bytesFreed); /* Make a path read-only recursively. */ void makePathReadOnly(const Path & path); diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 9a675fcd576a..c182dbe49c7a 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -544,10 +544,9 @@ static void opCheckValidity(Strings opFlags, Strings opArgs) } -static string showBytes(unsigned long long bytes, unsigned long long blocks) +static string showBytes(unsigned long long bytes) { - return (format("%d bytes (%.2f MiB, %d blocks)") - % bytes % (bytes / (1024.0 * 1024.0)) % blocks).str(); + return (format("%.2f MiB") % (bytes / (1024.0 * 1024.0))).str(); } @@ -562,7 +561,7 @@ struct PrintFreed if (show) cout << format("%1% store paths deleted, %2% freed\n") % results.paths.size() - % showBytes(results.bytesFreed, results.blocksFreed); + % showBytes(results.bytesFreed); } }; @@ -735,7 +734,7 @@ static void showOptimiseStats(OptimiseStats & stats) { printMsg(lvlError, format("%1% freed by hard-linking %2% files; there are %3% files with equal contents out of %4% files in total") - % showBytes(stats.bytesFreed, stats.blocksFreed) + % showBytes(stats.bytesFreed) % stats.filesLinked % stats.sameContents % stats.totalFiles); diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc index 74a619c71d0a..80c0d50609c7 100644 --- a/src/nix-worker/nix-worker.cc +++ b/src/nix-worker/nix-worker.cc @@ -503,7 +503,7 @@ static void performOp(unsigned int clientVersion, writeStrings(results.paths, to); writeLongLong(results.bytesFreed, to); - writeLongLong(results.blocksFreed, to); + writeLongLong(0, to); // obsolete break; } -- cgit 1.4.1 From 6763084ae53fc0228d50ab94bbbced89c1b14f1c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 1 Aug 2012 22:43:03 -0400 Subject: Count bytes freed deleting unused links --- src/libstore/gc.cc | 6 ++++-- src/libstore/local-store.hh | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/libstore/gc.cc') diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index a1bb4051cd1b..255dc3aa099f 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -575,7 +575,7 @@ bool LocalStore::tryToDelete(GCState & state, const Path & path) safely deleted. FIXME: race condition with optimisePath(): we might see a link count of 1 just before optimisePath() increases the link count. */ -void LocalStore::removeUnusedLinks() +void LocalStore::removeUnusedLinks(const GCState & state) { AutoCloseDir dir = opendir(linksDir.c_str()); if (!dir) throw SysError(format("opening directory `%1%'") % linksDir); @@ -604,6 +604,8 @@ void LocalStore::removeUnusedLinks() if (unlink(path.c_str()) == -1) throw SysError(format("deleting `%1%'") % path); + + state.results.bytesFreed += st.st_blocks * 512; } struct stat st; @@ -732,7 +734,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) /* Clean up the links directory. */ printMsg(lvlError, format("deleting unused links...")); - removeUnusedLinks(); + removeUnusedLinks(state); } diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 721cc6afbed5..6a5e3641c4eb 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -264,7 +264,7 @@ private: int openGCLock(LockType lockType); - void removeUnusedLinks(); + void removeUnusedLinks(const GCState & state); void startSubstituter(const Path & substituter, RunningSubstituter & runningSubstituter); -- cgit 1.4.1 From d025142f529731f05868f5397f5617011963c8b4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Sun, 5 Aug 2012 21:45:27 -0400 Subject: Handle amount of disk space saved by hard linking being negative Fixes bogus messages like "currently hard linking saves 17592186044416.00 MiB". --- src/libstore/gc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstore/gc.cc') diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 255dc3aa099f..406fce672e3b 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -580,7 +580,7 @@ void LocalStore::removeUnusedLinks(const GCState & state) AutoCloseDir dir = opendir(linksDir.c_str()); if (!dir) throw SysError(format("opening directory `%1%'") % linksDir); - unsigned long long actualSize = 0, unsharedSize = 0; + long long actualSize = 0, unsharedSize = 0; struct dirent * dirent; while (errno = 0, dirent = readdir(dir)) { @@ -611,7 +611,7 @@ void LocalStore::removeUnusedLinks(const GCState & state) struct stat st; if (stat(linksDir.c_str(), &st) == -1) throw SysError(format("statting `%1%'") % linksDir); - unsigned long long overhead = st.st_blocks * 512ULL; + long long overhead = st.st_blocks * 512ULL; printMsg(lvlInfo, format("note: currently hard linking saves %.2f MiB") % ((unsharedSize - actualSize - overhead) / (1024.0 * 1024.0))); -- cgit 1.4.1