Fix multilist_alloc_t bug (not triggerable in real operation but still a bug)
This commit is contained in:
@@ -2322,7 +2322,8 @@ void blockstore_heap_t::use_buffer_area(inode_t inode, uint64_t location, uint64
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(!(size % dsk->bitmap_granularity));
|
assert(!(size % dsk->bitmap_granularity));
|
||||||
buffer_alloc->use(location / dsk->bitmap_granularity, size / dsk->bitmap_granularity);
|
bool ok = buffer_alloc->use(location / dsk->bitmap_granularity, size / dsk->bitmap_granularity);
|
||||||
|
assert(ok);
|
||||||
buffer_area_used_space += size;
|
buffer_area_used_space += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ void multilist_alloc_t::print()
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void multilist_alloc_t::use(uint32_t pos, uint32_t size)
|
bool multilist_alloc_t::use(uint32_t pos, uint32_t size)
|
||||||
{
|
{
|
||||||
assert(pos+size <= count && size > 0);
|
assert(pos+size <= count && size > 0);
|
||||||
if (sizes[pos] <= 0)
|
if (sizes[pos] <= 0)
|
||||||
@@ -182,7 +182,8 @@ void multilist_alloc_t::use(uint32_t pos, uint32_t size)
|
|||||||
else
|
else
|
||||||
while (start > 0 && !sizes[start])
|
while (start > 0 && !sizes[start])
|
||||||
start--;
|
start--;
|
||||||
assert(sizes[start] >= size);
|
if (sizes[start] < size+(pos-start))
|
||||||
|
return false;
|
||||||
use_full(start);
|
use_full(start);
|
||||||
uint32_t full = sizes[start];
|
uint32_t full = sizes[start];
|
||||||
sizes[pos-1] = -pos+start;
|
sizes[pos-1] = -pos+start;
|
||||||
@@ -199,7 +200,8 @@ void multilist_alloc_t::use(uint32_t pos, uint32_t size)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(sizes[pos] >= size);
|
if (sizes[pos] < size)
|
||||||
|
return false;
|
||||||
use_full(pos);
|
use_full(pos);
|
||||||
if (sizes[pos] > size)
|
if (sizes[pos] > size)
|
||||||
{
|
{
|
||||||
@@ -214,12 +216,13 @@ void multilist_alloc_t::use(uint32_t pos, uint32_t size)
|
|||||||
#ifdef MULTILIST_TRACE
|
#ifdef MULTILIST_TRACE
|
||||||
print();
|
print();
|
||||||
#endif
|
#endif
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void multilist_alloc_t::use_full(uint32_t pos)
|
void multilist_alloc_t::use_full(uint32_t pos)
|
||||||
{
|
{
|
||||||
uint32_t prevsize = sizes[pos];
|
uint32_t prevsize = sizes[pos];
|
||||||
assert(prevsize);
|
assert(prevsize > 0);
|
||||||
assert(nexts[pos]);
|
assert(nexts[pos]);
|
||||||
uint32_t pi = (prevsize < maxn ? prevsize : maxn)-1;
|
uint32_t pi = (prevsize < maxn ? prevsize : maxn)-1;
|
||||||
if (heads[pi] == pos+1)
|
if (heads[pi] == pos+1)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ struct multilist_alloc_t
|
|||||||
bool is_free(uint32_t pos);
|
bool is_free(uint32_t pos);
|
||||||
uint32_t find(uint32_t size);
|
uint32_t find(uint32_t size);
|
||||||
void use_full(uint32_t pos);
|
void use_full(uint32_t pos);
|
||||||
void use(uint32_t pos, uint32_t size);
|
bool use(uint32_t pos, uint32_t size);
|
||||||
void do_free(uint32_t pos);
|
void do_free(uint32_t pos);
|
||||||
void free(uint32_t pos);
|
void free(uint32_t pos);
|
||||||
void verify();
|
void verify();
|
||||||
|
|||||||
@@ -1902,6 +1902,19 @@ void test_alloc_buffer()
|
|||||||
alloc.verify();
|
alloc.verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
multilist_alloc_t alloc(100, 10);
|
||||||
|
|
||||||
|
alloc.use(50, 10);
|
||||||
|
alloc.verify();
|
||||||
|
|
||||||
|
// 48, 5 overlaps with 50, 10 -> should fail to allocate
|
||||||
|
bool ok = alloc.use(48, 5);
|
||||||
|
assert(!ok);
|
||||||
|
|
||||||
|
alloc.verify();
|
||||||
|
}
|
||||||
|
|
||||||
blockstore_heap_t heap(&dsk, buffer_area.data());
|
blockstore_heap_t heap(&dsk, buffer_area.data());
|
||||||
heap.finish_recheck();
|
heap.finish_recheck();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user