File::GetFileVecs():
* Added debug output. * Rounding up the size argument could cause an overflow. Use uint64 and block indexes, now. * The iteration index wasn't incremented in the main loop. * The in-block index was ignored when filling the first vector. Shouldn't really matter since we pass back complete blocks only, so the file map should never supply an unaligned offset, but anyway. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37573 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
08e2a0556c
commit
5b3d789879
@ -253,34 +253,40 @@ status_t
|
||||
File::GetFileVecs(uint64 offset, size_t size, file_io_vec* vecs, size_t count,
|
||||
size_t& _count)
|
||||
{
|
||||
FUNCTION("offset: %" B_PRIu64 ", size: %" B_PRIuSIZE ", count: %" B_PRIuSIZE
|
||||
"\n", offset, size, count);
|
||||
|
||||
// Round size to block size, but restrict to file size. This semantics is
|
||||
// fine with the caller (the file map) and it will help avoiding partial
|
||||
// block I/O.
|
||||
uint32 inBlockOffset = offset % B_PAGE_SIZE;
|
||||
offset -= inBlockOffset;
|
||||
size = BLOCK_ROUND_UP(size + inBlockOffset);
|
||||
|
||||
uint64 fileSize = BLOCK_ROUND_UP(Size());
|
||||
if (offset >= fileSize) {
|
||||
uint64 firstBlock = offset / B_PAGE_SIZE;
|
||||
uint64 neededBlockCount = BLOCK_ROUND_UP((uint64)size + inBlockOffset)
|
||||
/ B_PAGE_SIZE;
|
||||
uint64 fileBlockCount = BLOCK_ROUND_UP(Size()) / B_PAGE_SIZE;
|
||||
|
||||
if (firstBlock >= fileBlockCount) {
|
||||
_count = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (offset + size > fileSize)
|
||||
size = fileSize - offset;
|
||||
|
||||
uint64 blockCount = fileSize / B_PAGE_SIZE;
|
||||
if (firstBlock + neededBlockCount > fileBlockCount)
|
||||
neededBlockCount = fileBlockCount - firstBlock;
|
||||
|
||||
// get the level infos
|
||||
int32 depth;
|
||||
LevelInfo* infos = _GetLevelInfos(blockCount, depth);
|
||||
LevelInfo* infos = _GetLevelInfos(fileBlockCount, depth);
|
||||
if (infos == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
ArrayDeleter<LevelInfo> infosDeleter(infos);
|
||||
|
||||
// prepare for the iteration
|
||||
uint64 firstBlock = offset / B_PAGE_SIZE;
|
||||
uint64 blockIndex = BlockIndex();
|
||||
|
||||
PRINT(" preparing iteration: firstBlock: %" B_PRIu64 ", blockIndex: %"
|
||||
B_PRIu64 "\n", firstBlock, blockIndex);
|
||||
|
||||
for (int32 i = 0; i < depth; i++) {
|
||||
LevelInfo& info = infos[i];
|
||||
if (!info.block.GetReadable(GetVolume(), blockIndex))
|
||||
@ -296,11 +302,14 @@ File::GetFileVecs(uint64 offset, size_t size, file_io_vec* vecs, size_t count,
|
||||
firstBlock -= (uint64)info.index << info.addressableShift;
|
||||
|
||||
blockIndex = info.blockData[info.index];
|
||||
|
||||
PRINT(" preparing level %" B_PRId32 ": index: %" B_PRId32
|
||||
", firstBlock: %" B_PRIu64 ", blockIndex: %" B_PRIu64 "\n", i,
|
||||
info.index, firstBlock, blockIndex);
|
||||
}
|
||||
|
||||
// and iterate
|
||||
int32 level = depth - 1;
|
||||
uint64 neededBlockCount = size / B_PAGE_SIZE;
|
||||
size_t countAdded = 0;
|
||||
|
||||
while (true) {
|
||||
@ -308,6 +317,9 @@ File::GetFileVecs(uint64 offset, size_t size, file_io_vec* vecs, size_t count,
|
||||
|
||||
if (info.index == (int32)kFileBlockMaxCount) {
|
||||
// end of block -- back track to next greater branch
|
||||
PRINT(" level: %" B_PRId32 ": index: %" B_PRId32 " -> back "
|
||||
"tracking\n", level, info.index);
|
||||
|
||||
level--;
|
||||
infos[level].index++;
|
||||
continue;
|
||||
@ -315,6 +327,9 @@ File::GetFileVecs(uint64 offset, size_t size, file_io_vec* vecs, size_t count,
|
||||
|
||||
blockIndex = info.blockData[info.index];
|
||||
|
||||
PRINT(" level: %" B_PRId32 ": index: %" B_PRId32 " -> blockIndex: %"
|
||||
B_PRIu64 "\n", level, info.index, blockIndex);
|
||||
|
||||
if (level < depth - 1) {
|
||||
// descend to next level
|
||||
level++;
|
||||
@ -327,6 +342,8 @@ File::GetFileVecs(uint64 offset, size_t size, file_io_vec* vecs, size_t count,
|
||||
continue;
|
||||
}
|
||||
|
||||
info.index++;
|
||||
|
||||
// add the block
|
||||
uint64 blockOffset = blockIndex * B_PAGE_SIZE;
|
||||
if (countAdded > 0
|
||||
@ -336,14 +353,23 @@ File::GetFileVecs(uint64 offset, size_t size, file_io_vec* vecs, size_t count,
|
||||
// the block continues where the previous block ends -- just extend
|
||||
// the vector
|
||||
vecs[countAdded - 1].length += B_PAGE_SIZE;
|
||||
|
||||
PRINT(" -> extended vector %" B_PRIuSIZE ": offset: %"
|
||||
B_PRIdOFF " size: %" B_PRIdOFF "\n", countAdded - 1,
|
||||
vecs[countAdded - 1].offset, vecs[countAdded - 1].length);
|
||||
} else {
|
||||
// we need a new block
|
||||
if (countAdded == count)
|
||||
break;
|
||||
|
||||
vecs[countAdded].offset = blockOffset;
|
||||
vecs[countAdded].length = B_PAGE_SIZE;
|
||||
vecs[countAdded].offset = blockOffset + inBlockOffset;
|
||||
vecs[countAdded].length = B_PAGE_SIZE - inBlockOffset;
|
||||
countAdded++;
|
||||
inBlockOffset = 0;
|
||||
|
||||
PRINT(" -> added vector %" B_PRIuSIZE ": offset: %"
|
||||
B_PRIdOFF " size: %" B_PRIdOFF "\n", countAdded - 1,
|
||||
vecs[countAdded - 1].offset, vecs[countAdded - 1].length);
|
||||
}
|
||||
|
||||
if (--neededBlockCount == 0)
|
||||
|
Loading…
Reference in New Issue
Block a user