fs: first pass at compressed storage (works on iridium with wip hac2l code)

This commit is contained in:
Michael Scire
2022-03-12 13:03:17 -08:00
committed by SciresM
parent df631d74f0
commit d638bbbb62
34 changed files with 2375 additions and 722 deletions

View File

@@ -21,6 +21,7 @@
#include <stratosphere/fs/fs_memory_management.hpp>
#include <stratosphere/fssystem/save/fssystem_i_save_file_system_driver.hpp>
#include <stratosphere/fssystem/buffers/fssystem_file_system_buffer_manager.hpp>
#include <stratosphere/fssystem/impl/fssystem_block_cache_manager.hpp>
namespace ams::fssystem::save {
@@ -30,7 +31,7 @@ namespace ams::fssystem::save {
constexpr inline size_t IntegrityLayerCountSaveDataMeta = 4;
struct FileSystemBufferManagerSet {
IBufferManager *buffers[IntegrityMaxLayerCount];
fs::IBufferManager *buffers[IntegrityMaxLayerCount];
};
static_assert(util::is_pod<FileSystemBufferManagerSet>::value);
@@ -40,51 +41,77 @@ namespace ams::fssystem::save {
public:
static constexpr size_t DefaultMaxCacheEntryCount = 24;
private:
using MemoryRange = std::pair<uintptr_t, size_t>;
using CacheIndex = s32;
using MemoryRange = fs::IBufferManager::MemoryRange;
struct AccessRange {
s64 offset;
size_t size;
s64 GetEndOffset() const {
return this->offset + this->size;
}
bool IsIncluded(s64 ofs) const {
return this->offset <= ofs && ofs < this->GetEndOffset();
}
};
static_assert(util::is_pod<AccessRange>::value);
struct CacheEntry {
size_t size;
AccessRange range;
bool is_valid;
bool is_write_back;
bool is_cached;
bool is_flushing;
s64 offset;
IBufferManager::CacheHandle handle;
u16 lru_counter;
fs::IBufferManager::CacheHandle handle;
uintptr_t memory_address;
size_t memory_size;
void Invalidate() {
this->is_write_back = false;
this->is_flushing = false;
}
bool IsAllocated() const {
return this->is_valid && (this->is_write_back ? this->memory_address != 0 : this->handle != 0);
}
bool IsWriteBack() const {
return this->is_write_back;
}
};
static_assert(util::is_pod<CacheEntry>::value);
using BlockCacheManager = ::ams::fssystem::impl::BlockCacheManager<CacheEntry, fs::IBufferManager>;
using CacheIndex = BlockCacheManager::CacheIndex;
enum Flag : s32 {
Flag_KeepBurstMode = (1 << 8),
Flag_RealData = (1 << 10),
};
private:
IBufferManager *m_buffer_manager;
os::SdkRecursiveMutex *m_mutex;
std::unique_ptr<CacheEntry[], ::ams::fs::impl::Deleter> m_entries;
IStorage *m_data_storage;
Result m_last_result;
s64 m_data_size;
size_t m_verification_block_size;
size_t m_verification_block_shift;
CacheIndex m_invalidate_index;
s32 m_max_cache_entry_count;
s32 m_flags;
s32 m_buffer_level;
fs::StorageType m_storage_type;
BlockCacheManager m_block_cache_manager;
public:
BlockCacheBufferedStorage();
virtual ~BlockCacheBufferedStorage() override;
Result Initialize(IBufferManager *bm, os::SdkRecursiveMutex *mtx, IStorage *data, s64 data_size, size_t verif_block_size, s32 max_cache_entries, bool is_real_data, s8 buffer_level, bool is_keep_burst_mode, fs::StorageType storage_type);
Result Initialize(fs::IBufferManager *bm, os::SdkRecursiveMutex *mtx, IStorage *data, s64 data_size, size_t verif_block_size, s32 max_cache_entries, bool is_real_data, s8 buffer_level, bool is_keep_burst_mode, fs::StorageType storage_type);
void Finalize();
virtual Result Read(s64 offset, void *buffer, size_t size) override;
virtual Result Write(s64 offset, const void *buffer, size_t size) override;
virtual Result SetSize(s64 size) override { AMS_UNUSED(size); return fs::ResultUnsupportedOperationInBlockCacheBufferedStorageA(); }
virtual Result SetSize(s64) override { R_THROW(fs::ResultUnsupportedOperationInBlockCacheBufferedStorageA()); }
virtual Result GetSize(s64 *out) override;
virtual Result Flush() override;
@@ -119,40 +146,24 @@ namespace ams::fssystem::save {
}
}
private:
s32 GetMaxCacheEntryCount() const {
return m_max_cache_entry_count;
}
Result ClearImpl(s64 offset, s64 size);
Result ClearSignatureImpl(s64 offset, s64 size);
Result InvalidateCacheImpl(s64 offset, s64 size);
Result FillZeroImpl(s64 offset, s64 size);
Result DestroySignatureImpl(s64 offset, s64 size);
Result InvalidateImpl();
Result QueryRangeImpl(void *dst, size_t dst_size, s64 offset, s64 size);
bool ExistsRedundantCacheEntry(const CacheEntry &entry) const;
Result GetAssociateBuffer(MemoryRange *out_range, CacheEntry *out_entry, s64 offset, size_t ideal_size, bool is_allocate_for_write);
void DestroyBuffer(CacheEntry *entry, const MemoryRange &range);
Result StoreAssociateBuffer(CacheIndex *out, const MemoryRange &range, const CacheEntry &entry);
Result StoreAssociateBuffer(const MemoryRange &range, const CacheEntry &entry) {
CacheIndex dummy;
return this->StoreAssociateBuffer(std::addressof(dummy), range, entry);
}
Result StoreOrDestroyBuffer(CacheIndex *out, const MemoryRange &range, CacheEntry *entry);
Result StoreOrDestroyBuffer(const MemoryRange &range, CacheEntry *entry) {
AMS_ASSERT(entry != nullptr);
ON_RESULT_FAILURE { this->DestroyBuffer(entry, range); };
R_TRY(this->StoreAssociateBuffer(range, *entry));
R_SUCCEED();
CacheIndex dummy;
R_RETURN(this->StoreOrDestroyBuffer(std::addressof(dummy), range, entry));
}
Result FlushCacheEntry(CacheIndex index, bool invalidate);
Result FlushRangeCacheEntries(s64 offset, s64 size, bool invalidate);
void InvalidateRangeCacheEntries(s64 offset, s64 size);
Result FlushAllCacheEntries();
Result InvalidateAllCacheEntries();

View File

@@ -18,7 +18,7 @@
#include <stratosphere/os.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
#include <stratosphere/fs/fs_substorage.hpp>
#include <stratosphere/fssystem/buffers/fssystem_i_buffer_manager.hpp>
#include <stratosphere/fs/fs_i_buffer_manager.hpp>
namespace ams::fssystem::save {
@@ -31,7 +31,7 @@ namespace ams::fssystem::save {
class SharedCache;
private:
fs::SubStorage m_base_storage;
IBufferManager *m_buffer_manager;
fs::IBufferManager *m_buffer_manager;
size_t m_block_size;
s64 m_base_storage_size;
std::unique_ptr<Cache[]> m_caches;
@@ -44,7 +44,7 @@ namespace ams::fssystem::save {
BufferedStorage();
virtual ~BufferedStorage();
Result Initialize(fs::SubStorage base_storage, IBufferManager *buffer_manager, size_t block_size, s32 buffer_count);
Result Initialize(fs::SubStorage base_storage, fs::IBufferManager *buffer_manager, size_t block_size, s32 buffer_count);
void Finalize();
bool IsInitialized() const { return m_caches != nullptr; }
@@ -61,7 +61,7 @@ namespace ams::fssystem::save {
void InvalidateCaches();
IBufferManager *GetBufferManager() const { return m_buffer_manager; }
fs::IBufferManager *GetBufferManager() const { return m_buffer_manager; }
void EnableBulkRead() { m_bulk_read_enabled = true; }
private:

View File

@@ -43,7 +43,7 @@ namespace ams::fssystem::save {
s64 m_verification_block_order;
s64 m_upper_layer_verification_block_size;
s64 m_upper_layer_verification_block_order;
IBufferManager *m_buffer_manager;
fs::IBufferManager *m_buffer_manager;
fs::HashSalt m_salt;
bool m_is_real_data;
fs::StorageType m_storage_type;
@@ -52,7 +52,7 @@ namespace ams::fssystem::save {
IntegrityVerificationStorage() : m_verification_block_size(0), m_verification_block_order(0), m_upper_layer_verification_block_size(0), m_upper_layer_verification_block_order(0), m_buffer_manager(nullptr) { /* ... */ }
virtual ~IntegrityVerificationStorage() override { this->Finalize(); }
Result Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const fs::HashSalt &salt, bool is_real_data, fs::StorageType storage_type);
Result Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, fs::IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const fs::HashSalt &salt, bool is_real_data, fs::StorageType storage_type);
void Finalize();
virtual Result Read(s64 offset, void *buffer, size_t size) override;