diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-04-23 14:29:15 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-04-23 14:30:26 +0200 |
commit | 8b4081a889b35cac3ccafa4f7109c72ccb087518 (patch) | |
tree | c23b86c73797cd0dbac4aa698d05957ced6c9395 /src/util.cpp | |
parent | e2746db66fd5b4a37ec1117de012a45ba3d8f3a5 (diff) | |
parent | cf0277928fa8d955d75f661021845789194dfff7 (diff) | |
download | bitcoin-8b4081a889b35cac3ccafa4f7109c72ccb087518.tar.xz |
Merge #13039: Add logging and error handling for file syncing
cf02779 Add logging and error handling for file syncing (Wladimir J. van der Laan)
Pull request description:
Add logging and error handling inside, and outside of FileCommit.
Functions such as fsync, fdatasync will return error in case of hardware I/O errors, and ignoring this means it can silently continue through data corruption.
(c.f. https://lwn.net/SubscriberLink/752063/12b232ab5039efbe/)
EINVAL is handled specially to avoid crashing out on (network, fuse) filesystems that don't handle `f[data]sync`.
I checked that the syncing inside leveldb is already generating an I/O error as appropriate.
Tree-SHA512: 64cc9bbedca3ecc97ff4bac0a7b7ac6526a7ed763c66f6786d03ca4f2e9e366e42b152cb908299c060448d98ca39ff03395280bffaca51d592e728aa2516f5dd
Diffstat (limited to 'src/util.cpp')
-rw-r--r-- | src/util.cpp | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/src/util.cpp b/src/util.cpp index 4fb027b731..9a3067259f 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -788,21 +788,37 @@ bool TryCreateDirectories(const fs::path& p) return false; } -void FileCommit(FILE *file) +bool FileCommit(FILE *file) { - fflush(file); // harmless if redundantly called + if (fflush(file) != 0) { // harmless if redundantly called + LogPrintf("%s: fflush failed: %d\n", __func__, errno); + return false; + } #ifdef WIN32 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file)); - FlushFileBuffers(hFile); + if (FlushFileBuffers(hFile) == 0) { + LogPrintf("%s: FlushFileBuffers failed: %d\n", __func__, GetLastError()); + return false; + } #else #if defined(__linux__) || defined(__NetBSD__) - fdatasync(fileno(file)); + if (fdatasync(fileno(file)) != 0 && errno != EINVAL) { // Ignore EINVAL for filesystems that don't support sync + LogPrintf("%s: fdatasync failed: %d\n", __func__, errno); + return false; + } #elif defined(__APPLE__) && defined(F_FULLFSYNC) - fcntl(fileno(file), F_FULLFSYNC, 0); + if (fcntl(fileno(file), F_FULLFSYNC, 0) == -1) { // Manpage says "value other than -1" is returned on success + LogPrintf("%s: fcntl F_FULLFSYNC failed: %d\n", __func__, errno); + return false; + } #else - fsync(fileno(file)); + if (fsync(fileno(file)) != 0 && errno != EINVAL) { + LogPrintf("%s: fsync failed: %d\n", __func__, errno); + return false; + } #endif #endif + return true; } bool TruncateFile(FILE *file, unsigned int length) { |