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 <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
waddlesplash
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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _FS_CACHE_H
|
#ifndef _FS_CACHE_H
|
||||||
@@ -66,14 +66,14 @@ extern void block_cache_discard(void *cache, off_t blockNumber,
|
|||||||
size_t numBlocks);
|
size_t numBlocks);
|
||||||
extern status_t block_cache_make_writable(void *cache, off_t blockNumber,
|
extern status_t block_cache_make_writable(void *cache, off_t blockNumber,
|
||||||
int32 transaction);
|
int32 transaction);
|
||||||
extern void *block_cache_get_writable_etc(void *cache, off_t blockNumber,
|
extern status_t block_cache_get_writable_etc(void *cache, off_t blockNumber,
|
||||||
off_t base, off_t length, int32 transaction);
|
off_t base, off_t length, int32 transaction, void** _block);
|
||||||
extern void *block_cache_get_writable(void *cache, off_t blockNumber,
|
extern void *block_cache_get_writable(void *cache, off_t blockNumber,
|
||||||
int32 transaction);
|
int32 transaction);
|
||||||
extern void *block_cache_get_empty(void *cache, off_t blockNumber,
|
extern void *block_cache_get_empty(void *cache, off_t blockNumber,
|
||||||
int32 transaction);
|
int32 transaction);
|
||||||
extern const void *block_cache_get_etc(void *cache, off_t blockNumber,
|
extern status_t block_cache_get_etc(void *cache, off_t blockNumber,
|
||||||
off_t base, off_t length);
|
off_t base, off_t length, const void** _block);
|
||||||
extern const void *block_cache_get(void *cache, off_t blockNumber);
|
extern const void *block_cache_get(void *cache, off_t blockNumber);
|
||||||
extern status_t block_cache_set_dirty(void *cache, off_t blockNumber,
|
extern status_t block_cache_set_dirty(void *cache, off_t blockNumber,
|
||||||
bool isDirty, int32 transaction);
|
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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _FSSH_FS_CACHE_H
|
#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);
|
fssh_off_t blockNumber, fssh_size_t numBlocks);
|
||||||
extern fssh_status_t fssh_block_cache_make_writable(void *_cache,
|
extern fssh_status_t fssh_block_cache_make_writable(void *_cache,
|
||||||
fssh_off_t blockNumber, int32_t transaction);
|
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 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,
|
extern void * fssh_block_cache_get_writable(void *_cache,
|
||||||
fssh_off_t blockNumber, int32_t transaction);
|
fssh_off_t blockNumber, int32_t transaction);
|
||||||
extern void * fssh_block_cache_get_empty(void *_cache,
|
extern void * fssh_block_cache_get_empty(void *_cache,
|
||||||
fssh_off_t blockNumber, int32_t transaction);
|
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 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,
|
extern const void * fssh_block_cache_get(void *_cache,
|
||||||
fssh_off_t blockNumber);
|
fssh_off_t blockNumber);
|
||||||
extern fssh_status_t fssh_block_cache_set_dirty(void *_cache,
|
extern fssh_status_t fssh_block_cache_set_dirty(void *_cache,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004-2017, Axel Dörfler, [email protected].
|
* Copyright 2004-2020, Axel Dörfler, [email protected].
|
||||||
* This file may be used under the terms of the MIT License.
|
* 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
|
// try to find it in the small data region
|
||||||
if (recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) {
|
if (recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) {
|
||||||
fNodeGetter.SetToNode(fInode);
|
status_t status = fNodeGetter.SetTo(fInode);
|
||||||
if (fNodeGetter.Node() == NULL)
|
if (status != B_OK)
|
||||||
return B_IO_ERROR;
|
return status;
|
||||||
|
|
||||||
fSmall = fInode->FindSmallData(fNodeGetter.Node(), (const char*)name);
|
fSmall = fInode->FindSmallData(fNodeGetter.Node(), (const char*)name);
|
||||||
if (fSmall != NULL)
|
if (fSmall != NULL)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2017, Axel Dörfler, [email protected].
|
* Copyright 2001-2020, Axel Dörfler, [email protected].
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ AllocationBlock::SetTo(AllocationGroup& group, uint16 block)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fWritable = false;
|
fWritable = false;
|
||||||
#endif
|
#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
|
#ifdef DEBUG
|
||||||
fWritable = true;
|
fWritable = true;
|
||||||
#endif
|
#endif
|
||||||
return CachedBlock::SetToWritable(transaction, group.Start() + block)
|
return CachedBlock::SetToWritable(transaction, group.Start() + block);
|
||||||
!= NULL ? B_OK : B_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.
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef CACHED_BLOCK_H
|
#ifndef CACHED_BLOCK_H
|
||||||
@@ -24,27 +24,26 @@
|
|||||||
class CachedBlock {
|
class CachedBlock {
|
||||||
public:
|
public:
|
||||||
CachedBlock(Volume* volume);
|
CachedBlock(Volume* volume);
|
||||||
CachedBlock(Volume* volume, off_t block);
|
|
||||||
CachedBlock(Volume* volume, block_run run);
|
|
||||||
CachedBlock(CachedBlock* cached);
|
CachedBlock(CachedBlock* cached);
|
||||||
~CachedBlock();
|
~CachedBlock();
|
||||||
|
|
||||||
inline void Keep();
|
inline void Keep();
|
||||||
inline void Unset();
|
inline void Unset();
|
||||||
|
|
||||||
inline const uint8* SetTo(off_t block, off_t base, size_t length);
|
inline status_t SetTo(off_t block, off_t base, size_t length);
|
||||||
inline const uint8* SetTo(off_t block);
|
inline status_t SetTo(off_t block);
|
||||||
inline const uint8* SetTo(block_run run);
|
inline status_t SetTo(block_run run);
|
||||||
inline uint8* SetToWritable(Transaction& transaction,
|
inline status_t SetToWritable(Transaction& transaction,
|
||||||
off_t block, off_t base, size_t length,
|
off_t block, off_t base, size_t length,
|
||||||
bool empty = false);
|
bool empty = false);
|
||||||
inline uint8* SetToWritable(Transaction& transaction,
|
inline status_t SetToWritable(Transaction& transaction,
|
||||||
off_t block, bool empty = false);
|
off_t block, bool empty = false);
|
||||||
inline uint8* SetToWritable(Transaction& transaction,
|
inline status_t SetToWritable(Transaction& transaction,
|
||||||
block_run run, bool empty = false);
|
block_run run, bool empty = false);
|
||||||
inline status_t MakeWritable(Transaction& transaction);
|
inline status_t MakeWritable(Transaction& transaction);
|
||||||
|
|
||||||
const uint8* Block() const { return fBlock; }
|
const uint8* Block() const { return fBlock; }
|
||||||
|
uint8* WritableBlock() const { return fBlock; }
|
||||||
off_t BlockNumber() const { return fBlockNumber; }
|
off_t BlockNumber() const { return fBlockNumber; }
|
||||||
uint32 BlockSize() const
|
uint32 BlockSize() const
|
||||||
{ return fVolume->BlockSize(); }
|
{ 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
|
inline
|
||||||
CachedBlock::CachedBlock(CachedBlock* cached)
|
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)
|
CachedBlock::SetTo(off_t block, off_t base, size_t length)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
fBlockNumber = block;
|
fBlockNumber = block;
|
||||||
return fBlock = (uint8*)block_cache_get_etc(fVolume->BlockCache(),
|
return block_cache_get_etc(fVolume->BlockCache(), block, base, length,
|
||||||
block, base, length);
|
(const void**)&fBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline const uint8*
|
inline status_t
|
||||||
CachedBlock::SetTo(off_t block)
|
CachedBlock::SetTo(off_t block)
|
||||||
{
|
{
|
||||||
return SetTo(block, block, 1);
|
return SetTo(block, block, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline const uint8*
|
inline status_t
|
||||||
CachedBlock::SetTo(block_run run)
|
CachedBlock::SetTo(block_run run)
|
||||||
{
|
{
|
||||||
return SetTo(fVolume->ToBlock(run));
|
return SetTo(fVolume->ToBlock(run));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline uint8*
|
inline status_t
|
||||||
CachedBlock::SetToWritable(Transaction& transaction, off_t block, off_t base,
|
CachedBlock::SetToWritable(Transaction& transaction, off_t block, off_t base,
|
||||||
size_t length, bool empty)
|
size_t length, bool empty)
|
||||||
{
|
{
|
||||||
@@ -167,23 +144,22 @@ CachedBlock::SetToWritable(Transaction& transaction, off_t block, off_t base,
|
|||||||
if (empty) {
|
if (empty) {
|
||||||
fBlock = (uint8*)block_cache_get_empty(fVolume->BlockCache(),
|
fBlock = (uint8*)block_cache_get_empty(fVolume->BlockCache(),
|
||||||
block, transaction.ID());
|
block, transaction.ID());
|
||||||
} else {
|
return fBlock != NULL ? B_OK : B_NO_MEMORY;
|
||||||
fBlock = (uint8*)block_cache_get_writable_etc(fVolume->BlockCache(),
|
|
||||||
block, base, length, transaction.ID());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
CachedBlock::SetToWritable(Transaction& transaction, off_t block, bool empty)
|
||||||
{
|
{
|
||||||
return SetToWritable(transaction, block, block, 1, empty);
|
return SetToWritable(transaction, block, block, 1, empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline uint8*
|
inline status_t
|
||||||
CachedBlock::SetToWritable(Transaction& transaction, block_run run, bool empty)
|
CachedBlock::SetToWritable(Transaction& transaction, block_run run, bool empty)
|
||||||
{
|
{
|
||||||
return SetToWritable(transaction, fVolume->ToBlock(run), 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
|
* Copyright 2012, Andreas Henriksson, sausageboy@gmail.com
|
||||||
* This file may be used under the terms of the MIT License.
|
* 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
|
// check if the inode's name is the same as in the b+tree
|
||||||
if (inode->IsRegularNode()) {
|
if (inode->IsRegularNode()) {
|
||||||
RecursiveLocker locker(inode->SmallDataLock());
|
RecursiveLocker locker(inode->SmallDataLock());
|
||||||
NodeGetter node(GetVolume(), inode);
|
NodeGetter node(GetVolume());
|
||||||
if (node.Node() == NULL) {
|
status_t status = node.SetTo(inode);
|
||||||
|
if (status != B_OK) {
|
||||||
Control().errors |= BFS_COULD_NOT_OPEN;
|
Control().errors |= BFS_COULD_NOT_OPEN;
|
||||||
Control().status = B_IO_ERROR;
|
Control().status = status;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,16 +497,17 @@ CheckVisitor::_CheckInodeBlocks(Inode* inode, const char* name)
|
|||||||
|
|
||||||
if (data->max_indirect_range) {
|
if (data->max_indirect_range) {
|
||||||
status = _CheckAllocated(data->indirect, "indirect");
|
status = _CheckAllocated(data->indirect, "indirect");
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
off_t block = GetVolume()->ToBlock(data->indirect);
|
off_t block = GetVolume()->ToBlock(data->indirect);
|
||||||
|
|
||||||
for (int32 i = 0; i < data->indirect.Length(); i++) {
|
for (int32 i = 0; i < data->indirect.Length(); i++) {
|
||||||
block_run* runs = (block_run*)cached.SetTo(block + i);
|
status = cached.SetTo(block + i);
|
||||||
if (runs == NULL)
|
if (status != B_OK)
|
||||||
RETURN_ERROR(B_IO_ERROR);
|
RETURN_ERROR(status);
|
||||||
|
|
||||||
|
block_run* runs = (block_run*)cached.Block();
|
||||||
int32 runsPerBlock = GetVolume()->BlockSize() / sizeof(block_run);
|
int32 runsPerBlock = GetVolume()->BlockSize() / sizeof(block_run);
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
for (; index < runsPerBlock; index++) {
|
for (; index < runsPerBlock; index++) {
|
||||||
@@ -542,12 +544,12 @@ CheckVisitor::_CheckInodeBlocks(Inode* inode, const char* name)
|
|||||||
for (int32 indirectIndex = 0; indirectIndex < runsPerArray;
|
for (int32 indirectIndex = 0; indirectIndex < runsPerArray;
|
||||||
indirectIndex++) {
|
indirectIndex++) {
|
||||||
// get the indirect array block
|
// get the indirect array block
|
||||||
block_run* array = (block_run*)cached.SetTo(
|
status = cached.SetTo(GetVolume()->ToBlock(data->double_indirect)
|
||||||
GetVolume()->ToBlock(data->double_indirect)
|
|
||||||
+ indirectIndex / runsPerBlock);
|
+ indirectIndex / runsPerBlock);
|
||||||
if (array == NULL)
|
if (status != B_OK)
|
||||||
return B_IO_ERROR;
|
return status;
|
||||||
|
|
||||||
|
block_run* array = (block_run*)cached.Block();
|
||||||
block_run indirect = array[indirectIndex % runsPerBlock];
|
block_run indirect = array[indirectIndex % runsPerBlock];
|
||||||
// are we finished yet?
|
// are we finished yet?
|
||||||
if (indirect.IsZero())
|
if (indirect.IsZero())
|
||||||
@@ -562,10 +564,12 @@ CheckVisitor::_CheckInodeBlocks(Inode* inode, const char* name)
|
|||||||
/ sizeof(block_run);
|
/ sizeof(block_run);
|
||||||
|
|
||||||
for (int32 index = 0; index < maxIndex; ) {
|
for (int32 index = 0; index < maxIndex; ) {
|
||||||
block_run* runs = (block_run*)cachedDirect.SetTo(
|
status = cachedDirect.SetTo(GetVolume()->ToBlock(indirect)
|
||||||
GetVolume()->ToBlock(indirect) + index / runsPerBlock);
|
+ index / runsPerBlock);
|
||||||
if (runs == NULL)
|
if (status != B_OK)
|
||||||
return B_IO_ERROR;
|
return status;
|
||||||
|
|
||||||
|
block_run* runs = (block_run*)cachedDirect.Block();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// are we finished yet?
|
// 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.
|
* 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");
|
rw_lock_init(&fLock, "bfs inode");
|
||||||
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
|
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
|
||||||
|
|
||||||
NodeGetter node(volume, transaction, this, true);
|
NodeGetter node(volume);
|
||||||
if (node.Node() == NULL) {
|
status_t status = node.SetToWritable(transaction, this, true);
|
||||||
FATAL(("Could not read inode block %" B_PRId64 "!\n", BlockNumber()));
|
if (status != B_OK) {
|
||||||
|
FATAL(("Could not read inode block %" B_PRId64 ": %s!\n", BlockNumber(),
|
||||||
|
strerror(status)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,9 +493,10 @@ Inode::WriteLockInTransaction(Transaction& transaction)
|
|||||||
status_t
|
status_t
|
||||||
Inode::WriteBack(Transaction& transaction)
|
Inode::WriteBack(Transaction& transaction)
|
||||||
{
|
{
|
||||||
NodeGetter node(fVolume, transaction, this);
|
NodeGetter node(fVolume);
|
||||||
if (node.WritableNode() == NULL)
|
status_t status = node.SetToWritable(transaction, this);
|
||||||
return B_IO_ERROR;
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
memcpy(node.WritableNode(), &Node(), sizeof(bfs_inode));
|
memcpy(node.WritableNode(), &Node(), sizeof(bfs_inode));
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -503,11 +506,12 @@ Inode::WriteBack(Transaction& transaction)
|
|||||||
status_t
|
status_t
|
||||||
Inode::UpdateNodeFromDisk()
|
Inode::UpdateNodeFromDisk()
|
||||||
{
|
{
|
||||||
NodeGetter node(fVolume, this);
|
NodeGetter node(fVolume);
|
||||||
if (node.Node() == NULL) {
|
status_t status = node.SetTo(this);
|
||||||
FATAL(("Failed to read block %" B_PRId64 " from disk!\n",
|
if (status != B_OK) {
|
||||||
BlockNumber()));
|
FATAL(("Failed to read block %" B_PRId64 " from disk: %s!\n",
|
||||||
return B_IO_ERROR;
|
BlockNumber(), strerror(status)));
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&fNode, node.Node(), sizeof(bfs_inode));
|
memcpy(&fNode, node.Node(), sizeof(bfs_inode));
|
||||||
@@ -677,9 +681,11 @@ Inode::_RemoveSmallData(Transaction& transaction, NodeGetter& nodeGetter,
|
|||||||
if (item->IsLast(node))
|
if (item->IsLast(node))
|
||||||
return B_ENTRY_NOT_FOUND;
|
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) {
|
if (status == B_OK) {
|
||||||
Node().status_change_time = HOST_ENDIAN_TO_BFS_INT64(
|
Node().status_change_time = HOST_ENDIAN_TO_BFS_INT64(
|
||||||
bfs_inode::ToInode(real_time_clock_usecs()));
|
bfs_inode::ToInode(real_time_clock_usecs()));
|
||||||
@@ -718,7 +724,10 @@ Inode::_AddSmallData(Transaction& transaction, NodeGetter& nodeGetter,
|
|||||||
if (spaceNeeded > fVolume->InodeSize() - sizeof(bfs_inode))
|
if (spaceNeeded > fVolume->InodeSize() - sizeof(bfs_inode))
|
||||||
return B_DEVICE_FULL;
|
return B_DEVICE_FULL;
|
||||||
|
|
||||||
nodeGetter.MakeWritable(transaction);
|
status_t status = nodeGetter.MakeWritable(transaction);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
RecursiveLocker locker(fSmallDataLock);
|
RecursiveLocker locker(fSmallDataLock);
|
||||||
|
|
||||||
// Find the last item or one with the same name we have to add
|
// 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
|
status_t
|
||||||
Inode::GetName(char* buffer, size_t size) const
|
Inode::GetName(char* buffer, size_t size) const
|
||||||
{
|
{
|
||||||
NodeGetter node(fVolume, this);
|
NodeGetter node(fVolume);
|
||||||
if (node.Node() == NULL)
|
status_t status = node.SetTo(this);
|
||||||
return B_IO_ERROR;
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
RecursiveLocker locker(fSmallDataLock);
|
RecursiveLocker locker(fSmallDataLock);
|
||||||
|
|
||||||
@@ -961,9 +971,10 @@ Inode::SetName(Transaction& transaction, const char* name)
|
|||||||
if (name == NULL || *name == '\0')
|
if (name == NULL || *name == '\0')
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
NodeGetter node(fVolume, transaction, this);
|
NodeGetter node(fVolume);
|
||||||
if (node.Node() == NULL)
|
status_t status = node.SetToWritable(transaction, this);
|
||||||
return B_IO_ERROR;
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
const char nameTag[2] = {FILE_NAME_NAME, 0};
|
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)
|
// search in the small_data section (which has to be locked first)
|
||||||
{
|
{
|
||||||
NodeGetter node(fVolume, this);
|
NodeGetter node(fVolume);
|
||||||
if (node.Node() == NULL)
|
status_t status = node.SetTo(this);
|
||||||
return B_IO_ERROR;
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
RecursiveLocker locker(fSmallDataLock);
|
RecursiveLocker locker(fSmallDataLock);
|
||||||
|
|
||||||
@@ -1107,9 +1119,10 @@ Inode::WriteAttribute(Transaction& transaction, const char* name, int32 type,
|
|||||||
// No attribute inode exists yet
|
// No attribute inode exists yet
|
||||||
|
|
||||||
// save the old attribute data
|
// save the old attribute data
|
||||||
NodeGetter node(fVolume, transaction, this);
|
NodeGetter node(fVolume);
|
||||||
if (node.Node() == NULL)
|
status = node.SetToWritable(transaction, this);
|
||||||
return B_IO_ERROR;
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
recursive_lock_lock(&fSmallDataLock);
|
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
|
// check if the data fits into the small_data section again
|
||||||
NodeGetter node(fVolume, transaction, this);
|
NodeGetter node(fVolume);
|
||||||
if (node.Node() == NULL)
|
status = node.SetToWritable(transaction, this);
|
||||||
return B_IO_ERROR;
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
status = _AddSmallData(transaction, node, name, type, pos, buffer,
|
status = _AddSmallData(transaction, node, name, type, pos, buffer,
|
||||||
*_length);
|
*_length);
|
||||||
@@ -1252,9 +1266,10 @@ Inode::RemoveAttribute(Transaction& transaction, const char* name)
|
|||||||
{
|
{
|
||||||
Index index(fVolume);
|
Index index(fVolume);
|
||||||
bool hasIndex = index.SetTo(name) == B_OK;
|
bool hasIndex = index.SetTo(name) == B_OK;
|
||||||
NodeGetter node(fVolume, this);
|
NodeGetter node(fVolume);
|
||||||
if (node.Node() == NULL)
|
status_t status = node.SetTo(this);
|
||||||
return B_IO_ERROR;
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
// update index for attributes in the small_data section
|
// 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()) {
|
if (status == B_ENTRY_NOT_FOUND && !Attributes().IsZero()) {
|
||||||
// remove the attribute file if it exists
|
// remove the attribute file if it exists
|
||||||
status = _RemoveAttribute(transaction, name, hasIndex, &index);
|
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();
|
off_t start = pos - data->MaxIndirectRange();
|
||||||
int32 index = start / indirectSize;
|
int32 index = start / indirectSize;
|
||||||
|
|
||||||
block_run* indirect = (block_run*)cached.SetTo(
|
status_t status = cached.SetTo(fVolume->ToBlock(
|
||||||
fVolume->ToBlock(data->double_indirect) + index / runsPerBlock);
|
data->double_indirect) + index / runsPerBlock);
|
||||||
if (indirect == NULL)
|
if (status != B_OK)
|
||||||
RETURN_ERROR(B_ERROR);
|
RETURN_ERROR(status);
|
||||||
|
|
||||||
|
block_run* indirect = (block_run*)cached.Block();
|
||||||
int32 current = (start % indirectSize) / directSize;
|
int32 current = (start % indirectSize) / directSize;
|
||||||
|
|
||||||
indirect = (block_run*)cached.SetTo(
|
status = cached.SetTo(fVolume->ToBlock(indirect[
|
||||||
fVolume->ToBlock(indirect[index % runsPerBlock])
|
index % runsPerBlock]) + current / runsPerBlock);
|
||||||
+ current / runsPerBlock);
|
if (status != B_OK)
|
||||||
if (indirect == NULL)
|
RETURN_ERROR(status);
|
||||||
RETURN_ERROR(B_ERROR);
|
|
||||||
|
|
||||||
|
indirect = (block_run*)cached.Block();
|
||||||
run = indirect[current % runsPerBlock];
|
run = indirect[current % runsPerBlock];
|
||||||
if (run.Length() != data->double_indirect.Length())
|
if (run.Length() != data->double_indirect.Length())
|
||||||
RETURN_ERROR(B_BAD_DATA);
|
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);
|
off_t block = fVolume->ToBlock(data->indirect);
|
||||||
|
|
||||||
for (int32 i = 0; i < data->indirect.Length(); i++) {
|
for (int32 i = 0; i < data->indirect.Length(); i++) {
|
||||||
block_run* indirect = (block_run*)cached.SetTo(block + i);
|
status_t status = cached.SetTo(block + i);
|
||||||
if (indirect == NULL)
|
if (status != B_OK)
|
||||||
RETURN_ERROR(B_IO_ERROR);
|
RETURN_ERROR(status);
|
||||||
|
|
||||||
|
block_run* indirect = (block_run*)cached.Block();
|
||||||
int32 current = -1;
|
int32 current = -1;
|
||||||
while (++current < runsPerBlock) {
|
while (++current < runsPerBlock) {
|
||||||
if (indirect[current].IsZero())
|
if (indirect[current].IsZero())
|
||||||
@@ -1689,10 +1706,9 @@ Inode::_AllocateBlockArray(Transaction& transaction, block_run& run,
|
|||||||
off_t block = fVolume->ToBlock(run);
|
off_t block = fVolume->ToBlock(run);
|
||||||
|
|
||||||
for (int32 i = 0; i < run.Length(); i++) {
|
for (int32 i = 0; i < run.Length(); i++) {
|
||||||
block_run* runs = (block_run*)cached.SetToWritable(transaction,
|
status = cached.SetToWritable(transaction, block + i, true);
|
||||||
block + i, true);
|
if (status != B_OK)
|
||||||
if (runs == NULL)
|
return status;
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
}
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -1851,7 +1867,11 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
|||||||
data->max_indirect_range = HOST_ENDIAN_TO_BFS_INT64(
|
data->max_indirect_range = HOST_ENDIAN_TO_BFS_INT64(
|
||||||
data->MaxDirectRange());
|
data->MaxDirectRange());
|
||||||
// insert the block_run in the first block
|
// 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 {
|
} else {
|
||||||
uint32 numberOfRuns = fVolume->BlockSize() / sizeof(block_run);
|
uint32 numberOfRuns = fVolume->BlockSize() / sizeof(block_run);
|
||||||
block = fVolume->ToBlock(data->indirect);
|
block = fVolume->ToBlock(data->indirect);
|
||||||
@@ -1859,9 +1879,11 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
|||||||
// search first empty entry
|
// search first empty entry
|
||||||
int32 i = 0;
|
int32 i = 0;
|
||||||
for (; i < data->indirect.Length(); i++) {
|
for (; i < data->indirect.Length(); i++) {
|
||||||
if ((runs = (block_run*)cached.SetTo(block + i)) == NULL)
|
status = cached.SetTo(block + i);
|
||||||
return B_IO_ERROR;
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
runs = (block_run*)cached.Block();
|
||||||
for (free = 0; free < numberOfRuns; free++)
|
for (free = 0; free < numberOfRuns; free++)
|
||||||
if (runs[free].IsZero())
|
if (runs[free].IsZero())
|
||||||
break;
|
break;
|
||||||
@@ -1971,10 +1993,12 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
|||||||
if (block >= minimum)
|
if (block >= minimum)
|
||||||
return EFBIG;
|
return EFBIG;
|
||||||
|
|
||||||
array = (block_run*)cached.SetTo(fVolume->ToBlock(
|
status = cached.SetTo(fVolume->ToBlock(
|
||||||
data->double_indirect) + block);
|
data->double_indirect) + block);
|
||||||
if (array == NULL)
|
if (status != B_OK)
|
||||||
return B_IO_ERROR;
|
return status;
|
||||||
|
|
||||||
|
array = (block_run*)cached.Block();
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -1989,11 +2013,13 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
block_run* runs = (block_run*)cachedDirect.SetToWritable(
|
status = cachedDirect.SetToWritable(transaction,
|
||||||
transaction, fVolume->ToBlock(array[indirectIndex
|
fVolume->ToBlock(array[indirectIndex
|
||||||
% runsPerBlock]) + index / runsPerBlock);
|
% runsPerBlock]) + index / runsPerBlock);
|
||||||
if (runs == NULL)
|
if (status != B_OK)
|
||||||
return B_IO_ERROR;
|
return status;
|
||||||
|
|
||||||
|
block_run* runs = (block_run*)cachedDirect.Block();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// insert the block_run into the array
|
// insert the block_run into the array
|
||||||
@@ -2079,10 +2105,11 @@ Inode::_FreeStaticStreamArray(Transaction& transaction, int32 level,
|
|||||||
offset += (off_t)index * indirectSize;
|
offset += (off_t)index * indirectSize;
|
||||||
|
|
||||||
for (int32 i = index / runsPerBlock; i < run.Length(); i++) {
|
for (int32 i = index / runsPerBlock; i < run.Length(); i++) {
|
||||||
block_run* array = (block_run*)cached.SetToWritable(transaction,
|
status_t status = cached.SetToWritable(transaction, blockNumber + i);
|
||||||
blockNumber + i);
|
if (status != B_OK)
|
||||||
if (array == NULL)
|
RETURN_ERROR(status);
|
||||||
RETURN_ERROR(B_ERROR);
|
|
||||||
|
block_run* array = (block_run*)cached.WritableBlock();
|
||||||
|
|
||||||
for (index = index % runsPerBlock; index < runsPerBlock; index++) {
|
for (index = index % runsPerBlock; index < runsPerBlock; index++) {
|
||||||
if (array[index].IsZero()) {
|
if (array[index].IsZero()) {
|
||||||
@@ -2201,10 +2228,11 @@ Inode::_ShrinkStream(Transaction& transaction, off_t size)
|
|||||||
off_t offset = data->MaxDirectRange();
|
off_t offset = data->MaxDirectRange();
|
||||||
|
|
||||||
for (int32 i = 0; i < data->indirect.Length(); i++) {
|
for (int32 i = 0; i < data->indirect.Length(); i++) {
|
||||||
block_run* array = (block_run*)cached.SetToWritable(transaction,
|
status = cached.SetToWritable(transaction, block + i);
|
||||||
block + i);
|
if (status != B_OK)
|
||||||
if (array == NULL)
|
return status;
|
||||||
break;
|
|
||||||
|
block_run* array = (block_run*)cached.WritableBlock();
|
||||||
|
|
||||||
off_t* maxIndirect = &data->max_indirect_range;
|
off_t* maxIndirect = &data->max_indirect_range;
|
||||||
// gcc 4 work-around: "error: cannot bind packed field
|
// 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&'"
|
// 'data->data_stream::max_direct_range' to 'off_t&'"
|
||||||
status = _FreeStreamArray(transaction, data->direct, NUM_DIRECT_BLOCKS,
|
status = _FreeStreamArray(transaction, data->direct, NUM_DIRECT_BLOCKS,
|
||||||
size, offset, *maxDirect);
|
size, offset, *maxDirect);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2392,9 +2420,11 @@ Inode::Sync()
|
|||||||
int32 count = fVolume->BlockSize() / sizeof(block_run);
|
int32 count = fVolume->BlockSize() / sizeof(block_run);
|
||||||
|
|
||||||
for (int32 j = 0; j < data->indirect.Length(); j++) {
|
for (int32 j = 0; j < data->indirect.Length(); j++) {
|
||||||
block_run* runs = (block_run*)cached.SetTo(block + j);
|
status = cached.SetTo(block + j);
|
||||||
if (runs == NULL)
|
if (status != B_OK)
|
||||||
break;
|
return status;
|
||||||
|
|
||||||
|
block_run* runs = (block_run*)cached.Block();
|
||||||
|
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
if (runs[i].IsZero())
|
if (runs[i].IsZero())
|
||||||
@@ -2415,10 +2445,11 @@ Inode::Sync()
|
|||||||
off_t indirectBlock = fVolume->ToBlock(data->double_indirect);
|
off_t indirectBlock = fVolume->ToBlock(data->double_indirect);
|
||||||
|
|
||||||
for (int32 l = 0; l < data->double_indirect.Length(); l++) {
|
for (int32 l = 0; l < data->double_indirect.Length(); l++) {
|
||||||
block_run* indirectRuns = (block_run*)cached.SetTo(indirectBlock + l);
|
status = cached.SetTo(indirectBlock + l);
|
||||||
if (indirectRuns == NULL)
|
if (status != B_OK)
|
||||||
return B_FILE_ERROR;
|
return status;
|
||||||
|
|
||||||
|
block_run* indirectRuns = (block_run*)cached.Block();
|
||||||
CachedBlock directCached(fVolume);
|
CachedBlock directCached(fVolume);
|
||||||
|
|
||||||
for (int32 k = 0; k < count; k++) {
|
for (int32 k = 0; k < count; k++) {
|
||||||
@@ -2427,9 +2458,11 @@ Inode::Sync()
|
|||||||
|
|
||||||
block = fVolume->ToBlock(indirectRuns[k]);
|
block = fVolume->ToBlock(indirectRuns[k]);
|
||||||
for (int32 j = 0; j < indirectRuns[k].Length(); j++) {
|
for (int32 j = 0; j < indirectRuns[k].Length(); j++) {
|
||||||
block_run* runs = (block_run*)directCached.SetTo(block + j);
|
status = directCached.SetTo(block + j);
|
||||||
if (runs == NULL)
|
if (status != B_OK)
|
||||||
return B_FILE_ERROR;
|
return status;
|
||||||
|
|
||||||
|
block_run* runs = (block_run*)directCached.Block();
|
||||||
|
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
if (runs[i].IsZero())
|
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
|
// read attributes out of the small data section
|
||||||
|
|
||||||
if (fCurrentSmallData >= 0) {
|
if (fCurrentSmallData >= 0) {
|
||||||
NodeGetter nodeGetter(fInode->GetVolume(), fInode);
|
NodeGetter nodeGetter(fInode->GetVolume());
|
||||||
if (nodeGetter.Node() == NULL)
|
status_t status = nodeGetter.SetTo(fInode);
|
||||||
return B_IO_ERROR;
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
const bfs_inode* node = nodeGetter.Node();
|
const bfs_inode* node = nodeGetter.Node();
|
||||||
const small_data* item = ((bfs_inode*)node)->SmallDataStart();
|
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.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef INODE_H
|
#ifndef INODE_H
|
||||||
@@ -338,30 +338,25 @@ private:
|
|||||||
class NodeGetter : public CachedBlock {
|
class NodeGetter : public CachedBlock {
|
||||||
public:
|
public:
|
||||||
NodeGetter(Volume* volume)
|
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()
|
~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(); }
|
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.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -484,11 +484,11 @@ Journal::_ReplayRunArray(int32* _start)
|
|||||||
|
|
||||||
CachedBlock cachedArray(fVolume);
|
CachedBlock cachedArray(fVolume);
|
||||||
|
|
||||||
const run_array* array = (const run_array*)cachedArray.SetTo(logOffset
|
status_t status = cachedArray.SetTo(logOffset + firstBlockNumber);
|
||||||
+ firstBlockNumber);
|
if (status != B_OK)
|
||||||
if (array == NULL)
|
return status;
|
||||||
return B_IO_ERROR;
|
|
||||||
|
|
||||||
|
const run_array* array = (const run_array*)cachedArray.Block();
|
||||||
if (_CheckRunArray(array) < B_OK)
|
if (_CheckRunArray(array) < B_OK)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
@@ -505,16 +505,16 @@ Journal::_ReplayRunArray(int32* _start)
|
|||||||
|
|
||||||
off_t offset = fVolume->ToOffset(run);
|
off_t offset = fVolume->ToOffset(run);
|
||||||
for (int32 i = 0; i < run.Length(); i++) {
|
for (int32 i = 0; i < run.Length(); i++) {
|
||||||
const uint8* data = cached.SetTo(logOffset + blockNumber);
|
status = cached.SetTo(logOffset + blockNumber);
|
||||||
if (data == NULL)
|
if (status != status)
|
||||||
RETURN_ERROR(B_IO_ERROR);
|
RETURN_ERROR(status);
|
||||||
|
|
||||||
// TODO: eventually check other well known offsets, like the
|
// TODO: eventually check other well known offsets, like the
|
||||||
// root and index dirs
|
// root and index dirs
|
||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
// This log entry writes over the superblock - check if
|
// This log entry writes over the superblock - check if
|
||||||
// it's valid!
|
// it's valid!
|
||||||
if (Volume::CheckSuperBlock(data) != B_OK) {
|
if (Volume::CheckSuperBlock(cached.Block()) != B_OK) {
|
||||||
FATAL(("Log contains invalid superblock!\n"));
|
FATAL(("Log contains invalid superblock!\n"));
|
||||||
RETURN_ERROR(B_BAD_DATA);
|
RETURN_ERROR(B_BAD_DATA);
|
||||||
}
|
}
|
||||||
@@ -537,12 +537,12 @@ Journal::_ReplayRunArray(int32* _start)
|
|||||||
|
|
||||||
off_t offset = fVolume->ToOffset(run);
|
off_t offset = fVolume->ToOffset(run);
|
||||||
for (int32 i = 0; i < run.Length(); i++) {
|
for (int32 i = 0; i < run.Length(); i++) {
|
||||||
const uint8* data = cached.SetTo(logOffset + blockNumber);
|
status = cached.SetTo(logOffset + blockNumber);
|
||||||
if (data == NULL)
|
if (status != B_OK)
|
||||||
RETURN_ERROR(B_IO_ERROR);
|
RETURN_ERROR(status);
|
||||||
|
|
||||||
ssize_t written = write_pos(fVolume->Device(), offset, data,
|
ssize_t written = write_pos(fVolume->Device(), offset,
|
||||||
blockSize);
|
cached.Block(), blockSize);
|
||||||
if (written != blockSize)
|
if (written != blockSize)
|
||||||
RETURN_ERROR(B_IO_ERROR);
|
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>
|
* Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de>
|
||||||
* This file may be used under the terms of the MIT License.
|
* 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);
|
buffer = const_cast<uint8*>(key);
|
||||||
} else if (!strcmp(fAttribute, "name")) {
|
} else if (!strcmp(fAttribute, "name")) {
|
||||||
// we need to lock before accessing Inode::Name()
|
// we need to lock before accessing Inode::Name()
|
||||||
nodeGetter.SetToNode(inode);
|
status_t status = nodeGetter.SetTo(inode);
|
||||||
if (nodeGetter.Node() == NULL)
|
if (status != B_OK)
|
||||||
return B_IO_ERROR;
|
return status;
|
||||||
|
|
||||||
recursive_lock_lock(&inode->SmallDataLock());
|
recursive_lock_lock(&inode->SmallDataLock());
|
||||||
locked = true;
|
locked = true;
|
||||||
@@ -417,9 +417,9 @@ Equation::Match(Inode* inode, const char* attributeName, int32 type,
|
|||||||
} else {
|
} else {
|
||||||
// then for attributes in the small_data section, and finally for the
|
// then for attributes in the small_data section, and finally for the
|
||||||
// real attributes
|
// real attributes
|
||||||
nodeGetter.SetToNode(inode);
|
status_t status = nodeGetter.SetTo(inode);
|
||||||
if (nodeGetter.Node() == NULL)
|
if (status != B_OK)
|
||||||
return B_IO_ERROR;
|
return status;
|
||||||
|
|
||||||
Inode* attribute;
|
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.
|
* 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;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedBlock cached(volume, id);
|
CachedBlock cached(volume);
|
||||||
bfs_inode* node = (bfs_inode*)cached.Block();
|
status_t status = cached.SetTo(id);
|
||||||
if (node == NULL) {
|
if (status != B_OK) {
|
||||||
FATAL(("could not read inode: %" B_PRIdINO "\n", id));
|
FATAL(("could not read inode: %" B_PRIdINO ": %s\n", id,
|
||||||
return B_IO_ERROR;
|
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 (status != B_OK) {
|
||||||
if ((node->Flags() & INODE_DELETED) != 0) {
|
if ((node->Flags() & INODE_DELETED) != 0) {
|
||||||
INFORM(("inode at %" B_PRIdINO " is already deleted!\n", id));
|
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();
|
status = checker->StartIndexPass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
status = user_memcpy(buffer, &checker->Control(),
|
status = user_memcpy(buffer, &checker->Control(),
|
||||||
sizeof(check_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,
|
PRINT(("write block_run(%ld, %d, %d)\n", run.allocation_group,
|
||||||
run.start, run.length));
|
run.start, run.length));
|
||||||
for (int32 i = 0;i < run.length;i++) {
|
for (int32 i = 0;i < run.length;i++) {
|
||||||
uint8* block = cached.SetToWritable(transaction, run);
|
status_t status = cached.SetToWritable(transaction, run);
|
||||||
if (block != NULL)
|
if (status == B_OK)
|
||||||
memset(block, 0, volume->BlockSize());
|
memset(cached.WritableBlock(), 0, volume->BlockSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -908,9 +908,11 @@ update_fsinfo(nspace *vol)
|
|||||||
{
|
{
|
||||||
if (vol->fat_bits == 32 && vol->fsinfo_sector != 0xffff
|
if (vol->fat_bits == 32 && vol->fsinfo_sector != 0xffff
|
||||||
&& (vol->flags & B_FS_IS_READONLY) == 0) {
|
&& (vol->flags & B_FS_IS_READONLY) == 0) {
|
||||||
uchar *buffer = (uchar *)block_cache_get_writable_etc(vol->fBlockCache,
|
uchar *buffer;
|
||||||
vol->fsinfo_sector, 0, vol->bytes_per_sector, -1);
|
status_t status = block_cache_get_writable_etc(vol->fBlockCache,
|
||||||
if (buffer != NULL) {
|
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)) {
|
if ((read32(buffer,0) == 0x41615252) && (read32(buffer,0x1e4) == 0x61417272) && (read16(buffer,0x1fe) == 0xaa55)) {
|
||||||
//number of free clusters
|
//number of free clusters
|
||||||
buffer[0x1e8] = (vol->free_clusters & 0xff);
|
buffer[0x1e8] = (vol->free_clusters & 0xff);
|
||||||
@@ -929,8 +931,8 @@ update_fsinfo(nspace *vol)
|
|||||||
}
|
}
|
||||||
block_cache_put(vol->fBlockCache, vol->fsinfo_sector);
|
block_cache_put(vol->fBlockCache, vol->fsinfo_sector);
|
||||||
} else {
|
} else {
|
||||||
dprintf("update_fsinfo: error getting fsinfo sector %x\n",
|
dprintf("update_fsinfo: error getting fsinfo sector %x: %s\n",
|
||||||
vol->fsinfo_sector);
|
vol->fsinfo_sector, strerror(status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -940,14 +942,17 @@ static status_t
|
|||||||
get_fsinfo(nspace *vol, uint32 *free_count, uint32 *last_allocated)
|
get_fsinfo(nspace *vol, uint32 *free_count, uint32 *last_allocated)
|
||||||
{
|
{
|
||||||
uchar *buffer;
|
uchar *buffer;
|
||||||
int32 result;
|
status_t result;
|
||||||
|
|
||||||
if ((vol->fat_bits != 32) || (vol->fsinfo_sector == 0xffff))
|
if ((vol->fat_bits != 32) || (vol->fsinfo_sector == 0xffff))
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
if ((buffer = (uchar *)block_cache_get_etc(vol->fBlockCache, vol->fsinfo_sector, 0, vol->bytes_per_sector)) == NULL) {
|
result = block_cache_get_etc(vol->fBlockCache, vol->fsinfo_sector, 0,
|
||||||
dprintf("get_fsinfo: error getting fsinfo sector %x\n", vol->fsinfo_sector);
|
vol->bytes_per_sector, &buffer);
|
||||||
return EIO;
|
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)) {
|
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) {
|
if (vol->vol_entry == -1) {
|
||||||
// stored in the bpb
|
// stored in the bpb
|
||||||
uchar *buffer = block_cache_get_writable_etc(vol->fBlockCache, 0, 0,
|
uchar *buffer;
|
||||||
vol->bytes_per_sector, -1);
|
result = block_cache_get_writable_etc(vol->fBlockCache, 0,
|
||||||
if (buffer == NULL) {
|
0, vol->bytes_per_sector, -1, (void**)&buffer);
|
||||||
result = EIO;
|
if (result != B_OK)
|
||||||
goto bi;
|
goto bi;
|
||||||
}
|
|
||||||
if ((vol->sectors_per_fat == 0 && (buffer[0x42] != 0x29
|
if ((vol->sectors_per_fat == 0 && (buffer[0x42] != 0x29
|
||||||
|| strncmp((const char *)buffer + 0x47, vol->vol_label, 11)
|
|| strncmp((const char *)buffer + 0x47, vol->vol_label, 11)
|
||||||
!= 0))
|
!= 0))
|
||||||
|
|||||||
@@ -37,11 +37,15 @@ mirror_fats(nspace *vol, uint32 sector, uint8 *buffer)
|
|||||||
|
|
||||||
for (i = 0; i < vol->fat_count; i++) {
|
for (i = 0; i < vol->fat_count; i++) {
|
||||||
char *blockData;
|
char *blockData;
|
||||||
|
status_t status;
|
||||||
if (i == vol->active_fat)
|
if (i == vol->active_fat)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
blockData = block_cache_get_writable_etc(vol->fBlockCache, sector
|
status = block_cache_get_writable_etc(vol->fBlockCache,
|
||||||
+ i * vol->sectors_per_fat, 0, 1, -1);
|
sector + i * vol->sectors_per_fat, 0, 1, -1, &blockData);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
memcpy(blockData, buffer, vol->bytes_per_sector);
|
memcpy(blockData, buffer, vol->bytes_per_sector);
|
||||||
block_cache_put(vol->fBlockCache, sector + i * vol->sectors_per_fat);
|
block_cache_put(vol->fBlockCache, sector + i * vol->sectors_per_fat);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,11 +112,17 @@ iter_csi(struct csi *csi, int sectors)
|
|||||||
uint8 *
|
uint8 *
|
||||||
csi_get_block(struct csi *csi)
|
csi_get_block(struct csi *csi)
|
||||||
{
|
{
|
||||||
|
status_t status;
|
||||||
|
const void* block;
|
||||||
|
|
||||||
if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0)
|
if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return (uint8 *)block_cache_get_etc(csi->vol->fBlockCache,
|
status = block_cache_get_etc(csi->vol->fBlockCache,
|
||||||
csi_to_block(csi), 1, csi->vol->bytes_per_sector);
|
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++) {
|
for (i = block; i < block + sectors; i++) {
|
||||||
char *blockData = block_cache_get_writable_etc(csi->vol->fBlockCache, i,
|
char *blockData;
|
||||||
0, 1, -1);
|
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);
|
memcpy(blockData, buf, csi->vol->bytes_per_sector);
|
||||||
buf += csi->vol->bytes_per_sector;
|
buf += csi->vol->bytes_per_sector;
|
||||||
block_cache_put(csi->vol->fBlockCache, i);
|
block_cache_put(csi->vol->fBlockCache, i);
|
||||||
@@ -233,6 +243,7 @@ csi_write_blocks(struct csi *csi, uint8 *buffer, ssize_t len)
|
|||||||
status_t
|
status_t
|
||||||
csi_write_block(struct csi *csi, uint8 *buffer)
|
csi_write_block(struct csi *csi, uint8 *buffer)
|
||||||
{
|
{
|
||||||
|
status_t status;
|
||||||
off_t block;
|
off_t block;
|
||||||
char *blockData;
|
char *blockData;
|
||||||
|
|
||||||
@@ -242,8 +253,11 @@ csi_write_block(struct csi *csi, uint8 *buffer)
|
|||||||
if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0)
|
if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
blockData = block_cache_get_writable_etc(csi->vol->fBlockCache, block, 0, 1,
|
status = block_cache_get_writable_etc(csi->vol->fBlockCache, block, 0, 1,
|
||||||
-1);
|
-1, &blockData);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
memcpy(blockData, buffer, csi->vol->bytes_per_sector);
|
memcpy(blockData, buffer, csi->vol->bytes_per_sector);
|
||||||
block_cache_put(csi->vol->fBlockCache, block);
|
block_cache_put(csi->vol->fBlockCache, block);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com
|
* Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com
|
||||||
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net
|
* 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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _UDF_CACHED_BLOCK_H
|
#ifndef _UDF_CACHED_BLOCK_H
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
/*! \file CachedBlock.h
|
/*! \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
|
Axel Dörfler, axeld@pinc-software.de
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -20,10 +20,10 @@
|
|||||||
#include "UdfStructures.h"
|
#include "UdfStructures.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
class CachedBlock {
|
class CachedBlock {
|
||||||
public:
|
public:
|
||||||
CachedBlock(Volume *volume);
|
CachedBlock(Volume *volume);
|
||||||
CachedBlock(Volume *volume, off_t block);
|
|
||||||
CachedBlock(CachedBlock *cached);
|
CachedBlock(CachedBlock *cached);
|
||||||
~CachedBlock();
|
~CachedBlock();
|
||||||
|
|
||||||
@@ -35,11 +35,12 @@ public:
|
|||||||
inline void Keep();
|
inline void Keep();
|
||||||
inline void Unset();
|
inline void Unset();
|
||||||
|
|
||||||
inline uint8 *SetTo(off_t block);
|
inline status_t SetTo(off_t block);
|
||||||
inline uint8 *SetTo(off_t block, off_t base, size_t length);
|
inline status_t SetTo(off_t block, off_t base, size_t length);
|
||||||
inline uint8 *SetTo(long_address address);
|
inline status_t SetTo(long_address address);
|
||||||
template <class Accessor, class Descriptor>
|
template <class Accessor, class Descriptor>
|
||||||
inline uint8* SetTo(Accessor &accessor, Descriptor &descriptor);
|
inline status_t SetTo(Accessor &accessor,
|
||||||
|
Descriptor &descriptor);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8 *fBlock;
|
uint8 *fBlock;
|
||||||
@@ -59,17 +60,6 @@ CachedBlock::CachedBlock(Volume *volume)
|
|||||||
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
CachedBlock::CachedBlock(Volume *volume, off_t block)
|
|
||||||
:
|
|
||||||
fBlock(NULL),
|
|
||||||
fBlockNumber(0),
|
|
||||||
fVolume(volume)
|
|
||||||
{
|
|
||||||
SetTo(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline
|
|
||||||
CachedBlock::CachedBlock(CachedBlock *cached)
|
CachedBlock::CachedBlock(CachedBlock *cached)
|
||||||
:
|
:
|
||||||
fBlock(cached->fBlock),
|
fBlock(cached->fBlock),
|
||||||
@@ -97,43 +87,43 @@ CachedBlock::Keep()
|
|||||||
inline void
|
inline void
|
||||||
CachedBlock::Unset()
|
CachedBlock::Unset()
|
||||||
{
|
{
|
||||||
if (fBlock) {
|
if (fBlock != NULL) {
|
||||||
block_cache_put(fVolume->BlockCache(), fBlockNumber);
|
block_cache_put(fVolume->BlockCache(), fBlockNumber);
|
||||||
fBlock = NULL;
|
fBlock = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline uint8*
|
inline status_t
|
||||||
CachedBlock::SetTo(off_t block)
|
CachedBlock::SetTo(off_t block)
|
||||||
{
|
{
|
||||||
return SetTo(block, block, 1);
|
return SetTo(block, block, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline uint8*
|
inline status_t
|
||||||
CachedBlock::SetTo(off_t block, off_t base, size_t length)
|
CachedBlock::SetTo(off_t block, off_t base, size_t length)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
fBlockNumber = block;
|
fBlockNumber = block;
|
||||||
return fBlock = (uint8 *)block_cache_get_etc(fVolume->BlockCache(),
|
return block_cache_get_etc(fVolume->BlockCache(), block, base, length,
|
||||||
block, base, length);
|
(const void**)&fBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline uint8 *
|
inline status_t
|
||||||
CachedBlock::SetTo(long_address address)
|
CachedBlock::SetTo(long_address address)
|
||||||
{
|
{
|
||||||
off_t block;
|
off_t block;
|
||||||
if (fVolume->MapBlock(address, &block) == B_OK)
|
if (fVolume->MapBlock(address, &block) == B_OK)
|
||||||
return SetTo(block, block, 1);
|
return SetTo(block, block, 1);
|
||||||
else
|
|
||||||
return NULL;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class Accessor, class Descriptor>
|
template <class Accessor, class Descriptor>
|
||||||
inline uint8*
|
inline status_t
|
||||||
CachedBlock::SetTo(Accessor &accessor, Descriptor &descriptor)
|
CachedBlock::SetTo(Accessor &accessor, Descriptor &descriptor)
|
||||||
{
|
{
|
||||||
// Make a long_address out of the descriptor and call it a day
|
// 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);
|
return SetTo(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // _UDF_CACHED_BLOCK_H
|
#endif // _UDF_CACHED_BLOCK_H
|
||||||
|
|||||||
@@ -123,20 +123,24 @@ Icb::Icb(Volume *volume, long_address address)
|
|||||||
|
|
||||||
off_t block;
|
off_t block;
|
||||||
status_t status = fVolume->MapBlock(address, &block);
|
status_t status = fVolume->MapBlock(address, &block);
|
||||||
if (!status) {
|
if (status == B_OK) {
|
||||||
icb_header *header = (icb_header *)fData.SetTo(block);
|
status = fData.SetTo(block);
|
||||||
if (header->tag().id() == TAGID_FILE_ENTRY) {
|
if (status == B_OK) {
|
||||||
file_icb_entry *entry = (file_icb_entry *)header;
|
icb_header *header = (icb_header *)fData.Block();
|
||||||
PDUMP(entry);
|
if (header->tag().id() == TAGID_FILE_ENTRY) {
|
||||||
(void)entry; // warning death
|
file_icb_entry *entry = (file_icb_entry *)header;
|
||||||
} else if (header->tag().id() == TAGID_EXTENDED_FILE_ENTRY) {
|
PDUMP(entry);
|
||||||
extended_file_icb_entry *entry = (extended_file_icb_entry *)header;
|
(void)entry; // warning death
|
||||||
PDUMP(entry);
|
} else if (header->tag().id() == TAGID_EXTENDED_FILE_ENTRY) {
|
||||||
(void)entry; // warning death
|
extended_file_icb_entry *entry
|
||||||
} else {
|
= (extended_file_icb_entry *)header;
|
||||||
PDUMP(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()) {
|
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"
|
TRACE(("Icb::_Read: %ld bytes from disk block %" B_PRIdOFF " using"
|
||||||
" block_cache_get_etc()\n", readLength, diskBlock));
|
" block_cache_get_etc()\n", readLength, diskBlock));
|
||||||
uint8 *data = (uint8*)block_cache_get_etc(volume->BlockCache(),
|
const uint8 *data;
|
||||||
diskBlock, 0, readLength);
|
status = block_cache_get_etc(volume->BlockCache(),
|
||||||
if (data == NULL)
|
diskBlock, 0, readLength, (const void**)&data);
|
||||||
|
if (status != B_OK)
|
||||||
break;
|
break;
|
||||||
memcpy(buffer, data + blockOffset, readLength);
|
memcpy(buffer, data + blockOffset, readLength);
|
||||||
block_cache_put(volume->BlockCache(), diskBlock);
|
block_cache_put(volume->BlockCache(), diskBlock);
|
||||||
|
|||||||
+61
-38
@@ -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.
|
* 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
|
data. If \c true, the cache will be temporarily unlocked while the
|
||||||
block is read in.
|
block is read in.
|
||||||
*/
|
*/
|
||||||
static cached_block*
|
static status_t
|
||||||
get_cached_block(block_cache* cache, off_t blockNumber, bool* _allocated,
|
get_cached_block(block_cache* cache, off_t blockNumber, bool* _allocated,
|
||||||
bool readBlock = true)
|
bool readBlock, cached_block** _block)
|
||||||
{
|
{
|
||||||
ASSERT_LOCKED_MUTEX(&cache->lock);
|
ASSERT_LOCKED_MUTEX(&cache->lock);
|
||||||
|
|
||||||
if (blockNumber < 0 || blockNumber >= cache->max_blocks) {
|
if (blockNumber < 0 || blockNumber >= cache->max_blocks) {
|
||||||
panic("get_cached_block: invalid block number %" B_PRIdOFF " (max %" B_PRIdOFF ")",
|
panic("get_cached_block: invalid block number %" B_PRIdOFF " (max %" B_PRIdOFF ")",
|
||||||
blockNumber, cache->max_blocks - 1);
|
blockNumber, cache->max_blocks - 1);
|
||||||
return NULL;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
@@ -1917,7 +1917,7 @@ retry:
|
|||||||
// put block into cache
|
// put block into cache
|
||||||
block = cache->NewBlock(blockNumber);
|
block = cache->NewBlock(blockNumber);
|
||||||
if (block == NULL)
|
if (block == NULL)
|
||||||
return NULL;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
cache->hash->Insert(block);
|
cache->hash->Insert(block);
|
||||||
*_allocated = true;
|
*_allocated = true;
|
||||||
@@ -1951,7 +1951,7 @@ retry:
|
|||||||
|
|
||||||
TRACE_ALWAYS(("could not read block %" B_PRIdOFF ": bytesRead: %zd, error: %s\n",
|
TRACE_ALWAYS(("could not read block %" B_PRIdOFF ": bytesRead: %zd, error: %s\n",
|
||||||
blockNumber, bytesRead, strerror(errno)));
|
blockNumber, bytesRead, strerror(errno)));
|
||||||
return NULL;
|
return errno;
|
||||||
}
|
}
|
||||||
TB(Read(cache, block));
|
TB(Read(cache, block));
|
||||||
|
|
||||||
@@ -1961,7 +1961,8 @@ retry:
|
|||||||
block->ref_count++;
|
block->ref_count++;
|
||||||
block->last_accessed = system_time() / 1000000L;
|
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
|
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.
|
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,
|
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",
|
TRACE(("get_writable_cached_block(blockNumber = %" B_PRIdOFF ", transaction = %" B_PRId32 ")\n",
|
||||||
blockNumber, transactionID));
|
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) {
|
if (blockNumber < 0 || blockNumber >= cache->max_blocks) {
|
||||||
panic("get_writable_cached_block: invalid block number %" B_PRIdOFF " (max %" B_PRIdOFF ")",
|
panic("get_writable_cached_block: invalid block number %" B_PRIdOFF " (max %" B_PRIdOFF ")",
|
||||||
blockNumber, cache->max_blocks - 1);
|
blockNumber, cache->max_blocks - 1);
|
||||||
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allocated;
|
bool allocated;
|
||||||
cached_block* block = get_cached_block(cache, blockNumber, &allocated,
|
cached_block* block;
|
||||||
!cleared);
|
status_t status = get_cached_block(cache, blockNumber, &allocated,
|
||||||
if (block == NULL)
|
!cleared, &block);
|
||||||
return NULL;
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
if (block->busy_writing)
|
if (block->busy_writing)
|
||||||
wait_for_busy_writing_block(cache, block);
|
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));
|
TB(Get(cache, block));
|
||||||
return block->current_data;
|
*_block = block->current_data;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_transaction* transaction = block->transaction;
|
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 "
|
panic("get_writable_cached_block(): asked to get busy writable block "
|
||||||
"(transaction %" B_PRId32 ")\n", block->transaction->id);
|
"(transaction %" B_PRId32 ")\n", block->transaction->id);
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
return NULL;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
if (transaction == NULL && transactionID != -1) {
|
if (transaction == NULL && transactionID != -1) {
|
||||||
// get new transaction
|
// 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",
|
panic("get_writable_cached_block(): invalid transaction %" B_PRId32 "!\n",
|
||||||
transactionID);
|
transactionID);
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
return NULL;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
if (!transaction->open) {
|
if (!transaction->open) {
|
||||||
panic("get_writable_cached_block(): transaction already done!\n");
|
panic("get_writable_cached_block(): transaction already done!\n");
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
return NULL;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
block->transaction = transaction;
|
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"));
|
TB(Error(cache, blockNumber, "allocate original failed"));
|
||||||
FATAL(("could not allocate original_data\n"));
|
FATAL(("could not allocate original_data\n"));
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
return NULL;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_block_busy_reading(cache, block);
|
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"));
|
TB(Error(cache, blockNumber, "allocate parent failed"));
|
||||||
FATAL(("could not allocate parent\n"));
|
FATAL(("could not allocate parent\n"));
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
return NULL;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_block_busy_reading(cache, block);
|
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));
|
TB(Get(cache, block));
|
||||||
TB2(BlockData(cache, block, "get writable"));
|
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!
|
// TODO: this can be done better!
|
||||||
void* block = get_writable_cached_block(cache, blockNumber,
|
void* block;
|
||||||
blockNumber, 1, transaction, false);
|
status_t status = get_writable_cached_block(cache, blockNumber,
|
||||||
if (block != NULL) {
|
blockNumber, 1, transaction, false, &block);
|
||||||
|
if (status == B_OK) {
|
||||||
put_cached_block((block_cache*)_cache, blockNumber);
|
put_cached_block((block_cache*)_cache, blockNumber);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_ERROR;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void*
|
status_t
|
||||||
block_cache_get_writable_etc(void* _cache, off_t blockNumber, off_t base,
|
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;
|
block_cache* cache = (block_cache*)_cache;
|
||||||
MutexLocker locker(&cache->lock);
|
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!");
|
panic("tried to get writable block on a read-only cache!");
|
||||||
|
|
||||||
return get_writable_cached_block(cache, blockNumber, base, length,
|
return get_writable_cached_block(cache, blockNumber, base, length,
|
||||||
transaction, false);
|
transaction, false, _block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void*
|
void*
|
||||||
block_cache_get_writable(void* _cache, off_t blockNumber, int32 transaction)
|
block_cache_get_writable(void* _cache, off_t blockNumber, int32 transaction)
|
||||||
{
|
{
|
||||||
return block_cache_get_writable_etc(_cache, blockNumber,
|
void* block;
|
||||||
blockNumber, 1, transaction);
|
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)
|
if (cache->read_only)
|
||||||
panic("tried to get empty writable block on a read-only cache!");
|
panic("tried to get empty writable block on a read-only cache!");
|
||||||
|
|
||||||
return get_writable_cached_block((block_cache*)_cache, blockNumber,
|
void* block;
|
||||||
blockNumber, 1, transaction, true);
|
if (get_writable_cached_block((block_cache*)_cache, blockNumber,
|
||||||
|
blockNumber, 1, transaction, true, &block) == B_OK)
|
||||||
|
return block;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const void*
|
status_t
|
||||||
block_cache_get_etc(void* _cache, off_t blockNumber, off_t base, off_t length)
|
block_cache_get_etc(void* _cache, off_t blockNumber, off_t base, off_t length,
|
||||||
|
const void** _block)
|
||||||
{
|
{
|
||||||
block_cache* cache = (block_cache*)_cache;
|
block_cache* cache = (block_cache*)_cache;
|
||||||
MutexLocker locker(&cache->lock);
|
MutexLocker locker(&cache->lock);
|
||||||
bool allocated;
|
bool allocated;
|
||||||
|
|
||||||
cached_block* block = get_cached_block(cache, blockNumber, &allocated);
|
cached_block* block;
|
||||||
if (block == NULL)
|
status_t status = get_cached_block(cache, blockNumber, &allocated, true,
|
||||||
return NULL;
|
&block);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
#if BLOCK_CACHE_DEBUG_CHANGED
|
#if BLOCK_CACHE_DEBUG_CHANGED
|
||||||
if (block->compare == NULL)
|
if (block->compare == NULL)
|
||||||
@@ -3654,14 +3671,20 @@ block_cache_get_etc(void* _cache, off_t blockNumber, off_t base, off_t length)
|
|||||||
#endif
|
#endif
|
||||||
TB(Get(cache, block));
|
TB(Get(cache, block));
|
||||||
|
|
||||||
return block->current_data;
|
*_block = block->current_data;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const void*
|
const void*
|
||||||
block_cache_get(void* _cache, off_t blockNumber)
|
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.
|
* 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
|
not already in the cache. The block you retrieve may contain random
|
||||||
data.
|
data.
|
||||||
*/
|
*/
|
||||||
static cached_block*
|
static fssh_status_t
|
||||||
get_cached_block(block_cache* cache, fssh_off_t blockNumber, bool* _allocated,
|
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) {
|
if (blockNumber < 0 || blockNumber >= cache->max_blocks) {
|
||||||
fssh_panic("get_cached_block: invalid block number %" FSSH_B_PRIdOFF
|
fssh_panic("get_cached_block: invalid block number %" FSSH_B_PRIdOFF
|
||||||
" (max %" FSSH_B_PRIdOFF ")", blockNumber, cache->max_blocks - 1);
|
" (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,
|
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
|
// read block into cache
|
||||||
block = cache->NewBlock(blockNumber);
|
block = cache->NewBlock(blockNumber);
|
||||||
if (block == NULL)
|
if (block == NULL)
|
||||||
return NULL;
|
return FSSH_B_NO_MEMORY;
|
||||||
|
|
||||||
hash_insert(cache->hash, block);
|
hash_insert(cache->hash, block);
|
||||||
*_allocated = true;
|
*_allocated = true;
|
||||||
@@ -747,7 +747,7 @@ get_cached_block(block_cache* cache, fssh_off_t blockNumber, bool* _allocated,
|
|||||||
blockSize) < blockSize) {
|
blockSize) < blockSize) {
|
||||||
cache->RemoveBlock(block);
|
cache->RemoveBlock(block);
|
||||||
FATAL(("could not read block %" FSSH_B_PRIdOFF "\n", blockNumber));
|
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->ref_count++;
|
||||||
block->accessed++;
|
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
|
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.
|
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,
|
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",
|
TRACE(("get_writable_cached_block(blockNumber = %Ld, transaction = %d)\n",
|
||||||
blockNumber, transactionID));
|
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_panic("get_writable_cached_block: invalid block number %"
|
||||||
FSSH_B_PRIdOFF " (max %" FSSH_B_PRIdOFF ")", blockNumber,
|
FSSH_B_PRIdOFF " (max %" FSSH_B_PRIdOFF ")", blockNumber,
|
||||||
cache->max_blocks - 1);
|
cache->max_blocks - 1);
|
||||||
|
return FSSH_B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allocated;
|
bool allocated;
|
||||||
cached_block* block = get_cached_block(cache, blockNumber, &allocated,
|
cached_block* block;
|
||||||
!cleared);
|
fssh_status_t status = get_cached_block(cache, blockNumber, &allocated,
|
||||||
if (block == NULL)
|
!cleared, &block);
|
||||||
return NULL;
|
if (status != FSSH_B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
block->discard = false;
|
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;
|
block->is_dirty = true;
|
||||||
// mark the block as dirty
|
// mark the block as dirty
|
||||||
|
|
||||||
return block->current_data;
|
*_block = block->current_data;
|
||||||
|
return FSSH_B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_transaction* transaction = block->transaction;
|
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.
|
// 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);
|
fssh_panic("get_writable_cached_block(): asked to get busy writable block (transaction %d)\n", (int)transaction->id);
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
return NULL;
|
return FSSH_B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
if (transaction == NULL && transactionID != -1) {
|
if (transaction == NULL && transactionID != -1) {
|
||||||
// get new transaction
|
// 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",
|
fssh_panic("get_writable_cached_block(): invalid transaction %d!\n",
|
||||||
(int)transactionID);
|
(int)transactionID);
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
return NULL;
|
return FSSH_B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
if (!transaction->open) {
|
if (!transaction->open) {
|
||||||
fssh_panic("get_writable_cached_block(): transaction already done!\n");
|
fssh_panic("get_writable_cached_block(): transaction already done!\n");
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
return NULL;
|
return FSSH_B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
block->transaction = transaction;
|
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) {
|
if (block->original_data == NULL) {
|
||||||
FATAL(("could not allocate original_data\n"));
|
FATAL(("could not allocate original_data\n"));
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
return NULL;
|
return FSSH_B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
fssh_memcpy(block->original_data, block->current_data, cache->block_size);
|
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...
|
// TODO: maybe we should just continue the current transaction in this case...
|
||||||
FATAL(("could not allocate parent\n"));
|
FATAL(("could not allocate parent\n"));
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
return NULL;
|
return FSSH_B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
fssh_memcpy(block->parent_data, block->current_data, cache->block_size);
|
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;
|
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!");
|
fssh_panic("tried to make block writable on a read-only cache!");
|
||||||
|
|
||||||
// TODO: this can be done better!
|
// TODO: this can be done better!
|
||||||
void* block = get_writable_cached_block(cache, blockNumber,
|
void* block;
|
||||||
blockNumber, 1, transaction, false);
|
fssh_status_t status = get_writable_cached_block(cache, blockNumber,
|
||||||
if (block != NULL) {
|
blockNumber, 1, transaction, false, &block);
|
||||||
|
if (status == FSSH_B_OK) {
|
||||||
put_cached_block((block_cache*)_cache, blockNumber);
|
put_cached_block((block_cache*)_cache, blockNumber);
|
||||||
return FSSH_B_OK;
|
return FSSH_B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FSSH_B_ERROR;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void*
|
fssh_status_t
|
||||||
fssh_block_cache_get_writable_etc(void* _cache, fssh_off_t blockNumber, fssh_off_t base,
|
fssh_block_cache_get_writable_etc(void* _cache, fssh_off_t blockNumber,
|
||||||
fssh_off_t length, int32_t transaction)
|
fssh_off_t base, fssh_off_t length, int32_t transaction, void** _block)
|
||||||
{
|
{
|
||||||
block_cache* cache = (block_cache*)_cache;
|
block_cache* cache = (block_cache*)_cache;
|
||||||
MutexLocker locker(&cache->lock);
|
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!");
|
fssh_panic("tried to get writable block on a read-only cache!");
|
||||||
|
|
||||||
return get_writable_cached_block(cache, blockNumber, base, length,
|
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,
|
fssh_block_cache_get_writable(void* _cache, fssh_off_t blockNumber,
|
||||||
int32_t transaction)
|
int32_t transaction)
|
||||||
{
|
{
|
||||||
return fssh_block_cache_get_writable_etc(_cache, blockNumber,
|
void* block;
|
||||||
blockNumber, 1, transaction);
|
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)
|
if (cache->read_only)
|
||||||
fssh_panic("tried to get empty writable block on a read-only cache!");
|
fssh_panic("tried to get empty writable block on a read-only cache!");
|
||||||
|
|
||||||
return get_writable_cached_block((block_cache*)_cache, blockNumber,
|
void* block;
|
||||||
blockNumber, 1, transaction, true);
|
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_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;
|
block_cache* cache = (block_cache*)_cache;
|
||||||
MutexLocker locker(&cache->lock);
|
MutexLocker locker(&cache->lock);
|
||||||
bool allocated;
|
bool allocated;
|
||||||
|
|
||||||
cached_block* block = get_cached_block(cache, blockNumber, &allocated);
|
cached_block* block;
|
||||||
if (block == NULL)
|
fssh_status_t status = get_cached_block(cache, blockNumber, &allocated,
|
||||||
return NULL;
|
true, &block);
|
||||||
|
if (status != FSSH_B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
#ifdef DEBUG_CHANGED
|
#ifdef DEBUG_CHANGED
|
||||||
if (block->compare == NULL)
|
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)
|
if (block->compare != NULL)
|
||||||
memcpy(block->compare, block->current_data, cache->block_size);
|
memcpy(block->compare, block->current_data, cache->block_size);
|
||||||
#endif
|
#endif
|
||||||
return block->current_data;
|
*_block = block->current_data;
|
||||||
|
return FSSH_B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const void*
|
const void*
|
||||||
fssh_block_cache_get(void* _cache, fssh_off_t blockNumber)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user