From 9637baae5b1950a1716bd64c02deabf2c8da7109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sun, 12 Dec 2010 11:18:59 +0000 Subject: [PATCH] moved FindBlock() from Inode to DataStream git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39820 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/file_systems/ext2/DataStream.cpp | 129 +++++++++++++++++- .../kernel/file_systems/ext2/DataStream.h | 3 + .../kernel/file_systems/ext2/Inode.cpp | 124 +---------------- 3 files changed, 134 insertions(+), 122 deletions(-) diff --git a/src/add-ons/kernel/file_systems/ext2/DataStream.cpp b/src/add-ons/kernel/file_systems/ext2/DataStream.cpp index 04063c60cd..68267a4504 100644 --- a/src/add-ons/kernel/file_systems/ext2/DataStream.cpp +++ b/src/add-ons/kernel/file_systems/ext2/DataStream.cpp @@ -40,9 +40,10 @@ DataStream::DataStream(Volume* volume, ext2_data_stream* stream, fWaiting(0), fFreeStart(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 DataStream::Enlarge(Transaction& transaction, off_t& numBlocks) { diff --git a/src/add-ons/kernel/file_systems/ext2/DataStream.h b/src/add-ons/kernel/file_systems/ext2/DataStream.h index 58ad825ea0..9c39332f0b 100644 --- a/src/add-ons/kernel/file_systems/ext2/DataStream.h +++ b/src/add-ons/kernel/file_systems/ext2/DataStream.h @@ -22,6 +22,8 @@ public: off_t size); ~DataStream(); + status_t FindBlock(off_t offset, off_t& block, + uint32 *_count = NULL); status_t Enlarge(Transaction& transaction, off_t& numBlocks); status_t Shrink(Transaction& transaction, off_t& numBlocks); @@ -88,6 +90,7 @@ private: off_t fNumBlocks; uint32 fRemovedBlocks; + off_t fSize; }; #endif // DATASTREAM_H diff --git a/src/add-ons/kernel/file_systems/ext2/Inode.cpp b/src/add-ons/kernel/file_systems/ext2/Inode.cpp index 7c7ed57a07..ebe03262b3 100644 --- a/src/add-ons/kernel/file_systems/ext2/Inode.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Inode.cpp @@ -226,125 +226,8 @@ Inode::CheckPermissions(int accessMode) const status_t Inode::FindBlock(off_t offset, off_t& block, uint32 *_count) { - uint32 perBlock = fVolume->BlockSize() / 4; - uint32 perIndirectBlock = perBlock * perBlock; - 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; + DataStream stream(fVolume, &fNode.stream, Size()); + return stream.FindBlock(offset, block, _count); } @@ -525,7 +408,8 @@ Inode::InitDirectory(Transaction& transaction, Inode* parent) return status; off_t blockNum; - status = FindBlock(0, blockNum); + DataStream stream(fVolume, &fNode.stream, Size()); + status = stream.FindBlock(0, blockNum); if (status != B_OK) return status;