moved FindBlock() from Inode to DataStream
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39820 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -40,9 +40,10 @@ DataStream::DataStream(Volume* volume, ext2_data_stream* stream,
|
|||||||
fWaiting(0),
|
fWaiting(0),
|
||||||
fFreeStart(0),
|
fFreeStart(0),
|
||||||
fFreeCount(0),
|
fFreeCount(0),
|
||||||
fRemovedBlocks(0)
|
fRemovedBlocks(0),
|
||||||
|
fSize(size)
|
||||||
{
|
{
|
||||||
fNumBlocks = size == 0 ? 0 : (size - 1) / kBlockSize + 1;
|
fNumBlocks = size == 0 ? 0 : ((size - 1) >> fVolume->BlockShift()) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -51,6 +52,130 @@ DataStream::~DataStream()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DataStream::FindBlock(off_t offset, off_t& block, uint32 *_count)
|
||||||
|
{
|
||||||
|
uint32 index = offset >> fVolume->BlockShift();
|
||||||
|
|
||||||
|
if (offset >= fSize) {
|
||||||
|
TRACE("FindBlock: offset larger than inode size\n");
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: we could return the size of the sparse range, as this might be more
|
||||||
|
// than just a block
|
||||||
|
|
||||||
|
if (index < EXT2_DIRECT_BLOCKS) {
|
||||||
|
// direct blocks
|
||||||
|
block = B_LENDIAN_TO_HOST_INT32(fStream->direct[index]);
|
||||||
|
ASSERT(block != 0);
|
||||||
|
if (_count) {
|
||||||
|
*_count = 1;
|
||||||
|
uint32 nextBlock = block;
|
||||||
|
while (++index < EXT2_DIRECT_BLOCKS
|
||||||
|
&& fStream->direct[index] == ++nextBlock)
|
||||||
|
(*_count)++;
|
||||||
|
}
|
||||||
|
} else if ((index -= EXT2_DIRECT_BLOCKS) < kIndirectsPerBlock) {
|
||||||
|
// indirect blocks
|
||||||
|
CachedBlock cached(fVolume);
|
||||||
|
uint32* indirectBlocks = (uint32*)cached.SetTo(B_LENDIAN_TO_HOST_INT32(
|
||||||
|
fStream->indirect));
|
||||||
|
if (indirectBlocks == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
block = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index]);
|
||||||
|
ASSERT(block != 0);
|
||||||
|
if (_count) {
|
||||||
|
*_count = 1;
|
||||||
|
uint32 nextBlock = block;
|
||||||
|
while (++index < kIndirectsPerBlock
|
||||||
|
&& indirectBlocks[index] == ++nextBlock)
|
||||||
|
(*_count)++;
|
||||||
|
}
|
||||||
|
} else if ((index -= kIndirectsPerBlock) < kIndirectsPerBlock2) {
|
||||||
|
// double indirect blocks
|
||||||
|
CachedBlock cached(fVolume);
|
||||||
|
uint32* indirectBlocks = (uint32*)cached.SetTo(B_LENDIAN_TO_HOST_INT32(
|
||||||
|
fStream->double_indirect));
|
||||||
|
if (indirectBlocks == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
uint32 indirectIndex = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index
|
||||||
|
/ kIndirectsPerBlock]);
|
||||||
|
if (indirectIndex == 0) {
|
||||||
|
// a sparse indirect block
|
||||||
|
block = 0;
|
||||||
|
} else {
|
||||||
|
indirectBlocks = (uint32*)cached.SetTo(indirectIndex);
|
||||||
|
if (indirectBlocks == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
block = B_LENDIAN_TO_HOST_INT32(
|
||||||
|
indirectBlocks[index & (kIndirectsPerBlock - 1)]);
|
||||||
|
if (_count) {
|
||||||
|
*_count = 1;
|
||||||
|
uint32 nextBlock = block;
|
||||||
|
while (((++index & (kIndirectsPerBlock - 1)) != 0)
|
||||||
|
&& indirectBlocks[index & (kIndirectsPerBlock - 1)]
|
||||||
|
== ++nextBlock)
|
||||||
|
(*_count)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(block != 0);
|
||||||
|
} else if ((index -= kIndirectsPerBlock2) < kIndirectsPerBlock3) {
|
||||||
|
// triple indirect blocks
|
||||||
|
CachedBlock cached(fVolume);
|
||||||
|
uint32* indirectBlocks = (uint32*)cached.SetTo(B_LENDIAN_TO_HOST_INT32(
|
||||||
|
fStream->triple_indirect));
|
||||||
|
if (indirectBlocks == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
uint32 indirectIndex = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index
|
||||||
|
/ kIndirectsPerBlock2]);
|
||||||
|
if (indirectIndex == 0) {
|
||||||
|
// a sparse indirect block
|
||||||
|
block = 0;
|
||||||
|
} else {
|
||||||
|
indirectBlocks = (uint32*)cached.SetTo(indirectIndex);
|
||||||
|
if (indirectBlocks == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
indirectIndex = B_LENDIAN_TO_HOST_INT32(
|
||||||
|
indirectBlocks[(index / kIndirectsPerBlock) & (kIndirectsPerBlock - 1)]);
|
||||||
|
if (indirectIndex == 0) {
|
||||||
|
// a sparse indirect block
|
||||||
|
block = 0;
|
||||||
|
} else {
|
||||||
|
indirectBlocks = (uint32*)cached.SetTo(indirectIndex);
|
||||||
|
if (indirectBlocks == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
block = B_LENDIAN_TO_HOST_INT32(
|
||||||
|
indirectBlocks[index & (kIndirectsPerBlock - 1)]);
|
||||||
|
if (_count) {
|
||||||
|
*_count = 1;
|
||||||
|
uint32 nextBlock = block;
|
||||||
|
while (((++index & (kIndirectsPerBlock - 1)) != 0)
|
||||||
|
&& indirectBlocks[index & (kIndirectsPerBlock - 1)]
|
||||||
|
== ++nextBlock)
|
||||||
|
(*_count)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(block != 0);
|
||||||
|
} else {
|
||||||
|
// Outside of the possible data stream
|
||||||
|
dprintf("ext2: block outside datastream!\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("inode %Ld: FindBlock(offset %lld): %lld %ld\n", ID(), offset, block,
|
||||||
|
_count != NULL ? *_count : 1);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DataStream::Enlarge(Transaction& transaction, off_t& numBlocks)
|
DataStream::Enlarge(Transaction& transaction, off_t& numBlocks)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ public:
|
|||||||
off_t size);
|
off_t size);
|
||||||
~DataStream();
|
~DataStream();
|
||||||
|
|
||||||
|
status_t FindBlock(off_t offset, off_t& block,
|
||||||
|
uint32 *_count = NULL);
|
||||||
status_t Enlarge(Transaction& transaction, off_t& numBlocks);
|
status_t Enlarge(Transaction& transaction, off_t& numBlocks);
|
||||||
status_t Shrink(Transaction& transaction, off_t& numBlocks);
|
status_t Shrink(Transaction& transaction, off_t& numBlocks);
|
||||||
|
|
||||||
@@ -88,6 +90,7 @@ private:
|
|||||||
|
|
||||||
off_t fNumBlocks;
|
off_t fNumBlocks;
|
||||||
uint32 fRemovedBlocks;
|
uint32 fRemovedBlocks;
|
||||||
|
off_t fSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DATASTREAM_H
|
#endif // DATASTREAM_H
|
||||||
|
|||||||
@@ -226,125 +226,8 @@ Inode::CheckPermissions(int accessMode) const
|
|||||||
status_t
|
status_t
|
||||||
Inode::FindBlock(off_t offset, off_t& block, uint32 *_count)
|
Inode::FindBlock(off_t offset, off_t& block, uint32 *_count)
|
||||||
{
|
{
|
||||||
uint32 perBlock = fVolume->BlockSize() / 4;
|
DataStream stream(fVolume, &fNode.stream, Size());
|
||||||
uint32 perIndirectBlock = perBlock * perBlock;
|
return stream.FindBlock(offset, block, _count);
|
||||||
uint32 index = offset >> fVolume->BlockShift();
|
|
||||||
|
|
||||||
if (offset >= Size()) {
|
|
||||||
TRACE("FindBlock: offset larger than inode size\n");
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: we could return the size of the sparse range, as this might be more
|
|
||||||
// than just a block
|
|
||||||
|
|
||||||
if (index < EXT2_DIRECT_BLOCKS) {
|
|
||||||
// direct blocks
|
|
||||||
block = B_LENDIAN_TO_HOST_INT32(Node().stream.direct[index]);
|
|
||||||
ASSERT(block != 0);
|
|
||||||
if (_count) {
|
|
||||||
*_count = 1;
|
|
||||||
uint32 nextBlock = block;
|
|
||||||
while (++index < EXT2_DIRECT_BLOCKS
|
|
||||||
&& Node().stream.direct[index] == ++nextBlock)
|
|
||||||
(*_count)++;
|
|
||||||
}
|
|
||||||
} else if ((index -= EXT2_DIRECT_BLOCKS) < perBlock) {
|
|
||||||
// indirect blocks
|
|
||||||
CachedBlock cached(fVolume);
|
|
||||||
uint32* indirectBlocks = (uint32*)cached.SetTo(B_LENDIAN_TO_HOST_INT32(
|
|
||||||
Node().stream.indirect));
|
|
||||||
if (indirectBlocks == NULL)
|
|
||||||
return B_IO_ERROR;
|
|
||||||
|
|
||||||
block = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index]);
|
|
||||||
ASSERT(block != 0);
|
|
||||||
if (_count) {
|
|
||||||
*_count = 1;
|
|
||||||
uint32 nextBlock = block;
|
|
||||||
while (++index < perBlock
|
|
||||||
&& indirectBlocks[index] == ++nextBlock)
|
|
||||||
(*_count)++;
|
|
||||||
}
|
|
||||||
} else if ((index -= perBlock) < perIndirectBlock) {
|
|
||||||
// double indirect blocks
|
|
||||||
CachedBlock cached(fVolume);
|
|
||||||
uint32* indirectBlocks = (uint32*)cached.SetTo(B_LENDIAN_TO_HOST_INT32(
|
|
||||||
Node().stream.double_indirect));
|
|
||||||
if (indirectBlocks == NULL)
|
|
||||||
return B_IO_ERROR;
|
|
||||||
|
|
||||||
uint32 indirectIndex
|
|
||||||
= B_LENDIAN_TO_HOST_INT32(indirectBlocks[index / perBlock]);
|
|
||||||
if (indirectIndex == 0) {
|
|
||||||
// a sparse indirect block
|
|
||||||
block = 0;
|
|
||||||
} else {
|
|
||||||
indirectBlocks = (uint32*)cached.SetTo(indirectIndex);
|
|
||||||
if (indirectBlocks == NULL)
|
|
||||||
return B_IO_ERROR;
|
|
||||||
|
|
||||||
block = B_LENDIAN_TO_HOST_INT32(
|
|
||||||
indirectBlocks[index & (perBlock - 1)]);
|
|
||||||
if (_count) {
|
|
||||||
*_count = 1;
|
|
||||||
uint32 nextBlock = block;
|
|
||||||
while (((++index & (perBlock - 1)) != 0)
|
|
||||||
&& indirectBlocks[index & (perBlock - 1)] == ++nextBlock)
|
|
||||||
(*_count)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSERT(block != 0);
|
|
||||||
} else if ((index -= perIndirectBlock) / perBlock < perIndirectBlock) {
|
|
||||||
// triple indirect blocks
|
|
||||||
CachedBlock cached(fVolume);
|
|
||||||
uint32* indirectBlocks = (uint32*)cached.SetTo(B_LENDIAN_TO_HOST_INT32(
|
|
||||||
Node().stream.triple_indirect));
|
|
||||||
if (indirectBlocks == NULL)
|
|
||||||
return B_IO_ERROR;
|
|
||||||
|
|
||||||
uint32 indirectIndex
|
|
||||||
= B_LENDIAN_TO_HOST_INT32(indirectBlocks[index / perIndirectBlock]);
|
|
||||||
if (indirectIndex == 0) {
|
|
||||||
// a sparse indirect block
|
|
||||||
block = 0;
|
|
||||||
} else {
|
|
||||||
indirectBlocks = (uint32*)cached.SetTo(indirectIndex);
|
|
||||||
if (indirectBlocks == NULL)
|
|
||||||
return B_IO_ERROR;
|
|
||||||
|
|
||||||
indirectIndex = B_LENDIAN_TO_HOST_INT32(
|
|
||||||
indirectBlocks[(index / perBlock) & (perBlock - 1)]);
|
|
||||||
if (indirectIndex == 0) {
|
|
||||||
// a sparse indirect block
|
|
||||||
block = 0;
|
|
||||||
} else {
|
|
||||||
indirectBlocks = (uint32*)cached.SetTo(indirectIndex);
|
|
||||||
if (indirectBlocks == NULL)
|
|
||||||
return B_IO_ERROR;
|
|
||||||
|
|
||||||
block = B_LENDIAN_TO_HOST_INT32(
|
|
||||||
indirectBlocks[index & (perBlock - 1)]);
|
|
||||||
if (_count) {
|
|
||||||
*_count = 1;
|
|
||||||
uint32 nextBlock = block;
|
|
||||||
while (((++index & (perBlock - 1)) != 0)
|
|
||||||
&& indirectBlocks[index & (perBlock - 1)]
|
|
||||||
== ++nextBlock)
|
|
||||||
(*_count)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSERT(block != 0);
|
|
||||||
} else {
|
|
||||||
// Outside of the possible data stream
|
|
||||||
dprintf("ext2: block outside datastream!\n");
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("inode %Ld: FindBlock(offset %lld): %lld %ld\n", ID(), offset, block,
|
|
||||||
_count != NULL ? *_count : 1);
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -525,7 +408,8 @@ Inode::InitDirectory(Transaction& transaction, Inode* parent)
|
|||||||
return status;
|
return status;
|
||||||
|
|
||||||
off_t blockNum;
|
off_t blockNum;
|
||||||
status = FindBlock(0, blockNum);
|
DataStream stream(fVolume, &fNode.stream, Size());
|
||||||
|
status = stream.FindBlock(0, blockNum);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user