Use the same "inflight" queue to track compaction

This commit is contained in:
Vitaliy Filippov
2025-12-02 01:52:12 +03:00
parent 5dc0b42146
commit 3ba3eed0cf
9 changed files with 207 additions and 74 deletions
+40 -12
View File
@@ -68,14 +68,14 @@ int journal_flusher_t::get_active()
return active_flushers; return active_flushers;
} }
uint64_t journal_flusher_t::get_counter() uint64_t journal_flusher_t::get_compact_counter()
{ {
return compact_counter; return compact_counter;
} }
bool journal_flusher_t::is_active() bool journal_flusher_t::is_active()
{ {
return active_flushers > 0 || bs->heap->get_compact_queue_size() > (force_start > 0 ? 0 : bs->flusher_start_threshold); return active_flushers > 0 || force_start > 0 || bs->heap->get_compact_queue_size() > bs->flusher_start_threshold;
} }
void journal_flusher_t::request_trim() void journal_flusher_t::request_trim()
@@ -158,10 +158,23 @@ bool journal_flusher_co::loop()
else if (wait_state == 15) goto resume_15; else if (wait_state == 15) goto resume_15;
else if (wait_state == 16) goto resume_16; else if (wait_state == 16) goto resume_16;
else if (wait_state == 17) goto resume_17; else if (wait_state == 17) goto resume_17;
else if (wait_state == 18) goto resume_18;
else if (wait_state == 19) goto resume_19;
else if (wait_state == 20) goto resume_20;
else if (wait_state == 21) goto resume_21;
resume_0: resume_0:
res = bs->heap->get_next_compact(cur_oid); res = bs->heap->get_next_compact(cur_oid);
if (res == ENOENT) if (res == ENOENT)
{ {
if (co_id == 0 && flusher->force_start > 0)
{
resume_18:
resume_19:
resume_20:
resume_21:
if (!trim_lsn(18))
return false;
}
cur_oid = {}; cur_oid = {};
wait_state = 0; wait_state = 0;
return true; return true;
@@ -203,7 +216,6 @@ resume_1:
read_vec.clear(); read_vec.clear();
for (auto wr = begin_wr; wr != end_wr; wr = wr->next()) for (auto wr = begin_wr; wr != end_wr; wr = wr->next())
{ {
min_compact_lsn = wr->lsn;
bs->prepare_read(read_vec, cur_obj, wr, 0, bs->dsk.data_block_size); bs->prepare_read(read_vec, cur_obj, wr, 0, bs->dsk.data_block_size);
} }
overwrite_start = overwrite_end = 0; overwrite_start = overwrite_end = 0;
@@ -277,19 +289,30 @@ resume_12:
resume_13: resume_13:
if (copy_count && !fsync_batch(false, 11)) if (copy_count && !fsync_batch(false, 11))
return false; return false;
// Lock is only needed to prevent freeing the big_write because we overwrite it...
bs->heap->unlock_entry(cur_oid, copy_id); bs->heap->unlock_entry(cur_oid, copy_id);
// Modify the metadata entry; don't write anything. Metadata block will be written on the next write // Mark the object compacted, but don't free and remove small_writes
// We'll free and remove them only when trimming
// The only thing we modify here are big_write block checksums if >4k block is used
cur_obj = bs->heap->read_entry(cur_oid, NULL);
if (!cur_obj)
{
// Abort compaction
goto release_oid;
}
calc_block_checksums(); calc_block_checksums();
bs->heap->compact_object(cur_oid, compact_lsn, new_data_csums); bs->heap->mark_object_compacted(cur_obj, compact_lsn);
// Done, free all buffers // Done, free all buffers
free_buffers(); free_buffers();
#ifdef BLOCKSTORE_DEBUG #ifdef BLOCKSTORE_DEBUG
printf("Compacted %jx:%jx v%ju (%d writes)\n", cur_oid.inode, cur_oid.stripe, cur_version, copy_count); printf("Compacted %jx:%jx v%ju (%d writes)\n", cur_oid.inode, cur_oid.stripe, cur_version, copy_count);
#endif #endif
flusher->compact_counter++;
flusher->active_flushers--;
// Advance compacted_lsn every <journal_trim_interval> objects // Advance compacted_lsn every <journal_trim_interval> objects
bs->heap->set_compacted_lsn(min_compact_lsn); if (co_id == 0 && !((++flusher->advance_lsn_counter) % bs->journal_trim_interval))
if (bs->journal_trim_interval && !((++flusher->advance_lsn_counter) % bs->journal_trim_interval))
{ {
flusher->advance_lsn_counter = 0;
resume_14: resume_14:
resume_15: resume_15:
resume_16: resume_16:
@@ -298,14 +321,12 @@ resume_17:
return false; return false;
} }
release_oid: release_oid:
flusher->active_flushers--;
if (should_repeat) if (should_repeat)
{ {
// Flush the same object again // Flush the same object again
goto resume_1; goto resume_1;
} }
// All done // All done
flusher->compact_counter++;
wait_state = 0; wait_state = 0;
goto resume_0; goto resume_0;
} }
@@ -479,7 +500,6 @@ void journal_flusher_co::calc_block_checksums()
if (bs->dsk.csum_block_size <= bs->dsk.bitmap_granularity) if (bs->dsk.csum_block_size <= bs->dsk.bitmap_granularity)
return; return;
new_data_csums = csum_buf + overwrite_start/bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF); new_data_csums = csum_buf + overwrite_start/bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF);
cur_obj = bs->heap->read_locked_entry(cur_oid, copy_id);
uint64_t block_offset = 0; uint64_t block_offset = 0;
uint32_t block_done = 0; uint32_t block_done = 0;
uint32_t block_csum = 0; uint32_t block_csum = 0;
@@ -667,6 +687,12 @@ bool journal_flusher_co::trim_lsn(int wait_base)
else if (wait_state == wait_base+1) goto resume_1; else if (wait_state == wait_base+1) goto resume_1;
else if (wait_state == wait_base+2) goto resume_2; else if (wait_state == wait_base+2) goto resume_2;
else if (wait_state == wait_base+3) goto resume_3; else if (wait_state == wait_base+3) goto resume_3;
compact_lsn = bs->heap->get_compacted_lsn();
if (((blockstore_meta_header_v3_t*)bs->meta_superblock)->compacted_lsn == compact_lsn)
{
return true;
}
flusher->active_flushers++;
if (!bs->disable_meta_fsync) if (!bs->disable_meta_fsync)
{ {
await_sqe(0); await_sqe(0);
@@ -681,7 +707,7 @@ resume_1:
return false; return false;
} }
} }
((blockstore_meta_header_v3_t*)bs->meta_superblock)->compacted_lsn = bs->heap->get_compacted_lsn(); ((blockstore_meta_header_v3_t*)bs->meta_superblock)->compacted_lsn = compact_lsn;
((blockstore_meta_header_v3_t*)bs->meta_superblock)->set_crc32c(); ((blockstore_meta_header_v3_t*)bs->meta_superblock)->set_crc32c();
await_sqe(2); await_sqe(2);
data->iov = (struct iovec){ bs->meta_superblock, (size_t)bs->dsk.meta_block_size }; data->iov = (struct iovec){ bs->meta_superblock, (size_t)bs->dsk.meta_block_size };
@@ -694,6 +720,8 @@ resume_3:
wait_state = wait_base+3; wait_state = wait_base+3;
return false; return false;
} }
flusher->advance_lsn_counter = 0; bs->heap->mark_lsn_trimmed(compact_lsn);
flusher->compact_counter++;
flusher->active_flushers--;
return true; return true;
} }
+1 -2
View File
@@ -51,7 +51,6 @@ class journal_flusher_co
object_id cur_oid; object_id cur_oid;
uint64_t copy_id; uint64_t copy_id;
uint64_t compact_lsn; uint64_t compact_lsn;
uint64_t min_compact_lsn;
uint64_t cur_version; uint64_t cur_version;
heap_object_t *cur_obj; heap_object_t *cur_obj;
heap_write_t *begin_wr, *end_wr; heap_write_t *begin_wr, *end_wr;
@@ -108,7 +107,7 @@ public:
~journal_flusher_t(); ~journal_flusher_t();
void loop(); void loop();
int get_active(); int get_active();
uint64_t get_counter(); uint64_t get_compact_counter();
bool is_active(); bool is_active();
void request_trim(); void request_trim();
void release_trim(); void release_trim();
+122 -37
View File
@@ -61,7 +61,7 @@ bool heap_write_t::needs_recheck(blockstore_heap_t *heap)
bool heap_write_t::needs_compact(uint64_t compacted_lsn) bool heap_write_t::needs_compact(uint64_t compacted_lsn)
{ {
return lsn > compacted_lsn && (flags == (BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE) || flags == (BS_HEAP_INTENT_WRITE|BS_HEAP_STABLE)); return lsn > compacted_lsn && flags == (BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE);
} }
bool heap_write_t::is_compacted(uint64_t compacted_lsn) bool heap_write_t::is_compacted(uint64_t compacted_lsn)
@@ -585,9 +585,9 @@ skip_object:
// Mark data block as used // Mark data block as used
use_data(obj->inode, wr->location); use_data(obj->inode, wr->location);
} }
if (wr->needs_compact(this->compacted_lsn)) if (wr->lsn > this->compacted_lsn)
{ {
tmp_compact_queue.push_back((heap_object_lsn_t){ .oid = oid, .lsn = wr->lsn }); tmp_compact_queue.push_back((tmp_compact_item_t){ .oid = oid, .lsn = wr->lsn, .compact = wr->needs_compact(0) });
} }
else if (wr->is_compacted(this->compacted_lsn)) else if (wr->is_compacted(this->compacted_lsn))
{ {
@@ -599,7 +599,7 @@ skip_object:
{ {
// We can't just collapse the object entry when csum_block_size is larger // We can't just collapse the object entry when csum_block_size is larger
// than bitmap_granularity, so we add the object into the compact queue // than bitmap_granularity, so we add the object into the compact queue
tmp_compact_queue.push_back((heap_object_lsn_t){ .oid = oid, .lsn = wr->lsn }); tmp_compact_queue.push_back((tmp_compact_item_t){ .oid = oid, .lsn = wr->lsn, .compact = wr->needs_compact(0) });
} }
} }
} }
@@ -643,13 +643,28 @@ skip_object:
void blockstore_heap_t::finish_load() void blockstore_heap_t::finish_load()
{ {
std::sort(tmp_compact_queue.begin(), tmp_compact_queue.end(), [this](const heap_object_lsn_t & a, const heap_object_lsn_t & b) completed_lsn = first_inflight_lsn = next_lsn+1;
if (!tmp_compact_queue.size())
{
return;
}
std::sort(tmp_compact_queue.begin(), tmp_compact_queue.end(), [this](const tmp_compact_item_t & a, const tmp_compact_item_t & b)
{ {
return a.lsn < b.lsn; return a.lsn < b.lsn;
}); });
first_inflight_lsn = tmp_compact_queue[0].lsn;
if (compacted_lsn < tmp_compact_queue[0].lsn-1)
{
compacted_lsn = tmp_compact_queue[0].lsn-1;
}
for (auto & e: tmp_compact_queue) for (auto & e: tmp_compact_queue)
{ {
compact_queue.push_back(e.oid); push_inflight_lsn(e.oid, e.lsn, HEAP_INFLIGHT_DONE | (e.compact ? HEAP_INFLIGHT_COMPACTABLE : 0));
}
while (compacted_lsn+1-first_inflight_lsn < inflight_lsn.size() &&
!(inflight_lsn[compacted_lsn+1-first_inflight_lsn].flags & HEAP_INFLIGHT_COMPACTABLE))
{
compacted_lsn++;
} }
tmp_compact_queue.clear(); tmp_compact_queue.clear();
} }
@@ -758,7 +773,7 @@ bool blockstore_heap_t::recheck_small_writes(std::function<void(bool is_data, ui
uint8_t *buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, wr->len); uint8_t *buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, wr->len);
if (log_level > 5) if (log_level > 5)
{ {
fprintf(stderr, "Notice: rechecking %u bytes at %ju in %s area\n", wr->len, loc, is_intent ? "data" : "buffer"); fprintf(stderr, "Notice: rechecking %u bytes at %ju in %s area (lsn %lu)\n", wr->len, loc, is_intent ? "data" : "buffer", wr->lsn);
} }
recheck_cb(is_intent, loc, wr->len, buf, [this, oid, lsn = wr->lsn, buf]() recheck_cb(is_intent, loc, wr->len, buf, [this, oid, lsn = wr->lsn, buf]()
{ {
@@ -1264,7 +1279,7 @@ int blockstore_heap_t::add_object(object_id oid, heap_write_t *wr, uint32_t *mod
new_wr->size = wr_size; new_wr->size = wr_size;
new_wr->lsn = ++next_lsn; new_wr->lsn = ++next_lsn;
wr->lsn = new_wr->lsn; wr->lsn = new_wr->lsn;
push_inflight_lsn(oid, new_wr); push_inflight_lsn(oid, new_wr->lsn, new_wr->needs_compact(0) ? HEAP_INFLIGHT_COMPACTABLE : 0);
if ((wr->flags & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE) if ((wr->flags & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE)
{ {
uint8_t *int_bitmap = new_wr->get_int_bitmap(this); uint8_t *int_bitmap = new_wr->get_int_bitmap(this);
@@ -1430,7 +1445,7 @@ int blockstore_heap_t::update_object(uint32_t block_num, heap_object_t *obj, hea
new_wr->size = wr_size; new_wr->size = wr_size;
new_wr->lsn = ++next_lsn; new_wr->lsn = ++next_lsn;
wr->lsn = new_wr->lsn; wr->lsn = new_wr->lsn;
push_inflight_lsn(oid, new_wr); push_inflight_lsn(oid, new_wr->lsn, new_wr->needs_compact(0) ? HEAP_INFLIGHT_COMPACTABLE : 0);
if ((wr->flags & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE) if ((wr->flags & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE)
{ {
uint8_t *int_bitmap = new_wr->get_int_bitmap(this); uint8_t *int_bitmap = new_wr->get_int_bitmap(this);
@@ -1528,7 +1543,7 @@ int blockstore_heap_t::post_stabilize(object_id oid, uint64_t version, uint32_t
{ {
wr->flags |= BS_HEAP_STABLE; wr->flags |= BS_HEAP_STABLE;
wr->lsn = last_lsn--; wr->lsn = last_lsn--;
push_inflight_lsn(oid, wr); push_inflight_lsn(oid, wr->lsn, wr->needs_compact(0) ? HEAP_INFLIGHT_COMPACTABLE : 0);
} }
} }
obj->crc32c = obj->calc_crc32c(); obj->crc32c = obj->calc_crc32c();
@@ -1608,10 +1623,24 @@ int blockstore_heap_t::post_delete(object_id oid, uint32_t *modified_block)
int blockstore_heap_t::get_next_compact(object_id & oid) int blockstore_heap_t::get_next_compact(object_id & oid)
{ {
while (compact_queue.size()) if (next_compact_lsn < first_inflight_lsn)
{ {
oid = compact_queue.front(); next_compact_lsn = first_inflight_lsn;
compact_queue.pop_front(); }
while (next_compact_lsn-first_inflight_lsn < inflight_lsn.size())
{
auto & item = inflight_lsn[next_compact_lsn-first_inflight_lsn];
if (!(item.flags & HEAP_INFLIGHT_COMPACTABLE))
{
next_compact_lsn++;
continue;
}
if (!(item.flags & HEAP_INFLIGHT_DONE))
{
break;
}
next_compact_lsn++;
oid = item.oid;
return 0; return 0;
} }
return ENOENT; return ENOENT;
@@ -1918,7 +1947,12 @@ uint32_t blockstore_heap_t::get_meta_nearfull_blocks()
uint32_t blockstore_heap_t::get_compact_queue_size() uint32_t blockstore_heap_t::get_compact_queue_size()
{ {
return compact_queue.size(); return to_compact_count;
}
uint32_t blockstore_heap_t::get_inflight_queue_size()
{
return inflight_lsn.size();
} }
uint32_t blockstore_heap_t::get_max_write_entry_size() uint32_t blockstore_heap_t::get_max_write_entry_size()
@@ -1931,39 +1965,95 @@ void blockstore_heap_t::set_fail_on_warn(bool fail)
fail_on_warn = fail; fail_on_warn = fail;
} }
void blockstore_heap_t::push_inflight_lsn(object_id oid, heap_write_t *wr) void blockstore_heap_t::push_inflight_lsn(object_id oid, uint64_t lsn, uint64_t flags)
{ {
uint64_t next_inf = first_inflight_lsn + inflight_lsn.size(); uint64_t next_inf = first_inflight_lsn + inflight_lsn.size();
uint64_t flags = wr->needs_compact(0) ? HEAP_INFLIGHT_COMPACTABLE : 0; if (flags & HEAP_INFLIGHT_COMPACTABLE)
if (wr->lsn == next_inf) {
to_compact_count++;
}
if (lsn == next_inf)
{ {
inflight_lsn.push_back((heap_inflight_lsn_t){ .oid = oid, .flags = flags }); inflight_lsn.push_back((heap_inflight_lsn_t){ .oid = oid, .flags = flags });
} }
else else
{ {
if (wr->lsn > next_inf) if (lsn > next_inf)
inflight_lsn.resize(wr->lsn-first_inflight_lsn+1); {
inflight_lsn[wr->lsn-first_inflight_lsn] = (heap_inflight_lsn_t){ .oid = oid, .flags = flags }; inflight_lsn.resize(lsn-first_inflight_lsn+1, (heap_inflight_lsn_t){ .flags = HEAP_INFLIGHT_DONE });
}
inflight_lsn[lsn-first_inflight_lsn] = (heap_inflight_lsn_t){ .oid = oid, .flags = flags };
} }
} }
void blockstore_heap_t::complete_lsn(uint64_t lsn) void blockstore_heap_t::mark_lsn_completed(uint64_t lsn)
{ {
assert(lsn >= first_inflight_lsn && lsn < first_inflight_lsn+inflight_lsn.size()); assert(lsn >= first_inflight_lsn && lsn < first_inflight_lsn+inflight_lsn.size());
assert(!(inflight_lsn[lsn - first_inflight_lsn].flags & HEAP_INFLIGHT_DONE)); auto & item = inflight_lsn[lsn - first_inflight_lsn];
inflight_lsn[lsn - first_inflight_lsn].flags |= HEAP_INFLIGHT_DONE; assert(!(item.flags & HEAP_INFLIGHT_DONE));
if (lsn == first_inflight_lsn) item.flags |= HEAP_INFLIGHT_DONE;
if (lsn == compacted_lsn+1 && !(item.flags & HEAP_INFLIGHT_COMPACTABLE))
{ {
while (inflight_lsn.size() && (inflight_lsn[0].flags & HEAP_INFLIGHT_DONE)) assert(compacted_lsn+1 >= first_inflight_lsn);
while (compacted_lsn+1-first_inflight_lsn < inflight_lsn.size() &&
(inflight_lsn[compacted_lsn+1-first_inflight_lsn].flags == HEAP_INFLIGHT_DONE))
{ {
if ((inflight_lsn[0].flags & HEAP_INFLIGHT_COMPACTABLE)) compacted_lsn++;
{
compact_queue.push_back(inflight_lsn[0].oid);
}
inflight_lsn.pop_front();
first_inflight_lsn++;
} }
completed_lsn = first_inflight_lsn-1; assert(inflight_lsn[compacted_lsn-first_inflight_lsn].flags == HEAP_INFLIGHT_DONE);
}
if (lsn > completed_lsn)
{
assert(completed_lsn+1 >= first_inflight_lsn);
while (completed_lsn+1-first_inflight_lsn < inflight_lsn.size() &&
(inflight_lsn[completed_lsn+1-first_inflight_lsn].flags & HEAP_INFLIGHT_DONE))
{
completed_lsn++;
}
}
}
void blockstore_heap_t::mark_lsn_compacted(uint64_t lsn)
{
assert(lsn >= first_inflight_lsn && lsn < first_inflight_lsn+inflight_lsn.size());
auto & item = inflight_lsn[lsn - first_inflight_lsn];
assert(item.flags & HEAP_INFLIGHT_DONE);
if (!(item.flags & HEAP_INFLIGHT_COMPACTABLE))
return;
item.flags -= HEAP_INFLIGHT_COMPACTABLE;
to_compact_count--;
if (lsn == compacted_lsn+1)
{
assert(completed_lsn+1 >= first_inflight_lsn);
while (compacted_lsn+1-first_inflight_lsn < inflight_lsn.size() &&
(inflight_lsn[compacted_lsn+1-first_inflight_lsn].flags == HEAP_INFLIGHT_DONE))
{
compacted_lsn++;
}
}
}
void blockstore_heap_t::mark_object_compacted(heap_object_t *obj, uint64_t max_lsn)
{
for (auto wr = obj->get_writes(); wr; wr = wr->next())
{
if (wr->is_compacted(max_lsn))
{
mark_lsn_compacted(wr->lsn);
}
}
}
void blockstore_heap_t::mark_lsn_trimmed(uint64_t lsn)
{
assert(lsn >= first_inflight_lsn && lsn < first_inflight_lsn+inflight_lsn.size());
while (first_inflight_lsn <= lsn && inflight_lsn.size() > 0)
{
assert(inflight_lsn[0].flags == HEAP_INFLIGHT_DONE);
// FIXME don't touch unflushable lsns
compact_object(inflight_lsn[0].oid, lsn, NULL); // FIXME from prev trimmed lsn
inflight_lsn.pop_front();
first_inflight_lsn++;
} }
} }
@@ -1971,8 +2061,3 @@ uint64_t blockstore_heap_t::get_completed_lsn()
{ {
return completed_lsn; return completed_lsn;
} }
void blockstore_heap_t::add_to_compact_queue(object_id oid)
{
compact_queue.push_back(oid);
}
+19 -7
View File
@@ -84,6 +84,13 @@ inline bool operator < (const heap_object_lsn_t & a, const heap_object_lsn_t & b
return a.oid < b.oid || a.oid == b.oid && a.lsn < b.lsn; return a.oid < b.oid || a.oid == b.oid && a.lsn < b.lsn;
} }
struct tmp_compact_item_t
{
object_id oid;
uint64_t lsn;
bool compact;
};
struct heap_object_mvcc_t struct heap_object_mvcc_t
{ {
uint32_t readers = 0; uint32_t readers = 0;
@@ -136,11 +143,9 @@ class blockstore_heap_t
const int meta_alloc_buckets = 4; const int meta_alloc_buckets = 4;
uint64_t next_lsn = 0; uint64_t next_lsn = 0;
uint64_t compacted_lsn = 0;
std::map<pool_id_t, pool_shard_settings_t> pool_shard_settings; std::map<pool_id_t, pool_shard_settings_t> pool_shard_settings;
// PG => inode => stripe => block number // PG => inode => stripe => block number
std::map<uint64_t, std::map<inode_t, btree::btree_map<uint64_t, uint64_t>>> block_index; std::map<uint64_t, std::map<inode_t, btree::btree_map<uint64_t, uint64_t>>> block_index;
std::deque<object_id> compact_queue;
std::vector<heap_block_info_t> block_info; std::vector<heap_block_info_t> block_info;
allocator_t *data_alloc = NULL; allocator_t *data_alloc = NULL;
allocator_t *meta_allocs[4] = {}; allocator_t *meta_allocs[4] = {};
@@ -154,11 +159,15 @@ class blockstore_heap_t
uint64_t buffer_area_used_space = 0; uint64_t buffer_area_used_space = 0;
uint64_t data_used_space = 0; uint64_t data_used_space = 0;
// LSN queue: inflight (writing) -> completed [-> fsynced] -> compactable -> compacted [-> fsynced] -> trimmed and removed
std::deque<heap_inflight_lsn_t> inflight_lsn; std::deque<heap_inflight_lsn_t> inflight_lsn;
uint64_t first_inflight_lsn = 1; uint32_t to_compact_count = 0;
uint64_t first_inflight_lsn = 0;
uint64_t completed_lsn = 0; uint64_t completed_lsn = 0;
uint64_t compacted_lsn = 0;
uint64_t next_compact_lsn = 0;
std::vector<heap_object_lsn_t> tmp_compact_queue; std::vector<tmp_compact_item_t> tmp_compact_queue;
std::deque<object_id> recheck_queue; std::deque<object_id> recheck_queue;
int recheck_in_progress = 0; int recheck_in_progress = 0;
bool in_recheck = false; bool in_recheck = false;
@@ -180,7 +189,7 @@ class blockstore_heap_t
void erase_block_index(inode_t inode, uint64_t stripe); void erase_block_index(inode_t inode, uint64_t stripe);
void free_object_space(inode_t inode, heap_write_t *from, heap_write_t *to, int mode = 0); void free_object_space(inode_t inode, heap_write_t *from, heap_write_t *to, int mode = 0);
void add_used_space(uint32_t block_num, int32_t used_delta); void add_used_space(uint32_t block_num, int32_t used_delta);
void push_inflight_lsn(object_id oid, heap_write_t *wr); void push_inflight_lsn(object_id oid, uint64_t lsn, uint64_t flags);
public: public:
blockstore_heap_t(blockstore_disk_t *dsk, uint8_t *buffer_area, int log_level = 0); blockstore_heap_t(blockstore_disk_t *dsk, uint8_t *buffer_area, int log_level = 0);
@@ -243,9 +252,11 @@ public:
int get_block_for_new_object(uint32_t & out_block_num); int get_block_for_new_object(uint32_t & out_block_num);
// inflight write tracking // inflight write tracking
void complete_lsn(uint64_t lsn); void mark_lsn_completed(uint64_t lsn);
void mark_lsn_compacted(uint64_t lsn);
void mark_object_compacted(heap_object_t *obj, uint64_t max_lsn);
void mark_lsn_trimmed(uint64_t lsn);
uint64_t get_completed_lsn(); uint64_t get_completed_lsn();
void add_to_compact_queue(object_id oid);
// data device block allocator functions // data device block allocator functions
uint64_t find_free_data(); uint64_t find_free_data();
@@ -269,6 +280,7 @@ public:
uint64_t get_meta_total_space(); uint64_t get_meta_total_space();
uint64_t get_meta_used_space(); uint64_t get_meta_used_space();
uint32_t get_meta_nearfull_blocks(); uint32_t get_meta_nearfull_blocks();
uint32_t get_inflight_queue_size();
uint32_t get_compact_queue_size(); uint32_t get_compact_queue_size();
// get maximum size for a temporary heap_write_t buffer // get maximum size for a temporary heap_write_t buffer
+1 -1
View File
@@ -244,7 +244,7 @@ void blockstore_impl_t::check_wait(blockstore_op_t *op)
} }
else if (PRIV(op)->wait_for == WAIT_COMPACTION) else if (PRIV(op)->wait_for == WAIT_COMPACTION)
{ {
if (flusher->get_counter() <= PRIV(op)->wait_detail) if (flusher->get_compact_counter() <= PRIV(op)->wait_detail)
{ {
// do not submit // do not submit
#ifdef BLOCKSTORE_DEBUG #ifdef BLOCKSTORE_DEBUG
+2 -1
View File
@@ -117,7 +117,7 @@ resume_1:
} }
else else
{ {
blockstore_meta_header_v2_t *hdr = (blockstore_meta_header_v2_t *)bs->meta_superblock; blockstore_meta_header_v3_t *hdr = (blockstore_meta_header_v3_t *)bs->meta_superblock;
if (hdr->zero != 0 || hdr->magic != BLOCKSTORE_META_MAGIC_V1 || hdr->version < BLOCKSTORE_META_FORMAT_V1) if (hdr->zero != 0 || hdr->magic != BLOCKSTORE_META_MAGIC_V1 || hdr->version < BLOCKSTORE_META_FORMAT_V1)
{ {
printf( printf(
@@ -153,6 +153,7 @@ resume_1:
); );
exit(1); exit(1);
} }
bs->heap->set_compacted_lsn(hdr->compacted_lsn);
} }
if (bs->dsk.inmemory_journal) if (bs->dsk.inmemory_journal)
{ {
+1 -1
View File
@@ -86,7 +86,7 @@ resume_4:
// FIXME: Also mark as fsynced // FIXME: Also mark as fsynced
for (uint64_t lsn = priv->lsn; lsn <= priv->to_lsn; lsn++) for (uint64_t lsn = priv->lsn; lsn <= priv->to_lsn; lsn++)
{ {
heap->complete_lsn(lsn); heap->mark_lsn_completed(lsn);
} }
// Done. Don't touch op->retval - if anything resulted in ENOENT, return it as is // Done. Don't touch op->retval - if anything resulted in ENOENT, return it as is
FINISH_OP(op); FINISH_OP(op);
+9 -9
View File
@@ -103,14 +103,14 @@ int blockstore_impl_t::dequeue_write(blockstore_op_t *op)
if (loc == UINT64_MAX || if (loc == UINT64_MAX ||
!obj && heap->get_block_for_new_object(tmp_block) != 0) !obj && heap->get_block_for_new_object(tmp_block) != 0)
{ {
if (!heap->get_compact_queue_size() && !write_iodepth && !flusher->get_active()) if (!heap->get_inflight_queue_size())
{ {
// no space // no space
cancel_all_writes(op, -ENOSPC); cancel_all_writes(op, -ENOSPC);
return 2; return 2;
} }
PRIV(op)->wait_for = WAIT_COMPACTION; PRIV(op)->wait_for = WAIT_COMPACTION;
PRIV(op)->wait_detail = flusher->get_counter(); PRIV(op)->wait_detail = flusher->get_compact_counter();
flusher->request_trim(); flusher->request_trim();
return 0; return 0;
} }
@@ -179,14 +179,14 @@ int blockstore_impl_t::dequeue_write(blockstore_op_t *op)
int res = heap->post_write(op->oid, wr, &modified_block); int res = heap->post_write(op->oid, wr, &modified_block);
if (res == ENOSPC) if (res == ENOSPC)
{ {
if (!heap->get_compact_queue_size() && !write_iodepth && !flusher->get_active()) if (!heap->get_inflight_queue_size())
{ {
// no space // no space
cancel_all_writes(op, -ENOSPC); cancel_all_writes(op, -ENOSPC);
return 2; return 2;
} }
PRIV(op)->wait_for = WAIT_COMPACTION; PRIV(op)->wait_for = WAIT_COMPACTION;
PRIV(op)->wait_detail = flusher->get_counter(); PRIV(op)->wait_detail = flusher->get_compact_counter();
flusher->request_trim(); flusher->request_trim();
return 0; return 0;
} }
@@ -205,7 +205,7 @@ int blockstore_impl_t::dequeue_write(blockstore_op_t *op)
if (loc == UINT64_MAX) if (loc == UINT64_MAX)
{ {
PRIV(op)->wait_for = WAIT_COMPACTION; PRIV(op)->wait_for = WAIT_COMPACTION;
PRIV(op)->wait_detail = flusher->get_counter(); PRIV(op)->wait_detail = flusher->get_compact_counter();
flusher->request_trim(); flusher->request_trim();
return 0; return 0;
} }
@@ -226,14 +226,14 @@ int blockstore_impl_t::dequeue_write(blockstore_op_t *op)
int res = heap->post_write(op->oid, wr, &modified_block); int res = heap->post_write(op->oid, wr, &modified_block);
if (res == ENOSPC) if (res == ENOSPC)
{ {
if (!heap->get_compact_queue_size() && !write_iodepth && !flusher->get_active()) if (!heap->get_inflight_queue_size())
{ {
// no space // no space
cancel_all_writes(op, -ENOSPC); cancel_all_writes(op, -ENOSPC);
return 2; return 2;
} }
PRIV(op)->wait_for = WAIT_COMPACTION; PRIV(op)->wait_for = WAIT_COMPACTION;
PRIV(op)->wait_detail = flusher->get_counter(); PRIV(op)->wait_detail = flusher->get_compact_counter();
flusher->request_trim(); flusher->request_trim();
return 0; return 0;
} }
@@ -315,7 +315,7 @@ resume_4:
if (res == ENOSPC) if (res == ENOSPC)
{ {
PRIV(op)->wait_for = WAIT_COMPACTION; PRIV(op)->wait_for = WAIT_COMPACTION;
PRIV(op)->wait_detail = flusher->get_counter(); PRIV(op)->wait_detail = flusher->get_compact_counter();
return 1; return 1;
} }
assert(res == 0); assert(res == 0);
@@ -364,7 +364,7 @@ resume_6:
resume_8: resume_8:
// Acknowledge write // Acknowledge write
op->retval = op->len; op->retval = op->len;
heap->complete_lsn(PRIV(op)->lsn); heap->mark_lsn_completed(PRIV(op)->lsn);
write_iodepth--; write_iodepth--;
FINISH_OP(op); FINISH_OP(op);
return 2; return 2;
+12 -4
View File
@@ -403,6 +403,7 @@ void test_compact(bool csum, bool stable)
_test_small_write(heap, dsk, 1, 0, 3, 8192, 4096, 16384, stable); _test_small_write(heap, dsk, 1, 0, 3, 8192, 4096, 16384, stable);
obj = heap.read_entry(oid, NULL); obj = heap.read_entry(oid, NULL);
uint64_t wr_size = obj->get_writes()->get_size(&heap); uint64_t wr_size = obj->get_writes()->get_size(&heap);
assert(obj->get_writes()->lsn == 2);
assert(check_used_space(heap, dsk, 0)); assert(check_used_space(heap, dsk, 0));
assert(heap.get_meta_block_used_space(0) == old_size + wr_size); assert(heap.get_meta_block_used_space(0) == old_size + wr_size);
@@ -412,6 +413,10 @@ void test_compact(bool csum, bool stable)
assert(obj); assert(obj);
assert(count_writes(obj) == 2); assert(count_writes(obj) == 2);
heap.mark_lsn_completed(1);
heap.mark_lsn_completed(2);
heap.mark_lsn_completed(3);
uint32_t mblock; uint32_t mblock;
object_id compact_oid = {}; object_id compact_oid = {};
if (!stable) if (!stable)
@@ -435,9 +440,9 @@ void test_compact(bool csum, bool stable)
assert(new_to_lsn == 4); assert(new_to_lsn == 4);
assert(check_used_space(heap, dsk, 0)); assert(check_used_space(heap, dsk, 0));
assert(heap.get_meta_block_used_space(0) == 2*old_size + wr_size); assert(heap.get_meta_block_used_space(0) == 2*old_size + wr_size);
heap.mark_lsn_completed(4);
} }
heap.add_to_compact_queue(oid);
assert(heap.get_compact_queue_size() == 1); assert(heap.get_compact_queue_size() == 1);
res = heap.get_next_compact(compact_oid); res = heap.get_next_compact(compact_oid);
assert(res == 0); assert(res == 0);
@@ -447,15 +452,18 @@ void test_compact(bool csum, bool stable)
obj = heap.read_entry(oid, NULL); obj = heap.read_entry(oid, NULL);
assert(obj); assert(obj);
assert(count_writes(obj) == 2); assert(count_writes(obj) == 2);
heap.get_compact_range(obj, UINT64_MAX, &compact_begin, &compact_end); heap.get_compact_range(obj, 4, &compact_begin, &compact_end);
assert(compact_begin == obj->get_writes()); assert(compact_begin == obj->get_writes());
assert(compact_end == obj->get_writes()->next()); assert(compact_end == obj->get_writes()->next());
heap.mark_object_compacted(obj, 4);
assert(heap.get_compacted_lsn() == (stable ? 3 : 4));
assert(heap.get_compact_queue_size() == 0);
res = heap.compact_object((object_id){ .inode = INODE_WITH_POOL(1, 3), .stripe = 0 }, compact_begin->lsn, NULL); res = heap.compact_object((object_id){ .inode = INODE_WITH_POOL(1, 3), .stripe = 0 }, compact_begin->lsn, NULL);
assert(res == ENOENT); assert(res == ENOENT);
res = heap.compact_object(compact_oid, compact_begin->lsn, NULL); heap.mark_lsn_trimmed((stable ? 3 : 4));
assert(res == 0);
assert(check_used_space(heap, dsk, 0)); assert(check_used_space(heap, dsk, 0));
assert(heap.get_meta_block_used_space(0) == 2*old_size); assert(heap.get_meta_block_used_space(0) == 2*old_size);