forked from lix-project/lix
* 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();
|
static void upgradeStore09();
|
||||||
|
|
||||||
|
|
||||||
void openDB()
|
void openDB(bool reserveSpace)
|
||||||
{
|
{
|
||||||
if (readOnlyMode) return;
|
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 {
|
try {
|
||||||
nixDB.open(nixDBPath);
|
nixDB.open(nixDBPath);
|
||||||
} catch (DbNoPermission & e) {
|
} catch (DbNoPermission & e) {
|
||||||
|
|
|
@ -37,8 +37,14 @@ struct Substitute
|
||||||
typedef list<Substitute> Substitutes;
|
typedef list<Substitute> Substitutes;
|
||||||
|
|
||||||
|
|
||||||
/* Open the database environment. */
|
/* Open the database environment. If `reserveSpace' is true, make
|
||||||
void openDB();
|
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. */
|
/* Create the required database tables. */
|
||||||
void initDB();
|
void initDB();
|
||||||
|
|
|
@ -686,7 +686,7 @@ void run(Strings args)
|
||||||
if (!op) throw UsageError("no operation specified");
|
if (!op) throw UsageError("no operation specified");
|
||||||
|
|
||||||
if (op != opDump && op != opRestore) /* !!! hack */
|
if (op != opDump && op != opRestore) /* !!! hack */
|
||||||
openDB();
|
openDB(op != opGC);
|
||||||
|
|
||||||
op(opFlags, opArgs);
|
op(opFlags, opArgs);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue