UDSRemoteStore: Support the 'root' store parameter

Useful when we're using a daemon with a chroot store, e.g.

  $ NIX_DAEMON_SOCKET_PATH=/tmp/chroot/nix/var/nix/daemon-socket/socket nix-daemon --store /tmp/chroot

Then the client can now connect with

  $ nix build --store unix:///tmp/chroot/nix/var/nix/daemon-socket/socket?root=/tmp/chroot nixpkgs#hello
This commit is contained in:
Eelco Dolstra 2021-06-18 17:04:11 +02:00
parent e6150de90d
commit 4202a3bc4e
7 changed files with 16 additions and 21 deletions

View file

@ -292,7 +292,7 @@ bool LocalDerivationGoal::cleanupDecideWhetherDiskFull()
auto & localStore = getLocalStore(); auto & localStore = getLocalStore();
uint64_t required = 8ULL * 1024 * 1024; // FIXME: make configurable uint64_t required = 8ULL * 1024 * 1024; // FIXME: make configurable
struct statvfs st; struct statvfs st;
if (statvfs(localStore.realStoreDir.c_str(), &st) == 0 && if (statvfs(localStore.realStoreDir.get().c_str(), &st) == 0 &&
(uint64_t) st.f_bavail * st.f_bsize < required) (uint64_t) st.f_bavail * st.f_bsize < required)
diskFull = true; diskFull = true;
if (statvfs(tmpDir.c_str(), &st) == 0 && if (statvfs(tmpDir.c_str(), &st) == 0 &&
@ -417,7 +417,7 @@ void LocalDerivationGoal::startBuilder()
} }
auto & localStore = getLocalStore(); auto & localStore = getLocalStore();
if (localStore.storeDir != localStore.realStoreDir) { if (localStore.storeDir != localStore.realStoreDir.get()) {
#if __linux__ #if __linux__
useChroot = true; useChroot = true;
#else #else

View file

@ -775,7 +775,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
try { try {
AutoCloseDir dir(opendir(realStoreDir.c_str())); AutoCloseDir dir(opendir(realStoreDir.get().c_str()));
if (!dir) throw SysError("opening directory '%1%'", realStoreDir); if (!dir) throw SysError("opening directory '%1%'", realStoreDir);
/* Read the store and immediately delete all paths that /* Read the store and immediately delete all paths that
@ -856,7 +856,7 @@ void LocalStore::autoGC(bool sync)
return std::stoll(readFile(*fakeFreeSpaceFile)); return std::stoll(readFile(*fakeFreeSpaceFile));
struct statvfs st; struct statvfs st;
if (statvfs(realStoreDir.c_str(), &st)) if (statvfs(realStoreDir.get().c_str(), &st))
throw SysError("getting filesystem info about '%s'", realStoreDir); throw SysError("getting filesystem info about '%s'", realStoreDir);
return (uint64_t) st.f_bavail * st.f_frsize; return (uint64_t) st.f_bavail * st.f_frsize;

View file

@ -18,6 +18,9 @@ struct LocalFSStoreConfig : virtual StoreConfig
const PathSetting logDir{(StoreConfig*) this, false, const PathSetting logDir{(StoreConfig*) this, false,
rootDir != "" ? rootDir + "/nix/var/log/nix" : settings.nixLogDir, rootDir != "" ? rootDir + "/nix/var/log/nix" : settings.nixLogDir,
"log", "directory where Nix will store state"}; "log", "directory where Nix will store state"};
const PathSetting realStoreDir{(StoreConfig*) this, false,
rootDir != "" ? rootDir + "/nix/store" : storeDir, "real",
"physical path to the Nix store"};
}; };
class LocalFSStore : public virtual LocalFSStoreConfig, public virtual Store class LocalFSStore : public virtual LocalFSStoreConfig, public virtual Store
@ -34,7 +37,7 @@ public:
/* Register a permanent GC root. */ /* Register a permanent GC root. */
Path addPermRoot(const StorePath & storePath, const Path & gcRoot); Path addPermRoot(const StorePath & storePath, const Path & gcRoot);
virtual Path getRealStoreDir() { return storeDir; } virtual Path getRealStoreDir() { return realStoreDir; }
Path toRealPath(const Path & storePath) override Path toRealPath(const Path & storePath) override
{ {

View file

@ -106,9 +106,6 @@ LocalStore::LocalStore(const Params & params)
, LocalStoreConfig(params) , LocalStoreConfig(params)
, Store(params) , Store(params)
, LocalFSStore(params) , LocalFSStore(params)
, realStoreDir_{this, false, rootDir != "" ? rootDir + "/nix/store" : storeDir, "real",
"physical path to the Nix store"}
, realStoreDir(realStoreDir_)
, dbDir(stateDir + "/db") , dbDir(stateDir + "/db")
, linksDir(realStoreDir + "/.links") , linksDir(realStoreDir + "/.links")
, reservedPath(dbDir + "/reserved") , reservedPath(dbDir + "/reserved")
@ -153,13 +150,13 @@ LocalStore::LocalStore(const Params & params)
printError("warning: the group '%1%' specified in 'build-users-group' does not exist", settings.buildUsersGroup); printError("warning: the group '%1%' specified in 'build-users-group' does not exist", settings.buildUsersGroup);
else { else {
struct stat st; struct stat st;
if (stat(realStoreDir.c_str(), &st)) if (stat(realStoreDir.get().c_str(), &st))
throw SysError("getting attributes of path '%1%'", realStoreDir); throw SysError("getting attributes of path '%1%'", realStoreDir);
if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) { if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) {
if (chown(realStoreDir.c_str(), 0, gr->gr_gid) == -1) if (chown(realStoreDir.get().c_str(), 0, gr->gr_gid) == -1)
throw SysError("changing ownership of path '%1%'", realStoreDir); throw SysError("changing ownership of path '%1%'", realStoreDir);
if (chmod(realStoreDir.c_str(), perm) == -1) if (chmod(realStoreDir.get().c_str(), perm) == -1)
throw SysError("changing permissions on path '%1%'", realStoreDir); throw SysError("changing permissions on path '%1%'", realStoreDir);
} }
} }
@ -437,14 +434,14 @@ void LocalStore::makeStoreWritable()
if (getuid() != 0) return; if (getuid() != 0) return;
/* Check if /nix/store is on a read-only mount. */ /* Check if /nix/store is on a read-only mount. */
struct statvfs stat; struct statvfs stat;
if (statvfs(realStoreDir.c_str(), &stat) != 0) if (statvfs(realStoreDir.get().c_str(), &stat) != 0)
throw SysError("getting info about the Nix store mount point"); throw SysError("getting info about the Nix store mount point");
if (stat.f_flag & ST_RDONLY) { if (stat.f_flag & ST_RDONLY) {
if (unshare(CLONE_NEWNS) == -1) if (unshare(CLONE_NEWNS) == -1)
throw SysError("setting up a private mount namespace"); throw SysError("setting up a private mount namespace");
if (mount(0, realStoreDir.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) if (mount(0, realStoreDir.get().c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
throw SysError("remounting %1% writable", realStoreDir); throw SysError("remounting %1% writable", realStoreDir);
} }
#endif #endif

View file

@ -83,9 +83,6 @@ private:
public: public:
PathSetting realStoreDir_;
const Path realStoreDir;
const Path dbDir; const Path dbDir;
const Path linksDir; const Path linksDir;
const Path reservedPath; const Path reservedPath;
@ -279,8 +276,6 @@ private:
void signPathInfo(ValidPathInfo & info); void signPathInfo(ValidPathInfo & info);
void signRealisation(Realisation &); void signRealisation(Realisation &);
Path getRealStoreDir() override { return realStoreDir; }
void createUser(const std::string & userName, uid_t userId) override; void createUser(const std::string & userName, uid_t userId) override;
// XXX: Make a generic `Store` method // XXX: Make a generic `Store` method

View file

@ -198,7 +198,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
/* Make the containing directory writable, but only if it's not /* Make the containing directory writable, but only if it's not
the store itself (we don't want or need to mess with its the store itself (we don't want or need to mess with its
permissions). */ permissions). */
bool mustToggle = dirOf(path) != realStoreDir; bool mustToggle = dirOf(path) != realStoreDir.get();
if (mustToggle) makeWritable(dirOf(path)); if (mustToggle) makeWritable(dirOf(path));
/* When we're done, make the directory read-only again and reset /* When we're done, make the directory read-only again and reset

View file

@ -43,8 +43,8 @@ struct RunCommon : virtual Command
helper program (chrootHelper() below) to do the work. */ helper program (chrootHelper() below) to do the work. */
auto store2 = store.dynamic_pointer_cast<LocalStore>(); auto store2 = store.dynamic_pointer_cast<LocalStore>();
if (store2 && store->storeDir != store2->realStoreDir) { if (store2 && store->storeDir != store2->getRealStoreDir()) {
Strings helperArgs = { chrootHelperName, store->storeDir, store2->realStoreDir, program }; Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program };
for (auto & arg : args) helperArgs.push_back(arg); for (auto & arg : args) helperArgs.push_back(arg);
execv(readLink("/proc/self/exe").c_str(), stringsToCharPtrs(helperArgs).data()); execv(readLink("/proc/self/exe").c_str(), stringsToCharPtrs(helperArgs).data());