1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2024-12-19 00:42:06 +00:00

fs: properly implement OperateRangeWithBuffer, correct OperationId names.

This commit is contained in:
Michael Scire 2021-04-29 20:09:45 -07:00
parent eb5542963f
commit 0dc308d92a
17 changed files with 54 additions and 34 deletions

View file

@ -68,7 +68,7 @@ namespace ams::fs {
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override { virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
switch (op_id) { switch (op_id) {
case OperationId::InvalidateCache: case OperationId::Invalidate:
return ResultSuccess(); return ResultSuccess();
case OperationId::QueryRange: case OperationId::QueryRange:
R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); R_UNLESS(dst != nullptr, fs::ResultNullptrArgument());

View file

@ -18,11 +18,16 @@
namespace ams::fs { namespace ams::fs {
enum class OperationId : u64 { enum class OperationId : s64 {
Clear = ::FsOperationId_Clear, FillZero = 0,
ClearSignature = ::FsOperationId_ClearSignature, DestroySignature = 1,
InvalidateCache = ::FsOperationId_InvalidateCache, Invalidate = 2,
QueryRange = ::FsOperationId_QueryRange, QueryRange = 3,
QueryUnpreparedRange = 4,
QueryLazyLoadCompletionRate = 5,
SetLazyLoadPriority = 6,
ReadLazyLoadFileForciblyForDebug = 10001,
}; };
} }

View file

@ -55,7 +55,7 @@ namespace ams::fs {
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final {
switch (op_id) { switch (op_id) {
case OperationId::InvalidateCache: case OperationId::Invalidate:
case OperationId::QueryRange: case OperationId::QueryRange:
return this->base_file->OperateRange(dst, dst_size, op_id, offset, size, src, src_size); return this->base_file->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
default: default:

View file

@ -72,7 +72,7 @@ namespace ams::fs {
Result FileStorage::OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { Result FileStorage::OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
switch (op_id) { switch (op_id) {
case OperationId::InvalidateCache: case OperationId::Invalidate:
case OperationId::QueryRange: case OperationId::QueryRange:
if (size == 0) { if (size == 0) {
if (op_id == OperationId::QueryRange) { if (op_id == OperationId::QueryRange) {

View file

@ -228,7 +228,7 @@ namespace ams::fs {
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
switch (op_id) { switch (op_id) {
case OperationId::InvalidateCache: case OperationId::Invalidate:
case OperationId::QueryRange: case OperationId::QueryRange:
{ {
R_UNLESS(offset >= 0, fs::ResultOutOfRange()); R_UNLESS(offset >= 0, fs::ResultOutOfRange());

View file

@ -32,7 +32,7 @@ namespace ams::fssrv::impl {
void FileInterfaceAdapter::InvalidateCache() { void FileInterfaceAdapter::InvalidateCache() {
AMS_ABORT_UNLESS(this->parent_filesystem->IsDeepRetryEnabled()); AMS_ABORT_UNLESS(this->parent_filesystem->IsDeepRetryEnabled());
std::scoped_lock<os::ReadWriteLock> scoped_write_lock(this->parent_filesystem->GetReadWriteLockForCacheInvalidation()); std::scoped_lock<os::ReadWriteLock> scoped_write_lock(this->parent_filesystem->GetReadWriteLockForCacheInvalidation());
this->base_file->OperateRange(nullptr, 0, fs::OperationId::InvalidateCache, 0, std::numeric_limits<s64>::max(), nullptr, 0); this->base_file->OperateRange(nullptr, 0, fs::OperationId::Invalidate, 0, std::numeric_limits<s64>::max(), nullptr, 0);
} }
Result FileInterfaceAdapter::Read(ams::sf::Out<s64> out, s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size, fs::ReadOption option) { Result FileInterfaceAdapter::Read(ams::sf::Out<s64> out, s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size, fs::ReadOption option) {
@ -90,11 +90,26 @@ namespace ams::fssrv::impl {
} }
Result FileInterfaceAdapter::OperateRangeWithBuffer(const ams::sf::OutNonSecureBuffer &out_buf, const ams::sf::InNonSecureBuffer &in_buf, s32 op_id, s64 offset, s64 size) { Result FileInterfaceAdapter::OperateRangeWithBuffer(const ams::sf::OutNonSecureBuffer &out_buf, const ams::sf::InNonSecureBuffer &in_buf, s32 op_id, s64 offset, s64 size) {
/* TODO: Nintendo supports calling info OperateRange using the provided buffers, when op_id is 4/5/6 or a class member is set. */ /* Check that we have permission to perform the operation. */
/* We should (in the future), determine what uses this, and mimic Nintendo's behavior to the extent that we can. */ switch (static_cast<fs::OperationId>(op_id)) {
using enum fs::OperationId;
case QueryUnpreparedRange:
case QueryLazyLoadCompletionRate:
case SetLazyLoadPriority:
/* Lazy load/unprepared operations are always allowed to be performed with buffer. */
break;
default:
/* TODO: Nintendo requires that a class member here be true here, but this class member seems to always be false. */
/* If this changes (or reverse engineering is wrong), this should be updated. */
return fs::ResultPermissionDenied(); return fs::ResultPermissionDenied();
} }
/* Perform the operation. */
R_TRY(this->base_file->OperateRange(out_buf.GetPointer(), out_buf.GetSize(), static_cast<fs::OperationId>(op_id), offset, size, in_buf.GetPointer(), in_buf.GetSize()));
return ResultSuccess();
}
DirectoryInterfaceAdapter::DirectoryInterfaceAdapter(std::unique_ptr<fs::fsa::IDirectory> &&dir, FileSystemInterfaceAdapter *parent, util::unique_lock<fssystem::SemaphoreAdapter> &&sema) DirectoryInterfaceAdapter::DirectoryInterfaceAdapter(std::unique_ptr<fs::fsa::IDirectory> &&dir, FileSystemInterfaceAdapter *parent, util::unique_lock<fssystem::SemaphoreAdapter> &&sema)
: parent_filesystem(parent, true), base_dir(std::move(dir)), open_count_semaphore(std::move(sema)) : parent_filesystem(parent, true), base_dir(std::move(dir)), open_count_semaphore(std::move(sema))
{ {

View file

@ -189,7 +189,7 @@ namespace ams::fssystem {
Result AesCtrCounterExtendedStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { Result AesCtrCounterExtendedStorage::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) { switch (op_id) {
case fs::OperationId::InvalidateCache: case fs::OperationId::Invalidate:
{ {
/* Validate preconditions. */ /* Validate preconditions. */
AMS_ASSERT(offset >= 0); AMS_ASSERT(offset >= 0);

View file

@ -236,7 +236,7 @@ namespace ams::fssystem {
{ {
s64 storage_size; s64 storage_size;
R_TRY(this->node_storage.GetSize(std::addressof(storage_size))); R_TRY(this->node_storage.GetSize(std::addressof(storage_size)));
R_TRY(this->node_storage.OperateRange(fs::OperationId::InvalidateCache, 0, storage_size)); R_TRY(this->node_storage.OperateRange(fs::OperationId::Invalidate, 0, storage_size));
} }
/* Refresh start/end offsets. */ /* Refresh start/end offsets. */
@ -270,7 +270,7 @@ namespace ams::fssystem {
{ {
s64 storage_size; s64 storage_size;
R_TRY(this->entry_storage.GetSize(std::addressof(storage_size))); R_TRY(this->entry_storage.GetSize(std::addressof(storage_size)));
R_TRY(this->entry_storage.OperateRange(fs::OperationId::InvalidateCache, 0, storage_size)); R_TRY(this->entry_storage.OperateRange(fs::OperationId::Invalidate, 0, storage_size));
} }
return ResultSuccess(); return ResultSuccess();

View file

@ -120,7 +120,7 @@ namespace ams::fssystem {
Result IndirectStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { 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) { switch (op_id) {
case fs::OperationId::InvalidateCache: case fs::OperationId::Invalidate:
{ {
if (size > 0) { if (size > 0) {
/* Validate arguments. */ /* Validate arguments. */

View file

@ -269,7 +269,7 @@ namespace ams::fssystem {
virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override { virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
switch (op_id) { switch (op_id) {
case fs::OperationId::InvalidateCache: case fs::OperationId::Invalidate:
{ {
R_TRY(this->true_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size)); R_TRY(this->true_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
R_TRY(this->false_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size)); R_TRY(this->false_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));

View file

@ -87,7 +87,7 @@ namespace ams::fssystem {
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final {
/* Validate preconditions for operation. */ /* Validate preconditions for operation. */
switch (op_id) { switch (op_id) {
case fs::OperationId::InvalidateCache: case fs::OperationId::Invalidate:
R_UNLESS((this->mode & fs::OpenMode_Read) != 0, fs::ResultReadNotPermitted()); R_UNLESS((this->mode & fs::OpenMode_Read) != 0, fs::ResultReadNotPermitted());
R_UNLESS((this->mode & fs::OpenMode_Write) == 0, fs::ResultUnsupportedOperationInPartitionFileB()); R_UNLESS((this->mode & fs::OpenMode_Write) == 0, fs::ResultUnsupportedOperationInPartitionFileB());
break; break;

View file

@ -92,7 +92,7 @@ namespace ams::fssystem {
AMS_ASSERT(util::IsAligned(size, this->block_size)); AMS_ASSERT(util::IsAligned(size, this->block_size));
/* If invalidating cache, invalidate our blocks. */ /* If invalidating cache, invalidate our blocks. */
if (op_id == fs::OperationId::InvalidateCache) { if (op_id == fs::OperationId::Invalidate) {
R_UNLESS(offset >= 0, fs::ResultInvalidOffset()); R_UNLESS(offset >= 0, fs::ResultInvalidOffset());
std::scoped_lock lk(this->mutex); std::scoped_lock lk(this->mutex);

View file

@ -73,7 +73,7 @@ namespace ams::fssystem {
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
switch (op_id) { switch (op_id) {
case fs::OperationId::InvalidateCache: case fs::OperationId::Invalidate:
case fs::OperationId::QueryRange: case fs::OperationId::QueryRange:
{ {
R_UNLESS(offset >= 0, fs::ResultOutOfRange()); R_UNLESS(offset >= 0, fs::ResultOutOfRange());

View file

@ -389,17 +389,17 @@ namespace ams::fssystem::save {
AMS_ASSERT(this->data_storage != nullptr); AMS_ASSERT(this->data_storage != nullptr);
switch (op_id) { switch (op_id) {
case fs::OperationId::Clear: case fs::OperationId::FillZero:
{ {
R_TRY(this->ClearImpl(offset, size)); R_TRY(this->ClearImpl(offset, size));
return ResultSuccess(); return ResultSuccess();
} }
case fs::OperationId::ClearSignature: case fs::OperationId::DestroySignature:
{ {
R_TRY(this->ClearSignatureImpl(offset, size)); R_TRY(this->ClearSignatureImpl(offset, size));
return ResultSuccess(); return ResultSuccess();
} }
case fs::OperationId::InvalidateCache: case fs::OperationId::Invalidate:
{ {
R_UNLESS(this->storage_type != fs::StorageType_SaveData, fs::ResultUnsupportedOperationInBlockCacheBufferedStorageB()); R_UNLESS(this->storage_type != fs::StorageType_SaveData, fs::ResultUnsupportedOperationInBlockCacheBufferedStorageB());
R_TRY(this->InvalidateCacheImpl(offset, size)); R_TRY(this->InvalidateCacheImpl(offset, size));
@ -531,7 +531,7 @@ namespace ams::fssystem::save {
R_SUCCEED_IF(start_offset == end_offset); R_SUCCEED_IF(start_offset == end_offset);
/* Clear the signature for the aligned range. */ /* Clear the signature for the aligned range. */
R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(fs::OperationId::Clear, start_offset, end_offset - start_offset))); R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(fs::OperationId::FillZero, start_offset, end_offset - start_offset)));
/* Set blocking buffer manager allocations. */ /* Set blocking buffer manager allocations. */
buffers::EnableBlockingBufferManagerAllocation(); buffers::EnableBlockingBufferManagerAllocation();
@ -558,7 +558,7 @@ namespace ams::fssystem::save {
R_TRY(this->UpdateLastResult(this->FlushRangeCacheEntries(offset, size, true))); R_TRY(this->UpdateLastResult(this->FlushRangeCacheEntries(offset, size, true)));
/* Clear the signature for the aligned range. */ /* Clear the signature for the aligned range. */
R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(fs::OperationId::ClearSignature, start_offset, end_offset - start_offset))); R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(fs::OperationId::DestroySignature, start_offset, end_offset - start_offset)));
/* Set blocking buffer manager allocations. */ /* Set blocking buffer manager allocations. */
buffers::EnableBlockingBufferManagerAllocation(); buffers::EnableBlockingBufferManagerAllocation();
@ -583,7 +583,7 @@ namespace ams::fssystem::save {
/* Invalidate the aligned range. */ /* Invalidate the aligned range. */
{ {
Result result = this->data_storage->OperateRange(fs::OperationId::InvalidateCache, aligned_offset, aligned_size); Result result = this->data_storage->OperateRange(fs::OperationId::Invalidate, aligned_offset, aligned_size);
AMS_ASSERT(!fs::ResultBufferAllocationFailed::Includes(result)); AMS_ASSERT(!fs::ResultBufferAllocationFailed::Includes(result));
R_TRY(result); R_TRY(result);
} }

View file

@ -718,7 +718,7 @@ namespace ams::fssystem::save {
AMS_ASSERT(this->IsInitialized()); AMS_ASSERT(this->IsInitialized());
/* Invalidate caches, if we should. */ /* Invalidate caches, if we should. */
if (op_id == fs::OperationId::InvalidateCache) { if (op_id == fs::OperationId::Invalidate) {
SharedCache cache(this); SharedCache cache(this);
while (cache.AcquireNextOverlappedCache(offset, size)) { while (cache.AcquireNextOverlappedCache(offset, size)) {
cache.Invalidate(); cache.Invalidate();

View file

@ -316,14 +316,14 @@ namespace ams::fssystem::save {
Result HierarchicalIntegrityVerificationStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { Result HierarchicalIntegrityVerificationStorage::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) { switch (op_id) {
case fs::OperationId::Clear: case fs::OperationId::FillZero:
case fs::OperationId::ClearSignature: case fs::OperationId::DestroySignature:
{ {
R_TRY(this->buffer_storages[this->max_layers - 2].OperateRange(dst, dst_size, op_id, offset, size, src, src_size)); R_TRY(this->buffer_storages[this->max_layers - 2].OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
this->is_written_for_rollback = true; this->is_written_for_rollback = true;
return ResultSuccess(); return ResultSuccess();
} }
case fs::OperationId::InvalidateCache: case fs::OperationId::Invalidate:
case fs::OperationId::QueryRange: case fs::OperationId::QueryRange:
{ {
R_TRY(this->buffer_storages[this->max_layers - 2].OperateRange(dst, dst_size, op_id, offset, size, src, src_size)); R_TRY(this->buffer_storages[this->max_layers - 2].OperateRange(dst, dst_size, op_id, offset, size, src, src_size));

View file

@ -256,7 +256,7 @@ namespace ams::fssystem::save {
AMS_ASSERT(util::IsAligned(size, static_cast<size_t>(this->verification_block_size))); AMS_ASSERT(util::IsAligned(size, static_cast<size_t>(this->verification_block_size)));
switch (op_id) { switch (op_id) {
case fs::OperationId::Clear: case fs::OperationId::FillZero:
{ {
/* Clear should only be called for save data. */ /* Clear should only be called for save data. */
AMS_ASSERT(this->storage_type == fs::StorageType_SaveData); AMS_ASSERT(this->storage_type == fs::StorageType_SaveData);
@ -289,7 +289,7 @@ namespace ams::fssystem::save {
return ResultSuccess(); return ResultSuccess();
} }
case fs::OperationId::ClearSignature: case fs::OperationId::DestroySignature:
{ {
/* Clear Signature should only be called for save data. */ /* Clear Signature should only be called for save data. */
AMS_ASSERT(this->storage_type == fs::StorageType_SaveData); AMS_ASSERT(this->storage_type == fs::StorageType_SaveData);
@ -319,7 +319,7 @@ namespace ams::fssystem::save {
/* Write the cleared signature. */ /* Write the cleared signature. */
return this->hash_storage.Write(sign_offset, buf.get(), sign_size); return this->hash_storage.Write(sign_offset, buf.get(), sign_size);
} }
case fs::OperationId::InvalidateCache: case fs::OperationId::Invalidate:
{ {
/* Only allow cache invalidation for RomFs. */ /* Only allow cache invalidation for RomFs. */
R_UNLESS(this->storage_type != fs::StorageType_SaveData, fs::ResultUnsupportedOperationInIntegrityVerificationStorageB()); R_UNLESS(this->storage_type != fs::StorageType_SaveData, fs::ResultUnsupportedOperationInIntegrityVerificationStorageB());