From 1d18d97b50ee8ff6eeb13261c47a68ec07d42a7b Mon Sep 17 00:00:00 2001 From: Marek Ledworowski Date: Sun, 16 Nov 2025 00:58:42 +0100 Subject: [PATCH] Added mutexes for qfs operations (fixes VTM Swansong) Shut up UE --- src/core/file_sys/quasifs/quasifs.h | 2 + .../file_sys/quasifs/src/quasifs_vdriver.cpp | 193 ++++++++++++------ src/core/libraries/kernel/memory.cpp | 6 +- 3 files changed, 135 insertions(+), 66 deletions(-) diff --git a/src/core/file_sys/quasifs/quasifs.h b/src/core/file_sys/quasifs/quasifs.h index 35b1850b8..ea4620f29 100644 --- a/src/core/file_sys/quasifs/quasifs.h +++ b/src/core/file_sys/quasifs/quasifs.h @@ -2,6 +2,7 @@ #pragma once +#include #include #include "common/types.h" @@ -58,6 +59,7 @@ private: private: QFS& qfs; OperationImpl& operator=(const OperationImpl&) = delete; + std::mutex c_mutex; public: OperationImpl(QFS& qfs) : qfs(qfs) {} diff --git a/src/core/file_sys/quasifs/src/quasifs_vdriver.cpp b/src/core/file_sys/quasifs/src/quasifs_vdriver.cpp index 715cda619..a6b8467dc 100644 --- a/src/core/file_sys/quasifs/src/quasifs_vdriver.cpp +++ b/src/core/file_sys/quasifs/src/quasifs_vdriver.cpp @@ -88,9 +88,12 @@ s32 QFS::OperationImpl::Open(const fs::path& path, int flags, u16 mode) { } } - qfs.vio_driver.SetCtx(&res, host_used, nullptr); - vio_status = qfs.vio_driver.Open(res.local_path, flags, mode); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(&res, host_used, nullptr); + vio_status = qfs.vio_driver.Open(res.local_path, flags, mode); + qfs.vio_driver.ClearCtx(); + } if (int tmp_hio_status = hio_status >= 0 ? 0 : hio_status; host_used && (tmp_hio_status != vio_status)) @@ -135,8 +138,11 @@ s32 QFS::OperationImpl::Close(s32 fd) { if (handle->host_fd >= 0) hio_status = qfs.hio_driver.Close(handle->host_fd); - // no further action is required, this is pro-forma - qfs.vio_driver.Close(fd); + { + std::lock_guard lock(c_mutex); + // no further action is required, this is pro-forma + qfs.vio_driver.Close(fd); + } // if it's the last entry, remove it to avoid blowing up fd table // not really helping with fragmentation, but may save resources on burst opens @@ -200,10 +206,13 @@ s32 QFS::OperationImpl::LinkSymbolic(const fs::path& src, const fs::path& dst) { return -QUASI_ENOSYS; } - qfs.vio_driver.SetCtx(&dst_res, host_used, nullptr); - // src stays 1:1 - vio_status = qfs.vio_driver.LinkSymbolic(src, dst_res.local_path); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(&dst_res, host_used, nullptr); + // src stays 1:1 + vio_status = qfs.vio_driver.LinkSymbolic(src, dst_res.local_path); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -260,9 +269,12 @@ s32 QFS::OperationImpl::Link(const fs::path& src, const fs::path& dst) { host_used = true; } - qfs.vio_driver.SetCtx(&src_res, host_used, nullptr); - vio_status = qfs.vio_driver.Link(src_res.local_path, dst_res.local_path); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(&src_res, host_used, nullptr); + vio_status = qfs.vio_driver.Link(src_res.local_path, dst_res.local_path); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -320,9 +332,12 @@ s32 QFS::OperationImpl::Unlink(const fs::path& path) { host_used = true; } - qfs.vio_driver.SetCtx(&res, host_used, nullptr); - vio_status = qfs.vio_driver.Unlink(res.local_path); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(&res, host_used, nullptr); + vio_status = qfs.vio_driver.Unlink(res.local_path); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -354,9 +369,12 @@ s32 QFS::OperationImpl::Flush(const s32 fd) { host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.Flush(fd); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.Flush(fd); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -373,9 +391,6 @@ s32 QFS::OperationImpl::FSync(const s32 fd) { if (nullptr == handle) return -QUASI_EBADF; - if (!handle->read) - return -QUASI_EBADF; - bool host_used = false; int hio_status = 0; int vio_status = 0; @@ -388,9 +403,12 @@ s32 QFS::OperationImpl::FSync(const s32 fd) { host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.FSync(fd); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.FSync(fd); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -425,9 +443,12 @@ s32 QFS::OperationImpl::Truncate(const fs::path& path, u64 length) { host_used = true; } - qfs.vio_driver.SetCtx(&res, host_used, nullptr); - vio_status = qfs.vio_driver.Truncate(res.local_path, length); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(&res, host_used, nullptr); + vio_status = qfs.vio_driver.Truncate(res.local_path, length); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -461,9 +482,12 @@ s32 QFS::OperationImpl::FTruncate(const s32 fd, u64 length) { host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.FTruncate(fd, length); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.FTruncate(fd, length); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -492,9 +516,12 @@ s64 QFS::OperationImpl::LSeek(const s32 fd, s64 offset, s32 whence) { host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.LSeek(fd, offset, whence); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.LSeek(fd, offset, whence); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -540,9 +567,12 @@ s64 QFS::OperationImpl::Read(const s32 fd, void* buf, u64 count) { host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.Read(fd, buf, count); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.Read(fd, buf, count); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -574,9 +604,12 @@ s64 QFS::OperationImpl::PRead(const s32 fd, void* buf, u64 count, s64 offset) { host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.PRead(fd, buf, count, offset); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.PRead(fd, buf, count, offset); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -608,9 +641,12 @@ s64 QFS::OperationImpl::ReadV(const s32 fd, Libraries::Kernel::OrbisKernelIovec* host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.ReadV(fd, iov, iovcnt); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.ReadV(fd, iov, iovcnt); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -643,9 +679,12 @@ s64 QFS::OperationImpl::PReadV(const s32 fd, Libraries::Kernel::OrbisKernelIovec host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.PReadV(fd, iov, iovcnt, offset); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.PReadV(fd, iov, iovcnt, offset); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -677,9 +716,12 @@ s64 QFS::OperationImpl::Write(const s32 fd, const void* buf, u64 count) { host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.Write(fd, buf, count); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.Write(fd, buf, count); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -711,9 +753,12 @@ s64 QFS::OperationImpl::PWrite(const s32 fd, const void* buf, u64 count, s64 off host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.PWrite(fd, buf, count, offset); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.PWrite(fd, buf, count, offset); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -746,9 +791,12 @@ s64 QFS::OperationImpl::WriteV(const s32 fd, const Libraries::Kernel::OrbisKerne host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.WriteV(fd, iov, iovcnt); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.WriteV(fd, iov, iovcnt); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -781,9 +829,12 @@ s64 QFS::OperationImpl::PWriteV(const s32 fd, const Libraries::Kernel::OrbisKern host_used = true; } - qfs.vio_driver.SetCtx(nullptr, host_used, handle); - vio_status = qfs.vio_driver.PWriteV(fd, iov, iovcnt, offset); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(nullptr, host_used, handle); + vio_status = qfs.vio_driver.PWriteV(fd, iov, iovcnt, offset); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -826,9 +877,12 @@ s32 QFS::OperationImpl::MKDir(const fs::path& path, u16 mode) { host_used = true; } - qfs.vio_driver.SetCtx(&res, host_used, nullptr); - vio_status = qfs.vio_driver.MKDir(res.local_path, mode); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(&res, host_used, nullptr); + vio_status = qfs.vio_driver.MKDir(res.local_path, mode); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -861,9 +915,12 @@ s32 QFS::OperationImpl::RMDir(const fs::path& path) { host_used = true; } - qfs.vio_driver.SetCtx(&res, host_used, nullptr); - status = qfs.vio_driver.RMDir(res.local_path); - qfs.vio_driver.ClearCtx(); + { + std::lock_guard lock(c_mutex); + qfs.vio_driver.SetCtx(&res, host_used, nullptr); + status = qfs.vio_driver.RMDir(res.local_path); + qfs.vio_driver.ClearCtx(); + } if (host_used && (hio_status != vio_status)) LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status, @@ -881,6 +938,8 @@ s32 QFS::OperationImpl::Stat(const fs::path& path, Libraries::Kernel::OrbisKerne return resolve_status; } + // too short to justify a separate block + std::lock_guard lock(c_mutex); qfs.vio_driver.SetCtx(&res, false, nullptr); int vio_status = qfs.vio_driver.Stat(res.local_path, statbuf); qfs.vio_driver.ClearCtx(); @@ -896,6 +955,8 @@ s32 QFS::OperationImpl::FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* if (nullptr == handle) return -QUASI_EBADF; + // too short to justify a separate block + std::lock_guard lock(c_mutex); qfs.vio_driver.SetCtx(nullptr, false, handle); int vio_status = qfs.vio_driver.FStat(fd, statbuf); qfs.vio_driver.ClearCtx(); @@ -912,6 +973,8 @@ s32 QFS::OperationImpl::Chmod(const fs::path& path, u16 mode) { return resolve_status; } + // too short to justify a separate block + std::lock_guard lock(c_mutex); qfs.vio_driver.SetCtx(&res, false, nullptr); int vio_status = qfs.vio_driver.Chmod(res.local_path, mode); qfs.vio_driver.ClearCtx(); @@ -930,6 +993,8 @@ s32 QFS::OperationImpl::FChmod(const s32 fd, u16 mode) { if (!handle->read) return -QUASI_EBADF; + // too short to justify a separate block + std::lock_guard lock(c_mutex); qfs.vio_driver.SetCtx(nullptr, false, handle); int vio_status = qfs.vio_driver.FChmod(fd, mode); qfs.vio_driver.ClearCtx(); @@ -948,6 +1013,8 @@ s64 QFS::OperationImpl::GetDents(const s32 fd, void* buf, u64 count, s64* basep) if (!handle->read) return -QUASI_EBADF; + // too short to justify a separate block + std::lock_guard lock(c_mutex); qfs.vio_driver.SetCtx(nullptr, false, handle); int vio_status = qfs.vio_driver.GetDents(fd, buf, count, basep); qfs.vio_driver.ClearCtx(); diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index 92280308d..661ddea63 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -543,8 +543,8 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolCommit(void* addr, u64 len, s32 type, s32 pr return ORBIS_KERNEL_ERROR_EINVAL; } - LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, type = {:#x}, prot = {:#x}, flags = {:#x}", - fmt::ptr(addr), len, type, prot, flags); + // LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, type = {:#x}, prot = {:#x}, flags = {:#x}", + // fmt::ptr(addr), len, type, prot, flags); const VAddr in_addr = reinterpret_cast(addr); auto* memory = Core::Memory::Instance(); @@ -561,7 +561,7 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, u64 len, s32 flags) { return ORBIS_KERNEL_ERROR_EINVAL; } - LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, flags = {:#x}", fmt::ptr(addr), len, flags); + // LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, flags = {:#x}", fmt::ptr(addr), len, flags); const VAddr pool_addr = reinterpret_cast(addr); auto* memory = Core::Memory::Instance();