* A simple hack to fix NIX-18: the garbage collector cannot run when
the disk is full (because to delete something from the Nix store, we need a Berkeley DB transaction, which takes up disk space). Under normal operation, we make sure that there exists a file /nix/var/nix/db/reserved of 1 MB. When running the garbage collector, we delete that file before we open the Berkeley DB environment.
This commit is contained in:
parent
d6f586d0ea
commit
651ab439cf
|
@ -76,10 +76,24 @@ static void upgradeStore07();
|
|||
static void upgradeStore09();
|
||||
|
||||
|
||||
void openDB()
|
||||
void openDB(bool reserveSpace)
|
||||
{
|
||||
if (readOnlyMode) return;
|
||||
|
||||
try {
|
||||
Path reservedPath = nixDBPath + "/reserved";
|
||||
off_t reservedSize = 1024 * 1024;
|
||||
if (reserveSpace) {
|
||||
struct stat st;
|
||||
if (stat(reservedPath.c_str(), &st) == -1 ||
|
||||
st.st_size != reservedSize)
|
||||
writeFile(reservedPath, string(1024 * 1024, 'X'));
|
||||
}
|
||||
else
|
||||
deletePath(reservedPath);
|
||||
} catch (SysError & e) { /* don't care about errors */
|
||||
}
|
||||
|
||||
try {
|
||||
nixDB.open(nixDBPath);
|
||||
} catch (DbNoPermission & e) {
|
||||
|
|
|
@ -37,8 +37,14 @@ struct Substitute
|
|||
typedef list<Substitute> Substitutes;
|
||||
|
||||
|
||||
/* Open the database environment. */
|
||||
void openDB();
|
||||
/* Open the database environment. If `reserveSpace' is true, make
|
||||
sure that a big empty file exists in /nix/var/nix/db/reserved. If
|
||||
`reserveSpace' is false, delete this file if it exists. The idea
|
||||
is that on normal operation, the file exists; but when we run the
|
||||
garbage collector, it is deleted. This is to ensure that the
|
||||
garbage collector has a small amount of disk space available, which
|
||||
is required to open the Berkeley DB environment. */
|
||||
void openDB(bool reserveSpace = true);
|
||||
|
||||
/* Create the required database tables. */
|
||||
void initDB();
|
||||
|
|
|
@ -686,7 +686,7 @@ void run(Strings args)
|
|||
if (!op) throw UsageError("no operation specified");
|
||||
|
||||
if (op != opDump && op != opRestore) /* !!! hack */
|
||||
openDB();
|
||||
openDB(op != opGC);
|
||||
|
||||
op(opFlags, opArgs);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue