From 336b9a806fd2266f47cf19f887748d02f144798d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Oct 2025 16:19:19 +0100 Subject: [PATCH] don't hold handle all the time to the file --- src/core/file_sys/vfs/vfs_real.cpp | 47 ++++++++++++++++++++++++++---- src/core/file_sys/vfs/vfs_real.h | 1 + 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/core/file_sys/vfs/vfs_real.cpp b/src/core/file_sys/vfs/vfs_real.cpp index 22443ac53f..1cf2cc8fd1 100644 --- a/src/core/file_sys/vfs/vfs_real.cpp +++ b/src/core/file_sys/vfs/vfs_real.cpp @@ -211,7 +211,8 @@ std::unique_lock RealVfsFilesystem::RefreshReference(const std::stri this->EvictSingleReferenceLocked(); reference.file = - FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile); + FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile, + FS::FileShareFlag::ShareReadWrite); if (reference.file) { num_open_files++; } @@ -236,6 +237,19 @@ void RealVfsFilesystem::DropReference(std::unique_ptr&& reference } } +void RealVfsFilesystem::CloseReference(FileReference& reference) { + std::scoped_lock lk{list_lock}; + if (!reference.file) { + return; + } + this->RemoveReferenceFromListLocked(reference); + reference.file.reset(); + if (num_open_files > 0) { + num_open_files--; + } + this->InsertReferenceIntoListLocked(reference); +} + void RealVfsFilesystem::EvictSingleReferenceLocked() { if (num_open_files < MaxOpenFiles || open_references.empty()) { return; @@ -304,13 +318,19 @@ std::size_t RealVfsFile::GetSize() const { return *size; } auto lk = base.RefreshReference(path, perms, *reference); - return reference->file ? reference->file->GetSize() : 0; + const auto result = reference->file ? reference->file->GetSize() : 0; + lk.unlock(); + base.CloseReference(*reference); + return result; } bool RealVfsFile::Resize(std::size_t new_size) { size.reset(); auto lk = base.RefreshReference(path, perms, *reference); - return reference->file ? reference->file->SetSize(new_size) : false; + const bool ok = reference->file ? reference->file->SetSize(new_size) : false; + lk.unlock(); + base.CloseReference(*reference); + return ok; } VirtualDir RealVfsFile::GetContainingDirectory() const { @@ -326,20 +346,37 @@ bool RealVfsFile::IsReadable() const { } std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { + if (length != 0 && data == nullptr) { + LOG_ERROR(Common_Filesystem, + "RealVfsFile::Read called with null buffer (len={}, off={}, path={})", + length, offset, path); + return 0; + } + auto lk = base.RefreshReference(path, perms, *reference); if (!reference->file || !reference->file->Seek(static_cast(offset))) { + lk.unlock(); + base.CloseReference(*reference); return 0; } - return reference->file->ReadSpan(std::span{data, length}); + const auto read = reference->file->ReadSpan(std::span{data, length}); + lk.unlock(); + base.CloseReference(*reference); + return read; } std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { size.reset(); auto lk = base.RefreshReference(path, perms, *reference); if (!reference->file || !reference->file->Seek(static_cast(offset))) { + lk.unlock(); + base.CloseReference(*reference); return 0; } - return reference->file->WriteSpan(std::span{data, length}); + const auto written = reference->file->WriteSpan(std::span{data, length}); + lk.unlock(); + base.CloseReference(*reference); + return written; } bool RealVfsFile::Rename(std::string_view name) { diff --git a/src/core/file_sys/vfs/vfs_real.h b/src/core/file_sys/vfs/vfs_real.h index a773fc375a..76a88f939a 100644 --- a/src/core/file_sys/vfs/vfs_real.h +++ b/src/core/file_sys/vfs/vfs_real.h @@ -58,6 +58,7 @@ private: std::unique_lock RefreshReference(const std::string& path, OpenMode perms, FileReference& reference); void DropReference(std::unique_ptr&& reference); + void CloseReference(FileReference& reference); private: friend class RealVfsDirectory;