savedata: scoped filesystem sync

This commit is contained in:
Antonino Di Guardo
2026-10-01 13:38:26 +00:00
committed by GitHub
parent 4d88114c92
commit dfc0542a9f
4 changed files with 43 additions and 4 deletions
+19 -1
View File
@@ -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
View File
@@ -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
{
+8 -1
View File
@@ -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))
+14
View File
@@ -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;