* Fixed the incorrect ASSERT that possibly dropped you into KDL while deleting

something (as reported by Marcus and Bruno on the mailing list).
* AllocationGroup::Allocate() would always invalidate the largest block if
  it did not cover the largest part of the group; now it only invalidates it
  if it has been cut before.
* Added small test app for the invalidation part.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28162 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-10-16 10:00:34 +00:00
parent a96b4beb84
commit 58a77fd3c9
3 changed files with 171 additions and 9 deletions

View File

@ -366,8 +366,7 @@ AllocationGroup::AddFreeRange(int32 start, int32 blocks)
status_t
AllocationGroup::Allocate(Transaction& transaction, uint16 start, int32 length)
{
if (start > fNumBits)
return B_ERROR;
ASSERT(start + length <= fNumBits);
// Update the allocation group info
// TODO: this info will be incorrect if something goes wrong later
@ -377,16 +376,22 @@ AllocationGroup::Allocate(Transaction& transaction, uint16 start, int32 length)
fFreeBits -= length;
if (fLargestValid) {
bool cut = false;
if (fLargestStart == start) {
// cut from start
fLargestStart += length;
fLargestLength -= length;
cut = true;
} else if (start > fLargestStart
&& start < fLargestStart + fLargestLength) {
// cut from end
fLargestLength = start - fLargestStart;
cut = true;
}
if (fLargestLength < fLargestStart
|| fLargestLength
< (int32)fNumBits - (fLargestStart + fLargestLength)) {
if (cut && (fLargestLength < fLargestStart
|| fLargestLength
< (int32)fNumBits - (fLargestStart + fLargestLength))) {
// might not be the largest block anymore
fLargestValid = false;
}
}
@ -430,8 +435,7 @@ AllocationGroup::Allocate(Transaction& transaction, uint16 start, int32 length)
status_t
AllocationGroup::Free(Transaction& transaction, uint16 start, int32 length)
{
if (start > fNumBits)
return B_ERROR;
ASSERT(start + length <= fNumBits);
// Update the allocation group info
// TODO: this info will be incorrect if something goes wrong later
@ -440,8 +444,8 @@ AllocationGroup::Free(Transaction& transaction, uint16 start, int32 length)
fFreeBits += length;
// The range to be freed cannot be part of the valid largest range
ASSERT(!fLargestValid || start < fLargestStart
|| start > fLargestStart + fLargestLength);
ASSERT(!fLargestValid || start + length <= fLargestStart
|| start > fLargestStart);
if (fLargestValid
&& (start + length == fLargestStart

View File

@ -1,5 +1,9 @@
SubDir HAIKU_TOP src tests add-ons kernel file_systems bfs ;
SimpleTest bfs_allocator_invalidate_largest :
bfs_allocator_invalidate_largest.cpp
;
SimpleTest bfs_attribute_iterator_test :
bfs_attribute_iterator_test.cpp
: be ;

View File

@ -0,0 +1,154 @@
/*
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int32_t fLargestStart = -1;
int32_t fLargestLength = -1;
bool fLargestValid = false;
int32_t fNumBits = 100;
void
allocate(uint16_t start, int32_t length)
{
if (start + length > fNumBits)
return;
if (fLargestValid) {
bool cut = false;
if (fLargestStart == start) {
// cut from start
fLargestStart += length;
fLargestLength -= length;
cut = true;
} else if (start > fLargestStart
&& start < fLargestStart + fLargestLength) {
// cut from end
fLargestLength = start - fLargestStart;
cut = true;
}
if (cut && (fLargestLength < fLargestStart
|| fLargestLength
< (int32_t)fNumBits - (fLargestStart + fLargestLength))) {
// might not be the largest block anymore
fLargestValid = false;
}
}
}
void
free(uint16_t start, int32_t length)
{
if (start + length > fNumBits)
return;
// The range to be freed cannot be part of the valid largest range
if (!(!fLargestValid || start + length <= fLargestStart
|| start > fLargestStart))
printf("ASSERT failed!\n");
if (fLargestValid
&& (start + length == fLargestStart
|| fLargestStart + fLargestLength == start
|| (start < fLargestStart && fLargestStart > fLargestLength)
|| (start > fLargestStart
&& (int32_t)fNumBits - (fLargestStart + fLargestLength)
> fLargestLength))) {
fLargestValid = false;
}
}
void
test(int32_t num, int32_t nextLargestStart, int32_t nextLargestLength,
bool nextLargestValid)
{
const char* error = NULL;
if (nextLargestValid != fLargestValid)
error = "valid differs";
else if (!nextLargestValid)
return;
if (nextLargestStart != fLargestStart)
error = "start differ";
else if (nextLargestLength != fLargestLength)
error = "length differs";
if (error == NULL)
return;
printf("%d: %s: is %d.%d%s, should be %d.%d%s\n", num, error, fLargestStart,
fLargestLength, fLargestValid ? "" : " (INVALID)", nextLargestStart,
nextLargestLength, nextLargestValid ? "" : " (INVALID)");
exit(1);
}
void
test_allocate(int32_t num, int32_t largestStart, int32_t largestLength,
int32_t start, int32_t length, int32_t nextLargestStart,
int32_t nextLargestLength, bool nextLargestValid)
{
fLargestStart = largestStart;
fLargestLength = largestLength;
fLargestValid = true;
printf("Test %d: %d.%d - allocate %d.%d\n", num, fLargestStart,
fLargestLength, start, length);
allocate(start, length);
test(num, nextLargestStart, nextLargestLength, nextLargestValid);
}
void
test_free(int32_t num, int32_t largestStart, int32_t largestLength, int32_t start,
int32_t length, int32_t nextLargestStart, int32_t nextLargestLength,
bool nextLargestValid)
{
fLargestStart = largestStart;
fLargestLength = largestLength;
fLargestValid = true;
printf("Test %d: %d.%d - free %d.%d\n", num, fLargestStart, fLargestLength,
start, length);
free(start, length);
test(num, nextLargestStart, nextLargestLength, nextLargestValid);
}
int
main(int argc, char** argv)
{
puts("------------- Allocate Tests -------------\n");
test_allocate(1, 40, 50, 20, 20, 40, 50, true); // touch start
test_allocate(2, 40, 50, 20, 19, 40, 50, true); // don't touch start
test_allocate(3, 40, 10, 40, 1, 41, 9, false); // cut start
test_allocate(4, 40, 50, 40, 1, 41, 49, true); // cut start
test_allocate(5, 40, 50, 90, 1, 40, 50, true); // touch end
test_allocate(6, 40, 50, 89, 1, 40, 49, true); // cut end
test_allocate(7, 40, 20, 59, 1, 40, 19, false); // cut end
test_allocate(8, 0, 51, 0, 1, 1, 50, true); // cut start
test_allocate(9, 0, 51, 0, 2, 2, 49, true); // cut start
test_allocate(10, 0, 51, 0, 3, 3, 48, false); // cut start
puts("------------- Free Tests -------------\n");
test_free(1, 40, 50, 20, 20, 40, 50, false); // touch start
test_free(2, 40, 50, 20, 19, 40, 50, true); // before start
test_free(3, 50, 40, 20, 19, 40, 50, false); // before start
test_free(4, 40, 40, 80, 20, 40, 80, false); // touch end
test_free(5, 40, 40, 81, 20, 40, 40, true); // after end
test_free(6, 40, 20, 60, 20, 40, 80, false); // touch end
test_free(7, 40, 20, 61, 20, 40, 80, false); // after end
test_free(8, 40, 20, 41, 20, 40, 80, false); // after end
return 0;
}