mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-10-11 22:49:55 +00:00
savedata: scoped filesystem sync
This commit is contained in:
+19
-1
@@ -1892,11 +1892,29 @@ bool fs::utime(const std::string& path, s64 atime, s64 mtime)
|
||||
#endif
|
||||
}
|
||||
|
||||
void fs::sync()
|
||||
void fs::sync(const std::string& path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
static_cast<void>(path);
|
||||
fs::g_tls_error = fs::error::unknown;
|
||||
#elif defined(__linux__)
|
||||
// Only flush the filesystem containing the path: a global sync() also waits on every other mounted
|
||||
// filesystem and may block indefinitely on a slow or stalled one (e.g. network or FUSE mounts)
|
||||
const int fd = ::open(path.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
fs::g_tls_error = to_error(errno);
|
||||
return;
|
||||
}
|
||||
|
||||
const int res = ::syncfs(fd);
|
||||
const int err = errno;
|
||||
::close(fd);
|
||||
|
||||
fs::g_tls_error = res == 0 ? fs::error::ok : to_error(err);
|
||||
#else
|
||||
static_cast<void>(path);
|
||||
::sync();
|
||||
fs::g_tls_error = fs::error::ok;
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -263,8 +263,8 @@ namespace fs
|
||||
// Set file access/modification time
|
||||
bool utime(const std::string& path, s64 atime, s64 mtime);
|
||||
|
||||
// Synchronize filesystems (TODO)
|
||||
void sync();
|
||||
// Synchronize the filesystem containing the given path (only that filesystem where supported)
|
||||
void sync(const std::string& path);
|
||||
|
||||
class file final
|
||||
{
|
||||
|
||||
@@ -2189,7 +2189,14 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
|
||||
// Remove old backup
|
||||
fs::remove_all(old_path);
|
||||
fs::sync();
|
||||
fs::sync(new_path);
|
||||
|
||||
#ifndef _WIN32
|
||||
if (fs::g_tls_error != fs::error::ok)
|
||||
{
|
||||
cellSaveData.warning("savedata_op(): Failed to sync filesystem of '%s' (%s)", new_path, fs::g_tls_error);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Backup old savedata
|
||||
if (!vfs::host::rename(dir_path, old_path, &g_mp_sys_dev_hdd0, false))
|
||||
|
||||
@@ -1094,6 +1094,10 @@ bool vfs::host::rename(const std::string& from, const std::string& to, const lv2
|
||||
|
||||
bool res = false;
|
||||
|
||||
const auto retry_start = std::chrono::steady_clock::now();
|
||||
auto retry_report = retry_start;
|
||||
u64 retry_count = 0;
|
||||
|
||||
for (;; std::this_thread::yield())
|
||||
{
|
||||
if (fs::rename(from, to, overwrite))
|
||||
@@ -1107,6 +1111,16 @@ bool vfs::host::rename(const std::string& from, const std::string& to, const lv2
|
||||
res = false;
|
||||
break;
|
||||
}
|
||||
|
||||
retry_count++;
|
||||
|
||||
// Report a retry loop which is taking long, it may never end if the error is persistent
|
||||
if (const auto now = std::chrono::steady_clock::now(); now - retry_report >= std::chrono::seconds(1))
|
||||
{
|
||||
retry_report = now;
|
||||
vfs_log.warning("vfs::host::rename(): Still retrying after %u attempts and %u ms (from='%s', to='%s', error=%s)", retry_count,
|
||||
static_cast<u64>(std::chrono::duration_cast<std::chrono::milliseconds>(now - retry_start).count()), from, to, fs::g_tls_error);
|
||||
}
|
||||
}
|
||||
|
||||
const auto fs_error = fs::g_tls_error;
|
||||
|
||||
Reference in New Issue
Block a user