mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
selftests: ublk: kublk: lift queue initialization out of thread
Currently, each ublk server I/O handler thread initializes its own queue. However, as we move towards decoupled ublk_queues and ublk server threads, this model does not make sense anymore, as there will no longer be a concept of a thread having "its own" queue. So lift queue initialization out of the per-thread ublk_io_handler_fn and into a loop in ublk_start_daemon (which runs once for each device). There is a part of ublk_queue_init (ring initialization) which does actually need to happen on the thread that will use the ring; that is separated into a separate ublk_thread_init which is still called by each I/O handler thread. Signed-off-by: Uday Shankar <ushankar@purestorage.com> Reviewed-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20250529-ublk_task_per_io-v8-4-e9d3b119336a@purestorage.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
9773709752
commit
8f75ba28b8
|
|
@ -412,6 +412,17 @@ static void ublk_queue_deinit(struct ublk_queue *q)
|
|||
int i;
|
||||
int nr_ios = q->q_depth;
|
||||
|
||||
if (q->io_cmd_buf)
|
||||
munmap(q->io_cmd_buf, ublk_queue_cmd_buf_sz(q));
|
||||
|
||||
for (i = 0; i < nr_ios; i++)
|
||||
free(q->ios[i].buf_addr);
|
||||
}
|
||||
|
||||
static void ublk_thread_deinit(struct ublk_queue *q)
|
||||
{
|
||||
q->tid = 0;
|
||||
|
||||
io_uring_unregister_buffers(&q->ring);
|
||||
|
||||
io_uring_unregister_ring_fd(&q->ring);
|
||||
|
|
@ -421,28 +432,20 @@ static void ublk_queue_deinit(struct ublk_queue *q)
|
|||
close(q->ring.ring_fd);
|
||||
q->ring.ring_fd = -1;
|
||||
}
|
||||
|
||||
if (q->io_cmd_buf)
|
||||
munmap(q->io_cmd_buf, ublk_queue_cmd_buf_sz(q));
|
||||
|
||||
for (i = 0; i < nr_ios; i++)
|
||||
free(q->ios[i].buf_addr);
|
||||
}
|
||||
|
||||
static int ublk_queue_init(struct ublk_queue *q, unsigned extra_flags)
|
||||
{
|
||||
struct ublk_dev *dev = q->dev;
|
||||
int depth = dev->dev_info.queue_depth;
|
||||
int i, ret = -1;
|
||||
int i;
|
||||
int cmd_buf_size, io_buf_size;
|
||||
unsigned long off;
|
||||
int ring_depth = dev->tgt.sq_depth, cq_depth = dev->tgt.cq_depth;
|
||||
|
||||
q->tgt_ops = dev->tgt.ops;
|
||||
q->state = 0;
|
||||
q->q_depth = depth;
|
||||
q->cmd_inflight = 0;
|
||||
q->tid = gettid();
|
||||
|
||||
if (dev->dev_info.flags & (UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_AUTO_BUF_REG)) {
|
||||
q->state |= UBLKSRV_NO_BUF;
|
||||
|
|
@ -479,6 +482,22 @@ static int ublk_queue_init(struct ublk_queue *q, unsigned extra_flags)
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
ublk_queue_deinit(q);
|
||||
ublk_err("ublk dev %d queue %d failed\n",
|
||||
dev->dev_info.dev_id, q->q_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int ublk_thread_init(struct ublk_queue *q)
|
||||
{
|
||||
struct ublk_dev *dev = q->dev;
|
||||
int ring_depth = dev->tgt.sq_depth, cq_depth = dev->tgt.cq_depth;
|
||||
int ret;
|
||||
|
||||
q->tid = gettid();
|
||||
|
||||
ret = ublk_setup_ring(&q->ring, ring_depth, cq_depth,
|
||||
IORING_SETUP_COOP_TASKRUN |
|
||||
IORING_SETUP_SINGLE_ISSUER |
|
||||
|
|
@ -508,9 +527,9 @@ static int ublk_queue_init(struct ublk_queue *q, unsigned extra_flags)
|
|||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
ublk_queue_deinit(q);
|
||||
ublk_err("ublk dev %d queue %d failed\n",
|
||||
fail:
|
||||
ublk_thread_deinit(q);
|
||||
ublk_err("ublk dev %d queue %d thread init failed\n",
|
||||
dev->dev_info.dev_id, q->q_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
@ -778,7 +797,6 @@ struct ublk_queue_info {
|
|||
struct ublk_queue *q;
|
||||
sem_t *queue_sem;
|
||||
cpu_set_t *affinity;
|
||||
unsigned char auto_zc_fallback;
|
||||
};
|
||||
|
||||
static void *ublk_io_handler_fn(void *data)
|
||||
|
|
@ -786,15 +804,11 @@ static void *ublk_io_handler_fn(void *data)
|
|||
struct ublk_queue_info *info = data;
|
||||
struct ublk_queue *q = info->q;
|
||||
int dev_id = q->dev->dev_info.dev_id;
|
||||
unsigned extra_flags = 0;
|
||||
int ret;
|
||||
|
||||
if (info->auto_zc_fallback)
|
||||
extra_flags = UBLKSRV_AUTO_BUF_REG_FALLBACK;
|
||||
|
||||
ret = ublk_queue_init(q, extra_flags);
|
||||
ret = ublk_thread_init(q);
|
||||
if (ret) {
|
||||
ublk_err("ublk dev %d queue %d init queue failed\n",
|
||||
ublk_err("ublk dev %d queue %d thread init failed\n",
|
||||
dev_id, q->q_id);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -813,7 +827,7 @@ static void *ublk_io_handler_fn(void *data)
|
|||
} while (1);
|
||||
|
||||
ublk_dbg(UBLK_DBG_QUEUE, "ublk dev %d queue %d exited\n", dev_id, q->q_id);
|
||||
ublk_queue_deinit(q);
|
||||
ublk_thread_deinit(q);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -857,6 +871,7 @@ static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev)
|
|||
{
|
||||
const struct ublksrv_ctrl_dev_info *dinfo = &dev->dev_info;
|
||||
struct ublk_queue_info *qinfo;
|
||||
unsigned extra_flags = 0;
|
||||
cpu_set_t *affinity_buf;
|
||||
void *thread_ret;
|
||||
sem_t queue_sem;
|
||||
|
|
@ -878,14 +893,23 @@ static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ctx->auto_zc_fallback)
|
||||
extra_flags = UBLKSRV_AUTO_BUF_REG_FALLBACK;
|
||||
|
||||
for (i = 0; i < dinfo->nr_hw_queues; i++) {
|
||||
dev->q[i].dev = dev;
|
||||
dev->q[i].q_id = i;
|
||||
|
||||
ret = ublk_queue_init(&dev->q[i], extra_flags);
|
||||
if (ret) {
|
||||
ublk_err("ublk dev %d queue %d init queue failed\n",
|
||||
dinfo->dev_id, i);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
qinfo[i].q = &dev->q[i];
|
||||
qinfo[i].queue_sem = &queue_sem;
|
||||
qinfo[i].affinity = &affinity_buf[i];
|
||||
qinfo[i].auto_zc_fallback = ctx->auto_zc_fallback;
|
||||
pthread_create(&dev->q[i].thread, NULL,
|
||||
ublk_io_handler_fn,
|
||||
&qinfo[i]);
|
||||
|
|
@ -918,6 +942,8 @@ static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev)
|
|||
for (i = 0; i < dinfo->nr_hw_queues; i++)
|
||||
pthread_join(dev->q[i].thread, &thread_ret);
|
||||
fail:
|
||||
for (i = 0; i < dinfo->nr_hw_queues; i++)
|
||||
ublk_queue_deinit(&dev->q[i]);
|
||||
ublk_dev_unprep(dev);
|
||||
ublk_dbg(UBLK_DBG_DEV, "%s exit\n", __func__);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user