mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-06 16:09:30 +00:00
Ext2FS: allocate_blocks allocates contiguous blocks (#1095)
This implementation uses the new helper method of Bitmap called find_longest_range_of_unset_bits. This method looks for the biggest range of contiguous bits unset in the bitmap and returns the start of the range back to the caller.
This commit is contained in:
parent
d847368c88
commit
da296f5865
41
AK/Bitmap.h
41
AK/Bitmap.h
|
@ -157,6 +157,46 @@ public:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int find_longest_range_of_unset_bits(int max_length, int& found_range_size) const
|
||||||
|
{
|
||||||
|
int first_index = find_first_unset();
|
||||||
|
if (first_index == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int free_region_start = first_index;
|
||||||
|
int free_region_size = 1;
|
||||||
|
|
||||||
|
int max_region_start = free_region_start;
|
||||||
|
int max_region_size = free_region_size;
|
||||||
|
|
||||||
|
// Let's try and find the best fit possible
|
||||||
|
for (int j = first_index + 1; j < m_size && free_region_size < max_length; j++) {
|
||||||
|
if (!get(j)) {
|
||||||
|
if (free_region_size == 0)
|
||||||
|
free_region_start = j;
|
||||||
|
free_region_size++;
|
||||||
|
} else {
|
||||||
|
if (max_region_size < free_region_size) {
|
||||||
|
max_region_size = free_region_size;
|
||||||
|
max_region_start = free_region_start;
|
||||||
|
}
|
||||||
|
free_region_start = 0;
|
||||||
|
free_region_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_region_size < free_region_size) {
|
||||||
|
max_region_size = free_region_size;
|
||||||
|
max_region_start = free_region_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
found_range_size = max_region_size;
|
||||||
|
if (max_region_size > 1)
|
||||||
|
return max_region_start;
|
||||||
|
// if the max free region size is one, then return the earliest one found
|
||||||
|
return first_index;
|
||||||
|
}
|
||||||
|
|
||||||
explicit Bitmap()
|
explicit Bitmap()
|
||||||
: m_size(0)
|
: m_size(0)
|
||||||
, m_owned(true)
|
, m_owned(true)
|
||||||
|
@ -181,7 +221,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int size_in_bytes() const { return ceil_div(m_size, 8); }
|
int size_in_bytes() const { return ceil_div(m_size, 8); }
|
||||||
|
|
||||||
u8* m_data { nullptr };
|
u8* m_data { nullptr };
|
||||||
|
|
|
@ -1080,12 +1080,49 @@ Vector<Ext2FS::BlockIndex> Ext2FS::allocate_blocks(GroupIndex preferred_group_in
|
||||||
dbg() << "Ext2FS: allocate_blocks:";
|
dbg() << "Ext2FS: allocate_blocks:";
|
||||||
#endif
|
#endif
|
||||||
blocks.ensure_capacity(count);
|
blocks.ensure_capacity(count);
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
auto block_index = allocate_block(preferred_group_index);
|
bool found_a_group = false;
|
||||||
blocks.unchecked_append(block_index);
|
GroupIndex group_index = preferred_group_index;
|
||||||
|
|
||||||
|
if (!group_descriptor(preferred_group_index).bg_free_blocks_count) {
|
||||||
|
group_index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (blocks.size() < count) {
|
||||||
|
if (group_descriptor(group_index).bg_free_blocks_count) {
|
||||||
|
found_a_group = true;
|
||||||
|
} else {
|
||||||
|
if (group_index == preferred_group_index)
|
||||||
|
group_index = 1;
|
||||||
|
for (; group_index < m_block_group_count; ++group_index) {
|
||||||
|
if (group_descriptor(group_index).bg_free_blocks_count) {
|
||||||
|
found_a_group = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(found_a_group);
|
||||||
|
auto& bgd = group_descriptor(group_index);
|
||||||
|
auto& cached_bitmap = get_bitmap_block(bgd.bg_block_bitmap);
|
||||||
|
|
||||||
|
int blocks_in_group = min(blocks_per_group(), super_block().s_blocks_count);
|
||||||
|
auto block_bitmap = Bitmap::wrap(cached_bitmap.buffer.data(), blocks_in_group);
|
||||||
|
|
||||||
|
BlockIndex first_block_in_group = (group_index - 1) * blocks_per_group() + first_block_index();
|
||||||
|
int free_region_size = 0;
|
||||||
|
int first_unset_bit_index = block_bitmap.find_longest_range_of_unset_bits(count - blocks.size(), free_region_size);
|
||||||
|
ASSERT(first_unset_bit_index != -1);
|
||||||
#ifdef EXT2_DEBUG
|
#ifdef EXT2_DEBUG
|
||||||
dbg() << " > " << block_index;
|
dbg() << "Ext2FS: allocating free region of size: " << free_region_size << "[" << group_index << "]";
|
||||||
#endif
|
#endif
|
||||||
|
for (int i = 0; i < free_region_size; ++i) {
|
||||||
|
BlockIndex block_index = (unsigned)(first_unset_bit_index + i) + first_block_in_group;
|
||||||
|
set_block_allocation_state(block_index, true);
|
||||||
|
blocks.unchecked_append(block_index);
|
||||||
|
#ifdef EXT2_DEBUG
|
||||||
|
dbg() << " allocated > " << block_index;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(blocks.size() == count);
|
ASSERT(blocks.size() == count);
|
||||||
|
|
Loading…
Reference in a new issue