From 896d8751879e8b7d3368ad7a515ccc1b0f1b3b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Thu, 29 Mar 2018 18:07:45 +0200 Subject: [PATCH] IOS/FS: Emulate Open() timing --- Source/Core/Core/IOS/FS/FileSystemProxy.cpp | 36 ++++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/IOS/FS/FileSystemProxy.cpp b/Source/Core/Core/IOS/FS/FileSystemProxy.cpp index 6291066145..4c3b8599c4 100644 --- a/Source/Core/Core/IOS/FS/FileSystemProxy.cpp +++ b/Source/Core/Core/IOS/FS/FileSystemProxy.cpp @@ -4,6 +4,7 @@ #include "Core/IOS/FS/FileSystemProxy.h" +#include #include #include "Common/Assert.h" @@ -56,29 +57,54 @@ static void LogResult(const std::string& command, const Result& result) LogResult(command, result.Succeeded() ? ResultCode::Success : result.Error()); } +enum class FileLookupMode +{ + Normal, + /// Timing model to use when FS splits the path into a parent and a file name + /// and looks up each of them individually. + Split, +}; +// Note: lookups normally stop at the first non existing path (as the FST cannot be traversed +// further when a directory doesn't exist). However for the sake of simplicity we assume that the +// entire lookup succeeds because otherwise we'd need to check whether every path component exists. +static u64 EstimateFileLookupTicks(const std::string& path, FileLookupMode mode) +{ + const size_t number_of_path_components = std::count(path.cbegin(), path.cend(), '/'); + if (number_of_path_components == 0) + return 0; + // Paths that end with a slash are invalid and rejected early in FS. + if (!path.empty() && *path.rbegin() == '/') + return 300; + if (mode == FileLookupMode::Normal) + return 680 * number_of_path_components; + return 1000 + 340 * number_of_path_components; +} + IPCCommandResult FS::Open(const OpenRequest& request) { if (m_fd_map.size() >= 16) - return GetDefaultReply(ConvertResult(ResultCode::NoFreeHandle)); + return GetFSReply(ConvertResult(ResultCode::NoFreeHandle)); if (request.path.size() >= 64) - return GetDefaultReply(ConvertResult(ResultCode::Invalid)); + return GetFSReply(ConvertResult(ResultCode::Invalid)); if (request.path == "/dev/fs") { m_fd_map[request.fd] = {request.gid, request.uid, INVALID_FD}; - return GetDefaultReply(IPC_SUCCESS); + return GetFSReply(IPC_SUCCESS); } + const u64 ticks = EstimateFileLookupTicks(request.path, FileLookupMode::Normal); + auto backend_fd = m_ios.GetFS()->OpenFile(request.uid, request.gid, request.path, static_cast(request.flags & 3)); LogResult(StringFromFormat("OpenFile(%s)", request.path.c_str()), backend_fd); if (!backend_fd) - return GetFSReply(ConvertResult(backend_fd.Error())); + return GetFSReply(ConvertResult(backend_fd.Error()), ticks); m_fd_map[request.fd] = {request.gid, request.uid, backend_fd->Release()}; std::strncpy(m_fd_map[request.fd].name.data(), request.path.c_str(), 64); - return GetFSReply(IPC_SUCCESS); + return GetFSReply(IPC_SUCCESS, ticks); } IPCCommandResult FS::Close(u32 fd)