nix-store -q --roots / --gc --print-roots: Print temporary / in-memory roots

For example,

  $ nix-store -q --roots /nix/store/7phd2sav7068nivgvmj2vpm3v47fd27l-patchelf-0.8pre845_0315148
  {temp:1}

denotes that the path is only being kept alive by a temporary root
(i.e. /nix/var/nix/temproots/). Similarly,

  $ nix-store --gc --print-roots
  ...
  {memory:9} -> /nix/store/094gpjn9f15ip17wzxhma4r51nvsj17p-curl-7.53.1

shows that curl is being used by some process.
This commit is contained in:
Eelco Dolstra 2017-09-14 14:38:36 +02:00
parent 970366266b
commit da1e4fdfb5
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
2 changed files with 41 additions and 22 deletions

View file

@ -196,8 +196,10 @@ void LocalStore::addTempRoot(const Path & path)
} }
void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds) PathSet LocalStore::readTempRoots(FDs & fds)
{ {
PathSet tempRoots;
/* Read the `temproots' directory for per-process temporary root /* Read the `temproots' directory for per-process temporary root
files. */ files. */
DirEntries tempRootFiles = readDirectory(tempRootsDir); DirEntries tempRootFiles = readDirectory(tempRootsDir);
@ -253,6 +255,8 @@ void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds)
fds.push_back(fd); /* keep open */ fds.push_back(fd); /* keep open */
} }
return tempRoots;
} }
@ -316,7 +320,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
} }
Roots LocalStore::findRoots() Roots LocalStore::findRootsNoTemp()
{ {
Roots roots; Roots roots;
@ -326,6 +330,27 @@ Roots LocalStore::findRoots()
findRoots(stateDir + "/manifests", DT_UNKNOWN, roots); findRoots(stateDir + "/manifests", DT_UNKNOWN, roots);
findRoots(stateDir + "/profiles", DT_UNKNOWN, roots); findRoots(stateDir + "/profiles", DT_UNKNOWN, roots);
/* Add additional roots returned by the program specified by the
NIX_ROOT_FINDER environment variable. This is typically used
to add running programs to the set of roots (to prevent them
from being garbage collected). */
size_t n = 0;
for (auto & root : findRuntimeRoots())
roots[fmt("{memory:%d}", n++)] = root;
return roots;
}
Roots LocalStore::findRoots()
{
Roots roots = findRootsNoTemp();
FDs fds;
size_t n = 0;
for (auto & root : readTempRoots(fds))
roots[fmt("{temp:%d}", n++)] = root;
return roots; return roots;
} }
@ -369,8 +394,9 @@ static void readFileRoots(const char * path, StringSet & paths)
} }
} }
void LocalStore::findRuntimeRoots(PathSet & roots) PathSet LocalStore::findRuntimeRoots()
{ {
PathSet roots;
StringSet paths; StringSet paths;
auto procDir = AutoCloseDir{opendir("/proc")}; auto procDir = AutoCloseDir{opendir("/proc")};
if (procDir) { if (procDir) {
@ -454,6 +480,8 @@ void LocalStore::findRuntimeRoots(PathSet & roots)
roots.insert(path); roots.insert(path);
} }
} }
return roots;
} }
@ -554,17 +582,13 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & path) bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & path)
{ {
if (visited.find(path) != visited.end()) return false; if (visited.count(path)) return false;
if (state.alive.find(path) != state.alive.end()) { if (state.alive.count(path)) return true;
return true;
}
if (state.dead.find(path) != state.dead.end()) { if (state.dead.count(path)) return false;
return false;
}
if (state.roots.find(path) != state.roots.end()) { if (state.roots.count(path)) {
debug(format("cannot delete '%1%' because it's a root") % path); debug(format("cannot delete '%1%' because it's a root") % path);
state.alive.insert(path); state.alive.insert(path);
return true; return true;
@ -724,22 +748,15 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
/* Find the roots. Since we've grabbed the GC lock, the set of /* Find the roots. Since we've grabbed the GC lock, the set of
permanent roots cannot increase now. */ permanent roots cannot increase now. */
printError(format("finding garbage collector roots...")); printError(format("finding garbage collector roots..."));
Roots rootMap = options.ignoreLiveness ? Roots() : findRoots(); Roots rootMap = options.ignoreLiveness ? Roots() : findRootsNoTemp();
for (auto & i : rootMap) state.roots.insert(i.second); for (auto & i : rootMap) state.roots.insert(i.second);
/* Add additional roots returned by the program specified by the
NIX_ROOT_FINDER environment variable. This is typically used
to add running programs to the set of roots (to prevent them
from being garbage collected). */
if (!options.ignoreLiveness)
findRuntimeRoots(state.roots);
/* Read the temporary roots. This acquires read locks on all /* Read the temporary roots. This acquires read locks on all
per-process temporary root files. So after this point no paths per-process temporary root files. So after this point no paths
can be added to the set of temporary roots. */ can be added to the set of temporary roots. */
FDs fds; FDs fds;
readTempRoots(state.tempRoots, fds); state.tempRoots = readTempRoots(fds);
state.roots.insert(state.tempRoots.begin(), state.tempRoots.end()); state.roots.insert(state.tempRoots.begin(), state.tempRoots.end());
/* After this point the set of roots or temporary roots cannot /* After this point the set of roots or temporary roots cannot

View file

@ -176,7 +176,7 @@ private:
typedef std::shared_ptr<AutoCloseFD> FDPtr; typedef std::shared_ptr<AutoCloseFD> FDPtr;
typedef list<FDPtr> FDs; typedef list<FDPtr> FDs;
void readTempRoots(PathSet & tempRoots, FDs & fds); PathSet readTempRoots(FDs & fds);
public: public:
@ -261,7 +261,9 @@ private:
void findRoots(const Path & path, unsigned char type, Roots & roots); void findRoots(const Path & path, unsigned char type, Roots & roots);
void findRuntimeRoots(PathSet & roots); Roots findRootsNoTemp();
PathSet findRuntimeRoots();
void removeUnusedLinks(const GCState & state); void removeUnusedLinks(const GCState & state);