mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-31 23:08:22 -04:00
fs.mitm: Cache IStorageInterfaces, store meta on SD instead of memory.
This commit is contained in:
parent
5d0aabaa44
commit
78a47dba6d
7 changed files with 176 additions and 39 deletions
|
@ -14,7 +14,12 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include <switch.h>
|
||||
#include <stratosphere.hpp>
|
||||
#include "fsmitm_service.hpp"
|
||||
#include "fs_shim.h"
|
||||
|
||||
|
@ -24,6 +29,37 @@
|
|||
|
||||
#include "debug.hpp"
|
||||
|
||||
static HosMutex g_StorageCacheLock;
|
||||
static std::unordered_map<u64, std::weak_ptr<IStorageInterface>> g_StorageCache;
|
||||
|
||||
static bool StorageCacheGetEntry(u64 title_id, std::shared_ptr<IStorageInterface> *out) {
|
||||
std::scoped_lock<HosMutex> lock(g_StorageCacheLock);
|
||||
if (g_StorageCache.find(title_id) == g_StorageCache.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto intf = g_StorageCache[title_id].lock();
|
||||
if (intf != nullptr) {
|
||||
*out = intf;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void StorageCacheSetEntry(u64 title_id, std::shared_ptr<IStorageInterface> *ptr) {
|
||||
std::scoped_lock<HosMutex> lock(g_StorageCacheLock);
|
||||
|
||||
/* Ensure we always use the cached copy if present. */
|
||||
if (g_StorageCache.find(title_id) != g_StorageCache.end()) {
|
||||
auto intf = g_StorageCache[title_id].lock();
|
||||
if (intf != nullptr) {
|
||||
*ptr = intf;
|
||||
}
|
||||
}
|
||||
|
||||
g_StorageCache[title_id] = *ptr;
|
||||
}
|
||||
|
||||
void FsMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) {
|
||||
auto this_ptr = static_cast<FsMitmService *>(obj);
|
||||
switch ((FspSrvCmd)ctx->cmd_id) {
|
||||
|
@ -49,16 +85,23 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora
|
|||
u32 out_domain_id = 0;
|
||||
Result rc = 0;
|
||||
|
||||
bool has_cache = StorageCacheGetEntry(this->title_id, &storage);
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (!has_cache) {
|
||||
StorageCacheSetEntry(this->title_id, &storage);
|
||||
}
|
||||
|
||||
out_storage.SetValue(std::move(storage));
|
||||
if (out_storage.IsDomain()) {
|
||||
out_storage.ChangeObjectId(out_domain_id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (this->romfs_storage != nullptr) {
|
||||
|
||||
|
||||
if (has_cache) {
|
||||
if (out_storage.IsDomain()) {
|
||||
FsStorage s = {0};
|
||||
rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service.get(), &s);
|
||||
|
@ -68,8 +111,8 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora
|
|||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
storage = this->romfs_storage;
|
||||
if (R_FAILED(rc)) {
|
||||
storage.reset();
|
||||
}
|
||||
} else {
|
||||
FsStorage data_storage;
|
||||
|
@ -86,7 +129,6 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora
|
|||
} else {
|
||||
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, this->title_id));
|
||||
}
|
||||
this->romfs_storage = storage;
|
||||
if (out_storage.IsDomain()) {
|
||||
out_domain_id = data_storage.s.object_id;
|
||||
}
|
||||
|
@ -106,13 +148,19 @@ Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterf
|
|||
FsStorageId storage_id = (FsStorageId)sid;
|
||||
FsStorage data_storage;
|
||||
FsFile data_file;
|
||||
|
||||
|
||||
std::shared_ptr<IStorageInterface> storage = nullptr;
|
||||
u32 out_domain_id = 0;
|
||||
Result rc = 0;
|
||||
|
||||
bool has_cache = StorageCacheGetEntry(data_id, &storage);
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (!has_cache) {
|
||||
StorageCacheSetEntry(data_id, &storage);
|
||||
}
|
||||
|
||||
out_storage.SetValue(std::move(storage));
|
||||
if (out_storage.IsDomain()) {
|
||||
out_storage.ChangeObjectId(out_domain_id);
|
||||
|
@ -120,23 +168,38 @@ Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterf
|
|||
}
|
||||
};
|
||||
|
||||
rc = fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &data_storage);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (Utils::HasSdRomfsContent(data_id)) {
|
||||
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
|
||||
if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) {
|
||||
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), data_id));
|
||||
} else {
|
||||
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, data_id));
|
||||
}
|
||||
if (out_storage.IsDomain()) {
|
||||
out_domain_id = data_storage.s.object_id;
|
||||
if (has_cache) {
|
||||
if (out_storage.IsDomain()) {
|
||||
FsStorage s = {0};
|
||||
rc = fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &s);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
out_domain_id = s.s.object_id;
|
||||
}
|
||||
} else {
|
||||
/* If we don't have anything to modify, there's no sense in maintaining a copy of the metadata tables. */
|
||||
fsStorageClose(&data_storage);
|
||||
rc = RESULT_FORWARD_TO_SESSION;
|
||||
rc = 0;
|
||||
}
|
||||
if (R_FAILED(rc)) {
|
||||
storage.reset();
|
||||
}
|
||||
} else {
|
||||
rc = fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &data_storage);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (Utils::HasSdRomfsContent(data_id)) {
|
||||
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
|
||||
if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) {
|
||||
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), data_id));
|
||||
} else {
|
||||
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, data_id));
|
||||
}
|
||||
if (out_storage.IsDomain()) {
|
||||
out_domain_id = data_storage.s.object_id;
|
||||
}
|
||||
} else {
|
||||
/* If we don't have anything to modify, there's no sense in maintaining a copy of the metadata tables. */
|
||||
fsStorageClose(&data_storage);
|
||||
rc = RESULT_FORWARD_TO_SESSION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue