mirror of
https://review.haiku-os.org/haiku
synced 2025-01-18 20:48:48 +01:00
block_cache: Change signature of *_etc() functions
* This allows file systems to retrieve the actual error code on a failure, and report it to the user. * All affected file systems have been adjusted to the API change. This is a binary incompatible change. Change-Id: Id73392aaf9c6cb7d643ff9adcb8bf80f3037874c Reviewed-on: https://review.haiku-os.org/c/haiku/+/2913 Reviewed-by: Axel Dörfler <axeld@pinc-software.de> Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
parent
cc7b6b5870
commit
93845aec95
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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?
|
||||
|
@ -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();
|
||||
|
@ -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(); }
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 <haiku@clemens-zeidler.de>
|
||||
* 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<uint8*>(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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 <class Accessor, class Descriptor>
|
||||
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 <class Accessor, class Descriptor>
|
||||
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
|
||||
|
@ -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);
|
||||
|
99
src/system/kernel/cache/block_cache.cpp
vendored
99
src/system/kernel/cache/block_cache.cpp
vendored
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user