~ruther/guix-local

12b6c951cf5ca6055a22a2eec85665353f5510e5 — Ludovic Courtès 9 years ago b1fd0ab
daemon: Do not error out when deduplication fails due to ENOSPC.

This solves a problem whereby if /gnu/store/.links had enough entries,
ext4's directory index would be full, leading to link(2) returning
ENOSPC.

* nix/libstore/optimise-store.cc (LocalStore::optimisePath_): Upon
ENOSPC from link(2), print a message and return instead of throwing a
'SysError'.
1 files changed, 18 insertions(+), 5 deletions(-)

M nix/libstore/optimise-store.cc
M nix/libstore/optimise-store.cc => nix/libstore/optimise-store.cc +18 -5
@@ 148,10 148,23 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
            inodeHash.insert(st.st_ino);
            return;
        }
        if (errno != EEXIST)

	switch (errno) {
	case EEXIST:
	    /* Fall through if another process created ‘linkPath’ before
	       we did. */
	    break;

	case ENOSPC:
	    /* On ext4, that probably means the directory index is full.  When
	       that happens, it's fine to ignore it: we just effectively
	       disable deduplication of this file.  */
	    printMsg(lvlInfo, format("cannot link `%1%' to `%2%': %m") % linkPath % path);
	    return;

	default:
            throw SysError(format("cannot link `%1%' to `%2%'") % linkPath % path);
        /* Fall through if another process created ‘linkPath’ before
           we did. */
	}
    }

    /* Yes!  We've seen a file with the same contents.  Replace the


@@ 195,8 208,8 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
                printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath);
            return;
        }
        throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath);
    }
	    throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath);
	}

    /* Atomically replace the old file with the new hard link. */
    if (rename(tempLink.c_str(), path.c_str()) == -1) {