VFS: Fix recursive locking

This commit is contained in:
Eladash 2023-10-03 04:43:39 +03:00 committed by Elad Ashkenazi
parent 4b827a8d9c
commit ce3d7f90fd
3 changed files with 15 additions and 10 deletions

View File

@ -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 // 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); cellSysutil.fatal("cellSysCache: failed to clear cache directory '%s%s' (%s)", cache_root, cache_id, fs::g_tls_error);
} }

View File

@ -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<std::string>()(path)), fmt::base57(utils::get_unique_tsc())); return fmt::format(u8"%s/%s%s", dev_root, fmt::base57(std::hash<std::string>()(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 // 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 from0 = std::string_view(from).substr(0, from.find_last_not_of(fs::delim) + 1);
const auto escaped_from = Emu.GetCallbacks().resolve_path(from); 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) 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 #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 #ifdef _WIN32
if (remove_root) 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) // 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); 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; 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; return false;
} }
@ -1093,7 +1098,7 @@ bool vfs::host::remove_all(const std::string& path, [[maybe_unused]] const std::
} }
else 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; return false;
} }

View File

@ -34,12 +34,12 @@ namespace vfs
std::string hash_path(const std::string& path, const std::string& dev_root); std::string hash_path(const std::string& path, const std::string& dev_root);
// Call fs::rename with retry on access error // 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 // Delete file without deleting its contents, emulated with MoveFileEx on Windows
bool unlink(const std::string& path, const std::string& dev_root); bool unlink(const std::string& path, const std::string& dev_root);
// Delete folder contents using rename, done atomically if remove_root is true // 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);
} }
} }