Fix incorrect batch big_write fsync logic in the new store

This commit is contained in:
Vitaliy Filippov
2026-06-18 00:04:15 +03:00
parent ba7637d9ad
commit 0c88884576
2 changed files with 40 additions and 30 deletions
+5 -2
View File
@@ -117,9 +117,12 @@ public:
journal_flusher_t *flusher; journal_flusher_t *flusher;
int write_iodepth = 0; int write_iodepth = 0;
int inflight_big = 0;
int intent_write_counter = 0; int intent_write_counter = 0;
bool fsyncing_data = false; uint64_t data_fsync_next = 0;
uint64_t data_fsync_cur = 0;
uint64_t data_fsync_sent = 0;
uint64_t data_fsync_done = 0;
std::deque<bool> data_fsyncs;
bool live = false, queue_stall = false; bool live = false, queue_stall = false;
ring_loop_i *ringloop = NULL; ring_loop_i *ringloop = NULL;
+35 -28
View File
@@ -180,13 +180,16 @@ enospc:
data->callback = [this, op](ring_data_t *data) { handle_write_event(data, op); }; data->callback = [this, op](ring_data_t *data) { handle_write_event(data, op); };
assert(loc+op->offset+op->len <= dsk.block_count*dsk.data_block_size); assert(loc+op->offset+op->len <= dsk.block_count*dsk.data_block_size);
io_uring_prep_writev(sqe, dsk.data_fd, &data->iov, 1, dsk.data_offset + loc + op->offset); io_uring_prep_writev(sqe, dsk.data_fd, &data->iov, 1, dsk.data_offset + loc + op->offset);
if (!dsk.disable_data_fsync)
{
// use PRIV->lsn for fsync_data_id
PRIV(op)->lsn = ++data_fsync_next;
data_fsyncs.push_back(false);
}
PRIV(op)->pending_ops++; PRIV(op)->pending_ops++;
write_iodepth++; write_iodepth++;
if (PRIV(op)->write_type == BS_HEAP_BIG_WRITE) if (PRIV(op)->write_type == BS_HEAP_BIG_WRITE)
{
PRIV(op)->op_state = 1; PRIV(op)->op_state = 1;
inflight_big++;
}
else else
PRIV(op)->op_state = 3; PRIV(op)->op_state = 3;
} }
@@ -297,8 +300,6 @@ again:
goto resume_10; goto resume_10;
else if (op_state == 11) else if (op_state == 11)
goto resume_11; goto resume_11;
else if (op_state == 12)
goto resume_12;
else else
{ {
// In progress // In progress
@@ -317,38 +318,44 @@ again:
resume_2: resume_2:
// We must fsync all big writes to avoid complex write workflows // We must fsync all big writes to avoid complex write workflows
// It's OK for all HDDs and for server SSDs, but slightly worse for desktop SSDs // It's OK for all HDDs and for server SSDs, but slightly worse for desktop SSDs
inflight_big--;
if (!dsk.disable_data_fsync) if (!dsk.disable_data_fsync)
{ {
// fsync data in a batch // Mark our data write as completed and advance data_fsync_cur
resume_11: data_fsyncs[PRIV(op)->lsn - data_fsync_cur - 1] = true;
if (inflight_big > 0) while (data_fsyncs.size() > 0 && data_fsyncs.front())
{
data_fsyncs.pop_front();
data_fsync_cur++;
}
PRIV(op)->op_state = 11;
// Then wait for all other data writes currently in progress to do less fsync calls
// I.e. to fsync data in batches
PRIV(op)->lsn = data_fsync_cur + data_fsyncs.size();
resume_11:
if (data_fsync_cur < PRIV(op)->lsn)
{ {
PRIV(op)->op_state = 11;
return 1; return 1;
} }
if (fsyncing_data) if (PRIV(op)->lsn > data_fsync_sent)
{ {
resume_12: BS_SUBMIT_GET_SQE(sqe, data);
if (fsyncing_data) io_uring_prep_fsync(sqe, dsk.data_fd, IORING_FSYNC_DATASYNC);
data->iov = { 0 };
data->callback = [this, op, fs = data_fsync_cur](ring_data_t *data)
{ {
PRIV(op)->op_state = 12; if (fs > data_fsync_done)
return 1; {
} data_fsync_done = fs;
goto resume_4; ringloop->wakeup();
}
};
data_fsync_sent = data_fsync_cur;
} }
fsyncing_data = true; if (PRIV(op)->lsn > data_fsync_done)
BS_SUBMIT_GET_SQE(sqe, data);
io_uring_prep_fsync(sqe, dsk.data_fd, IORING_FSYNC_DATASYNC);
data->iov = { 0 };
data->callback = [this, op](ring_data_t *data)
{ {
fsyncing_data = false; return 1;
handle_write_event(data, op); }
}; PRIV(op)->lsn = 0;
PRIV(op)->pending_ops++;
PRIV(op)->op_state = 3;
return 1;
} }
resume_4: resume_4:
{ {