diff --git a/headers/os/drivers/fs_cache.h b/headers/os/drivers/fs_cache.h index 8c8193c35d..fce3ea9042 100644 --- a/headers/os/drivers/fs_cache.h +++ b/headers/os/drivers/fs_cache.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008, Haiku Inc. All Rights Reserved. + * Copyright 2004-2020, Haiku Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _FS_CACHE_H @@ -66,14 +66,14 @@ extern void block_cache_discard(void *cache, off_t blockNumber, size_t numBlocks); extern status_t block_cache_make_writable(void *cache, off_t blockNumber, int32 transaction); -extern void *block_cache_get_writable_etc(void *cache, off_t blockNumber, - off_t base, off_t length, int32 transaction); +extern status_t block_cache_get_writable_etc(void *cache, off_t blockNumber, + off_t base, off_t length, int32 transaction, void** _block); extern void *block_cache_get_writable(void *cache, off_t blockNumber, int32 transaction); extern void *block_cache_get_empty(void *cache, off_t blockNumber, int32 transaction); -extern const void *block_cache_get_etc(void *cache, off_t blockNumber, - off_t base, off_t length); +extern status_t block_cache_get_etc(void *cache, off_t blockNumber, + off_t base, off_t length, const void** _block); extern const void *block_cache_get(void *cache, off_t blockNumber); extern status_t block_cache_set_dirty(void *cache, off_t blockNumber, bool isDirty, int32 transaction); diff --git a/headers/private/fs_shell/fssh_fs_cache.h b/headers/private/fs_shell/fssh_fs_cache.h index c27052c484..bbcd6b647d 100644 --- a/headers/private/fs_shell/fssh_fs_cache.h +++ b/headers/private/fs_shell/fssh_fs_cache.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008, Haiku Inc. All Rights Reserved. + * Copyright 2004-2020, Haiku Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _FSSH_FS_CACHE_H @@ -76,16 +76,17 @@ extern void fssh_block_cache_discard(void *_cache, fssh_off_t blockNumber, fssh_size_t numBlocks); extern fssh_status_t fssh_block_cache_make_writable(void *_cache, fssh_off_t blockNumber, int32_t transaction); -extern void * fssh_block_cache_get_writable_etc(void *_cache, +extern fssh_status_t fssh_block_cache_get_writable_etc(void *_cache, fssh_off_t blockNumber, fssh_off_t base, - fssh_off_t length, int32_t transaction); + fssh_off_t length, int32_t transaction, + void **_block); extern void * fssh_block_cache_get_writable(void *_cache, fssh_off_t blockNumber, int32_t transaction); extern void * fssh_block_cache_get_empty(void *_cache, fssh_off_t blockNumber, int32_t transaction); -extern const void * fssh_block_cache_get_etc(void *_cache, +extern fssh_status_t fssh_block_cache_get_etc(void *_cache, fssh_off_t blockNumber, fssh_off_t base, - fssh_off_t length); + fssh_off_t length, const void **_block); extern const void * fssh_block_cache_get(void *_cache, fssh_off_t blockNumber); extern fssh_status_t fssh_block_cache_set_dirty(void *_cache, diff --git a/src/add-ons/kernel/file_systems/bfs/Attribute.cpp b/src/add-ons/kernel/file_systems/bfs/Attribute.cpp index 3347e6414e..46339da610 100644 --- a/src/add-ons/kernel/file_systems/bfs/Attribute.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Attribute.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2017, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2004-2020, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ @@ -83,9 +83,9 @@ Attribute::Get(const char* name) // try to find it in the small data region if (recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) { - fNodeGetter.SetToNode(fInode); - if (fNodeGetter.Node() == NULL) - return B_IO_ERROR; + status_t status = fNodeGetter.SetTo(fInode); + if (status != B_OK) + return status; fSmall = fInode->FindSmallData(fNodeGetter.Node(), (const char*)name); if (fSmall != NULL) diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp index 81a5840527..5f4fa0a70c 100644 --- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2020, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ @@ -238,7 +238,7 @@ AllocationBlock::SetTo(AllocationGroup& group, uint16 block) #ifdef DEBUG fWritable = false; #endif - return CachedBlock::SetTo(group.Start() + block) != NULL ? B_OK : B_ERROR; + return CachedBlock::SetTo(group.Start() + block); } @@ -255,8 +255,7 @@ AllocationBlock::SetToWritable(Transaction& transaction, AllocationGroup& group, #ifdef DEBUG fWritable = true; #endif - return CachedBlock::SetToWritable(transaction, group.Start() + block) - != NULL ? B_OK : B_ERROR; + return CachedBlock::SetToWritable(transaction, group.Start() + block); } diff --git a/src/add-ons/kernel/file_systems/bfs/CachedBlock.h b/src/add-ons/kernel/file_systems/bfs/CachedBlock.h index 5bbc297dc0..07e8e7bcb4 100644 --- a/src/add-ons/kernel/file_systems/bfs/CachedBlock.h +++ b/src/add-ons/kernel/file_systems/bfs/CachedBlock.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2020, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ #ifndef CACHED_BLOCK_H @@ -24,27 +24,26 @@ class CachedBlock { public: CachedBlock(Volume* volume); - CachedBlock(Volume* volume, off_t block); - CachedBlock(Volume* volume, block_run run); CachedBlock(CachedBlock* cached); ~CachedBlock(); inline void Keep(); inline void Unset(); - inline const uint8* SetTo(off_t block, off_t base, size_t length); - inline const uint8* SetTo(off_t block); - inline const uint8* SetTo(block_run run); - inline uint8* SetToWritable(Transaction& transaction, + inline status_t SetTo(off_t block, off_t base, size_t length); + inline status_t SetTo(off_t block); + inline status_t SetTo(block_run run); + inline status_t SetToWritable(Transaction& transaction, off_t block, off_t base, size_t length, bool empty = false); - inline uint8* SetToWritable(Transaction& transaction, + inline status_t SetToWritable(Transaction& transaction, off_t block, bool empty = false); - inline uint8* SetToWritable(Transaction& transaction, + inline status_t SetToWritable(Transaction& transaction, block_run run, bool empty = false); inline status_t MakeWritable(Transaction& transaction); const uint8* Block() const { return fBlock; } + uint8* WritableBlock() const { return fBlock; } off_t BlockNumber() const { return fBlockNumber; } uint32 BlockSize() const { return fVolume->BlockSize(); } @@ -76,28 +75,6 @@ CachedBlock::CachedBlock(Volume* volume) } -inline -CachedBlock::CachedBlock(Volume* volume, off_t block) - : - fVolume(volume), - fBlockNumber(0), - fBlock(NULL) -{ - SetTo(block); -} - - -inline -CachedBlock::CachedBlock(Volume* volume, block_run run) - : - fVolume(volume), - fBlockNumber(0), - fBlock(NULL) -{ - SetTo(volume->ToBlock(run)); -} - - inline CachedBlock::CachedBlock(CachedBlock* cached) : @@ -133,31 +110,31 @@ CachedBlock::Unset() } -inline const uint8* +inline status_t CachedBlock::SetTo(off_t block, off_t base, size_t length) { Unset(); fBlockNumber = block; - return fBlock = (uint8*)block_cache_get_etc(fVolume->BlockCache(), - block, base, length); + return block_cache_get_etc(fVolume->BlockCache(), block, base, length, + (const void**)&fBlock); } -inline const uint8* +inline status_t CachedBlock::SetTo(off_t block) { return SetTo(block, block, 1); } -inline const uint8* +inline status_t CachedBlock::SetTo(block_run run) { return SetTo(fVolume->ToBlock(run)); } -inline uint8* +inline status_t CachedBlock::SetToWritable(Transaction& transaction, off_t block, off_t base, size_t length, bool empty) { @@ -167,23 +144,22 @@ CachedBlock::SetToWritable(Transaction& transaction, off_t block, off_t base, if (empty) { fBlock = (uint8*)block_cache_get_empty(fVolume->BlockCache(), block, transaction.ID()); - } else { - fBlock = (uint8*)block_cache_get_writable_etc(fVolume->BlockCache(), - block, base, length, transaction.ID()); + return fBlock != NULL ? B_OK : B_NO_MEMORY; } - return fBlock; + return block_cache_get_writable_etc(fVolume->BlockCache(), + block, base, length, transaction.ID(), (void**)&fBlock); } -inline uint8* +inline status_t CachedBlock::SetToWritable(Transaction& transaction, off_t block, bool empty) { return SetToWritable(transaction, block, block, 1, empty); } -inline uint8* +inline status_t CachedBlock::SetToWritable(Transaction& transaction, block_run run, bool empty) { return SetToWritable(transaction, fVolume->ToBlock(run), empty); diff --git a/src/add-ons/kernel/file_systems/bfs/CheckVisitor.cpp b/src/add-ons/kernel/file_systems/bfs/CheckVisitor.cpp index e8980e33d8..63bafa5cc9 100644 --- a/src/add-ons/kernel/file_systems/bfs/CheckVisitor.cpp +++ b/src/add-ons/kernel/file_systems/bfs/CheckVisitor.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002-2020, Axel Dörfler, axeld@pinc-software.de. * Copyright 2012, Andreas Henriksson, sausageboy@gmail.com * This file may be used under the terms of the MIT License. */ @@ -211,10 +211,11 @@ CheckVisitor::VisitDirectoryEntry(Inode* inode, Inode* parent, // check if the inode's name is the same as in the b+tree if (inode->IsRegularNode()) { RecursiveLocker locker(inode->SmallDataLock()); - NodeGetter node(GetVolume(), inode); - if (node.Node() == NULL) { + NodeGetter node(GetVolume()); + status_t status = node.SetTo(inode); + if (status != B_OK) { Control().errors |= BFS_COULD_NOT_OPEN; - Control().status = B_IO_ERROR; + Control().status = status; return B_OK; } @@ -496,16 +497,17 @@ CheckVisitor::_CheckInodeBlocks(Inode* inode, const char* name) if (data->max_indirect_range) { status = _CheckAllocated(data->indirect, "indirect"); - if (status < B_OK) + if (status != B_OK) return status; off_t block = GetVolume()->ToBlock(data->indirect); for (int32 i = 0; i < data->indirect.Length(); i++) { - block_run* runs = (block_run*)cached.SetTo(block + i); - if (runs == NULL) - RETURN_ERROR(B_IO_ERROR); + status = cached.SetTo(block + i); + if (status != B_OK) + RETURN_ERROR(status); + block_run* runs = (block_run*)cached.Block(); int32 runsPerBlock = GetVolume()->BlockSize() / sizeof(block_run); int32 index = 0; for (; index < runsPerBlock; index++) { @@ -542,12 +544,12 @@ CheckVisitor::_CheckInodeBlocks(Inode* inode, const char* name) for (int32 indirectIndex = 0; indirectIndex < runsPerArray; indirectIndex++) { // get the indirect array block - block_run* array = (block_run*)cached.SetTo( - GetVolume()->ToBlock(data->double_indirect) + status = cached.SetTo(GetVolume()->ToBlock(data->double_indirect) + indirectIndex / runsPerBlock); - if (array == NULL) - return B_IO_ERROR; + if (status != B_OK) + return status; + block_run* array = (block_run*)cached.Block(); block_run indirect = array[indirectIndex % runsPerBlock]; // are we finished yet? if (indirect.IsZero()) @@ -562,10 +564,12 @@ CheckVisitor::_CheckInodeBlocks(Inode* inode, const char* name) / sizeof(block_run); for (int32 index = 0; index < maxIndex; ) { - block_run* runs = (block_run*)cachedDirect.SetTo( - GetVolume()->ToBlock(indirect) + index / runsPerBlock); - if (runs == NULL) - return B_IO_ERROR; + status = cachedDirect.SetTo(GetVolume()->ToBlock(indirect) + + index / runsPerBlock); + if (status != B_OK) + return status; + + block_run* runs = (block_run*)cachedDirect.Block(); do { // are we finished yet? diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index 1d1ce8d7b4..e8930a7950 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2020, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ @@ -385,9 +385,11 @@ Inode::Inode(Volume* volume, Transaction& transaction, ino_t id, mode_t mode, rw_lock_init(&fLock, "bfs inode"); recursive_lock_init(&fSmallDataLock, "bfs inode small data"); - NodeGetter node(volume, transaction, this, true); - if (node.Node() == NULL) { - FATAL(("Could not read inode block %" B_PRId64 "!\n", BlockNumber())); + NodeGetter node(volume); + status_t status = node.SetToWritable(transaction, this, true); + if (status != B_OK) { + FATAL(("Could not read inode block %" B_PRId64 ": %s!\n", BlockNumber(), + strerror(status))); return; } @@ -491,9 +493,10 @@ Inode::WriteLockInTransaction(Transaction& transaction) status_t Inode::WriteBack(Transaction& transaction) { - NodeGetter node(fVolume, transaction, this); - if (node.WritableNode() == NULL) - return B_IO_ERROR; + NodeGetter node(fVolume); + status_t status = node.SetToWritable(transaction, this); + if (status != B_OK) + return status; memcpy(node.WritableNode(), &Node(), sizeof(bfs_inode)); return B_OK; @@ -503,11 +506,12 @@ Inode::WriteBack(Transaction& transaction) status_t Inode::UpdateNodeFromDisk() { - NodeGetter node(fVolume, this); - if (node.Node() == NULL) { - FATAL(("Failed to read block %" B_PRId64 " from disk!\n", - BlockNumber())); - return B_IO_ERROR; + NodeGetter node(fVolume); + status_t status = node.SetTo(this); + if (status != B_OK) { + FATAL(("Failed to read block %" B_PRId64 " from disk: %s!\n", + BlockNumber(), strerror(status))); + return status; } memcpy(&fNode, node.Node(), sizeof(bfs_inode)); @@ -677,9 +681,11 @@ Inode::_RemoveSmallData(Transaction& transaction, NodeGetter& nodeGetter, if (item->IsLast(node)) return B_ENTRY_NOT_FOUND; - nodeGetter.MakeWritable(transaction); + status_t status = nodeGetter.MakeWritable(transaction); + if (status != B_OK) + return status; - status_t status = _RemoveSmallData(node, item, index); + status = _RemoveSmallData(node, item, index); if (status == B_OK) { Node().status_change_time = HOST_ENDIAN_TO_BFS_INT64( bfs_inode::ToInode(real_time_clock_usecs())); @@ -718,7 +724,10 @@ Inode::_AddSmallData(Transaction& transaction, NodeGetter& nodeGetter, if (spaceNeeded > fVolume->InodeSize() - sizeof(bfs_inode)) return B_DEVICE_FULL; - nodeGetter.MakeWritable(transaction); + status_t status = nodeGetter.MakeWritable(transaction); + if (status != B_OK) + return status; + RecursiveLocker locker(fSmallDataLock); // Find the last item or one with the same name we have to add @@ -934,9 +943,10 @@ Inode::Name(const bfs_inode* node) const status_t Inode::GetName(char* buffer, size_t size) const { - NodeGetter node(fVolume, this); - if (node.Node() == NULL) - return B_IO_ERROR; + NodeGetter node(fVolume); + status_t status = node.SetTo(this); + if (status != B_OK) + return status; RecursiveLocker locker(fSmallDataLock); @@ -961,9 +971,10 @@ Inode::SetName(Transaction& transaction, const char* name) if (name == NULL || *name == '\0') return B_BAD_VALUE; - NodeGetter node(fVolume, transaction, this); - if (node.Node() == NULL) - return B_IO_ERROR; + NodeGetter node(fVolume); + status_t status = node.SetToWritable(transaction, this); + if (status != B_OK) + return status; const char nameTag[2] = {FILE_NAME_NAME, 0}; @@ -1037,9 +1048,10 @@ Inode::ReadAttribute(const char* name, int32 type, off_t pos, uint8* buffer, // search in the small_data section (which has to be locked first) { - NodeGetter node(fVolume, this); - if (node.Node() == NULL) - return B_IO_ERROR; + NodeGetter node(fVolume); + status_t status = node.SetTo(this); + if (status != B_OK) + return status; RecursiveLocker locker(fSmallDataLock); @@ -1107,9 +1119,10 @@ Inode::WriteAttribute(Transaction& transaction, const char* name, int32 type, // No attribute inode exists yet // save the old attribute data - NodeGetter node(fVolume, transaction, this); - if (node.Node() == NULL) - return B_IO_ERROR; + NodeGetter node(fVolume); + status = node.SetToWritable(transaction, this); + if (status != B_OK) + return status; recursive_lock_lock(&fSmallDataLock); @@ -1179,9 +1192,10 @@ Inode::WriteAttribute(Transaction& transaction, const char* name, int32 type, } // check if the data fits into the small_data section again - NodeGetter node(fVolume, transaction, this); - if (node.Node() == NULL) - return B_IO_ERROR; + NodeGetter node(fVolume); + status = node.SetToWritable(transaction, this); + if (status != B_OK) + return status; status = _AddSmallData(transaction, node, name, type, pos, buffer, *_length); @@ -1252,9 +1266,10 @@ Inode::RemoveAttribute(Transaction& transaction, const char* name) { Index index(fVolume); bool hasIndex = index.SetTo(name) == B_OK; - NodeGetter node(fVolume, this); - if (node.Node() == NULL) - return B_IO_ERROR; + NodeGetter node(fVolume); + status_t status = node.SetTo(this); + if (status != B_OK) + return status; // update index for attributes in the small_data section { @@ -1270,7 +1285,7 @@ Inode::RemoveAttribute(Transaction& transaction, const char* name) } } - status_t status = _RemoveSmallData(transaction, node, name); + status = _RemoveSmallData(transaction, node, name); if (status == B_ENTRY_NOT_FOUND && !Attributes().IsZero()) { // remove the attribute file if it exists status = _RemoveAttribute(transaction, name, hasIndex, &index); @@ -1477,19 +1492,20 @@ Inode::FindBlockRun(off_t pos, block_run& run, off_t& offset) off_t start = pos - data->MaxIndirectRange(); int32 index = start / indirectSize; - block_run* indirect = (block_run*)cached.SetTo( - fVolume->ToBlock(data->double_indirect) + index / runsPerBlock); - if (indirect == NULL) - RETURN_ERROR(B_ERROR); + status_t status = cached.SetTo(fVolume->ToBlock( + data->double_indirect) + index / runsPerBlock); + if (status != B_OK) + RETURN_ERROR(status); + block_run* indirect = (block_run*)cached.Block(); int32 current = (start % indirectSize) / directSize; - indirect = (block_run*)cached.SetTo( - fVolume->ToBlock(indirect[index % runsPerBlock]) - + current / runsPerBlock); - if (indirect == NULL) - RETURN_ERROR(B_ERROR); + status = cached.SetTo(fVolume->ToBlock(indirect[ + index % runsPerBlock]) + current / runsPerBlock); + if (status != B_OK) + RETURN_ERROR(status); + indirect = (block_run*)cached.Block(); run = indirect[current % runsPerBlock]; if (run.Length() != data->double_indirect.Length()) RETURN_ERROR(B_BAD_DATA); @@ -1506,10 +1522,11 @@ Inode::FindBlockRun(off_t pos, block_run& run, off_t& offset) off_t block = fVolume->ToBlock(data->indirect); for (int32 i = 0; i < data->indirect.Length(); i++) { - block_run* indirect = (block_run*)cached.SetTo(block + i); - if (indirect == NULL) - RETURN_ERROR(B_IO_ERROR); + status_t status = cached.SetTo(block + i); + if (status != B_OK) + RETURN_ERROR(status); + block_run* indirect = (block_run*)cached.Block(); int32 current = -1; while (++current < runsPerBlock) { if (indirect[current].IsZero()) @@ -1689,10 +1706,9 @@ Inode::_AllocateBlockArray(Transaction& transaction, block_run& run, off_t block = fVolume->ToBlock(run); for (int32 i = 0; i < run.Length(); i++) { - block_run* runs = (block_run*)cached.SetToWritable(transaction, - block + i, true); - if (runs == NULL) - return B_IO_ERROR; + status = cached.SetToWritable(transaction, block + i, true); + if (status != B_OK) + return status; } return B_OK; } @@ -1851,7 +1867,11 @@ Inode::_GrowStream(Transaction& transaction, off_t size) data->max_indirect_range = HOST_ENDIAN_TO_BFS_INT64( data->MaxDirectRange()); // insert the block_run in the first block - runs = (block_run*)cached.SetTo(data->indirect); + status = cached.SetTo(data->indirect); + if (status != B_OK) + return status; + + runs = (block_run*)cached.Block(); } else { uint32 numberOfRuns = fVolume->BlockSize() / sizeof(block_run); block = fVolume->ToBlock(data->indirect); @@ -1859,9 +1879,11 @@ Inode::_GrowStream(Transaction& transaction, off_t size) // search first empty entry int32 i = 0; for (; i < data->indirect.Length(); i++) { - if ((runs = (block_run*)cached.SetTo(block + i)) == NULL) - return B_IO_ERROR; + status = cached.SetTo(block + i); + if (status != B_OK) + return status; + runs = (block_run*)cached.Block(); for (free = 0; free < numberOfRuns; free++) if (runs[free].IsZero()) break; @@ -1971,10 +1993,12 @@ Inode::_GrowStream(Transaction& transaction, off_t size) if (block >= minimum) return EFBIG; - array = (block_run*)cached.SetTo(fVolume->ToBlock( + status = cached.SetTo(fVolume->ToBlock( data->double_indirect) + block); - if (array == NULL) - return B_IO_ERROR; + if (status != B_OK) + return status; + + array = (block_run*)cached.Block(); } do { @@ -1989,11 +2013,13 @@ Inode::_GrowStream(Transaction& transaction, off_t size) return status; } - block_run* runs = (block_run*)cachedDirect.SetToWritable( - transaction, fVolume->ToBlock(array[indirectIndex + status = cachedDirect.SetToWritable(transaction, + fVolume->ToBlock(array[indirectIndex % runsPerBlock]) + index / runsPerBlock); - if (runs == NULL) - return B_IO_ERROR; + if (status != B_OK) + return status; + + block_run* runs = (block_run*)cachedDirect.Block(); do { // insert the block_run into the array @@ -2079,10 +2105,11 @@ Inode::_FreeStaticStreamArray(Transaction& transaction, int32 level, offset += (off_t)index * indirectSize; for (int32 i = index / runsPerBlock; i < run.Length(); i++) { - block_run* array = (block_run*)cached.SetToWritable(transaction, - blockNumber + i); - if (array == NULL) - RETURN_ERROR(B_ERROR); + status_t status = cached.SetToWritable(transaction, blockNumber + i); + if (status != B_OK) + RETURN_ERROR(status); + + block_run* array = (block_run*)cached.WritableBlock(); for (index = index % runsPerBlock; index < runsPerBlock; index++) { if (array[index].IsZero()) { @@ -2201,10 +2228,11 @@ Inode::_ShrinkStream(Transaction& transaction, off_t size) off_t offset = data->MaxDirectRange(); for (int32 i = 0; i < data->indirect.Length(); i++) { - block_run* array = (block_run*)cached.SetToWritable(transaction, - block + i); - if (array == NULL) - break; + status = cached.SetToWritable(transaction, block + i); + if (status != B_OK) + return status; + + block_run* array = (block_run*)cached.WritableBlock(); off_t* maxIndirect = &data->max_indirect_range; // gcc 4 work-around: "error: cannot bind packed field @@ -2227,7 +2255,7 @@ Inode::_ShrinkStream(Transaction& transaction, off_t size) // 'data->data_stream::max_direct_range' to 'off_t&'" status = _FreeStreamArray(transaction, data->direct, NUM_DIRECT_BLOCKS, size, offset, *maxDirect); - if (status < B_OK) + if (status != B_OK) return status; } @@ -2392,9 +2420,11 @@ Inode::Sync() int32 count = fVolume->BlockSize() / sizeof(block_run); for (int32 j = 0; j < data->indirect.Length(); j++) { - block_run* runs = (block_run*)cached.SetTo(block + j); - if (runs == NULL) - break; + status = cached.SetTo(block + j); + if (status != B_OK) + return status; + + block_run* runs = (block_run*)cached.Block(); for (int32 i = 0; i < count; i++) { if (runs[i].IsZero()) @@ -2415,10 +2445,11 @@ Inode::Sync() off_t indirectBlock = fVolume->ToBlock(data->double_indirect); for (int32 l = 0; l < data->double_indirect.Length(); l++) { - block_run* indirectRuns = (block_run*)cached.SetTo(indirectBlock + l); - if (indirectRuns == NULL) - return B_FILE_ERROR; + status = cached.SetTo(indirectBlock + l); + if (status != B_OK) + return status; + block_run* indirectRuns = (block_run*)cached.Block(); CachedBlock directCached(fVolume); for (int32 k = 0; k < count; k++) { @@ -2427,9 +2458,11 @@ Inode::Sync() block = fVolume->ToBlock(indirectRuns[k]); for (int32 j = 0; j < indirectRuns[k].Length(); j++) { - block_run* runs = (block_run*)directCached.SetTo(block + j); - if (runs == NULL) - return B_FILE_ERROR; + status = directCached.SetTo(block + j); + if (status != B_OK) + return status; + + block_run* runs = (block_run*)directCached.Block(); for (int32 i = 0; i < count; i++) { if (runs[i].IsZero()) @@ -2848,9 +2881,10 @@ AttributeIterator::GetNext(char* name, size_t* _length, uint32* _type, // read attributes out of the small data section if (fCurrentSmallData >= 0) { - NodeGetter nodeGetter(fInode->GetVolume(), fInode); - if (nodeGetter.Node() == NULL) - return B_IO_ERROR; + NodeGetter nodeGetter(fInode->GetVolume()); + status_t status = nodeGetter.SetTo(fInode); + if (status != B_OK) + return status; const bfs_inode* node = nodeGetter.Node(); const small_data* item = ((bfs_inode*)node)->SmallDataStart(); diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.h b/src/add-ons/kernel/file_systems/bfs/Inode.h index 546f00da60..ef5afa053b 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.h +++ b/src/add-ons/kernel/file_systems/bfs/Inode.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2020, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ #ifndef INODE_H @@ -338,30 +338,25 @@ private: class NodeGetter : public CachedBlock { public: NodeGetter(Volume* volume) - : CachedBlock(volume) + : + CachedBlock(volume) { } - NodeGetter(Volume* volume, const Inode* inode) - : CachedBlock(volume) - { - SetTo(volume->VnodeToBlock(inode->ID())); - } - - NodeGetter(Volume* volume, Transaction& transaction, - const Inode* inode, bool empty = false) - : CachedBlock(volume) - { - SetToWritable(transaction, volume->VnodeToBlock(inode->ID()), empty); - } - ~NodeGetter() { } - const bfs_inode* SetToNode(const Inode* inode) + status_t SetTo(const Inode* inode) { - return (const bfs_inode*)SetTo(fVolume->VnodeToBlock(inode->ID())); + return CachedBlock::SetTo(fVolume->VnodeToBlock(inode->ID())); + } + + status_t SetToWritable(Transaction& transaction, const Inode* inode, + bool empty = false) + { + return CachedBlock::SetToWritable(transaction, + fVolume->VnodeToBlock(inode->ID()), empty); } const bfs_inode* Node() const { return (const bfs_inode*)Block(); } diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.cpp b/src/add-ons/kernel/file_systems/bfs/Journal.cpp index f664a011f4..567607074a 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Journal.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2020, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ @@ -484,11 +484,11 @@ Journal::_ReplayRunArray(int32* _start) CachedBlock cachedArray(fVolume); - const run_array* array = (const run_array*)cachedArray.SetTo(logOffset - + firstBlockNumber); - if (array == NULL) - return B_IO_ERROR; + status_t status = cachedArray.SetTo(logOffset + firstBlockNumber); + if (status != B_OK) + return status; + const run_array* array = (const run_array*)cachedArray.Block(); if (_CheckRunArray(array) < B_OK) return B_BAD_DATA; @@ -505,16 +505,16 @@ Journal::_ReplayRunArray(int32* _start) off_t offset = fVolume->ToOffset(run); for (int32 i = 0; i < run.Length(); i++) { - const uint8* data = cached.SetTo(logOffset + blockNumber); - if (data == NULL) - RETURN_ERROR(B_IO_ERROR); + status = cached.SetTo(logOffset + blockNumber); + if (status != status) + RETURN_ERROR(status); // TODO: eventually check other well known offsets, like the // root and index dirs if (offset == 0) { // This log entry writes over the superblock - check if // it's valid! - if (Volume::CheckSuperBlock(data) != B_OK) { + if (Volume::CheckSuperBlock(cached.Block()) != B_OK) { FATAL(("Log contains invalid superblock!\n")); RETURN_ERROR(B_BAD_DATA); } @@ -537,12 +537,12 @@ Journal::_ReplayRunArray(int32* _start) off_t offset = fVolume->ToOffset(run); for (int32 i = 0; i < run.Length(); i++) { - const uint8* data = cached.SetTo(logOffset + blockNumber); - if (data == NULL) - RETURN_ERROR(B_IO_ERROR); + status = cached.SetTo(logOffset + blockNumber); + if (status != B_OK) + RETURN_ERROR(status); - ssize_t written = write_pos(fVolume->Device(), offset, data, - blockSize); + ssize_t written = write_pos(fVolume->Device(), offset, + cached.Block(), blockSize); if (written != blockSize) RETURN_ERROR(B_IO_ERROR); diff --git a/src/add-ons/kernel/file_systems/bfs/Query.cpp b/src/add-ons/kernel/file_systems/bfs/Query.cpp index 46026bfb43..7b9042a1e3 100644 --- a/src/add-ons/kernel/file_systems/bfs/Query.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Query.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2020, Axel Dörfler, axeld@pinc-software.de. * Copyright 2010, Clemens Zeidler * This file may be used under the terms of the MIT License. */ @@ -384,9 +384,9 @@ Equation::Match(Inode* inode, const char* attributeName, int32 type, buffer = const_cast(key); } else if (!strcmp(fAttribute, "name")) { // we need to lock before accessing Inode::Name() - nodeGetter.SetToNode(inode); - if (nodeGetter.Node() == NULL) - return B_IO_ERROR; + status_t status = nodeGetter.SetTo(inode); + if (status != B_OK) + return status; recursive_lock_lock(&inode->SmallDataLock()); locked = true; @@ -417,9 +417,9 @@ Equation::Match(Inode* inode, const char* attributeName, int32 type, } else { // then for attributes in the small_data section, and finally for the // real attributes - nodeGetter.SetToNode(inode); - if (nodeGetter.Node() == NULL) - return B_IO_ERROR; + status_t status = nodeGetter.SetTo(inode); + if (status != B_OK) + return status; Inode* attribute; diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index 90e8d2203e..699160b3b2 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2020, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ @@ -294,14 +294,16 @@ bfs_get_vnode(fs_volume* _volume, ino_t id, fs_vnode* _node, int* _type, return B_ERROR; } - CachedBlock cached(volume, id); - bfs_inode* node = (bfs_inode*)cached.Block(); - if (node == NULL) { - FATAL(("could not read inode: %" B_PRIdINO "\n", id)); - return B_IO_ERROR; + CachedBlock cached(volume); + status_t status = cached.SetTo(id); + if (status != B_OK) { + FATAL(("could not read inode: %" B_PRIdINO ": %s\n", id, + strerror(status))); + return status; } + bfs_inode* node = (bfs_inode*)cached.Block(); - status_t status = node->InitCheck(volume); + status = node->InitCheck(volume); if (status != B_OK) { if ((node->Flags() & INODE_DELETED) != 0) { INFORM(("inode at %" B_PRIdINO " is already deleted!\n", id)); @@ -736,7 +738,7 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd, status = checker->StartIndexPass(); } } - + if (status == B_OK) { status = user_memcpy(buffer, &checker->Control(), sizeof(check_control)); @@ -803,9 +805,9 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd, PRINT(("write block_run(%ld, %d, %d)\n", run.allocation_group, run.start, run.length)); for (int32 i = 0;i < run.length;i++) { - uint8* block = cached.SetToWritable(transaction, run); - if (block != NULL) - memset(block, 0, volume->BlockSize()); + status_t status = cached.SetToWritable(transaction, run); + if (status == B_OK) + memset(cached.WritableBlock(), 0, volume->BlockSize()); } } return B_OK; diff --git a/src/add-ons/kernel/file_systems/fat/dosfs.c b/src/add-ons/kernel/file_systems/fat/dosfs.c index f4062e4504..01d9696c0a 100644 --- a/src/add-ons/kernel/file_systems/fat/dosfs.c +++ b/src/add-ons/kernel/file_systems/fat/dosfs.c @@ -908,9 +908,11 @@ update_fsinfo(nspace *vol) { if (vol->fat_bits == 32 && vol->fsinfo_sector != 0xffff && (vol->flags & B_FS_IS_READONLY) == 0) { - uchar *buffer = (uchar *)block_cache_get_writable_etc(vol->fBlockCache, - vol->fsinfo_sector, 0, vol->bytes_per_sector, -1); - if (buffer != NULL) { + uchar *buffer; + status_t status = block_cache_get_writable_etc(vol->fBlockCache, + vol->fsinfo_sector, 0, vol->bytes_per_sector, -1, + (void**)&buffer); + if (status == B_OK) { if ((read32(buffer,0) == 0x41615252) && (read32(buffer,0x1e4) == 0x61417272) && (read16(buffer,0x1fe) == 0xaa55)) { //number of free clusters buffer[0x1e8] = (vol->free_clusters & 0xff); @@ -929,8 +931,8 @@ update_fsinfo(nspace *vol) } block_cache_put(vol->fBlockCache, vol->fsinfo_sector); } else { - dprintf("update_fsinfo: error getting fsinfo sector %x\n", - vol->fsinfo_sector); + dprintf("update_fsinfo: error getting fsinfo sector %x: %s\n", + vol->fsinfo_sector, strerror(status)); } } } @@ -940,14 +942,17 @@ static status_t get_fsinfo(nspace *vol, uint32 *free_count, uint32 *last_allocated) { uchar *buffer; - int32 result; + status_t result; if ((vol->fat_bits != 32) || (vol->fsinfo_sector == 0xffff)) return B_ERROR; - if ((buffer = (uchar *)block_cache_get_etc(vol->fBlockCache, vol->fsinfo_sector, 0, vol->bytes_per_sector)) == NULL) { - dprintf("get_fsinfo: error getting fsinfo sector %x\n", vol->fsinfo_sector); - return EIO; + result = block_cache_get_etc(vol->fBlockCache, vol->fsinfo_sector, 0, + vol->bytes_per_sector, &buffer); + if (result != B_OK) { + dprintf("get_fsinfo: error getting fsinfo sector %x: %s\n", + vol->fsinfo_sector, strerror(result)); + return result; } if ((read32(buffer,0) == 0x41615252) && (read32(buffer,0x1e4) == 0x61417272) && (read16(buffer,0x1fe) == 0xaa55)) { @@ -1093,12 +1098,12 @@ dosfs_write_fs_stat(fs_volume *_vol, const struct fs_info * fss, uint32 mask) if (vol->vol_entry == -1) { // stored in the bpb - uchar *buffer = block_cache_get_writable_etc(vol->fBlockCache, 0, 0, - vol->bytes_per_sector, -1); - if (buffer == NULL) { - result = EIO; + uchar *buffer; + result = block_cache_get_writable_etc(vol->fBlockCache, 0, + 0, vol->bytes_per_sector, -1, (void**)&buffer); + if (result != B_OK) goto bi; - } + if ((vol->sectors_per_fat == 0 && (buffer[0x42] != 0x29 || strncmp((const char *)buffer + 0x47, vol->vol_label, 11) != 0)) diff --git a/src/add-ons/kernel/file_systems/fat/fat.c b/src/add-ons/kernel/file_systems/fat/fat.c index 6abc26688b..c202145234 100644 --- a/src/add-ons/kernel/file_systems/fat/fat.c +++ b/src/add-ons/kernel/file_systems/fat/fat.c @@ -37,11 +37,15 @@ mirror_fats(nspace *vol, uint32 sector, uint8 *buffer) for (i = 0; i < vol->fat_count; i++) { char *blockData; + status_t status; if (i == vol->active_fat) continue; - blockData = block_cache_get_writable_etc(vol->fBlockCache, sector - + i * vol->sectors_per_fat, 0, 1, -1); + status = block_cache_get_writable_etc(vol->fBlockCache, + sector + i * vol->sectors_per_fat, 0, 1, -1, &blockData); + if (status != B_OK) + return status; + memcpy(blockData, buffer, vol->bytes_per_sector); block_cache_put(vol->fBlockCache, sector + i * vol->sectors_per_fat); } diff --git a/src/add-ons/kernel/file_systems/fat/iter.c b/src/add-ons/kernel/file_systems/fat/iter.c index 90da4923a2..523d1d6b50 100644 --- a/src/add-ons/kernel/file_systems/fat/iter.c +++ b/src/add-ons/kernel/file_systems/fat/iter.c @@ -112,11 +112,17 @@ iter_csi(struct csi *csi, int sectors) uint8 * csi_get_block(struct csi *csi) { + status_t status; + const void* block; + if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0) return NULL; - return (uint8 *)block_cache_get_etc(csi->vol->fBlockCache, - csi_to_block(csi), 1, csi->vol->bytes_per_sector); + status = block_cache_get_etc(csi->vol->fBlockCache, + csi_to_block(csi), 1, csi->vol->bytes_per_sector, &block); + if (status != B_OK) + return NULL; + return (uint8 *)block; } @@ -214,8 +220,12 @@ csi_write_blocks(struct csi *csi, uint8 *buffer, ssize_t len) } for (i = block; i < block + sectors; i++) { - char *blockData = block_cache_get_writable_etc(csi->vol->fBlockCache, i, - 0, 1, -1); + char *blockData; + status_t status = block_cache_get_writable_etc(csi->vol->fBlockCache, + i, 0, 1, -1, &blockData); + if (status != B_OK) + return status; + memcpy(blockData, buf, csi->vol->bytes_per_sector); buf += csi->vol->bytes_per_sector; block_cache_put(csi->vol->fBlockCache, i); @@ -233,6 +243,7 @@ csi_write_blocks(struct csi *csi, uint8 *buffer, ssize_t len) status_t csi_write_block(struct csi *csi, uint8 *buffer) { + status_t status; off_t block; char *blockData; @@ -242,8 +253,11 @@ csi_write_block(struct csi *csi, uint8 *buffer) if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0) return EINVAL; - blockData = block_cache_get_writable_etc(csi->vol->fBlockCache, block, 0, 1, - -1); + status = block_cache_get_writable_etc(csi->vol->fBlockCache, block, 0, 1, + -1, &blockData); + if (status != B_OK) + return status; + memcpy(blockData, buffer, csi->vol->bytes_per_sector); block_cache_put(csi->vol->fBlockCache, block); diff --git a/src/add-ons/kernel/file_systems/udf/CachedBlock.h b/src/add-ons/kernel/file_systems/udf/CachedBlock.h index 80513525a0..54e4a20970 100644 --- a/src/add-ons/kernel/file_systems/udf/CachedBlock.h +++ b/src/add-ons/kernel/file_systems/udf/CachedBlock.h @@ -1,7 +1,7 @@ /* * Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com * Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net - * Copyright 2002, Axel Dörfler, axeld@pinc-software.de + * Copyright 2002-2020, Axel Dörfler, axeld@pinc-software.de * Distributed under the terms of the MIT License. */ #ifndef _UDF_CACHED_BLOCK_H @@ -9,7 +9,7 @@ /*! \file CachedBlock.h - Based on the CachedBlock class from OpenBFS, written by + Based on the CachedBlock class from BFS, written by Axel Dörfler, axeld@pinc-software.de */ @@ -20,10 +20,10 @@ #include "UdfStructures.h" #include "Volume.h" + class CachedBlock { public: CachedBlock(Volume *volume); - CachedBlock(Volume *volume, off_t block); CachedBlock(CachedBlock *cached); ~CachedBlock(); @@ -35,11 +35,12 @@ public: inline void Keep(); inline void Unset(); - inline uint8 *SetTo(off_t block); - inline uint8 *SetTo(off_t block, off_t base, size_t length); - inline uint8 *SetTo(long_address address); + inline status_t SetTo(off_t block); + inline status_t SetTo(off_t block, off_t base, size_t length); + inline status_t SetTo(long_address address); template - inline uint8* SetTo(Accessor &accessor, Descriptor &descriptor); + inline status_t SetTo(Accessor &accessor, + Descriptor &descriptor); protected: uint8 *fBlock; @@ -59,17 +60,6 @@ CachedBlock::CachedBlock(Volume *volume) inline -CachedBlock::CachedBlock(Volume *volume, off_t block) - : - fBlock(NULL), - fBlockNumber(0), - fVolume(volume) -{ - SetTo(block); -} - - -inline CachedBlock::CachedBlock(CachedBlock *cached) : fBlock(cached->fBlock), @@ -97,43 +87,43 @@ CachedBlock::Keep() inline void CachedBlock::Unset() { - if (fBlock) { + if (fBlock != NULL) { block_cache_put(fVolume->BlockCache(), fBlockNumber); fBlock = NULL; } } -inline uint8* +inline status_t CachedBlock::SetTo(off_t block) { return SetTo(block, block, 1); } -inline uint8* +inline status_t CachedBlock::SetTo(off_t block, off_t base, size_t length) { Unset(); fBlockNumber = block; - return fBlock = (uint8 *)block_cache_get_etc(fVolume->BlockCache(), - block, base, length); + return block_cache_get_etc(fVolume->BlockCache(), block, base, length, + (const void**)&fBlock); } -inline uint8 * +inline status_t CachedBlock::SetTo(long_address address) { off_t block; if (fVolume->MapBlock(address, &block) == B_OK) return SetTo(block, block, 1); - else - return NULL; + + return B_BAD_VALUE; } template -inline uint8* +inline status_t CachedBlock::SetTo(Accessor &accessor, Descriptor &descriptor) { // Make a long_address out of the descriptor and call it a day @@ -143,4 +133,5 @@ CachedBlock::SetTo(Accessor &accessor, Descriptor &descriptor) return SetTo(address); } + #endif // _UDF_CACHED_BLOCK_H diff --git a/src/add-ons/kernel/file_systems/udf/Icb.cpp b/src/add-ons/kernel/file_systems/udf/Icb.cpp index 4bd780685d..e60be96429 100644 --- a/src/add-ons/kernel/file_systems/udf/Icb.cpp +++ b/src/add-ons/kernel/file_systems/udf/Icb.cpp @@ -123,20 +123,24 @@ Icb::Icb(Volume *volume, long_address address) off_t block; status_t status = fVolume->MapBlock(address, &block); - if (!status) { - icb_header *header = (icb_header *)fData.SetTo(block); - if (header->tag().id() == TAGID_FILE_ENTRY) { - file_icb_entry *entry = (file_icb_entry *)header; - PDUMP(entry); - (void)entry; // warning death - } else if (header->tag().id() == TAGID_EXTENDED_FILE_ENTRY) { - extended_file_icb_entry *entry = (extended_file_icb_entry *)header; - PDUMP(entry); - (void)entry; // warning death - } else { - PDUMP(header); + if (status == B_OK) { + status = fData.SetTo(block); + if (status == B_OK) { + icb_header *header = (icb_header *)fData.Block(); + if (header->tag().id() == TAGID_FILE_ENTRY) { + file_icb_entry *entry = (file_icb_entry *)header; + PDUMP(entry); + (void)entry; // warning death + } else if (header->tag().id() == TAGID_EXTENDED_FILE_ENTRY) { + extended_file_icb_entry *entry + = (extended_file_icb_entry *)header; + PDUMP(entry); + (void)entry; // warning death + } else { + PDUMP(header); + } + status = header->tag().init_check(address.block()); } - status = header->tag().init_check(address.block()); } if (IsFile()) { @@ -447,9 +451,10 @@ Icb::_Read(DescriptorList &list, off_t pos, void *_buffer, size_t *length, uint3 TRACE(("Icb::_Read: %ld bytes from disk block %" B_PRIdOFF " using" " block_cache_get_etc()\n", readLength, diskBlock)); - uint8 *data = (uint8*)block_cache_get_etc(volume->BlockCache(), - diskBlock, 0, readLength); - if (data == NULL) + const uint8 *data; + status = block_cache_get_etc(volume->BlockCache(), + diskBlock, 0, readLength, (const void**)&data); + if (status != B_OK) break; memcpy(buffer, data + blockOffset, readLength); block_cache_put(volume->BlockCache(), diskBlock); diff --git a/src/system/kernel/cache/block_cache.cpp b/src/system/kernel/cache/block_cache.cpp index 6b4ac88f1e..ca5c1125f7 100644 --- a/src/system/kernel/cache/block_cache.cpp +++ b/src/system/kernel/cache/block_cache.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2012, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2004-2020, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -1897,16 +1897,16 @@ put_cached_block(block_cache* cache, off_t blockNumber) data. If \c true, the cache will be temporarily unlocked while the block is read in. */ -static cached_block* +static status_t get_cached_block(block_cache* cache, off_t blockNumber, bool* _allocated, - bool readBlock = true) + bool readBlock, cached_block** _block) { ASSERT_LOCKED_MUTEX(&cache->lock); if (blockNumber < 0 || blockNumber >= cache->max_blocks) { panic("get_cached_block: invalid block number %" B_PRIdOFF " (max %" B_PRIdOFF ")", blockNumber, cache->max_blocks - 1); - return NULL; + return B_BAD_VALUE; } retry: @@ -1917,7 +1917,7 @@ retry: // put block into cache block = cache->NewBlock(blockNumber); if (block == NULL) - return NULL; + return B_NO_MEMORY; cache->hash->Insert(block); *_allocated = true; @@ -1951,7 +1951,7 @@ retry: TRACE_ALWAYS(("could not read block %" B_PRIdOFF ": bytesRead: %zd, error: %s\n", blockNumber, bytesRead, strerror(errno))); - return NULL; + return errno; } TB(Read(cache, block)); @@ -1961,7 +1961,8 @@ retry: block->ref_count++; block->last_accessed = system_time() / 1000000L; - return block; + *_block = block; + return B_OK; } @@ -1972,9 +1973,9 @@ retry: This is the only method to insert a block into a transaction. It makes sure that the previous block contents are preserved in that case. */ -static void* +static status_t get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, - off_t length, int32 transactionID, bool cleared) + off_t length, int32 transactionID, bool cleared, void** _block) { TRACE(("get_writable_cached_block(blockNumber = %" B_PRIdOFF ", transaction = %" B_PRId32 ")\n", blockNumber, transactionID)); @@ -1982,13 +1983,15 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, if (blockNumber < 0 || blockNumber >= cache->max_blocks) { panic("get_writable_cached_block: invalid block number %" B_PRIdOFF " (max %" B_PRIdOFF ")", blockNumber, cache->max_blocks - 1); + return B_BAD_VALUE; } bool allocated; - cached_block* block = get_cached_block(cache, blockNumber, &allocated, - !cleared); - if (block == NULL) - return NULL; + cached_block* block; + status_t status = get_cached_block(cache, blockNumber, &allocated, + !cleared, &block); + if (status != B_OK) + return status; if (block->busy_writing) wait_for_busy_writing_block(cache, block); @@ -2016,7 +2019,8 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, } TB(Get(cache, block)); - return block->current_data; + *_block = block->current_data; + return B_OK; } cache_transaction* transaction = block->transaction; @@ -2027,7 +2031,7 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, panic("get_writable_cached_block(): asked to get busy writable block " "(transaction %" B_PRId32 ")\n", block->transaction->id); put_cached_block(cache, block); - return NULL; + return B_BAD_VALUE; } if (transaction == NULL && transactionID != -1) { // get new transaction @@ -2036,12 +2040,12 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, panic("get_writable_cached_block(): invalid transaction %" B_PRId32 "!\n", transactionID); put_cached_block(cache, block); - return NULL; + return B_BAD_VALUE; } if (!transaction->open) { panic("get_writable_cached_block(): transaction already done!\n"); put_cached_block(cache, block); - return NULL; + return B_BAD_VALUE; } block->transaction = transaction; @@ -2064,7 +2068,7 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, TB(Error(cache, blockNumber, "allocate original failed")); FATAL(("could not allocate original_data\n")); put_cached_block(cache, block); - return NULL; + return B_NO_MEMORY; } mark_block_busy_reading(cache, block); @@ -2084,7 +2088,7 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, TB(Error(cache, blockNumber, "allocate parent failed")); FATAL(("could not allocate parent\n")); put_cached_block(cache, block); - return NULL; + return B_NO_MEMORY; } mark_block_busy_reading(cache, block); @@ -2114,7 +2118,8 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, TB(Get(cache, block)); TB2(BlockData(cache, block, "get writable")); - return block->current_data; + *_block = block->current_data; + return B_OK; } @@ -3583,20 +3588,21 @@ block_cache_make_writable(void* _cache, off_t blockNumber, int32 transaction) } // TODO: this can be done better! - void* block = get_writable_cached_block(cache, blockNumber, - blockNumber, 1, transaction, false); - if (block != NULL) { + void* block; + status_t status = get_writable_cached_block(cache, blockNumber, + blockNumber, 1, transaction, false, &block); + if (status == B_OK) { put_cached_block((block_cache*)_cache, blockNumber); return B_OK; } - return B_ERROR; + return status; } -void* +status_t block_cache_get_writable_etc(void* _cache, off_t blockNumber, off_t base, - off_t length, int32 transaction) + off_t length, int32 transaction, void** _block) { block_cache* cache = (block_cache*)_cache; MutexLocker locker(&cache->lock); @@ -3607,15 +3613,19 @@ block_cache_get_writable_etc(void* _cache, off_t blockNumber, off_t base, panic("tried to get writable block on a read-only cache!"); return get_writable_cached_block(cache, blockNumber, base, length, - transaction, false); + transaction, false, _block); } void* block_cache_get_writable(void* _cache, off_t blockNumber, int32 transaction) { - return block_cache_get_writable_etc(_cache, blockNumber, - blockNumber, 1, transaction); + void* block; + if (block_cache_get_writable_etc(_cache, blockNumber, + blockNumber, 1, transaction, &block) == B_OK) + return block; + + return NULL; } @@ -3630,21 +3640,28 @@ block_cache_get_empty(void* _cache, off_t blockNumber, int32 transaction) if (cache->read_only) panic("tried to get empty writable block on a read-only cache!"); - return get_writable_cached_block((block_cache*)_cache, blockNumber, - blockNumber, 1, transaction, true); + void* block; + if (get_writable_cached_block((block_cache*)_cache, blockNumber, + blockNumber, 1, transaction, true, &block) == B_OK) + return block; + + return NULL; } -const void* -block_cache_get_etc(void* _cache, off_t blockNumber, off_t base, off_t length) +status_t +block_cache_get_etc(void* _cache, off_t blockNumber, off_t base, off_t length, + const void** _block) { block_cache* cache = (block_cache*)_cache; MutexLocker locker(&cache->lock); bool allocated; - cached_block* block = get_cached_block(cache, blockNumber, &allocated); - if (block == NULL) - return NULL; + cached_block* block; + status_t status = get_cached_block(cache, blockNumber, &allocated, true, + &block); + if (status != B_OK) + return status; #if BLOCK_CACHE_DEBUG_CHANGED if (block->compare == NULL) @@ -3654,14 +3671,20 @@ block_cache_get_etc(void* _cache, off_t blockNumber, off_t base, off_t length) #endif TB(Get(cache, block)); - return block->current_data; + *_block = block->current_data; + return B_OK; } const void* block_cache_get(void* _cache, off_t blockNumber) { - return block_cache_get_etc(_cache, blockNumber, blockNumber, 1); + const void* block; + if (block_cache_get_etc(_cache, blockNumber, blockNumber, 1, &block) + == B_OK) + return block; + + return NULL; } diff --git a/src/tools/fs_shell/block_cache.cpp b/src/tools/fs_shell/block_cache.cpp index 26132ec664..dea256172b 100644 --- a/src/tools/fs_shell/block_cache.cpp +++ b/src/tools/fs_shell/block_cache.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2004-2020, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -716,14 +716,14 @@ put_cached_block(block_cache* cache, fssh_off_t blockNumber) not already in the cache. The block you retrieve may contain random data. */ -static cached_block* +static fssh_status_t get_cached_block(block_cache* cache, fssh_off_t blockNumber, bool* _allocated, - bool readBlock = true) + bool readBlock, cached_block** _block) { if (blockNumber < 0 || blockNumber >= cache->max_blocks) { fssh_panic("get_cached_block: invalid block number %" FSSH_B_PRIdOFF " (max %" FSSH_B_PRIdOFF ")", blockNumber, cache->max_blocks - 1); - return NULL; + return FSSH_B_BAD_VALUE; } cached_block* block = (cached_block*)hash_lookup(cache->hash, @@ -734,7 +734,7 @@ get_cached_block(block_cache* cache, fssh_off_t blockNumber, bool* _allocated, // read block into cache block = cache->NewBlock(blockNumber); if (block == NULL) - return NULL; + return FSSH_B_NO_MEMORY; hash_insert(cache->hash, block); *_allocated = true; @@ -747,7 +747,7 @@ get_cached_block(block_cache* cache, fssh_off_t blockNumber, bool* _allocated, blockSize) < blockSize) { cache->RemoveBlock(block); FATAL(("could not read block %" FSSH_B_PRIdOFF "\n", blockNumber)); - return NULL; + return fssh_errno; } } @@ -760,7 +760,8 @@ get_cached_block(block_cache* cache, fssh_off_t blockNumber, bool* _allocated, block->ref_count++; block->accessed++; - return block; + *_block = block; + return FSSH_B_OK; } @@ -771,9 +772,9 @@ get_cached_block(block_cache* cache, fssh_off_t blockNumber, bool* _allocated, This is the only method to insert a block into a transaction. It makes sure that the previous block contents are preserved in that case. */ -static void* +static fssh_status_t get_writable_cached_block(block_cache* cache, fssh_off_t blockNumber, fssh_off_t base, - fssh_off_t length, int32_t transactionID, bool cleared) + fssh_off_t length, int32_t transactionID, bool cleared, void** _block) { TRACE(("get_writable_cached_block(blockNumber = %Ld, transaction = %d)\n", blockNumber, transactionID)); @@ -782,13 +783,15 @@ get_writable_cached_block(block_cache* cache, fssh_off_t blockNumber, fssh_off_t fssh_panic("get_writable_cached_block: invalid block number %" FSSH_B_PRIdOFF " (max %" FSSH_B_PRIdOFF ")", blockNumber, cache->max_blocks - 1); + return FSSH_B_BAD_VALUE; } bool allocated; - cached_block* block = get_cached_block(cache, blockNumber, &allocated, - !cleared); - if (block == NULL) - return NULL; + cached_block* block; + fssh_status_t status = get_cached_block(cache, blockNumber, &allocated, + !cleared, &block); + if (status != FSSH_B_OK) + return status; block->discard = false; @@ -800,7 +803,8 @@ get_writable_cached_block(block_cache* cache, fssh_off_t blockNumber, fssh_off_t block->is_dirty = true; // mark the block as dirty - return block->current_data; + *_block = block->current_data; + return FSSH_B_OK; } cache_transaction* transaction = block->transaction; @@ -810,7 +814,7 @@ get_writable_cached_block(block_cache* cache, fssh_off_t blockNumber, fssh_off_t // Maybe we should even panic, since we can't prevent any deadlocks. fssh_panic("get_writable_cached_block(): asked to get busy writable block (transaction %d)\n", (int)transaction->id); put_cached_block(cache, block); - return NULL; + return FSSH_B_BAD_VALUE; } if (transaction == NULL && transactionID != -1) { // get new transaction @@ -819,12 +823,12 @@ get_writable_cached_block(block_cache* cache, fssh_off_t blockNumber, fssh_off_t fssh_panic("get_writable_cached_block(): invalid transaction %d!\n", (int)transactionID); put_cached_block(cache, block); - return NULL; + return FSSH_B_BAD_VALUE; } if (!transaction->open) { fssh_panic("get_writable_cached_block(): transaction already done!\n"); put_cached_block(cache, block); - return NULL; + return FSSH_B_BAD_VALUE; } block->transaction = transaction; @@ -844,7 +848,7 @@ get_writable_cached_block(block_cache* cache, fssh_off_t blockNumber, fssh_off_t if (block->original_data == NULL) { FATAL(("could not allocate original_data\n")); put_cached_block(cache, block); - return NULL; + return FSSH_B_NO_MEMORY; } fssh_memcpy(block->original_data, block->current_data, cache->block_size); @@ -856,7 +860,7 @@ get_writable_cached_block(block_cache* cache, fssh_off_t blockNumber, fssh_off_t // TODO: maybe we should just continue the current transaction in this case... FATAL(("could not allocate parent\n")); put_cached_block(cache, block); - return NULL; + return FSSH_B_NO_MEMORY; } fssh_memcpy(block->parent_data, block->current_data, cache->block_size); @@ -870,7 +874,8 @@ get_writable_cached_block(block_cache* cache, fssh_off_t blockNumber, fssh_off_t block->is_dirty = true; - return block->current_data; + *_block = block->current_data; + return FSSH_B_OK; } @@ -1634,20 +1639,21 @@ fssh_block_cache_make_writable(void* _cache, fssh_off_t blockNumber, fssh_panic("tried to make block writable on a read-only cache!"); // TODO: this can be done better! - void* block = get_writable_cached_block(cache, blockNumber, - blockNumber, 1, transaction, false); - if (block != NULL) { + void* block; + fssh_status_t status = get_writable_cached_block(cache, blockNumber, + blockNumber, 1, transaction, false, &block); + if (status == FSSH_B_OK) { put_cached_block((block_cache*)_cache, blockNumber); return FSSH_B_OK; } - return FSSH_B_ERROR; + return status; } -void* -fssh_block_cache_get_writable_etc(void* _cache, fssh_off_t blockNumber, fssh_off_t base, - fssh_off_t length, int32_t transaction) +fssh_status_t +fssh_block_cache_get_writable_etc(void* _cache, fssh_off_t blockNumber, + fssh_off_t base, fssh_off_t length, int32_t transaction, void** _block) { block_cache* cache = (block_cache*)_cache; MutexLocker locker(&cache->lock); @@ -1658,7 +1664,7 @@ fssh_block_cache_get_writable_etc(void* _cache, fssh_off_t blockNumber, fssh_off fssh_panic("tried to get writable block on a read-only cache!"); return get_writable_cached_block(cache, blockNumber, base, length, - transaction, false); + transaction, false, _block); } @@ -1666,8 +1672,13 @@ void* fssh_block_cache_get_writable(void* _cache, fssh_off_t blockNumber, int32_t transaction) { - return fssh_block_cache_get_writable_etc(_cache, blockNumber, - blockNumber, 1, transaction); + void* block; + fssh_status_t status = fssh_block_cache_get_writable_etc(_cache, + blockNumber, blockNumber, 1, transaction, &block); + if (status == FSSH_B_OK) + return block; + + return NULL; } @@ -1683,22 +1694,28 @@ fssh_block_cache_get_empty(void* _cache, fssh_off_t blockNumber, if (cache->read_only) fssh_panic("tried to get empty writable block on a read-only cache!"); - return get_writable_cached_block((block_cache*)_cache, blockNumber, - blockNumber, 1, transaction, true); + void* block; + if (get_writable_cached_block((block_cache*)_cache, blockNumber, + blockNumber, 1, transaction, true, &block) == FSSH_B_OK) + return block; + + return NULL; } -const void* +fssh_status_t fssh_block_cache_get_etc(void* _cache, fssh_off_t blockNumber, fssh_off_t base, - fssh_off_t length) + fssh_off_t length, const void** _block) { block_cache* cache = (block_cache*)_cache; MutexLocker locker(&cache->lock); bool allocated; - cached_block* block = get_cached_block(cache, blockNumber, &allocated); - if (block == NULL) - return NULL; + cached_block* block; + fssh_status_t status = get_cached_block(cache, blockNumber, &allocated, + true, &block); + if (status != FSSH_B_OK) + return status; #ifdef DEBUG_CHANGED if (block->compare == NULL) @@ -1706,14 +1723,20 @@ fssh_block_cache_get_etc(void* _cache, fssh_off_t blockNumber, fssh_off_t base, if (block->compare != NULL) memcpy(block->compare, block->current_data, cache->block_size); #endif - return block->current_data; + *_block = block->current_data; + return FSSH_B_OK; } const void* fssh_block_cache_get(void* _cache, fssh_off_t blockNumber) { - return fssh_block_cache_get_etc(_cache, blockNumber, blockNumber, 1); + const void* block; + if (fssh_block_cache_get_etc(_cache, blockNumber, blockNumber, 1, &block) + == FSSH_B_OK) + return block; + + return NULL; }