diff --git a/src/addrdb.cpp b/src/addrdb.cpp --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -53,7 +53,9 @@ if (!SerializeDB(chainParams, fileout, data)) { return false; } - FileCommit(fileout.Get()); + if (!FileCommit(fileout.Get())) { + return error("%s: Failed to flush file %s", __func__, pathTmp.string()); + } fileout.fclose(); // replace existing file, if any, with new file diff --git a/src/util.h b/src/util.h --- a/src/util.h +++ b/src/util.h @@ -67,7 +67,7 @@ } void PrintExceptionContinue(const std::exception *pex, const char *pszThread); -void FileCommit(FILE *file); +bool FileCommit(FILE *file); bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); diff --git a/src/util.cpp b/src/util.cpp --- a/src/util.cpp +++ b/src/util.cpp @@ -978,21 +978,40 @@ return false; } -void FileCommit(FILE *file) { - // Harmless if redundantly called. - fflush(file); +bool FileCommit(FILE *file) { + // harmless if redundantly called + if (fflush(file) != 0) { + 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)); + // Ignore EINVAL for filesystems that don't support sync + if (fdatasync(fileno(file)) != 0 && errno != EINVAL) { + LogPrintf("%s: fdatasync failed: %d\n", __func__, errno); + return false; + } #elif defined(__APPLE__) && defined(F_FULLFSYNC) - fcntl(fileno(file), F_FULLFSYNC, 0); + // Manpage says "value other than -1" is returned on success + if (fcntl(fileno(file), F_FULLFSYNC, 0) == -1) { + 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) { diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1487,24 +1487,32 @@ LOCK(cs_LastBlockFile); CDiskBlockPos posOld(nLastBlockFile, 0); + bool status = true; FILE *fileOld = OpenBlockFile(posOld); if (fileOld) { if (fFinalize) { - TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nSize); + status &= + TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nSize); } - FileCommit(fileOld); + status &= FileCommit(fileOld); fclose(fileOld); } fileOld = OpenUndoFile(posOld); if (fileOld) { if (fFinalize) { - TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nUndoSize); + status &= + TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nUndoSize); } - FileCommit(fileOld); + status &= FileCommit(fileOld); fclose(fileOld); } + + if (!status) { + AbortNode("Flushing block file to disk failed. This is likely the " + "result of an I/O error."); + } } static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, @@ -5625,7 +5633,9 @@ } file << mapDeltas; - FileCommit(file.Get()); + if (!FileCommit(file.Get())) { + throw std::runtime_error("FileCommit failed"); + } file.fclose(); RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat");