summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2023-06-22 21:46:50 -0700
committerGravatar GitHub2023-06-22 21:46:50 -0700
commit3f3e4efb30de021fed52badc34808008276db9e7 (patch)
tree14462b7b13e1ba9f978667f6f2586d6a3fe5df50 /src
parentMerge pull request #10794 from 8bitDream/multiples (diff)
parentvfs_real: ensure size cache is reset on write (diff)
downloadyuzu-3f3e4efb30de021fed52badc34808008276db9e7.tar.gz
yuzu-3f3e4efb30de021fed52badc34808008276db9e7.tar.xz
yuzu-3f3e4efb30de021fed52badc34808008276db9e7.zip
Merge pull request #10806 from liamwhite/worst-fs-implementation-ever
vfs_real: misc optimizations
Diffstat (limited to 'src')
-rw-r--r--src/common/fs/fs.cpp8
-rw-r--r--src/common/fs/fs_types.h2
-rw-r--r--src/core/file_sys/patch_manager.cpp9
-rw-r--r--src/core/file_sys/vfs_real.cpp46
-rw-r--r--src/core/file_sys/vfs_real.h11
5 files changed, 47 insertions, 29 deletions
diff --git a/src/common/fs/fs.cpp b/src/common/fs/fs.cpp
index 6d66c926d..1baf6d746 100644
--- a/src/common/fs/fs.cpp
+++ b/src/common/fs/fs.cpp
@@ -436,7 +436,7 @@ void IterateDirEntries(const std::filesystem::path& path, const DirEntryCallable
436 436
437 if (True(filter & DirEntryFilter::File) && 437 if (True(filter & DirEntryFilter::File) &&
438 entry.status().type() == fs::file_type::regular) { 438 entry.status().type() == fs::file_type::regular) {
439 if (!callback(entry.path())) { 439 if (!callback(entry)) {
440 callback_error = true; 440 callback_error = true;
441 break; 441 break;
442 } 442 }
@@ -444,7 +444,7 @@ void IterateDirEntries(const std::filesystem::path& path, const DirEntryCallable
444 444
445 if (True(filter & DirEntryFilter::Directory) && 445 if (True(filter & DirEntryFilter::Directory) &&
446 entry.status().type() == fs::file_type::directory) { 446 entry.status().type() == fs::file_type::directory) {
447 if (!callback(entry.path())) { 447 if (!callback(entry)) {
448 callback_error = true; 448 callback_error = true;
449 break; 449 break;
450 } 450 }
@@ -493,7 +493,7 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path,
493 493
494 if (True(filter & DirEntryFilter::File) && 494 if (True(filter & DirEntryFilter::File) &&
495 entry.status().type() == fs::file_type::regular) { 495 entry.status().type() == fs::file_type::regular) {
496 if (!callback(entry.path())) { 496 if (!callback(entry)) {
497 callback_error = true; 497 callback_error = true;
498 break; 498 break;
499 } 499 }
@@ -501,7 +501,7 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path,
501 501
502 if (True(filter & DirEntryFilter::Directory) && 502 if (True(filter & DirEntryFilter::Directory) &&
503 entry.status().type() == fs::file_type::directory) { 503 entry.status().type() == fs::file_type::directory) {
504 if (!callback(entry.path())) { 504 if (!callback(entry)) {
505 callback_error = true; 505 callback_error = true;
506 break; 506 break;
507 } 507 }
diff --git a/src/common/fs/fs_types.h b/src/common/fs/fs_types.h
index 5a4090c19..900f85d24 100644
--- a/src/common/fs/fs_types.h
+++ b/src/common/fs/fs_types.h
@@ -66,6 +66,6 @@ DECLARE_ENUM_FLAG_OPERATORS(DirEntryFilter);
66 * @returns A boolean value. 66 * @returns A boolean value.
67 * Return true to indicate whether the callback is successful, false otherwise. 67 * Return true to indicate whether the callback is successful, false otherwise.
68 */ 68 */
69using DirEntryCallable = std::function<bool(const std::filesystem::path& path)>; 69using DirEntryCallable = std::function<bool(const std::filesystem::directory_entry& entry)>;
70 70
71} // namespace Common::FS 71} // namespace Common::FS
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 4e61d4335..d3286b352 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -153,7 +153,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
153 const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); 153 const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);
154 154
155 std::vector<VirtualDir> patch_dirs = {sdmc_load_dir}; 155 std::vector<VirtualDir> patch_dirs = {sdmc_load_dir};
156 if (load_dir != nullptr && load_dir->GetSize() > 0) { 156 if (load_dir != nullptr) {
157 const auto load_patch_dirs = load_dir->GetSubdirectories(); 157 const auto load_patch_dirs = load_dir->GetSubdirectories();
158 patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end()); 158 patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end());
159 } 159 }
@@ -354,8 +354,7 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t
354 const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); 354 const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
355 const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); 355 const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);
356 if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || 356 if ((type != ContentRecordType::Program && type != ContentRecordType::Data) ||
357 ((load_dir == nullptr || load_dir->GetSize() <= 0) && 357 (load_dir == nullptr && sdmc_load_dir == nullptr)) {
358 (sdmc_load_dir == nullptr || sdmc_load_dir->GetSize() <= 0))) {
359 return; 358 return;
360 } 359 }
361 360
@@ -496,7 +495,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
496 495
497 // General Mods (LayeredFS and IPS) 496 // General Mods (LayeredFS and IPS)
498 const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id); 497 const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id);
499 if (mod_dir != nullptr && mod_dir->GetSize() > 0) { 498 if (mod_dir != nullptr) {
500 for (const auto& mod : mod_dir->GetSubdirectories()) { 499 for (const auto& mod : mod_dir->GetSubdirectories()) {
501 std::string types; 500 std::string types;
502 501
@@ -540,7 +539,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
540 539
541 // SDMC mod directory (RomFS LayeredFS) 540 // SDMC mod directory (RomFS LayeredFS)
542 const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); 541 const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);
543 if (sdmc_mod_dir != nullptr && sdmc_mod_dir->GetSize() > 0) { 542 if (sdmc_mod_dir != nullptr) {
544 std::string types; 543 std::string types;
545 if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "exefs"))) { 544 if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "exefs"))) {
546 AppendCommaIfNotEmpty(types, "LayeredExeFS"); 545 AppendCommaIfNotEmpty(types, "LayeredExeFS");
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 7a15d8438..fcc81a664 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -10,6 +10,7 @@
10#include "common/fs/fs.h" 10#include "common/fs/fs.h"
11#include "common/fs/path_util.h" 11#include "common/fs/path_util.h"
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "core/file_sys/vfs.h"
13#include "core/file_sys/vfs_real.h" 14#include "core/file_sys/vfs_real.h"
14 15
15// For FileTimeStampRaw 16// For FileTimeStampRaw
@@ -72,7 +73,8 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const {
72 return VfsEntryType::File; 73 return VfsEntryType::File;
73} 74}
74 75
75VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { 76VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::optional<u64> size,
77 Mode perms) {
76 const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); 78 const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
77 79
78 if (auto it = cache.find(path); it != cache.end()) { 80 if (auto it = cache.find(path); it != cache.end()) {
@@ -81,20 +83,24 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
81 } 83 }
82 } 84 }
83 85
84 if (!FS::Exists(path) || !FS::IsFile(path)) { 86 if (!size && !FS::IsFile(path)) {
85 return nullptr; 87 return nullptr;
86 } 88 }
87 89
88 auto reference = std::make_unique<FileReference>(); 90 auto reference = std::make_unique<FileReference>();
89 this->InsertReferenceIntoList(*reference); 91 this->InsertReferenceIntoList(*reference);
90 92
91 auto file = 93 auto file = std::shared_ptr<RealVfsFile>(
92 std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, std::move(reference), path, perms)); 94 new RealVfsFile(*this, std::move(reference), path, perms, size));
93 cache[path] = file; 95 cache[path] = file;
94 96
95 return file; 97 return file;
96} 98}
97 99
100VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
101 return OpenFileFromEntry(path_, {}, perms);
102}
103
98VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { 104VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) {
99 const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); 105 const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
100 cache.erase(path); 106 cache.erase(path);
@@ -243,10 +249,10 @@ void RealVfsFilesystem::RemoveReferenceFromList(FileReference& reference) {
243} 249}
244 250
245RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_, 251RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_,
246 const std::string& path_, Mode perms_) 252 const std::string& path_, Mode perms_, std::optional<u64> size_)
247 : base(base_), reference(std::move(reference_)), path(path_), 253 : base(base_), reference(std::move(reference_)), path(path_),
248 parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)), 254 parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)),
249 perms(perms_) {} 255 size(size_), perms(perms_) {}
250 256
251RealVfsFile::~RealVfsFile() { 257RealVfsFile::~RealVfsFile() {
252 base.DropReference(std::move(reference)); 258 base.DropReference(std::move(reference));
@@ -257,11 +263,14 @@ std::string RealVfsFile::GetName() const {
257} 263}
258 264
259std::size_t RealVfsFile::GetSize() const { 265std::size_t RealVfsFile::GetSize() const {
260 base.RefreshReference(path, perms, *reference); 266 if (size) {
261 return reference->file ? reference->file->GetSize() : 0; 267 return *size;
268 }
269 return FS::GetSize(path);
262} 270}
263 271
264bool RealVfsFile::Resize(std::size_t new_size) { 272bool RealVfsFile::Resize(std::size_t new_size) {
273 size.reset();
265 base.RefreshReference(path, perms, *reference); 274 base.RefreshReference(path, perms, *reference);
266 return reference->file ? reference->file->SetSize(new_size) : false; 275 return reference->file ? reference->file->SetSize(new_size) : false;
267} 276}
@@ -287,6 +296,7 @@ std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset)
287} 296}
288 297
289std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { 298std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) {
299 size.reset();
290 base.RefreshReference(path, perms, *reference); 300 base.RefreshReference(path, perms, *reference);
291 if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) { 301 if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) {
292 return 0; 302 return 0;
@@ -309,10 +319,11 @@ std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>(
309 319
310 std::vector<VirtualFile> out; 320 std::vector<VirtualFile> out;
311 321
312 const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) { 322 const FS::DirEntryCallable callback = [this,
313 const auto full_path_string = FS::PathToUTF8String(full_path); 323 &out](const std::filesystem::directory_entry& entry) {
324 const auto full_path_string = FS::PathToUTF8String(entry.path());
314 325
315 out.emplace_back(base.OpenFile(full_path_string, perms)); 326 out.emplace_back(base.OpenFileFromEntry(full_path_string, entry.file_size(), perms));
316 327
317 return true; 328 return true;
318 }; 329 };
@@ -330,8 +341,9 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi
330 341
331 std::vector<VirtualDir> out; 342 std::vector<VirtualDir> out;
332 343
333 const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) { 344 const FS::DirEntryCallable callback = [this,
334 const auto full_path_string = FS::PathToUTF8String(full_path); 345 &out](const std::filesystem::directory_entry& entry) {
346 const auto full_path_string = FS::PathToUTF8String(entry.path());
335 347
336 out.emplace_back(base.OpenDirectory(full_path_string, perms)); 348 out.emplace_back(base.OpenDirectory(full_path_string, perms));
337 349
@@ -483,12 +495,10 @@ std::map<std::string, VfsEntryType, std::less<>> RealVfsDirectory::GetEntries()
483 495
484 std::map<std::string, VfsEntryType, std::less<>> out; 496 std::map<std::string, VfsEntryType, std::less<>> out;
485 497
486 const FS::DirEntryCallable callback = [&out](const std::filesystem::path& full_path) { 498 const FS::DirEntryCallable callback = [&out](const std::filesystem::directory_entry& entry) {
487 const auto filename = FS::PathToUTF8String(full_path.filename()); 499 const auto filename = FS::PathToUTF8String(entry.path().filename());
488
489 out.insert_or_assign(filename, 500 out.insert_or_assign(filename,
490 FS::IsDir(full_path) ? VfsEntryType::Directory : VfsEntryType::File); 501 entry.is_directory() ? VfsEntryType::Directory : VfsEntryType::File);
491
492 return true; 502 return true;
493 }; 503 };
494 504
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h
index d8c900e33..67f4c4422 100644
--- a/src/core/file_sys/vfs_real.h
+++ b/src/core/file_sys/vfs_real.h
@@ -4,6 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include <map> 6#include <map>
7#include <optional>
7#include <string_view> 8#include <string_view>
8#include "common/intrusive_list.h" 9#include "common/intrusive_list.h"
9#include "core/file_sys/mode.h" 10#include "core/file_sys/mode.h"
@@ -20,6 +21,8 @@ struct FileReference : public Common::IntrusiveListBaseNode<FileReference> {
20}; 21};
21 22
22class RealVfsFile; 23class RealVfsFile;
24class RealVfsDirectory;
25
23class RealVfsFilesystem : public VfsFilesystem { 26class RealVfsFilesystem : public VfsFilesystem {
24public: 27public:
25 RealVfsFilesystem(); 28 RealVfsFilesystem();
@@ -56,6 +59,11 @@ private:
56private: 59private:
57 void InsertReferenceIntoList(FileReference& reference); 60 void InsertReferenceIntoList(FileReference& reference);
58 void RemoveReferenceFromList(FileReference& reference); 61 void RemoveReferenceFromList(FileReference& reference);
62
63private:
64 friend class RealVfsDirectory;
65 VirtualFile OpenFileFromEntry(std::string_view path, std::optional<u64> size,
66 Mode perms = Mode::Read);
59}; 67};
60 68
61// An implementation of VfsFile that represents a file on the user's computer. 69// An implementation of VfsFile that represents a file on the user's computer.
@@ -78,13 +86,14 @@ public:
78 86
79private: 87private:
80 RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference, 88 RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference,
81 const std::string& path, Mode perms = Mode::Read); 89 const std::string& path, Mode perms = Mode::Read, std::optional<u64> size = {});
82 90
83 RealVfsFilesystem& base; 91 RealVfsFilesystem& base;
84 std::unique_ptr<FileReference> reference; 92 std::unique_ptr<FileReference> reference;
85 std::string path; 93 std::string path;
86 std::string parent_path; 94 std::string parent_path;
87 std::vector<std::string> path_components; 95 std::vector<std::string> path_components;
96 std::optional<u64> size;
88 Mode perms; 97 Mode perms;
89}; 98};
90 99