forked from vitalif/vitastor
Check for op->wait_for conditions
It's almost identical to just re-submit... so maybe it was pointlessblocking-uring-test
parent
a5f2d8b85e
commit
90f081f398
|
@ -164,51 +164,95 @@ void blockstore::loop()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// try to submit ops
|
// try to submit ops
|
||||||
auto op = submit_queue.begin();
|
auto cur = submit_queue.begin();
|
||||||
while (op != submit_queue.end())
|
while (cur != submit_queue.end())
|
||||||
{
|
{
|
||||||
auto cur = op++;
|
auto op_ptr = cur;
|
||||||
if ((*cur)->wait_for == WAIT_SQE)
|
auto op = *(cur++);
|
||||||
|
if (op->wait_for)
|
||||||
{
|
{
|
||||||
|
if (op->wait_for == WAIT_SQE)
|
||||||
|
{
|
||||||
|
if (io_uring_sq_space_left(ringloop->ring) < op->wait_detail)
|
||||||
|
{
|
||||||
|
// stop submission if there's still no free space
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
op->wait_for = 0;
|
||||||
|
}
|
||||||
|
else if (op->wait_for == WAIT_IN_FLIGHT)
|
||||||
|
{
|
||||||
|
auto dirty_it = dirty_db.find((obj_ver_id){
|
||||||
|
.oid = op->oid,
|
||||||
|
.version = op->wait_detail,
|
||||||
|
});
|
||||||
|
if (dirty_it != dirty_db.end() && IS_IN_FLIGHT(dirty_it->second.state))
|
||||||
|
{
|
||||||
|
// do not submit
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
op->wait_for = 0;
|
||||||
|
}
|
||||||
|
else if (op->wait_for == WAIT_JOURNAL)
|
||||||
|
{
|
||||||
|
if (journal.used_start < op->wait_detail)
|
||||||
|
{
|
||||||
|
// do not submit
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
op->wait_for = 0;
|
||||||
|
}
|
||||||
|
else if (op->wait_for == WAIT_JOURNAL_BUFFER)
|
||||||
|
{
|
||||||
|
if (journal.sector_info[((journal.cur_sector + 1) % journal.sector_count)].usage_count > 0)
|
||||||
|
{
|
||||||
|
// do not submit
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
op->wait_for = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new std::runtime_error("BUG: op->wait_for value is unexpected");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ((*cur)->wait_for == WAIT_IN_FLIGHT)
|
if ((op->flags & OP_TYPE_MASK) == OP_READ_DIRTY ||
|
||||||
|
(op->flags & OP_TYPE_MASK) == OP_READ)
|
||||||
{
|
{
|
||||||
|
int dequeue_op = dequeue_read(op);
|
||||||
}
|
|
||||||
if (((*cur)->flags & OP_TYPE_MASK) == OP_READ_DIRTY ||
|
|
||||||
((*cur)->flags & OP_TYPE_MASK) == OP_READ)
|
|
||||||
{
|
|
||||||
int dequeue_op = dequeue_read(*cur);
|
|
||||||
if (dequeue_op)
|
if (dequeue_op)
|
||||||
{
|
{
|
||||||
submit_queue.erase(cur);
|
submit_queue.erase(op_ptr);
|
||||||
}
|
}
|
||||||
else if ((*cur)->wait_for == WAIT_SQE)
|
else if (op->wait_for == WAIT_SQE)
|
||||||
{
|
{
|
||||||
// ring is full, stop submission
|
// ring is full, stop submission
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (((*cur)->flags & OP_TYPE_MASK) == OP_WRITE ||
|
else if ((op->flags & OP_TYPE_MASK) == OP_WRITE ||
|
||||||
((*cur)->flags & OP_TYPE_MASK) == OP_DELETE)
|
(op->flags & OP_TYPE_MASK) == OP_DELETE)
|
||||||
{
|
{
|
||||||
int dequeue_op = dequeue_write(*cur);
|
int dequeue_op = dequeue_write(op);
|
||||||
if (dequeue_op)
|
if (dequeue_op)
|
||||||
{
|
{
|
||||||
submit_queue.erase(cur);
|
submit_queue.erase(op_ptr);
|
||||||
}
|
}
|
||||||
else if ((*cur)->wait_for == WAIT_SQE)
|
else if (op->wait_for == WAIT_SQE)
|
||||||
{
|
{
|
||||||
// ring is full, stop submission
|
// ring is full, stop submission
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (((*cur)->flags & OP_TYPE_MASK) == OP_SYNC)
|
else if ((op->flags & OP_TYPE_MASK) == OP_SYNC)
|
||||||
{
|
{
|
||||||
|
// wait for all small writes to be submitted
|
||||||
|
// wait for all big writes to complete, submit data device fsync
|
||||||
|
// wait for the data device fsync to complete, then submit journal writes for big writes
|
||||||
|
// then submit an fsync operation
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (((*cur)->flags & OP_TYPE_MASK) == OP_STABLE)
|
else if ((op->flags & OP_TYPE_MASK) == OP_STABLE)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@ int blockstore::dequeue_read(blockstore_operation *read_op)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
unsigned prev_sqe_pos = ringloop->ring->sq.sqe_tail;
|
unsigned prev_sqe_pos = ringloop->ring->sq.sqe_tail;
|
||||||
|
unsigned ring_space = io_uring_sq_space_left(ringloop->ring);
|
||||||
uint64_t fulfilled = 0;
|
uint64_t fulfilled = 0;
|
||||||
if (dirty_found)
|
if (dirty_found)
|
||||||
{
|
{
|
||||||
|
@ -108,6 +109,10 @@ int blockstore::dequeue_read(blockstore_operation *read_op)
|
||||||
dirty.state, dirty_it->first.version, dirty.location) < 0)
|
dirty.state, dirty_it->first.version, dirty.location) < 0)
|
||||||
{
|
{
|
||||||
// need to wait. undo added requests, don't dequeue op
|
// need to wait. undo added requests, don't dequeue op
|
||||||
|
if (read_op->wait_for == WAIT_SQE)
|
||||||
|
{
|
||||||
|
read_op->wait_detail = 1 + ring_space;
|
||||||
|
}
|
||||||
ringloop->ring->sq.sqe_tail = prev_sqe_pos;
|
ringloop->ring->sq.sqe_tail = prev_sqe_pos;
|
||||||
read_op->read_vec.clear();
|
read_op->read_vec.clear();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -121,6 +126,10 @@ int blockstore::dequeue_read(blockstore_operation *read_op)
|
||||||
if (fulfill_read(read_op, 0, block_size, ST_CURRENT, 0, clean_it->second.location) < 0)
|
if (fulfill_read(read_op, 0, block_size, ST_CURRENT, 0, clean_it->second.location) < 0)
|
||||||
{
|
{
|
||||||
// need to wait. undo added requests, don't dequeue op
|
// need to wait. undo added requests, don't dequeue op
|
||||||
|
if (read_op->wait_for == WAIT_SQE)
|
||||||
|
{
|
||||||
|
read_op->wait_detail = 1 + ring_space;
|
||||||
|
}
|
||||||
ringloop->ring->sq.sqe_tail = prev_sqe_pos;
|
ringloop->ring->sq.sqe_tail = prev_sqe_pos;
|
||||||
read_op->read_vec.clear();
|
read_op->read_vec.clear();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -23,6 +23,7 @@ int blockstore::dequeue_write(blockstore_operation *op)
|
||||||
{
|
{
|
||||||
// Pause until there are more requests available
|
// Pause until there are more requests available
|
||||||
op->wait_for = WAIT_SQE;
|
op->wait_for = WAIT_SQE;
|
||||||
|
op->wait_detail = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
struct ring_data_t *data = ((ring_data_t*)sqe->user_data);
|
struct ring_data_t *data = ((ring_data_t*)sqe->user_data);
|
||||||
|
@ -67,15 +68,18 @@ int blockstore::dequeue_write(blockstore_operation *op)
|
||||||
{
|
{
|
||||||
// No space in the journal. Wait for it.
|
// No space in the journal. Wait for it.
|
||||||
op->wait_for = WAIT_JOURNAL;
|
op->wait_for = WAIT_JOURNAL;
|
||||||
op->wait_detail = next_pos - journal.used_start;
|
op->wait_detail = next_pos;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// There is sufficient space. Get SQE(s)
|
// There is sufficient space. Get SQE(s)
|
||||||
|
unsigned prev_sqe_pos = ringloop->ring->sq.sqe_tail;
|
||||||
struct io_uring_sqe *sqe1 = get_sqe(), *sqe2 = two_sqes ? get_sqe() : NULL;
|
struct io_uring_sqe *sqe1 = get_sqe(), *sqe2 = two_sqes ? get_sqe() : NULL;
|
||||||
if (!sqe1 || two_sqes && !sqe2)
|
if (!sqe1 || two_sqes && !sqe2)
|
||||||
{
|
{
|
||||||
// Pause until there are more requests available
|
// Pause until there are more requests available
|
||||||
op->wait_for = WAIT_SQE;
|
op->wait_for = WAIT_SQE;
|
||||||
|
op->wait_detail = two_sqes ? 2 : 1;
|
||||||
|
ringloop->ring->sq.sqe_tail = prev_sqe_pos;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
struct ring_data_t *data1 = ((ring_data_t*)sqe1->user_data);
|
struct ring_data_t *data1 = ((ring_data_t*)sqe1->user_data);
|
||||||
|
|
Loading…
Reference in New Issue