daemon: optimizePath: Detect some .links corruptions.
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.
This commit is contained in:
parent
14fb686a21
commit
e134baae77
@ -120,7 +120,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
|
|||||||
return;
|
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)) {
|
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;
|
return;
|
||||||
@ -141,6 +141,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
|
|||||||
/* Check if this is a known hash. */
|
/* Check if this is a known hash. */
|
||||||
Path linkPath = linksDir + "/" + printHash32(hash);
|
Path linkPath = linksDir + "/" + printHash32(hash);
|
||||||
|
|
||||||
|
retry:
|
||||||
if (!pathExists(linkPath)) {
|
if (!pathExists(linkPath)) {
|
||||||
/* Nope, create a hard link in the links directory. */
|
/* Nope, create a hard link in the links directory. */
|
||||||
if (link(path.c_str(), linkPath.c_str()) == 0) {
|
if (link(path.c_str(), linkPath.c_str()) == 0) {
|
||||||
@ -164,7 +165,13 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printMsg(lvlTalkative, format("linking `%1%' to `%2%'") % path % linkPath);
|
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
|
/* Make the containing directory writable, but only if it's not
|
||||||
the store itself (we don't want or need to mess with its
|
the store itself (we don't want or need to mess with its
|
||||||
|
Loading…
Reference in New Issue
Block a user