summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2016-10-28 20:34:15 +0200
committerLudovic Courtès <ludo@gnu.org>2016-10-28 22:30:17 +0200
commit12b6c951cf5ca6055a22a2eec85665353f5510e5 (patch)
treed5350f52cf28075df53819e8912c97c84a86eb12
parentb1fd0ab73425e682a0a1404da6963f47a033bb34 (diff)
downloadguix-12b6c951cf5ca6055a22a2eec85665353f5510e5.tar.gz
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'.
-rw-r--r--nix/libstore/optimise-store.cc23
1 files 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) {