fs_user: Add a delay for each file open

This commit is contained in:
fearlessTobi 2018-11-02 18:11:22 +01:00
parent d0de727a97
commit fc7e6c9cc9
14 changed files with 153 additions and 11 deletions

View file

@ -12,6 +12,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/swap.h" #include "common/swap.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "delay_generator.h"
namespace FileSys { namespace FileSys {
@ -153,6 +154,27 @@ public:
* @return The number of free bytes in the archive * @return The number of free bytes in the archive
*/ */
virtual u64 GetFreeBytes() const = 0; virtual u64 GetFreeBytes() const = 0;
u64 GetReadDelayNs(std::size_t length) {
if (delay_generator != nullptr) {
return delay_generator->GetReadDelayNs(length);
}
LOG_ERROR(Service_FS, "Delay generator was not initalized. Using default");
delay_generator = std::make_unique<DefaultDelayGenerator>();
return delay_generator->GetReadDelayNs(length);
}
u64 GetOpenDelayNs() {
if (delay_generator != nullptr) {
return delay_generator->GetOpenDelayNs();
}
LOG_ERROR(Service_FS, "Delay generator was not initalized. Using default");
delay_generator = std::make_unique<DefaultDelayGenerator>();
return delay_generator->GetOpenDelayNs();
}
protected:
std::unique_ptr<DelayGenerator> delay_generator;
}; };
class ArchiveFactory : NonCopyable { class ArchiveFactory : NonCopyable {

View file

@ -59,7 +59,7 @@ private:
class ExtSaveDataDelayGenerator : public DelayGenerator { class ExtSaveDataDelayGenerator : public DelayGenerator {
public: public:
u64 GetReadDelayNs(std::size_t length) override { u64 GetReadDelayNs(std::size_t length) override {
// This is the delay measured for a savedate read, // This is the delay measured for a savedata read,
// not for extsaveData // not for extsaveData
// For now we will take that // For now we will take that
static constexpr u64 slope(183); static constexpr u64 slope(183);
@ -69,6 +69,14 @@ public:
std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); std::max<u64>(static_cast<u64>(length) * slope + offset, minimum);
return ipc_delay_nanoseconds; return ipc_delay_nanoseconds;
} }
u64 GetOpenDelayNs() override {
// This is the delay measured for a savedata open,
// not for extsaveData
// For now we will take that
static constexpr u64 IPCDelayNanoseconds(269082);
return IPCDelayNanoseconds;
}
}; };
/** /**
@ -80,7 +88,11 @@ public:
*/ */
class ExtSaveDataArchive : public SaveDataArchive { class ExtSaveDataArchive : public SaveDataArchive {
public: public:
explicit ExtSaveDataArchive(const std::string& mount_point) : SaveDataArchive(mount_point) {} explicit ExtSaveDataArchive(const std::string& mount_point,
std::unique_ptr<DelayGenerator> delay_generator_)
: SaveDataArchive(mount_point) {
delay_generator = std::move(delay_generator_);
}
std::string GetName() const override { std::string GetName() const override {
return "ExtSaveDataArchive: " + mount_point; return "ExtSaveDataArchive: " + mount_point;
@ -232,7 +244,8 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons
return ERR_NOT_FORMATTED; return ERR_NOT_FORMATTED;
} }
} }
auto archive = std::make_unique<ExtSaveDataArchive>(fullpath); std::unique_ptr<DelayGenerator> delay_generator = std::make_unique<ExtSaveDataDelayGenerator>();
auto archive = std::make_unique<ExtSaveDataArchive>(fullpath, std::move(delay_generator));
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
} }

View file

@ -29,6 +29,14 @@ public:
u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum);
return IPCDelayNanoseconds; return IPCDelayNanoseconds;
} }
u64 GetOpenDelayNs() override {
// This is the delay measured on O3DS and O2DS with
// https://gist.github.com/FearlessTobi/c37e143c314789251f98f2c45cd706d2
// from the results the average of each length was taken.
static constexpr u64 IPCDelayNanoseconds(269082);
return IPCDelayNanoseconds;
}
}; };
ResultVal<std::unique_ptr<FileBackend>> SDMCArchive::OpenFile(const Path& path, ResultVal<std::unique_ptr<FileBackend>> SDMCArchive::OpenFile(const Path& path,
@ -378,7 +386,8 @@ bool ArchiveFactory_SDMC::Initialize() {
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path, ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path,
u64 program_id) { u64 program_id) {
auto archive = std::make_unique<SDMCArchive>(sdmc_directory); std::unique_ptr<DelayGenerator> delay_generator = std::make_unique<SDMCDelayGenerator>();
auto archive = std::make_unique<SDMCArchive>(sdmc_directory, std::move(delay_generator));
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
} }

View file

@ -17,7 +17,11 @@ namespace FileSys {
/// Archive backend for SDMC archive /// Archive backend for SDMC archive
class SDMCArchive : public ArchiveBackend { class SDMCArchive : public ArchiveBackend {
public: public:
explicit SDMCArchive(const std::string& mount_point_) : mount_point(mount_point_) {} explicit SDMCArchive(const std::string& mount_point_,
std::unique_ptr<DelayGenerator> delay_generator_)
: mount_point(mount_point_) {
delay_generator = std::move(delay_generator_);
}
std::string GetName() const override { std::string GetName() const override {
return "SDMCArchive: " + mount_point; return "SDMCArchive: " + mount_point;

View file

@ -15,6 +15,28 @@
namespace FileSys { namespace FileSys {
class SDMCWriteOnlyDelayGenerator : public DelayGenerator {
public:
u64 GetReadDelayNs(std::size_t length) override {
// This is the delay measured on O3DS and O2DS with
// https://gist.github.com/B3n30/ac40eac20603f519ff106107f4ac9182
// from the results the average of each length was taken.
static constexpr u64 slope(183);
static constexpr u64 offset(524879);
static constexpr u64 minimum(631826);
u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum);
return IPCDelayNanoseconds;
}
u64 GetOpenDelayNs() override {
// This is the delay measured on O3DS and O2DS with
// https://gist.github.com/FearlessTobi/c37e143c314789251f98f2c45cd706d2
// from the results the average of each length was taken.
static constexpr u64 IPCDelayNanoseconds(269082);
return IPCDelayNanoseconds;
}
};
ResultVal<std::unique_ptr<FileBackend>> SDMCWriteOnlyArchive::OpenFile(const Path& path, ResultVal<std::unique_ptr<FileBackend>> SDMCWriteOnlyArchive::OpenFile(const Path& path,
const Mode& mode) const { const Mode& mode) const {
if (mode.read_flag) { if (mode.read_flag) {
@ -51,7 +73,10 @@ bool ArchiveFactory_SDMCWriteOnly::Initialize() {
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMCWriteOnly::Open(const Path& path, ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMCWriteOnly::Open(const Path& path,
u64 program_id) { u64 program_id) {
auto archive = std::make_unique<SDMCWriteOnlyArchive>(sdmc_directory); std::unique_ptr<DelayGenerator> delay_generator =
std::make_unique<SDMCWriteOnlyDelayGenerator>();
auto archive =
std::make_unique<SDMCWriteOnlyArchive>(sdmc_directory, std::move(delay_generator));
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
} }

View file

@ -19,7 +19,9 @@ namespace FileSys {
*/ */
class SDMCWriteOnlyArchive : public SDMCArchive { class SDMCWriteOnlyArchive : public SDMCArchive {
public: public:
explicit SDMCWriteOnlyArchive(const std::string& mount_point) : SDMCArchive(mount_point) {} explicit SDMCWriteOnlyArchive(const std::string& mount_point,
std::unique_ptr<DelayGenerator> delay_generator_)
: SDMCArchive(mount_point, std::move(delay_generator_)) {}
std::string GetName() const override { std::string GetName() const override {
return "SDMCWriteOnlyArchive: " + mount_point; return "SDMCWriteOnlyArchive: " + mount_point;

View file

@ -19,4 +19,11 @@ u64 DefaultDelayGenerator::GetReadDelayNs(std::size_t length) {
return IPCDelayNanoseconds; return IPCDelayNanoseconds;
} }
u64 DefaultDelayGenerator::GetOpenDelayNs() {
// This is the delay measured for a romfs open.
// For now we will take that as a default
static constexpr u64 IPCDelayNanoseconds(9438006);
return IPCDelayNanoseconds;
}
} // namespace FileSys } // namespace FileSys

View file

@ -13,6 +13,7 @@ class DelayGenerator {
public: public:
virtual ~DelayGenerator(); virtual ~DelayGenerator();
virtual u64 GetReadDelayNs(std::size_t length) = 0; virtual u64 GetReadDelayNs(std::size_t length) = 0;
virtual u64 GetOpenDelayNs() = 0;
// TODO (B3N30): Add getter for all other file/directory io operations // TODO (B3N30): Add getter for all other file/directory io operations
}; };
@ -20,6 +21,7 @@ public:
class DefaultDelayGenerator : public DelayGenerator { class DefaultDelayGenerator : public DelayGenerator {
public: public:
u64 GetReadDelayNs(std::size_t length) override; u64 GetReadDelayNs(std::size_t length) override;
u64 GetOpenDelayNs() override;
}; };
} // namespace FileSys } // namespace FileSys

View file

@ -55,6 +55,15 @@ public:
return delay_generator->GetReadDelayNs(length); return delay_generator->GetReadDelayNs(length);
} }
u64 GetOpenDelayNs() {
if (delay_generator != nullptr) {
return delay_generator->GetOpenDelayNs();
}
LOG_ERROR(Service_FS, "Delay generator was not initalized. Using default");
delay_generator = std::make_unique<DefaultDelayGenerator>();
return delay_generator->GetOpenDelayNs();
}
/** /**
* Get the size of the file in bytes * Get the size of the file in bytes
* @return Size of the file in bytes * @return Size of the file in bytes

View file

@ -14,7 +14,11 @@
namespace FileSys { namespace FileSys {
IVFCArchive::IVFCArchive(std::shared_ptr<RomFSReader> file) : romfs_file(std::move(file)) {} IVFCArchive::IVFCArchive(std::shared_ptr<RomFSReader> file,
std::unique_ptr<DelayGenerator> delay_generator_)
: romfs_file(std::move(file)) {
delay_generator = std::move(delay_generator_);
}
std::string IVFCArchive::GetName() const { std::string IVFCArchive::GetName() const {
return "IVFC"; return "IVFC";

View file

@ -31,6 +31,13 @@ class IVFCDelayGenerator : public DelayGenerator {
u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum);
return IPCDelayNanoseconds; return IPCDelayNanoseconds;
} }
u64 GetOpenDelayNs() override {
// This is the delay measured for a romfs open.
// For now we will take that as a default
static constexpr u64 IPCDelayNanoseconds(9438006);
return IPCDelayNanoseconds;
}
}; };
class RomFSDelayGenerator : public DelayGenerator { class RomFSDelayGenerator : public DelayGenerator {
@ -45,6 +52,14 @@ public:
u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum);
return IPCDelayNanoseconds; return IPCDelayNanoseconds;
} }
u64 GetOpenDelayNs() override {
// This is the delay measured on O3DS and O2DS with
// https://gist.github.com/FearlessTobi/eb1d70619c65c7e6f02141d71e79a36e
// from the results the average of each length was taken.
static constexpr u64 IPCDelayNanoseconds(9438006);
return IPCDelayNanoseconds;
}
}; };
class ExeFSDelayGenerator : public DelayGenerator { class ExeFSDelayGenerator : public DelayGenerator {
@ -59,6 +74,14 @@ public:
u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum);
return IPCDelayNanoseconds; return IPCDelayNanoseconds;
} }
u64 GetOpenDelayNs() override {
// This is the delay measured on O3DS and O2DS with
// https://gist.github.com/FearlessTobi/eb1d70619c65c7e6f02141d71e79a36e
// from the results the average of each length was taken.
static constexpr u64 IPCDelayNanoseconds(9438006);
return IPCDelayNanoseconds;
}
}; };
/** /**
@ -68,7 +91,8 @@ public:
*/ */
class IVFCArchive : public ArchiveBackend { class IVFCArchive : public ArchiveBackend {
public: public:
IVFCArchive(std::shared_ptr<RomFSReader> file); IVFCArchive(std::shared_ptr<RomFSReader> file,
std::unique_ptr<DelayGenerator> delay_generator_);
std::string GetName() const override; std::string GetName() const override;

View file

@ -25,6 +25,14 @@ public:
u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum);
return IPCDelayNanoseconds; return IPCDelayNanoseconds;
} }
u64 GetOpenDelayNs() override {
// This is the delay measured on O3DS and O2DS with
// https://gist.github.com/FearlessTobi/c37e143c314789251f98f2c45cd706d2
// from the results the average of each length was taken.
static constexpr u64 IPCDelayNanoseconds(269082);
return IPCDelayNanoseconds;
}
}; };
ResultVal<std::unique_ptr<FileBackend>> SaveDataArchive::OpenFile(const Path& path, ResultVal<std::unique_ptr<FileBackend>> SaveDataArchive::OpenFile(const Path& path,

View file

@ -234,6 +234,8 @@ public:
/// Registers a new NCCH file with the SelfNCCH archive factory /// Registers a new NCCH file with the SelfNCCH archive factory
void RegisterSelfNCCH(Loader::AppLoader& app_loader); void RegisterSelfNCCH(Loader::AppLoader& app_loader);
ArchiveBackend* GetArchive(ArchiveHandle handle);
private: private:
Core::System& system; Core::System& system;
@ -248,8 +250,6 @@ private:
/// Register all archive types /// Register all archive types
void RegisterArchiveTypes(); void RegisterArchiveTypes();
ArchiveBackend* GetArchive(ArchiveHandle handle);
/** /**
* Map of registered archives, identified by id code. Once an archive is registered here, it is * Map of registered archives, identified by id code. Once an archive is registered here, it is
* never removed until UnregisterArchiveTypes is called. * never removed until UnregisterArchiveTypes is called.

View file

@ -16,6 +16,7 @@
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
#include "core/hle/kernel/server_session.h" #include "core/hle/kernel/server_session.h"
#include "core/hle/result.h" #include "core/hle/result.h"
@ -70,6 +71,18 @@ void FS_USER::OpenFile(Kernel::HLERequestContext& ctx) {
rb.PushMoveObjects<Kernel::Object>(nullptr); rb.PushMoveObjects<Kernel::Object>(nullptr);
LOG_ERROR(Service_FS, "failed to get a handle for file {}", file_path.DebugStr()); LOG_ERROR(Service_FS, "failed to get a handle for file {}", file_path.DebugStr());
} }
auto archive = archives.GetArchive(archive_handle);
if (archive == nullptr)
return;
std::chrono::nanoseconds open_timeout_ns{archive->GetOpenDelayNs()};
ctx.SleepClientThread(system.Kernel().GetThreadManager().GetCurrentThread(), "fs_user::open",
open_timeout_ns,
[](Kernel::SharedPtr<Kernel::Thread> thread,
Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) {
// Nothing to do here
});
} }
void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) {