* Fixed double indirect ranges again: I've messed them up when I tried to make
them more BeOS compatible while still keeping them somewhat flexible. * _GrowStream() did actually not check if the double indirect region was already filled up - this caused it to overwrite innocent memory. This fixes the bug Rudolf showed me on this laptop that happened while copying a large file. * Loosened file size restriction on a heavy fragmented disk: the indirect block does not require a minimum array size anymore; before, you just couldn't let a stream grow into the indirect range if it couldn't allocate NUM_ARRAY_BLOCKS (4) blocks in a row. This considerably reduced the maximum file size in this case. * Removed no longer valid TODO. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33675 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1583,12 +1583,13 @@ Inode::FillGapWithZeros(off_t pos, off_t newSize)
|
||||
*/
|
||||
status_t
|
||||
Inode::_AllocateBlockArray(Transaction& transaction, block_run& run,
|
||||
size_t length)
|
||||
size_t length, bool variableSize)
|
||||
{
|
||||
if (!run.IsZero())
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t status = fVolume->Allocate(transaction, this, length, run, length);
|
||||
status_t status = fVolume->Allocate(transaction, this, length, run,
|
||||
variableSize ? 1 : length);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
@@ -1708,9 +1709,6 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
||||
// okay, we have the needed blocks, so just distribute them to the
|
||||
// different ranges of the stream (direct, indirect & double indirect)
|
||||
|
||||
// TODO: if anything goes wrong here, we probably want to free the
|
||||
// blocks that couldn't be distributed into the stream!
|
||||
|
||||
blocksNeeded -= run.Length();
|
||||
// don't preallocate if the first allocation was already too small
|
||||
blocksRequested = blocksNeeded;
|
||||
@@ -1720,9 +1718,10 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
||||
if (data->Size() <= data->MaxDirectRange()) {
|
||||
// let's try to put them into the direct block range
|
||||
int32 free = 0;
|
||||
for (; free < NUM_DIRECT_BLOCKS; free++)
|
||||
for (; free < NUM_DIRECT_BLOCKS; free++) {
|
||||
if (data->direct[free].IsZero())
|
||||
break;
|
||||
}
|
||||
|
||||
if (free < NUM_DIRECT_BLOCKS) {
|
||||
// can we merge the last allocated run with the new one?
|
||||
@@ -1754,7 +1753,7 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
||||
// if there is no indirect block yet, create one
|
||||
if (data->indirect.IsZero()) {
|
||||
status = _AllocateBlockArray(transaction, data->indirect,
|
||||
NUM_ARRAY_BLOCKS);
|
||||
NUM_ARRAY_BLOCKS, true);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
@@ -1875,8 +1874,12 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
||||
while (run.length != 0) {
|
||||
// get the indirect array block
|
||||
if (array == NULL) {
|
||||
uint32 block = indirectIndex / runsPerBlock;
|
||||
if (block >= minimum)
|
||||
return EFBIG;
|
||||
|
||||
array = (block_run*)cached.SetTo(fVolume->ToBlock(
|
||||
data->double_indirect) + indirectIndex / runsPerBlock);
|
||||
data->double_indirect) + block);
|
||||
if (array == NULL)
|
||||
return B_IO_ERROR;
|
||||
}
|
||||
@@ -1903,13 +1906,13 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
||||
// insert the block_run into the array
|
||||
runs[index % runsPerBlock] = run;
|
||||
runs[index % runsPerBlock].length
|
||||
= HOST_ENDIAN_TO_BFS_INT16(NUM_ARRAY_BLOCKS);
|
||||
= HOST_ENDIAN_TO_BFS_INT16(minimum);
|
||||
|
||||
// alter the remaining block_run
|
||||
run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start()
|
||||
+ NUM_ARRAY_BLOCKS);
|
||||
+ minimum);
|
||||
run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length()
|
||||
- NUM_ARRAY_BLOCKS);
|
||||
- minimum);
|
||||
} while ((++index % runsPerBlock) != 0 && run.length);
|
||||
} while ((index % runsPerArray) != 0 && run.length);
|
||||
|
||||
|
||||
@@ -220,7 +220,8 @@ private:
|
||||
block_run* array, uint32 arrayLength,
|
||||
off_t size, off_t& offset, off_t& max);
|
||||
status_t _AllocateBlockArray(Transaction& transaction,
|
||||
block_run& run, size_t length);
|
||||
block_run& run, size_t length,
|
||||
bool variableSize = false);
|
||||
status_t _GrowStream(Transaction& transaction, off_t size);
|
||||
status_t _ShrinkStream(Transaction& transaction, off_t size);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user