Since STOP_DEV turns the server away until it closes /dev/ublkcN, UBLK_U_IO_PREP_IO_CMDS can complete with UBLK_IO_RES_ABORT when it races STOP_DEV. kublk asserts that PREP succeeds, so the daemon aborts before it reports to `kublk add`, which then waits for the start event forever. Stop the thread like a failed FETCH_IO_CMDS does. The daemon's START_DEV then fails, and `kublk add` gets the error. Reported-by: Josef Bacik Closes: https://lore.kernel.org/linux-block/63d8149c093169706e7478e779116b61.josef@toxicpanda.com/ Signed-off-by: Ming Lei --- tools/testing/selftests/ublk/batch.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/ublk/batch.c b/tools/testing/selftests/ublk/batch.c index d8d9ebed5979..dfc81ee17d07 100644 --- a/tools/testing/selftests/ublk/batch.c +++ b/tools/testing/selftests/ublk/batch.c @@ -410,9 +410,16 @@ static void ublk_batch_compl_commit_cmd(struct ublk_thread *t, { unsigned short buf_idx = user_data_to_tag(cqe->user_data); - if (op == _IOC_NR(UBLK_U_IO_PREP_IO_CMDS)) - ublk_assert(cqe->res == 0); - else if (op == _IOC_NR(UBLK_U_IO_COMMIT_IO_CMDS)) { + if (op == _IOC_NR(UBLK_U_IO_PREP_IO_CMDS)) { + /* e.g. UBLK_IO_RES_ABORT after STOP_DEV: stop like a FETCH */ + if (cqe->res < 0) { + ublk_dbg(UBLK_DBG_IO_CMD, "%s: prep failed %d\n", + __func__, cqe->res); + t->state |= UBLKS_T_STOPPING; + } else { + ublk_assert(cqe->res == 0); + } + } else if (op == _IOC_NR(UBLK_U_IO_COMMIT_IO_CMDS)) { int nr_elem = user_data_to_tgt_data(cqe->user_data); ublk_assert(cqe->res == t->commit_buf_elem_size * nr_elem); -- 2.55.0