From 12b6c951cf5ca6055a22a2eec85665353f5510e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= Date: Fri, 28 Oct 2016 20:34:15 +0200 Subject: [PATCH] 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'. --- nix/libstore/optimise-store.cc | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/nix/libstore/optimise-store.cc b/nix/libstore/optimise-store.cc index d7508b025e..565c62ca83 100644 --- a/nix/libstore/optimise-store.cc +++ b/nix/libstore/optimise-store.cc @@ -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) {