Use new LSNs on stabilize

This commit is contained in:
Vitaliy Filippov
2025-11-23 19:07:43 +03:00
parent a52dd0dfb5
commit 0fd557fe95
4 changed files with 48 additions and 46 deletions
+36 -34
View File
@@ -14,45 +14,53 @@ int blockstore_impl_t::dequeue_stable(blockstore_op_t *op)
else if (priv->op_state == 3) goto resume_3;
else if (priv->op_state == 4) goto resume_4;
assert(!priv->op_state);
// Modify in-memory state and assign contiguous LSNs
priv->stab_pos = 0;
op->retval = 0;
priv->to_compact.resize(op->len);
priv->lsn = priv->to_lsn = 0;
while (priv->stab_pos < op->len)
{
io_uring_sqe *sqe = get_sqe();
if (!sqe)
{
if (priv->pending_ops > 0)
return 1;
priv->wait_detail = 1;
priv->wait_for = WAIT_SQE;
return 0;
}
uint32_t modified_block = 0;
uint64_t before_compact = 0;
uint64_t to_compact = 0;
uint64_t new_lsn = 0;
uint64_t new_to_lsn = 0;
int res = op->opcode == BS_OP_STABLE
? heap->post_stabilize(v[priv->stab_pos].oid, v[priv->stab_pos].version, &modified_block, &before_compact, &to_compact)
? heap->post_stabilize(v[priv->stab_pos].oid, v[priv->stab_pos].version, &modified_block, &new_lsn, &new_to_lsn)
: heap->post_rollback(v[priv->stab_pos].oid, v[priv->stab_pos].version, &modified_block);
if (res != 0)
{
assert(res == ENOENT || res == EBUSY);
op->retval = -res;
FINISH_OP(op);
return 2;
}
if (modified_block)
if (new_lsn)
{
if (to_compact)
{
priv->to_compact[priv->stab_pos] = true;
committing_lsn[v[priv->stab_pos].oid] = before_compact;
}
prepare_meta_block_write(op, modified_block);
priv->pending_ops++;
if (!priv->lsn)
priv->lsn = new_lsn;
priv->to_lsn = new_to_lsn;
}
priv->stab_pos++;
}
// Submit metadata writes
priv->stab_pos = 0;
resume_1:
priv->op_state = 1;
while (priv->stab_pos < op->len)
{
uint32_t block_num = 0;
heap_object_t *obj = heap->read_entry(v[priv->stab_pos].oid, &block_num);
if (obj)
{
io_uring_sqe *sqe = get_sqe();
if (!sqe)
{
if (priv->pending_ops > 0)
return 1;
priv->wait_detail = 1;
priv->wait_for = WAIT_SQE;
return 0;
}
prepare_meta_block_write(op, block_num, sqe);
}
priv->stab_pos++;
}
if (priv->pending_ops > 0)
{
priv->op_state = 1;
@@ -74,17 +82,11 @@ resume_3:
return 0;
}
resume_4:
for (int i = 0; i < op->len; i++)
// Mark writes as completed to allow compaction
// FIXME: Also mark as fsynced
for (uint64_t lsn = priv->lsn; lsn <= priv->to_lsn; lsn++)
{
if (priv->to_compact[i])
{
// Add to compact queue only when metadata writes are finished
heap->add_to_compact_queue(v[i].oid);
auto cm_it = committing_lsn.find(v[i].oid);
assert(cm_it != committing_lsn.end());
if (cm_it->second <= priv->to_compact[i])
committing_lsn.erase(cm_it);
}
heap->complete_lsn(lsn);
}
// Done. Don't touch op->retval - if anything resulted in ENOENT, return it as is
FINISH_OP(op);