aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2015-11-09 20:48:09 +0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2015-11-09 21:28:25 +0100
commit4384bbd2e151e7b6f627cb022ea1cc4f5dcbe180 (patch)
treef6d22513f89a797897584342dcd0c563e6e9be8b /src
parent7759a56bedf5136704605409a3b5b758fd4233d4 (diff)
optimizePath(): Detect some .links corruption
If automatic store optimisation is enabled, and a hard-linked file in the store gets corrupted, then the corresponding .links entry will also be corrupted. In that case, trying to repair with --repair or --repair-path won't work, because the new "good" file will be replaced by a hard link to the corrupted file. We can catch most of these cases by doing a sanity-check on the file sizes.
Diffstat (limited to 'src')
-rw-r--r--src/libstore/optimise-store.cc11
1 files changed, 9 insertions, 2 deletions
diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc
index 6f6696179..23cbe7e26 100644
--- a/src/libstore/optimise-store.cc
+++ b/src/libstore/optimise-store.cc
@@ -120,9 +120,9 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
return;
}
- /* This can still happen on top-level files */
+ /* This can still happen on top-level files. */
if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) {
- printMsg(lvlDebug, format("‘%1%’ is already linked, with %2% other file(s).") % path % (st.st_nlink - 2));
+ printMsg(lvlDebug, format("‘%1%’ is already linked, with %2% other file(s)") % path % (st.st_nlink - 2));
return;
}
@@ -141,6 +141,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
/* Check if this is a known hash. */
Path linkPath = linksDir + "/" + printHash32(hash);
+ retry:
if (!pathExists(linkPath)) {
/* Nope, create a hard link in the links directory. */
if (link(path.c_str(), linkPath.c_str()) == 0) {
@@ -164,6 +165,12 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
return;
}
+ if (st.st_size != stLink.st_size) {
+ printMsg(lvlError, format("removing corrupted link ‘%1%’") % linkPath);
+ unlink(linkPath.c_str());
+ goto retry;
+ }
+
printMsg(lvlTalkative, format("linking ‘%1%’ to ‘%2%’") % path % linkPath);
/* Make the containing directory writable, but only if it's not