Fixed two bugs in the block allocator:

- the maximum number of blocks a block_run can cover is 65535 not 65536
- allocations over a block boundary in the block bitmap always failed due
  to a incorrectly handled status

Both bugs could prevent BFS to create the VM swap file which led BeOS to
stop booting under certain circumstances.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@989 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2002-09-07 02:44:42 +00:00
parent 9a82280a11
commit b98d9a335a
3 changed files with 29 additions and 15 deletions
@@ -162,8 +162,8 @@ AllocationGroup::AllocationGroup()
void void
AllocationGroup::AddFreeRange(int32 start, int32 blocks) AllocationGroup::AddFreeRange(int32 start, int32 blocks)
{ {
D(if (blocks > 512) //D(if (blocks > 512)
PRINT(("range of %ld blocks starting at %ld\n",blocks,start))); // PRINT(("range of %ld blocks starting at %ld\n",blocks,start)));
if (fFirstFree == -1) if (fFirstFree == -1)
fFirstFree = start; fFirstFree = start;
@@ -279,6 +279,9 @@ BlockAllocator::initialize(BlockAllocator *allocator)
status_t status_t
BlockAllocator::AllocateBlocks(Transaction *transaction,int32 group,uint16 start,uint16 maximum,uint16 minimum, block_run &run) BlockAllocator::AllocateBlocks(Transaction *transaction,int32 group,uint16 start,uint16 maximum,uint16 minimum, block_run &run)
{ {
if (maximum == 0)
return B_BAD_VALUE;
AllocationBlock cached(fVolume); AllocationBlock cached(fVolume);
Locker lock(fLock); Locker lock(fLock);
@@ -364,9 +367,9 @@ BlockAllocator::AllocateBlocks(Transaction *transaction,int32 group,uint16 start
// set the blocks in the previous block // set the blocks in the previous block
if (cached.SetTo(fGroups[group], block - 1) < B_OK) if (cached.SetTo(fGroups[group], block - 1) < B_OK)
cached.Allocate(rangeStart);
else
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
cached.Allocate(rangeStart);
} else { } else {
// just allocate the bits in the current block // just allocate the bits in the current block
cached.Allocate(rangeStart,numBlocks); cached.Allocate(rangeStart,numBlocks);
@@ -420,12 +423,24 @@ BlockAllocator::Allocate(Transaction *transaction,const Inode *inode, off_t numB
if (numBlocks > fGroups[0].fNumBits) if (numBlocks > fGroups[0].fNumBits)
numBlocks = fGroups[0].fNumBits; numBlocks = fGroups[0].fNumBits;
// since block_run.length is uint16, the largest number of blocks that
// can be covered by a block_run is 65535
// ToDo: if we drop compatibility, couldn't we do this any better?
// There are basically two possibilities:
// a) since a length of zero doesn't have any sense, take that for 65536 -
// but that could cause many problems (bugs) in other areas
// b) reduce the maximum amount of blocks per block_run, so that the remaining
// number of free blocks can be used in a useful manner (like 4 blocks) -
// but that would also reduce the maximum file size
if (numBlocks == 65536)
numBlocks = 65535;
// apply some allocation policies here (AllocateBlocks() will break them // apply some allocation policies here (AllocateBlocks() will break them
// if necessary) // if necessary)
uint16 group = inode->BlockRun().allocation_group; uint16 group = inode->BlockRun().allocation_group;
uint16 start = 0; uint16 start = 0;
// are there already allocated blocks? (then just allocate near the last) // are there already allocated blocks? (then just try to allocate near the last one)
if (inode->Size() > 0) { if (inode->Size() > 0) {
data_stream *data = &inode->Node()->data; data_stream *data = &inode->Node()->data;
// we currently don't care for when the data stream is // we currently don't care for when the data stream is
+2 -3
View File
@@ -1,4 +1,4 @@
BFS - ToDo, August 12th, 2002 BFS - ToDo, September 7th, 2002
----- -----
BlockAllocator BlockAllocator
@@ -11,9 +11,8 @@ BlockAllocator
DataStream DataStream
- growing/shrinking the stream size is not implemented for the double indirect range
- only files are trimmed back (in bfs_close()), but every inode has a preallocated stream... - only files are trimmed back (in bfs_close()), but every inode has a preallocated stream...
- merging of block_runs doesn't work between range/block boundaries - Inode::GrowStream(): merging of block_runs doesn't work between range/block boundaries
Queries Queries