flush OS write buffers before saving control file

This ensures that pieces are physically written to disk before
marking them as finished in the control file.

This should prevent data loss and corruption when resuming downloads
after a system crash.

Signed-off-by: Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com>
pull/1644/head
Ali MJ Al-Nasrawy 2020-06-17 09:51:04 +03:00
parent 870e2a6014
commit 01969fc530
9 changed files with 42 additions and 0 deletions

View File

@ -590,4 +590,16 @@ void AbstractDiskWriter::dropCache(int64_t len, int64_t offset)
#endif // HAVE_POSIX_FADVISE #endif // HAVE_POSIX_FADVISE
} }
void AbstractDiskWriter::flushOSBuffers()
{
if (fd_ == A2_BAD_FD) {
return;
}
#ifdef __MINGW32__
FlushFileBuffers(fd_);
#else // !__MINGW32__
fsync(fd_);
#endif // __MINGW32__
}
} // namespace aria2 } // namespace aria2

View File

@ -100,6 +100,8 @@ public:
virtual void enableMmap() CXX11_OVERRIDE; virtual void enableMmap() CXX11_OVERRIDE;
virtual void dropCache(int64_t len, int64_t offset) CXX11_OVERRIDE; virtual void dropCache(int64_t len, int64_t offset) CXX11_OVERRIDE;
virtual void flushOSBuffers() CXX11_OVERRIDE;
}; };
} // namespace aria2 } // namespace aria2

View File

@ -103,6 +103,11 @@ void AbstractSingleDiskAdaptor::writeCache(const WrDiskCacheEntry* entry)
} }
} }
void AbstractSingleDiskAdaptor::flushOSBuffers()
{
diskWriter_->flushOSBuffers();
}
bool AbstractSingleDiskAdaptor::fileExists() bool AbstractSingleDiskAdaptor::fileExists()
{ {
return File(getFilePath()).exists(); return File(getFilePath()).exists();

View File

@ -72,6 +72,8 @@ public:
virtual void writeCache(const WrDiskCacheEntry* entry) CXX11_OVERRIDE; virtual void writeCache(const WrDiskCacheEntry* entry) CXX11_OVERRIDE;
virtual void flushOSBuffers() CXX11_OVERRIDE;
virtual bool fileExists() CXX11_OVERRIDE; virtual bool fileExists() CXX11_OVERRIDE;
virtual int64_t size() CXX11_OVERRIDE; virtual int64_t size() CXX11_OVERRIDE;

View File

@ -114,6 +114,9 @@ public:
// Writes cached data to the underlying disk. // Writes cached data to the underlying disk.
virtual void writeCache(const WrDiskCacheEntry* entry) = 0; virtual void writeCache(const WrDiskCacheEntry* entry) = 0;
// Force physical write of data from OS buffer cache.
virtual void flushOSBuffers() {};
void setFileAllocationMethod(FileAllocationMethod method) void setFileAllocationMethod(FileAllocationMethod method)
{ {
fileAllocationMethod_ = method; fileAllocationMethod_ = method;

View File

@ -85,6 +85,9 @@ public:
// Drops cache in range [offset, offset + len) // Drops cache in range [offset, offset + len)
virtual void dropCache(int64_t len, int64_t offset) {} virtual void dropCache(int64_t len, int64_t offset) {}
// Force physical write of data from OS buffer cache.
virtual void flushOSBuffers() {}
}; };
} // namespace aria2 } // namespace aria2

View File

@ -419,6 +419,17 @@ void MultiDiskAdaptor::writeCache(const WrDiskCacheEntry* entry)
} }
} }
void MultiDiskAdaptor::flushOSBuffers()
{
for (auto& dwent : openedDiskWriterEntries_) {
auto& dw = dwent->getDiskWriter();
if (!dw) {
continue;
}
dw->flushOSBuffers();
}
}
bool MultiDiskAdaptor::fileExists() bool MultiDiskAdaptor::fileExists()
{ {
return std::find_if(std::begin(getFileEntries()), std::end(getFileEntries()), return std::find_if(std::begin(getFileEntries()), std::end(getFileEntries()),

View File

@ -135,6 +135,8 @@ public:
virtual void writeCache(const WrDiskCacheEntry* entry) CXX11_OVERRIDE; virtual void writeCache(const WrDiskCacheEntry* entry) CXX11_OVERRIDE;
virtual void flushOSBuffers() CXX11_OVERRIDE;
virtual bool fileExists() CXX11_OVERRIDE; virtual bool fileExists() CXX11_OVERRIDE;
virtual int64_t size() CXX11_OVERRIDE; virtual int64_t size() CXX11_OVERRIDE;

View File

@ -211,6 +211,7 @@ void RequestGroup::closeFile()
{ {
if (pieceStorage_) { if (pieceStorage_) {
pieceStorage_->flushWrDiskCacheEntry(true); pieceStorage_->flushWrDiskCacheEntry(true);
pieceStorage_->getDiskAdaptor()->flushOSBuffers();
pieceStorage_->getDiskAdaptor()->closeFile(); pieceStorage_->getDiskAdaptor()->closeFile();
} }
} }
@ -1292,6 +1293,7 @@ void RequestGroup::saveControlFile() const
if (saveControlFile_) { if (saveControlFile_) {
if (pieceStorage_) { if (pieceStorage_) {
pieceStorage_->flushWrDiskCacheEntry(false); pieceStorage_->flushWrDiskCacheEntry(false);
pieceStorage_->getDiskAdaptor()->flushOSBuffers();
} }
progressInfoFile_->save(); progressInfoFile_->save();
} }