* Fixed a bug introduced with big-endian fixes in r17557; the super block's blocks_per_ag

field was always 1, and therefore, the last allocation group could grow too large.
  Thanks to Samuel Rodriguez Perez for reporting the error (bfs_shell was crashing on
  larger images).
* Minor cleanup in BlockAllocator::_Initialize().


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21053 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-05-07 10:56:40 +00:00
parent fbe10cf294
commit 68f08f67f5
3 changed files with 29 additions and 22 deletions
@@ -1,9 +1,10 @@
/* BlockAllocator - block bitmap handling and allocation policies /*
*
* Copyright 2001-2007, Axel Dörfler, [email protected]. * Copyright 2001-2007, Axel Dörfler, [email protected].
* This file may be used under the terms of the MIT License. * This file may be used under the terms of the MIT License.
*/ */
//! block bitmap handling and allocation policies
#include "Debug.h" #include "Debug.h"
#include "BlockAllocator.h" #include "BlockAllocator.h"
@@ -451,11 +452,10 @@ BlockAllocator::_Initialize(BlockAllocator *allocator)
Volume *volume = allocator->fVolume; Volume *volume = allocator->fVolume;
uint32 blocks = allocator->fBlocksPerGroup; uint32 blocks = allocator->fBlocksPerGroup;
uint32 numBits = 8 * blocks * volume->BlockSize();
uint32 blockShift = volume->BlockShift(); uint32 blockShift = volume->BlockShift();
off_t freeBlocks = 0; off_t freeBlocks = 0;
uint32 *buffer = (uint32 *)malloc(numBits >> 3); uint32 *buffer = (uint32 *)malloc(blocks << blockShift);
if (buffer == NULL) { if (buffer == NULL) {
allocator->fLock.Unlock(); allocator->fLock.Unlock();
RETURN_ERROR(B_NO_MEMORY); RETURN_ERROR(B_NO_MEMORY);
@@ -463,36 +463,41 @@ BlockAllocator::_Initialize(BlockAllocator *allocator)
AllocationGroup *groups = allocator->fGroups; AllocationGroup *groups = allocator->fGroups;
off_t offset = 1; off_t offset = 1;
int32 num = allocator->fNumGroups; uint32 bitsPerGroup = 8 * (blocks << blockShift);
int32 numGroups = allocator->fNumGroups;
for (int32 i = 0; i < num; i++) { for (int32 i = 0; i < numGroups; i++) {
if (read_pos(volume->Device(), offset << blockShift, buffer, if (read_pos(volume->Device(), offset << blockShift, buffer,
blocks << blockShift) < B_OK) blocks << blockShift) < B_OK)
break; break;
// the last allocation group may contain less blocks than the others // the last allocation group may contain less blocks than the others
if (i == num - 1) { if (i == numGroups - 1) {
groups[i].fNumBits = volume->NumBlocks() - i * numBits; groups[i].fNumBits = volume->NumBlocks() - i * bitsPerGroup;
groups[i].fNumBlocks = 1 + ((groups[i].NumBits() - 1) >> (blockShift + 3)); groups[i].fNumBlocks = 1 + ((groups[i].NumBits() - 1) >> (blockShift + 3));
} else { } else {
groups[i].fNumBits = numBits; groups[i].fNumBits = bitsPerGroup;
groups[i].fNumBlocks = blocks; groups[i].fNumBlocks = blocks;
} }
groups[i].fStart = offset; groups[i].fStart = offset;
// finds all free ranges in this allocation group // finds all free ranges in this allocation group
int32 start = -1, range = 0; int32 start = -1, range = 0;
int32 size = groups[i].fNumBits, num = 0; int32 numBits = groups[i].fNumBits, bit = 0;
int32 count = (numBits + 31) / 32;
for (int32 k = 0;k < (size >> 2);k++) { for (int32 k = 0; k < count; k++) {
for (int32 j = 0; j < 32 && num < size; j++, num++) { for (int32 j = 0; j < 32 && bit < numBits; j++, bit++) {
if (buffer[k] & (1UL << j)) { if (buffer[k] & (1UL << j)) {
// block is in use
if (range > 0) { if (range > 0) {
groups[i].AddFreeRange(start, range); groups[i].AddFreeRange(start, range);
range = 0; range = 0;
} }
} else if (range++ == 0) } else if (range++ == 0) {
start = num; // block is free, start new free range
start = bit;
}
} }
} }
if (range) if (range)
@@ -1,9 +1,10 @@
/* Volume - BFS super block, mounting, etc. /*
* * Copyright 2001-2007, Axel Dörfler, [email protected].
* Copyright 2001-2006, Axel Dörfler, [email protected].
* This file may be used under the terms of the MIT License. * This file may be used under the terms of the MIT License.
*/ */
//! super block, mounting, etc.
#include "Debug.h" #include "Debug.h"
#include "Volume.h" #include "Volume.h"
@@ -233,7 +234,7 @@ disk_super_block::Initialize(const char *diskName, off_t numBlocks, uint32 block
} }
num_ags = HOST_ENDIAN_TO_BFS_INT32(numGroups); num_ags = HOST_ENDIAN_TO_BFS_INT32(numGroups);
blocks_per_ag = HOST_ENDIAN_TO_BFS_INT32(1); blocks_per_ag = HOST_ENDIAN_TO_BFS_INT32(blocksPerGroup);
ag_shift = HOST_ENDIAN_TO_BFS_INT32(groupShift); ag_shift = HOST_ENDIAN_TO_BFS_INT32(groupShift);
} }
@@ -1,9 +1,10 @@
/* Volume - BFS super block, mounting, etc. /*
* * Copyright 2001-2007, Axel Dörfler, [email protected]. All Rights Reserved.
* Copyright 2001-2006, Axel Dörfler, [email protected]. All Rights Reserved.
* This file may be used under the terms of the MIT License. * This file may be used under the terms of the MIT License.
*/ */
//! super block, mounting, etc.
#include "Debug.h" #include "Debug.h"
#include "Volume.h" #include "Volume.h"
@@ -223,7 +224,7 @@ disk_super_block::Initialize(const char *diskName, off_t numBlocks, uint32 block
} }
num_ags = HOST_ENDIAN_TO_BFS_INT32(numGroups); num_ags = HOST_ENDIAN_TO_BFS_INT32(numGroups);
blocks_per_ag = HOST_ENDIAN_TO_BFS_INT32(1); blocks_per_ag = HOST_ENDIAN_TO_BFS_INT32(blocksPerGroup);
ag_shift = HOST_ENDIAN_TO_BFS_INT32(groupShift); ag_shift = HOST_ENDIAN_TO_BFS_INT32(groupShift);
} }