Remap without intermediate hashmap

This commit is contained in:
Vitaliy Filippov
2025-12-02 01:52:12 +03:00
parent ec8527c89d
commit 82f5fb7edd
+27 -43
View File
@@ -836,12 +836,6 @@ heap_entry_t *blockstore_heap_t::read_entry(object_id oid)
return obj;
}
struct heap_defrag_remap_t
{
object_id oid;
uint64_t new_pos;
};
void blockstore_heap_t::defragment_block(uint32_t block_num)
{
auto & inf = block_info[block_num];
@@ -851,7 +845,6 @@ void blockstore_heap_t::defragment_block(uint32_t block_num)
uint8_t *old = inf.data;
uint8_t *cur = new_data;
uint32_t removed_garbage = 0;
robin_hood::unordered_flat_map<uint64_t, heap_defrag_remap_t> remap;
while (old <= end-2)
{
heap_entry_t *obj = (heap_entry_t *)old;
@@ -882,9 +875,35 @@ void blockstore_heap_t::defragment_block(uint32_t block_num)
// live entry, we need to change linked list pointer(s) to it
// but the change should be applied carefully, after copying all entries,
// because they may reference each other
uint64_t block_start = entry_pos(block_num, 0);
uint64_t old_pos = entry_pos(block_num, old - inf.data);
uint64_t new_pos = entry_pos(block_num, ((uint8_t*)new_obj - new_data));
remap[old_pos] = (heap_defrag_remap_t){ .oid = oid, new_pos = new_pos };
auto & idx = block_index[get_pg_id(oid.inode, oid.stripe)][oid.inode][oid.stripe];
if (idx.pos == old_pos)
{
idx.pos = new_pos;
}
else
{
// entry is already moved if it's >= block_start and <= old_pos
heap_entry_t *wr = idx.pos >= block_start && idx.pos <= old_pos
? (heap_entry_t*)(new_data + (idx.pos % dsk->meta_block_size) - 1)
: entry_from_pos(idx.pos);
while (true)
{
assert(!(wr->prev_pos & GARBAGE_BIT));
if (!wr->prev_pos)
break;
if (wr->prev_pos == old_pos)
{
wr->prev_pos = new_pos;
break;
}
wr = wr->prev_pos >= block_start && wr->prev_pos <= old_pos
? (heap_entry_t*)(new_data + (wr->prev_pos % dsk->meta_block_size) - 1)
: entry_from_pos(wr->prev_pos);
}
}
}
memcpy(cur, obj, obj->size);
cur += obj->size;
@@ -896,41 +915,6 @@ void blockstore_heap_t::defragment_block(uint32_t block_num)
*((uint16_t*)cur) = FREE_SPACE_BIT | (dsk->meta_block_size-(cur-new_data));
memset(cur+2, 0, dsk->meta_block_size-(cur-new_data)-2);
}
for (auto rp_it = remap.begin(); rp_it != remap.end(); rp_it++)
{
auto oid = rp_it->second.oid;
if (!rp_it->second.new_pos)
{
// Remap each object only once
continue;
}
auto & idx = block_index[get_pg_id(oid.inode, oid.stripe)][oid.inode][oid.stripe];
auto new_it = remap.find(idx.pos);
heap_entry_t *wr = NULL;
if (new_it != remap.end())
{
idx.pos = new_it->second.new_pos;
wr = (heap_entry_t*)(new_data + (new_it->second.new_pos % dsk->meta_block_size) - 1); // like entry_from_pos
new_it->second.new_pos = 0;
}
else
wr = entry_from_pos(idx.pos);
while (wr)
{
assert(!(wr->prev_pos & GARBAGE_BIT));
if (!wr->prev_pos)
break;
new_it = remap.find(wr->prev_pos);
if (new_it != remap.end())
{
wr->prev_pos = new_it->second.new_pos;
wr = (heap_entry_t*)(new_data + (new_it->second.new_pos % dsk->meta_block_size) - 1); // like entry_from_pos
new_it->second.new_pos = 0;
}
else
wr = entry_from_pos(wr->prev_pos);
}
}
free(inf.data);
modify_alloc(block_num, [&](heap_block_info_t & inf)
{