mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-29 05:55:16 -04:00
fs: first pass at compressed storage (works on iridium with wip hac2l code)
This commit is contained in:
parent
df631d74f0
commit
d638bbbb62
34 changed files with 2375 additions and 722 deletions
|
@ -239,10 +239,10 @@ namespace ams::fssystem {
|
|||
return it != m_attr_list.end() ? std::addressof(*it) : nullptr;
|
||||
}
|
||||
|
||||
const std::pair<uintptr_t, size_t> FileSystemBufferManager::AllocateBufferImpl(size_t size, const BufferAttribute &attr) {
|
||||
const fs::IBufferManager::MemoryRange FileSystemBufferManager::DoAllocateBuffer(size_t size, const BufferAttribute &attr) {
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
std::pair<uintptr_t, size_t> range = {};
|
||||
fs::IBufferManager::MemoryRange range = {};
|
||||
const auto order = m_buddy_heap.GetOrderFromBytes(size);
|
||||
AMS_ASSERT(order >= 0);
|
||||
|
||||
|
@ -277,7 +277,7 @@ namespace ams::fssystem {
|
|||
return range;
|
||||
}
|
||||
|
||||
void FileSystemBufferManager::DeallocateBufferImpl(uintptr_t address, size_t size) {
|
||||
void FileSystemBufferManager::DoDeallocateBuffer(uintptr_t address, size_t size) {
|
||||
AMS_ASSERT(util::IsPowerOfTwo(size));
|
||||
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
@ -285,7 +285,7 @@ namespace ams::fssystem {
|
|||
m_buddy_heap.Free(reinterpret_cast<void *>(address), m_buddy_heap.GetOrderFromBytes(size));
|
||||
}
|
||||
|
||||
FileSystemBufferManager::CacheHandle FileSystemBufferManager::RegisterCacheImpl(uintptr_t address, size_t size, const BufferAttribute &attr) {
|
||||
FileSystemBufferManager::CacheHandle FileSystemBufferManager::DoRegisterCache(uintptr_t address, size_t size, const BufferAttribute &attr) {
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
CacheHandle handle = 0;
|
||||
|
@ -312,10 +312,10 @@ namespace ams::fssystem {
|
|||
return handle;
|
||||
}
|
||||
|
||||
const std::pair<uintptr_t, size_t> FileSystemBufferManager::AcquireCacheImpl(CacheHandle handle) {
|
||||
const fs::IBufferManager::MemoryRange FileSystemBufferManager::DoAcquireCache(CacheHandle handle) {
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
std::pair<uintptr_t, size_t> range = {};
|
||||
fs::IBufferManager::MemoryRange range = {};
|
||||
if (m_cache_handle_table.Unregister(std::addressof(range.first), std::addressof(range.second), handle)) {
|
||||
const size_t total_allocatable_size = m_buddy_heap.GetTotalFreeSize() + m_cache_handle_table.GetTotalCacheSize();
|
||||
m_peak_total_allocatable_size = std::min(m_peak_total_allocatable_size, total_allocatable_size);
|
||||
|
@ -327,33 +327,33 @@ namespace ams::fssystem {
|
|||
return range;
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetTotalSizeImpl() const {
|
||||
size_t FileSystemBufferManager::DoGetTotalSize() const {
|
||||
return m_total_size;
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetFreeSizeImpl() const {
|
||||
size_t FileSystemBufferManager::DoGetFreeSize() const {
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
return m_buddy_heap.GetTotalFreeSize();
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetTotalAllocatableSizeImpl() const {
|
||||
size_t FileSystemBufferManager::DoGetTotalAllocatableSize() const {
|
||||
return this->GetFreeSize() + m_cache_handle_table.GetTotalCacheSize();
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetPeakFreeSizeImpl() const {
|
||||
size_t FileSystemBufferManager::DoGetFreeSizePeak() const {
|
||||
return m_peak_free_size;
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetPeakTotalAllocatableSizeImpl() const {
|
||||
size_t FileSystemBufferManager::DoGetTotalAllocatableSizePeak() const {
|
||||
return m_peak_total_allocatable_size;
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetRetriedCountImpl() const {
|
||||
size_t FileSystemBufferManager::DoGetRetriedCount() const {
|
||||
return m_retried_count;
|
||||
}
|
||||
|
||||
void FileSystemBufferManager::ClearPeakImpl() {
|
||||
void FileSystemBufferManager::DoClearPeak() {
|
||||
m_peak_free_size = this->GetFreeSize();
|
||||
m_retried_count = 0;
|
||||
}
|
||||
|
|
|
@ -117,7 +117,11 @@ namespace ams::fssystem {
|
|||
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
|
||||
R_UNLESS(util::IsAligned(offset, BlockSize), fs::ResultInvalidOffset());
|
||||
R_UNLESS(util::IsAligned(size, BlockSize), fs::ResultInvalidSize());
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
BucketTree::Offsets table_offsets;
|
||||
R_TRY(m_table.GetOffsets(std::addressof(table_offsets)));
|
||||
|
||||
R_UNLESS(table_offsets.IsInclude(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
/* Read the data. */
|
||||
R_TRY(m_data_storage.Read(offset, buffer, size));
|
||||
|
@ -130,8 +134,8 @@ namespace ams::fssystem {
|
|||
R_TRY(m_table.Find(std::addressof(visitor), offset));
|
||||
{
|
||||
const auto entry_offset = visitor.Get<Entry>()->GetOffset();
|
||||
R_UNLESS(util::IsAligned(entry_offset, BlockSize), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
R_UNLESS(0 <= entry_offset && m_table.Includes(entry_offset), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
R_UNLESS(util::IsAligned(entry_offset, BlockSize), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
R_UNLESS(0 <= entry_offset && table_offsets.IsInclude(entry_offset), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
}
|
||||
|
||||
/* Prepare to read in chunks. */
|
||||
|
@ -152,9 +156,9 @@ namespace ams::fssystem {
|
|||
if (visitor.CanMoveNext()) {
|
||||
R_TRY(visitor.MoveNext());
|
||||
next_entry_offset = visitor.Get<Entry>()->GetOffset();
|
||||
R_UNLESS(m_table.Includes(next_entry_offset), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
R_UNLESS(table_offsets.IsInclude(next_entry_offset), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
} else {
|
||||
next_entry_offset = m_table.GetEnd();
|
||||
next_entry_offset = table_offsets.end_offset;
|
||||
}
|
||||
R_UNLESS(util::IsAligned(next_entry_offset, BlockSize), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
R_UNLESS(cur_offset < next_entry_offset, fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
|
@ -192,22 +196,13 @@ namespace ams::fssystem {
|
|||
case fs::OperationId::Invalidate:
|
||||
{
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(offset >= 0);
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
|
||||
/* Succeed if there's nothing to operate on. */
|
||||
R_SUCCEED_IF(size == 0);
|
||||
|
||||
/* Validate arguments. */
|
||||
R_UNLESS(util::IsAligned(offset, BlockSize), fs::ResultInvalidOffset());
|
||||
R_UNLESS(util::IsAligned(size, BlockSize), fs::ResultInvalidSize());
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
/* Invalidate our table's cache. */
|
||||
R_TRY(m_table.InvalidateCache());
|
||||
|
||||
/* Operate on our data storage. */
|
||||
R_TRY(m_data_storage.OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(m_data_storage.OperateRange(fs::OperationId::Invalidate, 0, std::numeric_limits<s64>::max()));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
@ -230,7 +225,11 @@ namespace ams::fssystem {
|
|||
/* Validate arguments. */
|
||||
R_UNLESS(util::IsAligned(offset, BlockSize), fs::ResultInvalidOffset());
|
||||
R_UNLESS(util::IsAligned(size, BlockSize), fs::ResultInvalidSize());
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
BucketTree::Offsets table_offsets;
|
||||
R_TRY(m_table.GetOffsets(std::addressof(table_offsets)));
|
||||
|
||||
R_UNLESS(table_offsets.IsInclude(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
/* Operate on our data storage. */
|
||||
R_TRY(m_data_storage.OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
|
|
|
@ -249,9 +249,10 @@ namespace ams::fssystem {
|
|||
|
||||
/* Handle any data after the aligned portion. */
|
||||
if (core_offset_end < offset_end) {
|
||||
const auto tail_size = static_cast<size_t>(offset_end - core_offset_end);
|
||||
const auto tail_buffer = static_cast<char *>(buffer) + (core_offset_end - offset);
|
||||
const auto tail_size = static_cast<size_t>(offset_end - core_offset_end);
|
||||
R_TRY(m_base_storage->Read(core_offset_end, pooled_buffer.GetBuffer(), m_data_align));
|
||||
std::memcpy(buffer, pooled_buffer.GetBuffer(), tail_size);
|
||||
std::memcpy(tail_buffer, pooled_buffer.GetBuffer(), tail_size);
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
|
|
|
@ -154,7 +154,7 @@ namespace ams::fssystem {
|
|||
|
||||
/* Allocate node. */
|
||||
R_UNLESS(m_node_l1.Allocate(allocator, node_size), fs::ResultBufferAllocationFailed());
|
||||
auto node_guard = SCOPE_GUARD { m_node_l1.Free(node_size); };
|
||||
ON_RESULT_FAILURE { m_node_l1.Free(node_size); };
|
||||
|
||||
/* Read node. */
|
||||
R_TRY(node_storage.Read(0, m_node_l1.Get(), node_size));
|
||||
|
@ -186,12 +186,13 @@ namespace ams::fssystem {
|
|||
m_entry_count = entry_count;
|
||||
m_offset_count = offset_count;
|
||||
m_entry_set_count = entry_set_count;
|
||||
m_start_offset = start_offset;
|
||||
m_end_offset = end_offset;
|
||||
|
||||
m_offset_cache.offsets.start_offset = start_offset;
|
||||
m_offset_cache.offsets.end_offset = end_offset;
|
||||
m_offset_cache.is_initialized = true;
|
||||
|
||||
/* Cancel guard. */
|
||||
node_guard.Cancel();
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void BucketTree::Initialize(size_t node_size, s64 end_offset) {
|
||||
|
@ -201,7 +202,10 @@ namespace ams::fssystem {
|
|||
AMS_ASSERT(!this->IsInitialized());
|
||||
|
||||
m_node_size = node_size;
|
||||
m_end_offset = end_offset;
|
||||
|
||||
m_offset_cache.offsets.start_offset = 0;
|
||||
m_offset_cache.offsets.end_offset = end_offset;
|
||||
m_offset_cache.is_initialized = true;
|
||||
}
|
||||
|
||||
void BucketTree::Finalize() {
|
||||
|
@ -214,69 +218,77 @@ namespace ams::fssystem {
|
|||
m_entry_count = 0;
|
||||
m_offset_count = 0;
|
||||
m_entry_set_count = 0;
|
||||
m_start_offset = 0;
|
||||
m_end_offset = 0;
|
||||
|
||||
m_offset_cache.offsets.start_offset = 0;
|
||||
m_offset_cache.offsets.end_offset = 0;
|
||||
m_offset_cache.is_initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
Result BucketTree::Find(Visitor *visitor, s64 virtual_address) const {
|
||||
Result BucketTree::Find(Visitor *visitor, s64 virtual_address) {
|
||||
AMS_ASSERT(visitor != nullptr);
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
|
||||
R_UNLESS(virtual_address >= 0, fs::ResultInvalidOffset());
|
||||
R_UNLESS(!this->IsEmpty(), fs::ResultOutOfRange());
|
||||
|
||||
R_TRY(visitor->Initialize(this));
|
||||
BucketTree::Offsets offsets;
|
||||
R_TRY(this->GetOffsets(std::addressof(offsets)));
|
||||
|
||||
R_TRY(visitor->Initialize(this, offsets));
|
||||
|
||||
return visitor->Find(virtual_address);
|
||||
}
|
||||
|
||||
Result BucketTree::InvalidateCache() {
|
||||
/* Invalidate the node storage cache. */
|
||||
{
|
||||
s64 storage_size;
|
||||
R_TRY(m_node_storage.GetSize(std::addressof(storage_size)));
|
||||
R_TRY(m_node_storage.OperateRange(fs::OperationId::Invalidate, 0, storage_size));
|
||||
}
|
||||
|
||||
/* Refresh start/end offsets. */
|
||||
{
|
||||
/* Read node. */
|
||||
R_TRY(m_node_storage.Read(0, m_node_l1.Get(), m_node_size));
|
||||
|
||||
/* Verify node. */
|
||||
R_TRY(m_node_l1->Verify(0, m_node_size, sizeof(s64)));
|
||||
|
||||
/* Validate offsets. */
|
||||
const auto * const node = m_node_l1.Get<Node>();
|
||||
|
||||
s64 start_offset;
|
||||
if (m_offset_count < m_entry_set_count && node->GetCount() < m_offset_count) {
|
||||
start_offset = *node->GetEnd();
|
||||
} else {
|
||||
start_offset = *node->GetBegin();
|
||||
}
|
||||
const auto end_offset = node->GetEndOffset();
|
||||
|
||||
R_UNLESS(0 <= start_offset && start_offset <= node->GetBeginOffset(), fs::ResultInvalidBucketTreeEntryOffset());
|
||||
R_UNLESS(start_offset < end_offset, fs::ResultInvalidBucketTreeEntryOffset());
|
||||
|
||||
/* Set refreshed offsets. */
|
||||
m_start_offset = start_offset;
|
||||
m_end_offset = end_offset;
|
||||
}
|
||||
R_TRY(m_node_storage.OperateRange(fs::OperationId::Invalidate, 0, std::numeric_limits<s64>::max()));
|
||||
|
||||
/* Invalidate the entry storage cache. */
|
||||
{
|
||||
s64 storage_size;
|
||||
R_TRY(m_entry_storage.GetSize(std::addressof(storage_size)));
|
||||
R_TRY(m_entry_storage.OperateRange(fs::OperationId::Invalidate, 0, storage_size));
|
||||
}
|
||||
R_TRY(m_entry_storage.OperateRange(fs::OperationId::Invalidate, 0, std::numeric_limits<s64>::max()));
|
||||
|
||||
return ResultSuccess();
|
||||
/* Reset our offsets. */
|
||||
m_offset_cache.is_initialized = false;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result BucketTree::Visitor::Initialize(const BucketTree *tree) {
|
||||
Result BucketTree::EnsureOffsetCache() {
|
||||
/* If we already have an offset cache, we're good. */
|
||||
R_SUCCEED_IF(m_offset_cache.is_initialized);
|
||||
|
||||
/* Acquire exclusive right to edit the offset cache. */
|
||||
std::scoped_lock lk(m_offset_cache.mutex);
|
||||
|
||||
/* Check again, to be sure. */
|
||||
R_SUCCEED_IF(m_offset_cache.is_initialized);
|
||||
|
||||
/* Read/verify L1. */
|
||||
R_TRY(m_node_storage.Read(0, m_node_l1.Get(), m_node_size));
|
||||
R_TRY(m_node_l1->Verify(0, m_node_size, sizeof(s64)));
|
||||
|
||||
/* Get the node. */
|
||||
auto * const node = m_node_l1.Get<Node>();
|
||||
|
||||
s64 start_offset;
|
||||
if (m_offset_count < m_entry_set_count && node->GetCount() < m_offset_count) {
|
||||
start_offset = *node->GetEnd();
|
||||
} else {
|
||||
start_offset = *node->GetBegin();
|
||||
}
|
||||
const auto end_offset = node->GetEndOffset();
|
||||
|
||||
R_UNLESS(0 <= start_offset && start_offset <= node->GetBeginOffset(), fs::ResultInvalidBucketTreeEntryOffset());
|
||||
R_UNLESS(start_offset < end_offset, fs::ResultInvalidBucketTreeEntryOffset());
|
||||
|
||||
m_offset_cache.offsets.start_offset = start_offset;
|
||||
m_offset_cache.offsets.end_offset = end_offset;
|
||||
m_offset_cache.is_initialized = true;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result BucketTree::Visitor::Initialize(const BucketTree *tree, const BucketTree::Offsets &offsets) {
|
||||
AMS_ASSERT(tree != nullptr);
|
||||
AMS_ASSERT(m_tree == nullptr || m_tree == tree);
|
||||
|
||||
|
@ -284,7 +296,8 @@ namespace ams::fssystem {
|
|||
m_entry = tree->GetAllocator()->Allocate(tree->m_entry_size);
|
||||
R_UNLESS(m_entry != nullptr, fs::ResultBufferAllocationFailed());
|
||||
|
||||
m_tree = tree;
|
||||
m_tree = tree;
|
||||
m_offsets = offsets;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
|
@ -319,7 +332,7 @@ namespace ams::fssystem {
|
|||
/* Read the new entry. */
|
||||
const auto entry_size = m_tree->m_entry_size;
|
||||
const auto entry_offset = impl::GetBucketTreeEntryOffset(m_entry_set.info.index, m_tree->m_node_size, entry_size, entry_index);
|
||||
R_TRY(m_tree->m_entry_storage.Read(entry_offset, std::addressof(m_entry), entry_size));
|
||||
R_TRY(m_tree->m_entry_storage.Read(entry_offset, m_entry, entry_size));
|
||||
|
||||
/* Note that we changed index. */
|
||||
m_entry_index = entry_index;
|
||||
|
@ -357,7 +370,7 @@ namespace ams::fssystem {
|
|||
/* Read the new entry. */
|
||||
const auto entry_size = m_tree->m_entry_size;
|
||||
const auto entry_offset = impl::GetBucketTreeEntryOffset(m_entry_set.info.index, m_tree->m_node_size, entry_size, entry_index);
|
||||
R_TRY(m_tree->m_entry_storage.Read(entry_offset, std::addressof(m_entry), entry_size));
|
||||
R_TRY(m_tree->m_entry_storage.Read(entry_offset, m_entry, entry_size));
|
||||
|
||||
/* Note that we changed index. */
|
||||
m_entry_index = entry_index;
|
||||
|
|
|
@ -59,14 +59,17 @@ namespace ams::fssystem {
|
|||
R_UNLESS(out_entries != nullptr || entry_count == 0, fs::ResultNullptrArgument());
|
||||
|
||||
/* Check that our range is valid. */
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
BucketTree::Offsets table_offsets;
|
||||
R_TRY(m_table.GetOffsets(std::addressof(table_offsets)));
|
||||
|
||||
R_UNLESS(table_offsets.IsInclude(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
/* Find the offset in our tree. */
|
||||
BucketTree::Visitor visitor;
|
||||
R_TRY(m_table.Find(std::addressof(visitor), offset));
|
||||
{
|
||||
const auto entry_offset = visitor.Get<Entry>()->GetVirtualOffset();
|
||||
R_UNLESS(0 <= entry_offset && m_table.Includes(entry_offset), fs::ResultInvalidIndirectEntryOffset());
|
||||
R_UNLESS(0 <= entry_offset && table_offsets.IsInclude(entry_offset), fs::ResultInvalidIndirectEntryOffset());
|
||||
}
|
||||
|
||||
/* Prepare to loop over entries. */
|
||||
|
@ -96,7 +99,7 @@ namespace ams::fssystem {
|
|||
|
||||
/* Write the output count. */
|
||||
*out_entry_count = count;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IndirectStorage::Read(s64 offset, void *buffer, size_t size) {
|
||||
|
@ -110,35 +113,28 @@ namespace ams::fssystem {
|
|||
/* Ensure that we have a buffer to read to. */
|
||||
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
R_TRY(this->OperatePerEntry<true>(offset, size, [=](fs::IStorage *storage, s64 data_offset, s64 cur_offset, s64 cur_size) -> Result {
|
||||
R_TRY((this->OperatePerEntry<true, true>(offset, size, [=](fs::IStorage *storage, s64 data_offset, s64 cur_offset, s64 cur_size) -> Result {
|
||||
R_TRY(storage->Read(data_offset, reinterpret_cast<u8 *>(buffer) + (cur_offset - offset), static_cast<size_t>(cur_size)));
|
||||
return ResultSuccess();
|
||||
}));
|
||||
R_SUCCEED();
|
||||
})));
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IndirectStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
|
||||
switch (op_id) {
|
||||
case fs::OperationId::Invalidate:
|
||||
{
|
||||
if (size > 0) {
|
||||
/* Validate arguments. */
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
if (!m_table.IsEmpty()) {
|
||||
/* Invalidate our table's cache. */
|
||||
R_TRY(m_table.InvalidateCache());
|
||||
if (!m_table.IsEmpty()) {
|
||||
/* Invalidate our table's cache. */
|
||||
R_TRY(m_table.InvalidateCache());
|
||||
|
||||
/* Operate on our entries. */
|
||||
R_TRY(this->OperatePerEntry<false>(offset, size, [=](fs::IStorage *storage, s64 data_offset, s64 cur_offset, s64 cur_size) -> Result {
|
||||
AMS_UNUSED(cur_offset);
|
||||
R_TRY(storage->OperateRange(dst, dst_size, op_id, data_offset, cur_size, src, src_size));
|
||||
return ResultSuccess();
|
||||
}));
|
||||
/* Invalidate our storages. */
|
||||
for (auto &storage : m_data_storage) {
|
||||
R_TRY(storage.OperateRange(fs::OperationId::Invalidate, 0, std::numeric_limits<s64>::max()));
|
||||
}
|
||||
return ResultSuccess();
|
||||
}
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
case fs::OperationId::QueryRange:
|
||||
{
|
||||
|
@ -148,33 +144,37 @@ namespace ams::fssystem {
|
|||
|
||||
if (size > 0) {
|
||||
/* Validate arguments. */
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
BucketTree::Offsets table_offsets;
|
||||
R_TRY(m_table.GetOffsets(std::addressof(table_offsets)));
|
||||
|
||||
R_UNLESS(table_offsets.IsInclude(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
if (!m_table.IsEmpty()) {
|
||||
/* Create a new info. */
|
||||
fs::QueryRangeInfo merged_info;
|
||||
merged_info.Clear();
|
||||
|
||||
/* Operate on our entries. */
|
||||
R_TRY(this->OperatePerEntry<false>(offset, size, [=, &merged_info](fs::IStorage *storage, s64 data_offset, s64 cur_offset, s64 cur_size) -> Result {
|
||||
R_TRY((this->OperatePerEntry<false, true>(offset, size, [=, &merged_info](fs::IStorage *storage, s64 data_offset, s64 cur_offset, s64 cur_size) -> Result {
|
||||
AMS_UNUSED(cur_offset);
|
||||
|
||||
fs::QueryRangeInfo cur_info;
|
||||
R_TRY(storage->OperateRange(std::addressof(cur_info), sizeof(cur_info), op_id, data_offset, cur_size, src, src_size));
|
||||
merged_info.Merge(cur_info);
|
||||
return ResultSuccess();
|
||||
}));
|
||||
R_SUCCEED();
|
||||
})));
|
||||
|
||||
/* Write the merged info. */
|
||||
*reinterpret_cast<fs::QueryRangeInfo *>(dst) = merged_info;
|
||||
}
|
||||
}
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
default:
|
||||
return fs::ResultUnsupportedOperationInIndirectStorageC();
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
namespace ams::fssystem {
|
||||
|
||||
Result IntegrityRomFsStorage::Initialize(save::HierarchicalIntegrityVerificationInformation level_hash_info, Hash master_hash, save::HierarchicalIntegrityVerificationStorage::HierarchicalStorageInformation storage_info, IBufferManager *bm, IHash256GeneratorFactory *hgf) {
|
||||
Result IntegrityRomFsStorage::Initialize(save::HierarchicalIntegrityVerificationInformation level_hash_info, Hash master_hash, save::HierarchicalIntegrityVerificationStorage::HierarchicalStorageInformation storage_info, fs::IBufferManager *bm, IHash256GeneratorFactory *hgf) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(bm != nullptr);
|
||||
|
||||
|
|
|
@ -1105,7 +1105,7 @@ namespace ams::fssystem {
|
|||
return this->CreateCompressedStorage(out, out_cmp, out_meta, std::move(base_storage), compression_info, m_reader->GetDecompressor(), m_allocator, m_buffer_manager);
|
||||
}
|
||||
|
||||
Result NcaFileSystemDriver::CreateCompressedStorage(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::CompressedStorage> *out_cmp, std::shared_ptr<fs::IStorage> *out_meta, std::shared_ptr<fs::IStorage> base_storage, const NcaCompressionInfo &compression_info, GetDecompressorFunction get_decompressor, MemoryResource *allocator, IBufferManager *buffer_manager) {
|
||||
Result NcaFileSystemDriver::CreateCompressedStorage(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::CompressedStorage> *out_cmp, std::shared_ptr<fs::IStorage> *out_meta, std::shared_ptr<fs::IStorage> base_storage, const NcaCompressionInfo &compression_info, GetDecompressorFunction get_decompressor, MemoryResource *allocator, fs::IBufferManager *buffer_manager) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(out != nullptr);
|
||||
AMS_ASSERT(base_storage != nullptr);
|
||||
|
|
|
@ -29,13 +29,17 @@ namespace ams::fssystem {
|
|||
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
if (this->GetEntryTable().IsEmpty()) {
|
||||
R_UNLESS(this->GetEntryTable().Includes(offset, size), fs::ResultOutOfRange());
|
||||
BucketTree::Offsets table_offsets;
|
||||
R_TRY(this->GetEntryTable().GetOffsets(std::addressof(table_offsets)));
|
||||
|
||||
R_UNLESS(table_offsets.IsInclude(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
std::memset(buffer, 0, size);
|
||||
} else {
|
||||
R_TRY(this->OperatePerEntry<false>(offset, size, [=](fs::IStorage *storage, s64 data_offset, s64 cur_offset, s64 cur_size) -> Result {
|
||||
R_TRY((this->OperatePerEntry<false, true>(offset, size, [=](fs::IStorage *storage, s64 data_offset, s64 cur_offset, s64 cur_size) -> Result {
|
||||
R_TRY(storage->Read(data_offset, reinterpret_cast<u8 *>(buffer) + (cur_offset - offset), static_cast<size_t>(cur_size)));
|
||||
return ResultSuccess();
|
||||
}));
|
||||
})));
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -35,7 +35,7 @@ namespace ams::fssystem::save {
|
|||
private:
|
||||
BufferedStorage *m_buffered_storage;
|
||||
std::pair<uintptr_t, size_t> m_memory_range;
|
||||
IBufferManager::CacheHandle m_cache_handle;
|
||||
fs::IBufferManager::CacheHandle m_cache_handle;
|
||||
s64 m_offset;
|
||||
std::atomic<bool> m_is_valid;
|
||||
std::atomic<bool> m_is_dirty;
|
||||
|
@ -139,7 +139,7 @@ namespace ams::fssystem::save {
|
|||
/* Ensure our buffer state is coherent. */
|
||||
if (m_memory_range.first != InvalidAddress && !m_is_dirty) {
|
||||
if (this->IsValid()) {
|
||||
m_cache_handle = m_buffered_storage->m_buffer_manager->RegisterCache(m_memory_range.first, m_memory_range.second, IBufferManager::BufferAttribute());
|
||||
m_cache_handle = m_buffered_storage->m_buffer_manager->RegisterCache(m_memory_range.first, m_memory_range.second, fs::IBufferManager::BufferAttribute());
|
||||
} else {
|
||||
m_buffered_storage->m_buffer_manager->DeallocateBuffer(m_memory_range.first, m_memory_range.second);
|
||||
}
|
||||
|
@ -360,11 +360,11 @@ namespace ams::fssystem::save {
|
|||
}
|
||||
private:
|
||||
Result AllocateFetchBuffer() {
|
||||
IBufferManager *buffer_manager = m_buffered_storage->m_buffer_manager;
|
||||
fs::IBufferManager *buffer_manager = m_buffered_storage->m_buffer_manager;
|
||||
AMS_ASSERT(buffer_manager->AcquireCache(m_cache_handle).first == InvalidAddress);
|
||||
|
||||
auto range_guard = SCOPE_GUARD { m_memory_range.first = InvalidAddress; };
|
||||
R_TRY(buffers::AllocateBufferUsingBufferManagerContext(std::addressof(m_memory_range), buffer_manager, m_buffered_storage->m_block_size, IBufferManager::BufferAttribute(), [](const std::pair<uintptr_t, size_t> &buffer) {
|
||||
R_TRY(buffers::AllocateBufferUsingBufferManagerContext(std::addressof(m_memory_range), buffer_manager, m_buffered_storage->m_block_size, fs::IBufferManager::BufferAttribute(), [](const std::pair<uintptr_t, size_t> &buffer) {
|
||||
return buffer.first != 0;
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
|
||||
|
@ -591,7 +591,7 @@ namespace ams::fssystem::save {
|
|||
this->Finalize();
|
||||
}
|
||||
|
||||
Result BufferedStorage::Initialize(fs::SubStorage base_storage, IBufferManager *buffer_manager, size_t block_size, s32 buffer_count) {
|
||||
Result BufferedStorage::Initialize(fs::SubStorage base_storage, fs::IBufferManager *buffer_manager, size_t block_size, s32 buffer_count) {
|
||||
AMS_ASSERT(buffer_manager != nullptr);
|
||||
AMS_ASSERT(block_size > 0);
|
||||
AMS_ASSERT(util::IsPowerOfTwo(block_size));
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
namespace ams::fssystem::save {
|
||||
|
||||
Result IntegrityVerificationStorage::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 IntegrityVerificationStorage::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) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(verif_block_size >= HashSize);
|
||||
AMS_ASSERT(bm != nullptr);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue