diff --git a/rpcs3/Emu/Cell/Modules/cellSysCache.cpp b/rpcs3/Emu/Cell/Modules/cellSysCache.cpp index d82d46b15c..e0b8920811 100644 --- a/rpcs3/Emu/Cell/Modules/cellSysCache.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysCache.cpp @@ -69,10 +69,10 @@ struct syscache_info } } - void clear(bool remove_root) const noexcept + void clear(bool remove_root, bool lock = false) const noexcept { // Clear cache - if (!vfs::host::remove_all(cache_root + cache_id, cache_root, &g_mp_sys_dev_hdd1, remove_root)) + if (!vfs::host::remove_all(cache_root + cache_id, cache_root, &g_mp_sys_dev_hdd1, remove_root, lock)) { cellSysutil.fatal("cellSysCache: failed to clear cache directory '%s%s' (%s)", cache_root, cache_id, fs::g_tls_error); } diff --git a/rpcs3/Emu/VFS.cpp b/rpcs3/Emu/VFS.cpp index 9fe7cb214d..9aa4862144 100644 --- a/rpcs3/Emu/VFS.cpp +++ b/rpcs3/Emu/VFS.cpp @@ -927,13 +927,18 @@ std::string vfs::host::hash_path(const std::string& path, const std::string& dev return fmt::format(u8"%s/$%s%s", dev_root, fmt::base57(std::hash()(path)), fmt::base57(utils::get_unique_tsc())); } -bool vfs::host::rename(const std::string& from, const std::string& to, const lv2_fs_mount_point* mp, bool overwrite) +bool vfs::host::rename(const std::string& from, const std::string& to, const lv2_fs_mount_point* mp, bool overwrite, bool lock) { // Lock mount point, close file descriptors, retry const auto from0 = std::string_view(from).substr(0, from.find_last_not_of(fs::delim) + 1); const auto escaped_from = Emu.GetCallbacks().resolve_path(from); - std::lock_guard lock(mp->mutex); + std::unique_lock mp_lock(mp->mutex, std::defer_lock); + + if (lock) + { + mp_lock.lock(); + } auto check_path = [&](std::string_view path) { @@ -1045,7 +1050,7 @@ bool vfs::host::unlink(const std::string& path, [[maybe_unused]] const std::stri #endif } -bool vfs::host::remove_all(const std::string& path, [[maybe_unused]] const std::string& dev_root, [[maybe_unused]] const lv2_fs_mount_point* mp, bool remove_root) +bool vfs::host::remove_all(const std::string& path, [[maybe_unused]] const std::string& dev_root, [[maybe_unused]] const lv2_fs_mount_point* mp, bool remove_root, bool lock) { #ifdef _WIN32 if (remove_root) @@ -1053,12 +1058,12 @@ bool vfs::host::remove_all(const std::string& path, [[maybe_unused]] const std:: // Rename to special dummy folder which will be ignored by VFS (but opened file handles can still read or write it) const std::string dummy = hash_path(path, dev_root); - if (!vfs::host::rename(path, dummy, mp, false)) + if (!vfs::host::rename(path, dummy, mp, false, lock)) { return false; } - if (!vfs::host::remove_all(dummy, dev_root, mp, false)) + if (!vfs::host::remove_all(dummy, dev_root, mp, false, lock)) { return false; } @@ -1093,7 +1098,7 @@ bool vfs::host::remove_all(const std::string& path, [[maybe_unused]] const std:: } else { - if (!vfs::host::remove_all(path + '/' + entry.name, dev_root, mp)) + if (!vfs::host::remove_all(path + '/' + entry.name, dev_root, mp, true, lock)) { return false; } diff --git a/rpcs3/Emu/VFS.h b/rpcs3/Emu/VFS.h index 0f69a2b697..7b71e6d83b 100644 --- a/rpcs3/Emu/VFS.h +++ b/rpcs3/Emu/VFS.h @@ -34,12 +34,12 @@ namespace vfs std::string hash_path(const std::string& path, const std::string& dev_root); // Call fs::rename with retry on access error - bool rename(const std::string& from, const std::string& to, const lv2_fs_mount_point* mp, bool overwrite); + bool rename(const std::string& from, const std::string& to, const lv2_fs_mount_point* mp, bool overwrite, bool lock = true); // Delete file without deleting its contents, emulated with MoveFileEx on Windows bool unlink(const std::string& path, const std::string& dev_root); // Delete folder contents using rename, done atomically if remove_root is true - bool remove_all(const std::string& path, const std::string& dev_root, const lv2_fs_mount_point* mp, bool remove_root = true); + bool remove_all(const std::string& path, const std::string& dev_root, const lv2_fs_mount_point* mp, bool remove_root = true, bool lock = true); } }