From ccb10220228250066e8dc487894fb1e11b338c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= Date: Mon, 14 Nov 2016 13:33:36 +0100 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'. --- src/libstore/optimise-store.cc | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 1bf8b7d83..2fd9a9bb8 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -148,10 +148,24 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa inodeHash.insert(st.st_ino); return; } - if (errno != EEXIST) - throw SysError(format("cannot link ‘%1%’ to ‘%2%’") % linkPath % path); - /* Fall through if another process created ‘linkPath’ before - we did. */ + + 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. */ + printInfo("cannot link ‘%s’ to ‘%s’: %m", linkPath, path); + return; + + default: + throw SysError("cannot link ‘%1%’ to ‘%2%’", linkPath, path); + } } /* Yes! We've seen a file with the same contents. Replace the @@ -195,7 +209,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa printInfo(format("‘%1%’ has maximum number of links") % linkPath); return; } - throw SysError(format("cannot link ‘%1%’ to ‘%2%’") % tempLink % linkPath); + throw SysError("cannot link ‘%1%’ to ‘%2%’", tempLink, linkPath); } /* Atomically replace the old file with the new hard link. */