From b3c78b04ac6b80e171271a833c0221b8ab3b2b00 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 12 Mar 2025 07:33:55 +0000 Subject: [PATCH] loop: debug: add threaded aio Signed-off-by: Ming Lei --- drivers/block/loop.c | 47 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 393f38573169..113e29b3ac80 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -86,6 +86,8 @@ struct loop_cmd { struct bio_vec *bvec; struct cgroup_subsys_state *blkcg_css; struct cgroup_subsys_state *memcg_css; + + struct work_struct work; }; #define LOOP_IDLE_WORKER_TIMEOUT (60 * HZ) @@ -98,6 +100,8 @@ static DEFINE_IDR(loop_index_idr); static DEFINE_MUTEX(loop_ctl_mutex); static DEFINE_MUTEX(loop_validate_mutex); +static unsigned int threaded_aio = 0; + /** * loop_global_lock_killable() - take locks for safe loop_validate_file() test * @@ -508,10 +512,17 @@ static int lo_rw_aio_prep(struct loop_device *lo, struct loop_cmd *cmd, static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, loff_t pos) { unsigned int nr_bvec = lo_cmd_nr_bvec(cmd); - int ret; + int ret = 0; + + if (threaded_aio) { + ret = lo_rw_aio_prep(lo, cmd, nr_bvec); + if (ret < 0) + goto exit; + } cmd->iocb.ki_flags &= ~IOCB_NOWAIT; ret = lo_submit_rw_aio(lo, cmd, pos, nr_bvec); +exit: if (ret != -EIOCBQUEUED) lo_rw_aio_complete(&cmd->iocb, ret); return 0; @@ -1941,10 +1952,39 @@ static const struct kernel_param_ops loop_nr_hw_q_param_ops = { device_param_cb(nr_hw_queues, &loop_nr_hw_q_param_ops, &nr_hw_queues, 0444); MODULE_PARM_DESC(nr_hw_queues, "number of hardware queues. Default: " __stringify(LOOP_DEFAULT_NR_HW_Q)); +module_param(threaded_aio, uint, 0644); +MODULE_PARM_DESC(threaded_aio, "threaded aio"); + MODULE_DESCRIPTION("Loopback device support"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); +static void loop_aio_workfn(struct work_struct *work) +{ + struct loop_cmd *cmd = container_of(work, struct loop_cmd, work); + struct request *rq = blk_mq_rq_from_pdu(cmd); + struct loop_device *lo = rq->q->queuedata; + int ret = do_req_filebacked(lo, rq); + + if (!cmd->use_aio || ret) { + if (ret == -EOPNOTSUPP) + cmd->ret = ret; + else + cmd->ret = ret ? -EIO : 0; + if (likely(!blk_should_fake_timeout(rq->q))) + blk_mq_complete_request(rq); + } +} + +static void loop_queue_rq_threaded_aio(struct loop_cmd *cmd) +{ + struct request *rq = blk_mq_rq_from_pdu(cmd); + struct loop_device *lo = rq->q->queuedata; + + INIT_WORK(&cmd->work, loop_aio_workfn); + queue_work(lo->workqueue, &cmd->work); +} + static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) { @@ -1968,6 +2008,11 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx, break; } + if (threaded_aio) { + loop_queue_rq_threaded_aio(cmd); + return BLK_STS_OK; + } + if (cmd->use_aio) { loff_t pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset; int ret = lo_rw_aio_nowait(lo, cmd, pos); -- 2.47.1