Handle full io_uring in ublk-server

This commit is contained in:
Vitaliy Filippov
2026-06-21 01:40:49 +03:00
parent 6b003bcc34
commit d4a42f61cf
+47 -1
View File
@@ -62,6 +62,13 @@ const char *help_text =
"All usual Vitastor config options like --config_path <path_to_config> may also be specified in CLI.\n" "All usual Vitastor config options like --config_path <path_to_config> may also be specified in CLI.\n"
; ;
struct ublk_request
{
uint64_t ublk_cmd;
int index;
int result;
};
class ublk_server class ublk_server
{ {
protected: protected:
@@ -331,6 +338,11 @@ help:
daemonize_fork(notifyfd); daemonize_fork(notifyfd);
close(notifyfd[0]); close(notifyfd[0]);
} }
consumer.loop = [this]()
{
submit_postponed();
};
ringloop->register_consumer(&consumer);
start_device(recover); start_device(recover);
if (pidfile != "") if (pidfile != "")
write_pid(); write_pid();
@@ -350,6 +362,7 @@ help:
ringloop->wait(); ringloop->wait();
} }
cli->flush(); cli->flush();
ringloop->unregister_consumer(&consumer);
delete cli; delete cli;
delete epmgr; delete epmgr;
cli = NULL; cli = NULL;
@@ -553,6 +566,8 @@ protected:
ublksrv_ctrl_dev_info ublk_dev = {}; ublksrv_ctrl_dev_info ublk_dev = {};
ublksrv_io_desc *ublk_queue = NULL; ublksrv_io_desc *ublk_queue = NULL;
std::vector<uint8_t*> buffers; std::vector<uint8_t*> buffers;
ring_consumer_t consumer;
std::vector<ublk_request> postponed_requests;
void open_control() void open_control()
{ {
@@ -734,9 +749,19 @@ protected:
ctrl_fd = -1; ctrl_fd = -1;
} }
void submit_request(uint64_t ublk_cmd, int i, int res) bool submit_request(uint64_t ublk_cmd, int i, int res)
{ {
io_uring_sqe *sqe = ringloop->get_sqe(); io_uring_sqe *sqe = ringloop->get_sqe();
if (!sqe)
{
// Handle full io_uring by postponing the request
postponed_requests.push_back((ublk_request){
.ublk_cmd = ublk_cmd,
.index = i,
.result = res,
});
return false;
}
ring_data_t* data = ((ring_data_t*)sqe->user_data); ring_data_t* data = ((ring_data_t*)sqe->user_data);
sqe->fd = cdev_fd; sqe->fd = cdev_fd;
sqe->opcode = IORING_OP_URING_CMD; sqe->opcode = IORING_OP_URING_CMD;
@@ -750,6 +775,22 @@ protected:
cmd->addr = (uint64_t)buffers[i]; cmd->addr = (uint64_t)buffers[i];
cmd->result = res; cmd->result = res;
data->callback = [this, i](ring_data_t *data) { exec_request(data->res, i); }; data->callback = [this, i](ring_data_t *data) { exec_request(data->res, i); };
return true;
}
void submit_postponed()
{
int sent = 0;
while (postponed_requests.size())
{
ublk_request r = postponed_requests.back();
postponed_requests.pop_back();
if (!submit_request(r.ublk_cmd, r.index, r.result))
break;
sent++;
}
if (sent)
ringloop->submit();
} }
void exec_request(int res, int i) void exec_request(int res, int i)
@@ -864,6 +905,11 @@ protected:
int sync_ublk_cmd(uint32_t cmd_op, void *addr, uint32_t len, uint16_t dev_path_len = 0, uint64_t data0 = 0) int sync_ublk_cmd(uint32_t cmd_op, void *addr, uint32_t len, uint16_t dev_path_len = 0, uint64_t data0 = 0)
{ {
io_uring_sqe *sqe = ringloop->get_sqe(); io_uring_sqe *sqe = ringloop->get_sqe();
if (!sqe)
{
fprintf(stderr, "Error: io_uring is full when trying to execute a control command\n");
exit(1);
}
sqe->fd = ctrl_fd; sqe->fd = ctrl_fd;
sqe->opcode = IORING_OP_URING_CMD; sqe->opcode = IORING_OP_URING_CMD;
sqe->ioprio = 0; sqe->ioprio = 0;