* [PATCH 0/2] ublk: fix ublk_queue_rqs() and selftests test_stress_03
@ 2025-06-23 1:19 Ming Lei
2025-06-23 1:19 ` [PATCH 1/2] ublk: build per-io-ring-ctx batch list Ming Lei
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Ming Lei @ 2025-06-23 1:19 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Uday Shankar, Caleb Sander Mateos, Ming Lei
Hi Jens,
The 1st patch fixes ublk_queue_rqs().
The 2nd patch fixes test_stress_03.sh.
Thanks,
Ming Lei (2):
ublk: build per-io-ring-ctx batch list
selftests: ublk: don't take same backing file for more than one ublk
devices
drivers/block/ublk_drv.c | 17 +++++++++--------
tools/testing/selftests/ublk/test_stress_03.sh | 5 +++--
2 files changed, 12 insertions(+), 10 deletions(-)
--
2.47.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] ublk: build per-io-ring-ctx batch list
2025-06-23 1:19 [PATCH 0/2] ublk: fix ublk_queue_rqs() and selftests test_stress_03 Ming Lei
@ 2025-06-23 1:19 ` Ming Lei
2025-06-23 17:51 ` Caleb Sander Mateos
2025-06-23 1:19 ` [PATCH 2/2] selftests: ublk: don't take same backing file for more than one ublk devices Ming Lei
2025-06-24 14:51 ` [PATCH 0/2] ublk: fix ublk_queue_rqs() and selftests test_stress_03 Jens Axboe
2 siblings, 1 reply; 12+ messages in thread
From: Ming Lei @ 2025-06-23 1:19 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Uday Shankar, Caleb Sander Mateos, Ming Lei
ublk_queue_cmd_list() dispatches the whole batch list by scheduling task
work via the tail request's io_uring_cmd, this way is fine even though
more than one io_ring_ctx are involved for this batch since it is just
one running context.
However, the task work handler ublk_cmd_list_tw_cb() takes `issue_flags`
of tail uring_cmd's io_ring_ctx for completing all commands. This way is
wrong if any uring_cmd is issued from different io_ring_ctx.
Fixes it by always building per-io-ring-ctx batch list.
For typical per-queue or per-io daemon implementation, this way shouldn't
make difference from performance viewpoint, because single io_ring_ctx is
often taken in each daemon.
Fixes: d796cea7b9f3 ("ublk: implement ->queue_rqs()")
Fixes: ab03a61c6614 ("ublk: have a per-io daemon instead of a per-queue daemon")
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
drivers/block/ublk_drv.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index c637ea010d34..e79b04e61047 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -1336,9 +1336,8 @@ static void ublk_cmd_list_tw_cb(struct io_uring_cmd *cmd,
} while (rq);
}
-static void ublk_queue_cmd_list(struct ublk_io *io, struct rq_list *l)
+static void ublk_queue_cmd_list(struct io_uring_cmd *cmd, struct rq_list *l)
{
- struct io_uring_cmd *cmd = io->cmd;
struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
pdu->req_list = rq_list_peek(l);
@@ -1420,16 +1419,18 @@ static void ublk_queue_rqs(struct rq_list *rqlist)
{
struct rq_list requeue_list = { };
struct rq_list submit_list = { };
- struct ublk_io *io = NULL;
+ struct io_uring_cmd *cmd = NULL;
struct request *req;
while ((req = rq_list_pop(rqlist))) {
struct ublk_queue *this_q = req->mq_hctx->driver_data;
- struct ublk_io *this_io = &this_q->ios[req->tag];
+ struct io_uring_cmd *this_cmd = this_q->ios[req->tag].cmd;
- if (io && io->task != this_io->task && !rq_list_empty(&submit_list))
- ublk_queue_cmd_list(io, &submit_list);
- io = this_io;
+ if (cmd && io_uring_cmd_ctx_handle(cmd) !=
+ io_uring_cmd_ctx_handle(this_cmd) &&
+ !rq_list_empty(&submit_list))
+ ublk_queue_cmd_list(cmd, &submit_list);
+ cmd = this_cmd;
if (ublk_prep_req(this_q, req, true) == BLK_STS_OK)
rq_list_add_tail(&submit_list, req);
@@ -1438,7 +1439,7 @@ static void ublk_queue_rqs(struct rq_list *rqlist)
}
if (!rq_list_empty(&submit_list))
- ublk_queue_cmd_list(io, &submit_list);
+ ublk_queue_cmd_list(cmd, &submit_list);
*rqlist = requeue_list;
}
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/2] selftests: ublk: don't take same backing file for more than one ublk devices
2025-06-23 1:19 [PATCH 0/2] ublk: fix ublk_queue_rqs() and selftests test_stress_03 Ming Lei
2025-06-23 1:19 ` [PATCH 1/2] ublk: build per-io-ring-ctx batch list Ming Lei
@ 2025-06-23 1:19 ` Ming Lei
2025-06-23 17:54 ` Caleb Sander Mateos
2025-06-24 14:51 ` [PATCH 0/2] ublk: fix ublk_queue_rqs() and selftests test_stress_03 Jens Axboe
2 siblings, 1 reply; 12+ messages in thread
From: Ming Lei @ 2025-06-23 1:19 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Uday Shankar, Caleb Sander Mateos, Ming Lei
Don't use same backing file for more than one ublk devices, and avoid
concurrent write on same file from more ublk disks.
Fixes: 8ccebc19ee3d ("selftests: ublk: support UBLK_F_AUTO_BUF_REG")
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
tools/testing/selftests/ublk/test_stress_03.sh | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/ublk/test_stress_03.sh b/tools/testing/selftests/ublk/test_stress_03.sh
index 6eef282d569f..3ed4c9b2d8c0 100755
--- a/tools/testing/selftests/ublk/test_stress_03.sh
+++ b/tools/testing/selftests/ublk/test_stress_03.sh
@@ -32,22 +32,23 @@ _create_backfile 2 128M
ublk_io_and_remove 8G -t null -q 4 -z &
ublk_io_and_remove 256M -t loop -q 4 -z "${UBLK_BACKFILES[0]}" &
ublk_io_and_remove 256M -t stripe -q 4 -z "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
+wait
if _have_feature "AUTO_BUF_REG"; then
ublk_io_and_remove 8G -t null -q 4 --auto_zc &
ublk_io_and_remove 256M -t loop -q 4 --auto_zc "${UBLK_BACKFILES[0]}" &
ublk_io_and_remove 256M -t stripe -q 4 --auto_zc "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
ublk_io_and_remove 8G -t null -q 4 -z --auto_zc --auto_zc_fallback &
+ wait
fi
-wait
if _have_feature "PER_IO_DAEMON"; then
ublk_io_and_remove 8G -t null -q 4 --auto_zc --nthreads 8 --per_io_tasks &
ublk_io_and_remove 256M -t loop -q 4 --auto_zc --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" &
ublk_io_and_remove 256M -t stripe -q 4 --auto_zc --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
ublk_io_and_remove 8G -t null -q 4 -z --auto_zc --auto_zc_fallback --nthreads 8 --per_io_tasks &
+ wait
fi
-wait
_cleanup_test "stress"
_show_result $TID $ERR_CODE
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] ublk: build per-io-ring-ctx batch list
2025-06-23 1:19 ` [PATCH 1/2] ublk: build per-io-ring-ctx batch list Ming Lei
@ 2025-06-23 17:51 ` Caleb Sander Mateos
2025-06-24 1:24 ` Ming Lei
0 siblings, 1 reply; 12+ messages in thread
From: Caleb Sander Mateos @ 2025-06-23 17:51 UTC (permalink / raw)
To: Ming Lei; +Cc: Jens Axboe, linux-block, Uday Shankar
On Sun, Jun 22, 2025 at 6:19 PM Ming Lei <ming.lei@redhat.com> wrote:
>
> ublk_queue_cmd_list() dispatches the whole batch list by scheduling task
> work via the tail request's io_uring_cmd, this way is fine even though
> more than one io_ring_ctx are involved for this batch since it is just
> one running context.
>
> However, the task work handler ublk_cmd_list_tw_cb() takes `issue_flags`
> of tail uring_cmd's io_ring_ctx for completing all commands. This way is
> wrong if any uring_cmd is issued from different io_ring_ctx.
>
> Fixes it by always building per-io-ring-ctx batch list.
>
> For typical per-queue or per-io daemon implementation, this way shouldn't
> make difference from performance viewpoint, because single io_ring_ctx is
> often taken in each daemon.
>
> Fixes: d796cea7b9f3 ("ublk: implement ->queue_rqs()")
> Fixes: ab03a61c6614 ("ublk: have a per-io daemon instead of a per-queue daemon")
> Signed-off-by: Ming Lei <ming.lei@redhat.com>
> ---
> drivers/block/ublk_drv.c | 17 +++++++++--------
> 1 file changed, 9 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> index c637ea010d34..e79b04e61047 100644
> --- a/drivers/block/ublk_drv.c
> +++ b/drivers/block/ublk_drv.c
> @@ -1336,9 +1336,8 @@ static void ublk_cmd_list_tw_cb(struct io_uring_cmd *cmd,
> } while (rq);
> }
>
> -static void ublk_queue_cmd_list(struct ublk_io *io, struct rq_list *l)
> +static void ublk_queue_cmd_list(struct io_uring_cmd *cmd, struct rq_list *l)
> {
> - struct io_uring_cmd *cmd = io->cmd;
> struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
>
> pdu->req_list = rq_list_peek(l);
> @@ -1420,16 +1419,18 @@ static void ublk_queue_rqs(struct rq_list *rqlist)
> {
> struct rq_list requeue_list = { };
> struct rq_list submit_list = { };
> - struct ublk_io *io = NULL;
> + struct io_uring_cmd *cmd = NULL;
> struct request *req;
>
> while ((req = rq_list_pop(rqlist))) {
> struct ublk_queue *this_q = req->mq_hctx->driver_data;
> - struct ublk_io *this_io = &this_q->ios[req->tag];
> + struct io_uring_cmd *this_cmd = this_q->ios[req->tag].cmd;
>
> - if (io && io->task != this_io->task && !rq_list_empty(&submit_list))
> - ublk_queue_cmd_list(io, &submit_list);
> - io = this_io;
> + if (cmd && io_uring_cmd_ctx_handle(cmd) !=
> + io_uring_cmd_ctx_handle(this_cmd) &&
> + !rq_list_empty(&submit_list))
> + ublk_queue_cmd_list(cmd, &submit_list);
I don't think we can assume that ublk commands submitted to the same
io_uring have the same daemon task. It's possible for multiple tasks
to submit to the same io_uring, even though that's not a common or
performant way to use io_uring. Probably we need to check that both
the task and io_ring_ctx match.
Best,
Caleb
> + cmd = this_cmd;
>
> if (ublk_prep_req(this_q, req, true) == BLK_STS_OK)
> rq_list_add_tail(&submit_list, req);
> @@ -1438,7 +1439,7 @@ static void ublk_queue_rqs(struct rq_list *rqlist)
> }
>
> if (!rq_list_empty(&submit_list))
> - ublk_queue_cmd_list(io, &submit_list);
> + ublk_queue_cmd_list(cmd, &submit_list);
> *rqlist = requeue_list;
> }
>
> --
> 2.47.0
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] selftests: ublk: don't take same backing file for more than one ublk devices
2025-06-23 1:19 ` [PATCH 2/2] selftests: ublk: don't take same backing file for more than one ublk devices Ming Lei
@ 2025-06-23 17:54 ` Caleb Sander Mateos
2025-06-24 1:13 ` Ming Lei
0 siblings, 1 reply; 12+ messages in thread
From: Caleb Sander Mateos @ 2025-06-23 17:54 UTC (permalink / raw)
To: Ming Lei; +Cc: Jens Axboe, linux-block, Uday Shankar
On Sun, Jun 22, 2025 at 6:19 PM Ming Lei <ming.lei@redhat.com> wrote:
>
> Don't use same backing file for more than one ublk devices, and avoid
> concurrent write on same file from more ublk disks.
>
> Fixes: 8ccebc19ee3d ("selftests: ublk: support UBLK_F_AUTO_BUF_REG")
> Signed-off-by: Ming Lei <ming.lei@redhat.com>
> ---
> tools/testing/selftests/ublk/test_stress_03.sh | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/tools/testing/selftests/ublk/test_stress_03.sh b/tools/testing/selftests/ublk/test_stress_03.sh
> index 6eef282d569f..3ed4c9b2d8c0 100755
> --- a/tools/testing/selftests/ublk/test_stress_03.sh
> +++ b/tools/testing/selftests/ublk/test_stress_03.sh
> @@ -32,22 +32,23 @@ _create_backfile 2 128M
> ublk_io_and_remove 8G -t null -q 4 -z &
> ublk_io_and_remove 256M -t loop -q 4 -z "${UBLK_BACKFILES[0]}" &
> ublk_io_and_remove 256M -t stripe -q 4 -z "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
> +wait
Why is wait necessary here? It looks like __run_io_and_remove, which
is called from run_io_and_remove, already ends with a wait. Am I
missing something?
Best,
Caleb
>
> if _have_feature "AUTO_BUF_REG"; then
> ublk_io_and_remove 8G -t null -q 4 --auto_zc &
> ublk_io_and_remove 256M -t loop -q 4 --auto_zc "${UBLK_BACKFILES[0]}" &
> ublk_io_and_remove 256M -t stripe -q 4 --auto_zc "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
> ublk_io_and_remove 8G -t null -q 4 -z --auto_zc --auto_zc_fallback &
> + wait
> fi
> -wait
>
> if _have_feature "PER_IO_DAEMON"; then
> ublk_io_and_remove 8G -t null -q 4 --auto_zc --nthreads 8 --per_io_tasks &
> ublk_io_and_remove 256M -t loop -q 4 --auto_zc --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" &
> ublk_io_and_remove 256M -t stripe -q 4 --auto_zc --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
> ublk_io_and_remove 8G -t null -q 4 -z --auto_zc --auto_zc_fallback --nthreads 8 --per_io_tasks &
> + wait
> fi
> -wait
>
> _cleanup_test "stress"
> _show_result $TID $ERR_CODE
> --
> 2.47.0
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] selftests: ublk: don't take same backing file for more than one ublk devices
2025-06-23 17:54 ` Caleb Sander Mateos
@ 2025-06-24 1:13 ` Ming Lei
2025-06-24 15:20 ` Caleb Sander Mateos
0 siblings, 1 reply; 12+ messages in thread
From: Ming Lei @ 2025-06-24 1:13 UTC (permalink / raw)
To: Caleb Sander Mateos; +Cc: Jens Axboe, linux-block, Uday Shankar
On Mon, Jun 23, 2025 at 10:54:58AM -0700, Caleb Sander Mateos wrote:
> On Sun, Jun 22, 2025 at 6:19 PM Ming Lei <ming.lei@redhat.com> wrote:
> >
> > Don't use same backing file for more than one ublk devices, and avoid
> > concurrent write on same file from more ublk disks.
> >
> > Fixes: 8ccebc19ee3d ("selftests: ublk: support UBLK_F_AUTO_BUF_REG")
> > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > ---
> > tools/testing/selftests/ublk/test_stress_03.sh | 5 +++--
> > 1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/tools/testing/selftests/ublk/test_stress_03.sh b/tools/testing/selftests/ublk/test_stress_03.sh
> > index 6eef282d569f..3ed4c9b2d8c0 100755
> > --- a/tools/testing/selftests/ublk/test_stress_03.sh
> > +++ b/tools/testing/selftests/ublk/test_stress_03.sh
> > @@ -32,22 +32,23 @@ _create_backfile 2 128M
> > ublk_io_and_remove 8G -t null -q 4 -z &
> > ublk_io_and_remove 256M -t loop -q 4 -z "${UBLK_BACKFILES[0]}" &
> > ublk_io_and_remove 256M -t stripe -q 4 -z "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
> > +wait
>
> Why is wait necessary here? It looks like __run_io_and_remove, which
> is called from run_io_and_remove, already ends with a wait. Am I
> missing something?
All tests share the three backing files, this way just avoids concurrent
write to the same file from each test/ublk device.
Thanks,
Ming
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] ublk: build per-io-ring-ctx batch list
2025-06-23 17:51 ` Caleb Sander Mateos
@ 2025-06-24 1:24 ` Ming Lei
2025-06-24 15:26 ` Caleb Sander Mateos
0 siblings, 1 reply; 12+ messages in thread
From: Ming Lei @ 2025-06-24 1:24 UTC (permalink / raw)
To: Caleb Sander Mateos; +Cc: Jens Axboe, linux-block, Uday Shankar
On Mon, Jun 23, 2025 at 10:51:00AM -0700, Caleb Sander Mateos wrote:
> On Sun, Jun 22, 2025 at 6:19 PM Ming Lei <ming.lei@redhat.com> wrote:
> >
> > ublk_queue_cmd_list() dispatches the whole batch list by scheduling task
> > work via the tail request's io_uring_cmd, this way is fine even though
> > more than one io_ring_ctx are involved for this batch since it is just
> > one running context.
> >
> > However, the task work handler ublk_cmd_list_tw_cb() takes `issue_flags`
> > of tail uring_cmd's io_ring_ctx for completing all commands. This way is
> > wrong if any uring_cmd is issued from different io_ring_ctx.
> >
> > Fixes it by always building per-io-ring-ctx batch list.
> >
> > For typical per-queue or per-io daemon implementation, this way shouldn't
> > make difference from performance viewpoint, because single io_ring_ctx is
> > often taken in each daemon.
> >
> > Fixes: d796cea7b9f3 ("ublk: implement ->queue_rqs()")
> > Fixes: ab03a61c6614 ("ublk: have a per-io daemon instead of a per-queue daemon")
> > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > ---
> > drivers/block/ublk_drv.c | 17 +++++++++--------
> > 1 file changed, 9 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> > index c637ea010d34..e79b04e61047 100644
> > --- a/drivers/block/ublk_drv.c
> > +++ b/drivers/block/ublk_drv.c
> > @@ -1336,9 +1336,8 @@ static void ublk_cmd_list_tw_cb(struct io_uring_cmd *cmd,
> > } while (rq);
> > }
> >
> > -static void ublk_queue_cmd_list(struct ublk_io *io, struct rq_list *l)
> > +static void ublk_queue_cmd_list(struct io_uring_cmd *cmd, struct rq_list *l)
> > {
> > - struct io_uring_cmd *cmd = io->cmd;
> > struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
> >
> > pdu->req_list = rq_list_peek(l);
> > @@ -1420,16 +1419,18 @@ static void ublk_queue_rqs(struct rq_list *rqlist)
> > {
> > struct rq_list requeue_list = { };
> > struct rq_list submit_list = { };
> > - struct ublk_io *io = NULL;
> > + struct io_uring_cmd *cmd = NULL;
> > struct request *req;
> >
> > while ((req = rq_list_pop(rqlist))) {
> > struct ublk_queue *this_q = req->mq_hctx->driver_data;
> > - struct ublk_io *this_io = &this_q->ios[req->tag];
> > + struct io_uring_cmd *this_cmd = this_q->ios[req->tag].cmd;
> >
> > - if (io && io->task != this_io->task && !rq_list_empty(&submit_list))
> > - ublk_queue_cmd_list(io, &submit_list);
> > - io = this_io;
> > + if (cmd && io_uring_cmd_ctx_handle(cmd) !=
> > + io_uring_cmd_ctx_handle(this_cmd) &&
> > + !rq_list_empty(&submit_list))
> > + ublk_queue_cmd_list(cmd, &submit_list);
>
> I don't think we can assume that ublk commands submitted to the same
> io_uring have the same daemon task. It's possible for multiple tasks
> to submit to the same io_uring, even though that's not a common or
> performant way to use io_uring. Probably we need to check that both
> the task and io_ring_ctx match.
Here the problem is in 'issue_flags' passed from io_uring, especially for
grabbing io_ring_ctx lock.
If two uring_cmd are issued via same io_ring_ctx from two tasks, it is
fine to share 'issue_flags' from one of tasks, what matters is that the
io_ring_ctx lock is handled correctly when calling io_uring_cmd_done().
Thanks,
Ming
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 0/2] ublk: fix ublk_queue_rqs() and selftests test_stress_03
2025-06-23 1:19 [PATCH 0/2] ublk: fix ublk_queue_rqs() and selftests test_stress_03 Ming Lei
2025-06-23 1:19 ` [PATCH 1/2] ublk: build per-io-ring-ctx batch list Ming Lei
2025-06-23 1:19 ` [PATCH 2/2] selftests: ublk: don't take same backing file for more than one ublk devices Ming Lei
@ 2025-06-24 14:51 ` Jens Axboe
2 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2025-06-24 14:51 UTC (permalink / raw)
To: linux-block, Ming Lei; +Cc: Uday Shankar, Caleb Sander Mateos
On Mon, 23 Jun 2025 09:19:25 +0800, Ming Lei wrote:
> The 1st patch fixes ublk_queue_rqs().
>
> The 2nd patch fixes test_stress_03.sh.
>
> Thanks,
>
>
> [...]
Applied, thanks!
[1/2] ublk: build per-io-ring-ctx batch list
commit: e867d6c4d51a564943e88e08fb1b27bc68a81b49
[2/2] selftests: ublk: don't take same backing file for more than one ublk devices
commit: 4cb1a3d63eb7d4d0263b2d3ab4f61555263b69aa
Best regards,
--
Jens Axboe
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] selftests: ublk: don't take same backing file for more than one ublk devices
2025-06-24 1:13 ` Ming Lei
@ 2025-06-24 15:20 ` Caleb Sander Mateos
0 siblings, 0 replies; 12+ messages in thread
From: Caleb Sander Mateos @ 2025-06-24 15:20 UTC (permalink / raw)
To: Ming Lei; +Cc: Jens Axboe, linux-block, Uday Shankar
On Mon, Jun 23, 2025 at 6:13 PM Ming Lei <ming.lei@redhat.com> wrote:
>
> On Mon, Jun 23, 2025 at 10:54:58AM -0700, Caleb Sander Mateos wrote:
> > On Sun, Jun 22, 2025 at 6:19 PM Ming Lei <ming.lei@redhat.com> wrote:
> > >
> > > Don't use same backing file for more than one ublk devices, and avoid
> > > concurrent write on same file from more ublk disks.
> > >
> > > Fixes: 8ccebc19ee3d ("selftests: ublk: support UBLK_F_AUTO_BUF_REG")
> > > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > > ---
> > > tools/testing/selftests/ublk/test_stress_03.sh | 5 +++--
> > > 1 file changed, 3 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/tools/testing/selftests/ublk/test_stress_03.sh b/tools/testing/selftests/ublk/test_stress_03.sh
> > > index 6eef282d569f..3ed4c9b2d8c0 100755
> > > --- a/tools/testing/selftests/ublk/test_stress_03.sh
> > > +++ b/tools/testing/selftests/ublk/test_stress_03.sh
> > > @@ -32,22 +32,23 @@ _create_backfile 2 128M
> > > ublk_io_and_remove 8G -t null -q 4 -z &
> > > ublk_io_and_remove 256M -t loop -q 4 -z "${UBLK_BACKFILES[0]}" &
> > > ublk_io_and_remove 256M -t stripe -q 4 -z "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
> > > +wait
> >
> > Why is wait necessary here? It looks like __run_io_and_remove, which
> > is called from run_io_and_remove, already ends with a wait. Am I
> > missing something?
>
> All tests share the three backing files, this way just avoids concurrent
> write to the same file from each test/ublk device.
Sorry, I didn't see the "&" at the end of the ublk_io_and_remove commands.
Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] ublk: build per-io-ring-ctx batch list
2025-06-24 1:24 ` Ming Lei
@ 2025-06-24 15:26 ` Caleb Sander Mateos
2025-06-25 1:22 ` Ming Lei
0 siblings, 1 reply; 12+ messages in thread
From: Caleb Sander Mateos @ 2025-06-24 15:26 UTC (permalink / raw)
To: Ming Lei; +Cc: Jens Axboe, linux-block, Uday Shankar
On Mon, Jun 23, 2025 at 6:24 PM Ming Lei <ming.lei@redhat.com> wrote:
>
> On Mon, Jun 23, 2025 at 10:51:00AM -0700, Caleb Sander Mateos wrote:
> > On Sun, Jun 22, 2025 at 6:19 PM Ming Lei <ming.lei@redhat.com> wrote:
> > >
> > > ublk_queue_cmd_list() dispatches the whole batch list by scheduling task
> > > work via the tail request's io_uring_cmd, this way is fine even though
> > > more than one io_ring_ctx are involved for this batch since it is just
> > > one running context.
> > >
> > > However, the task work handler ublk_cmd_list_tw_cb() takes `issue_flags`
> > > of tail uring_cmd's io_ring_ctx for completing all commands. This way is
> > > wrong if any uring_cmd is issued from different io_ring_ctx.
> > >
> > > Fixes it by always building per-io-ring-ctx batch list.
> > >
> > > For typical per-queue or per-io daemon implementation, this way shouldn't
> > > make difference from performance viewpoint, because single io_ring_ctx is
> > > often taken in each daemon.
> > >
> > > Fixes: d796cea7b9f3 ("ublk: implement ->queue_rqs()")
> > > Fixes: ab03a61c6614 ("ublk: have a per-io daemon instead of a per-queue daemon")
> > > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > > ---
> > > drivers/block/ublk_drv.c | 17 +++++++++--------
> > > 1 file changed, 9 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> > > index c637ea010d34..e79b04e61047 100644
> > > --- a/drivers/block/ublk_drv.c
> > > +++ b/drivers/block/ublk_drv.c
> > > @@ -1336,9 +1336,8 @@ static void ublk_cmd_list_tw_cb(struct io_uring_cmd *cmd,
> > > } while (rq);
> > > }
> > >
> > > -static void ublk_queue_cmd_list(struct ublk_io *io, struct rq_list *l)
> > > +static void ublk_queue_cmd_list(struct io_uring_cmd *cmd, struct rq_list *l)
> > > {
> > > - struct io_uring_cmd *cmd = io->cmd;
> > > struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
> > >
> > > pdu->req_list = rq_list_peek(l);
> > > @@ -1420,16 +1419,18 @@ static void ublk_queue_rqs(struct rq_list *rqlist)
> > > {
> > > struct rq_list requeue_list = { };
> > > struct rq_list submit_list = { };
> > > - struct ublk_io *io = NULL;
> > > + struct io_uring_cmd *cmd = NULL;
> > > struct request *req;
> > >
> > > while ((req = rq_list_pop(rqlist))) {
> > > struct ublk_queue *this_q = req->mq_hctx->driver_data;
> > > - struct ublk_io *this_io = &this_q->ios[req->tag];
> > > + struct io_uring_cmd *this_cmd = this_q->ios[req->tag].cmd;
> > >
> > > - if (io && io->task != this_io->task && !rq_list_empty(&submit_list))
> > > - ublk_queue_cmd_list(io, &submit_list);
> > > - io = this_io;
> > > + if (cmd && io_uring_cmd_ctx_handle(cmd) !=
> > > + io_uring_cmd_ctx_handle(this_cmd) &&
> > > + !rq_list_empty(&submit_list))
> > > + ublk_queue_cmd_list(cmd, &submit_list);
> >
> > I don't think we can assume that ublk commands submitted to the same
> > io_uring have the same daemon task. It's possible for multiple tasks
> > to submit to the same io_uring, even though that's not a common or
> > performant way to use io_uring. Probably we need to check that both
> > the task and io_ring_ctx match.
>
> Here the problem is in 'issue_flags' passed from io_uring, especially for
> grabbing io_ring_ctx lock.
>
> If two uring_cmd are issued via same io_ring_ctx from two tasks, it is
> fine to share 'issue_flags' from one of tasks, what matters is that the
> io_ring_ctx lock is handled correctly when calling io_uring_cmd_done().
Right, I understand the issue you are trying to solve. I agree it's a
problem for submit_list to contain commands from multiple
io_ring_ctxs. But it's also a problem if it contains commands with
different daemon tasks, because ublk_queue_cmd_list() will schedule
ublk_cmd_list_tw_cb() to be called in the *last command's task*. But
ublk_cmd_list_tw_cb() will call ublk_dispatch_req() for all the
commands in the list. So if submit_list contains commands with
multiple daemon tasks, ublk_dispatch_req() will fail on the current !=
io->task check. So I still feel we need to call
ublk_queue_cmd_list(io, &submit_list) if io->task != this_io->task (as
well as if the io_ring_ctxs differ).
Best,
Caleb
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] ublk: build per-io-ring-ctx batch list
2025-06-24 15:26 ` Caleb Sander Mateos
@ 2025-06-25 1:22 ` Ming Lei
2025-06-25 2:44 ` Jens Axboe
0 siblings, 1 reply; 12+ messages in thread
From: Ming Lei @ 2025-06-25 1:22 UTC (permalink / raw)
To: Caleb Sander Mateos; +Cc: Jens Axboe, linux-block, Uday Shankar
On Tue, Jun 24, 2025 at 08:26:51AM -0700, Caleb Sander Mateos wrote:
> On Mon, Jun 23, 2025 at 6:24 PM Ming Lei <ming.lei@redhat.com> wrote:
> >
> > On Mon, Jun 23, 2025 at 10:51:00AM -0700, Caleb Sander Mateos wrote:
> > > On Sun, Jun 22, 2025 at 6:19 PM Ming Lei <ming.lei@redhat.com> wrote:
> > > >
> > > > ublk_queue_cmd_list() dispatches the whole batch list by scheduling task
> > > > work via the tail request's io_uring_cmd, this way is fine even though
> > > > more than one io_ring_ctx are involved for this batch since it is just
> > > > one running context.
> > > >
> > > > However, the task work handler ublk_cmd_list_tw_cb() takes `issue_flags`
> > > > of tail uring_cmd's io_ring_ctx for completing all commands. This way is
> > > > wrong if any uring_cmd is issued from different io_ring_ctx.
> > > >
> > > > Fixes it by always building per-io-ring-ctx batch list.
> > > >
> > > > For typical per-queue or per-io daemon implementation, this way shouldn't
> > > > make difference from performance viewpoint, because single io_ring_ctx is
> > > > often taken in each daemon.
> > > >
> > > > Fixes: d796cea7b9f3 ("ublk: implement ->queue_rqs()")
> > > > Fixes: ab03a61c6614 ("ublk: have a per-io daemon instead of a per-queue daemon")
> > > > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > > > ---
> > > > drivers/block/ublk_drv.c | 17 +++++++++--------
> > > > 1 file changed, 9 insertions(+), 8 deletions(-)
> > > >
> > > > diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> > > > index c637ea010d34..e79b04e61047 100644
> > > > --- a/drivers/block/ublk_drv.c
> > > > +++ b/drivers/block/ublk_drv.c
> > > > @@ -1336,9 +1336,8 @@ static void ublk_cmd_list_tw_cb(struct io_uring_cmd *cmd,
> > > > } while (rq);
> > > > }
> > > >
> > > > -static void ublk_queue_cmd_list(struct ublk_io *io, struct rq_list *l)
> > > > +static void ublk_queue_cmd_list(struct io_uring_cmd *cmd, struct rq_list *l)
> > > > {
> > > > - struct io_uring_cmd *cmd = io->cmd;
> > > > struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
> > > >
> > > > pdu->req_list = rq_list_peek(l);
> > > > @@ -1420,16 +1419,18 @@ static void ublk_queue_rqs(struct rq_list *rqlist)
> > > > {
> > > > struct rq_list requeue_list = { };
> > > > struct rq_list submit_list = { };
> > > > - struct ublk_io *io = NULL;
> > > > + struct io_uring_cmd *cmd = NULL;
> > > > struct request *req;
> > > >
> > > > while ((req = rq_list_pop(rqlist))) {
> > > > struct ublk_queue *this_q = req->mq_hctx->driver_data;
> > > > - struct ublk_io *this_io = &this_q->ios[req->tag];
> > > > + struct io_uring_cmd *this_cmd = this_q->ios[req->tag].cmd;
> > > >
> > > > - if (io && io->task != this_io->task && !rq_list_empty(&submit_list))
> > > > - ublk_queue_cmd_list(io, &submit_list);
> > > > - io = this_io;
> > > > + if (cmd && io_uring_cmd_ctx_handle(cmd) !=
> > > > + io_uring_cmd_ctx_handle(this_cmd) &&
> > > > + !rq_list_empty(&submit_list))
> > > > + ublk_queue_cmd_list(cmd, &submit_list);
> > >
> > > I don't think we can assume that ublk commands submitted to the same
> > > io_uring have the same daemon task. It's possible for multiple tasks
> > > to submit to the same io_uring, even though that's not a common or
> > > performant way to use io_uring. Probably we need to check that both
> > > the task and io_ring_ctx match.
> >
> > Here the problem is in 'issue_flags' passed from io_uring, especially for
> > grabbing io_ring_ctx lock.
> >
> > If two uring_cmd are issued via same io_ring_ctx from two tasks, it is
> > fine to share 'issue_flags' from one of tasks, what matters is that the
> > io_ring_ctx lock is handled correctly when calling io_uring_cmd_done().
>
> Right, I understand the issue you are trying to solve. I agree it's a
> problem for submit_list to contain commands from multiple
> io_ring_ctxs. But it's also a problem if it contains commands with
> different daemon tasks, because ublk_queue_cmd_list() will schedule
> ublk_cmd_list_tw_cb() to be called in the *last command's task*. But
> ublk_cmd_list_tw_cb() will call ublk_dispatch_req() for all the
> commands in the list. So if submit_list contains commands with
> multiple daemon tasks, ublk_dispatch_req() will fail on the current !=
> io->task check. So I still feel we need to call
> ublk_queue_cmd_list(io, &submit_list) if io->task != this_io->task (as
> well as if the io_ring_ctxs differ).
Indeed, I will send a V2 for covering different task case.
Jens, can you drop this patch?
Thanks,
Ming
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] ublk: build per-io-ring-ctx batch list
2025-06-25 1:22 ` Ming Lei
@ 2025-06-25 2:44 ` Jens Axboe
0 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2025-06-25 2:44 UTC (permalink / raw)
To: Ming Lei, Caleb Sander Mateos; +Cc: linux-block, Uday Shankar
On 6/24/25 7:22 PM, Ming Lei wrote:
> On Tue, Jun 24, 2025 at 08:26:51AM -0700, Caleb Sander Mateos wrote:
>> On Mon, Jun 23, 2025 at 6:24 PM Ming Lei <ming.lei@redhat.com> wrote:
>>>
>>> On Mon, Jun 23, 2025 at 10:51:00AM -0700, Caleb Sander Mateos wrote:
>>>> On Sun, Jun 22, 2025 at 6:19 PM Ming Lei <ming.lei@redhat.com> wrote:
>>>>>
>>>>> ublk_queue_cmd_list() dispatches the whole batch list by scheduling task
>>>>> work via the tail request's io_uring_cmd, this way is fine even though
>>>>> more than one io_ring_ctx are involved for this batch since it is just
>>>>> one running context.
>>>>>
>>>>> However, the task work handler ublk_cmd_list_tw_cb() takes `issue_flags`
>>>>> of tail uring_cmd's io_ring_ctx for completing all commands. This way is
>>>>> wrong if any uring_cmd is issued from different io_ring_ctx.
>>>>>
>>>>> Fixes it by always building per-io-ring-ctx batch list.
>>>>>
>>>>> For typical per-queue or per-io daemon implementation, this way shouldn't
>>>>> make difference from performance viewpoint, because single io_ring_ctx is
>>>>> often taken in each daemon.
>>>>>
>>>>> Fixes: d796cea7b9f3 ("ublk: implement ->queue_rqs()")
>>>>> Fixes: ab03a61c6614 ("ublk: have a per-io daemon instead of a per-queue daemon")
>>>>> Signed-off-by: Ming Lei <ming.lei@redhat.com>
>>>>> ---
>>>>> drivers/block/ublk_drv.c | 17 +++++++++--------
>>>>> 1 file changed, 9 insertions(+), 8 deletions(-)
>>>>>
>>>>> diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
>>>>> index c637ea010d34..e79b04e61047 100644
>>>>> --- a/drivers/block/ublk_drv.c
>>>>> +++ b/drivers/block/ublk_drv.c
>>>>> @@ -1336,9 +1336,8 @@ static void ublk_cmd_list_tw_cb(struct io_uring_cmd *cmd,
>>>>> } while (rq);
>>>>> }
>>>>>
>>>>> -static void ublk_queue_cmd_list(struct ublk_io *io, struct rq_list *l)
>>>>> +static void ublk_queue_cmd_list(struct io_uring_cmd *cmd, struct rq_list *l)
>>>>> {
>>>>> - struct io_uring_cmd *cmd = io->cmd;
>>>>> struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
>>>>>
>>>>> pdu->req_list = rq_list_peek(l);
>>>>> @@ -1420,16 +1419,18 @@ static void ublk_queue_rqs(struct rq_list *rqlist)
>>>>> {
>>>>> struct rq_list requeue_list = { };
>>>>> struct rq_list submit_list = { };
>>>>> - struct ublk_io *io = NULL;
>>>>> + struct io_uring_cmd *cmd = NULL;
>>>>> struct request *req;
>>>>>
>>>>> while ((req = rq_list_pop(rqlist))) {
>>>>> struct ublk_queue *this_q = req->mq_hctx->driver_data;
>>>>> - struct ublk_io *this_io = &this_q->ios[req->tag];
>>>>> + struct io_uring_cmd *this_cmd = this_q->ios[req->tag].cmd;
>>>>>
>>>>> - if (io && io->task != this_io->task && !rq_list_empty(&submit_list))
>>>>> - ublk_queue_cmd_list(io, &submit_list);
>>>>> - io = this_io;
>>>>> + if (cmd && io_uring_cmd_ctx_handle(cmd) !=
>>>>> + io_uring_cmd_ctx_handle(this_cmd) &&
>>>>> + !rq_list_empty(&submit_list))
>>>>> + ublk_queue_cmd_list(cmd, &submit_list);
>>>>
>>>> I don't think we can assume that ublk commands submitted to the same
>>>> io_uring have the same daemon task. It's possible for multiple tasks
>>>> to submit to the same io_uring, even though that's not a common or
>>>> performant way to use io_uring. Probably we need to check that both
>>>> the task and io_ring_ctx match.
>>>
>>> Here the problem is in 'issue_flags' passed from io_uring, especially for
>>> grabbing io_ring_ctx lock.
>>>
>>> If two uring_cmd are issued via same io_ring_ctx from two tasks, it is
>>> fine to share 'issue_flags' from one of tasks, what matters is that the
>>> io_ring_ctx lock is handled correctly when calling io_uring_cmd_done().
>>
>> Right, I understand the issue you are trying to solve. I agree it's a
>> problem for submit_list to contain commands from multiple
>> io_ring_ctxs. But it's also a problem if it contains commands with
>> different daemon tasks, because ublk_queue_cmd_list() will schedule
>> ublk_cmd_list_tw_cb() to be called in the *last command's task*. But
>> ublk_cmd_list_tw_cb() will call ublk_dispatch_req() for all the
>> commands in the list. So if submit_list contains commands with
>> multiple daemon tasks, ublk_dispatch_req() will fail on the current !=
>> io->task check. So I still feel we need to call
>> ublk_queue_cmd_list(io, &submit_list) if io->task != this_io->task (as
>> well as if the io_ring_ctxs differ).
>
> Indeed, I will send a V2 for covering different task case.
>
> Jens, can you drop this patch?
Done
--
Jens Axboe
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-06-25 2:44 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-23 1:19 [PATCH 0/2] ublk: fix ublk_queue_rqs() and selftests test_stress_03 Ming Lei
2025-06-23 1:19 ` [PATCH 1/2] ublk: build per-io-ring-ctx batch list Ming Lei
2025-06-23 17:51 ` Caleb Sander Mateos
2025-06-24 1:24 ` Ming Lei
2025-06-24 15:26 ` Caleb Sander Mateos
2025-06-25 1:22 ` Ming Lei
2025-06-25 2:44 ` Jens Axboe
2025-06-23 1:19 ` [PATCH 2/2] selftests: ublk: don't take same backing file for more than one ublk devices Ming Lei
2025-06-23 17:54 ` Caleb Sander Mateos
2025-06-24 1:13 ` Ming Lei
2025-06-24 15:20 ` Caleb Sander Mateos
2025-06-24 14:51 ` [PATCH 0/2] ublk: fix ublk_queue_rqs() and selftests test_stress_03 Jens Axboe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox