mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 20:14:06 +02:00
selftests: ublk: kublk: improve behavior on init failure
Some failure modes are handled poorly by kublk. For example, if ublk_drv is built as a module but not currently loaded into the kernel, ./kublk add ... just hangs forever. This happens because in this case (and a few others), the worker process does not notify its parent (via a write to the shared eventfd) that it has tried and failed to initialize, so the parent hangs forever. Fix this by ensuring that we always notify the parent process of any initialization failure, and have the parent print a (not very descriptive) log line when this happens. Signed-off-by: Uday Shankar <ushankar@purestorage.com> Reviewed-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20250603-ublk_init_fail-v1-1-87c91486230e@purestorage.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
43a67dd812
commit
a2f4c1ae16
|
|
@ -1112,7 +1112,7 @@ static int __cmd_dev_add(const struct dev_ctx *ctx)
|
|||
__u64 features;
|
||||
const struct ublk_tgt_ops *ops;
|
||||
struct ublksrv_ctrl_dev_info *info;
|
||||
struct ublk_dev *dev;
|
||||
struct ublk_dev *dev = NULL;
|
||||
int dev_id = ctx->dev_id;
|
||||
int ret, i;
|
||||
|
||||
|
|
@ -1120,13 +1120,15 @@ static int __cmd_dev_add(const struct dev_ctx *ctx)
|
|||
if (!ops) {
|
||||
ublk_err("%s: no such tgt type, type %s\n",
|
||||
__func__, tgt_type);
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (nr_queues > UBLK_MAX_QUEUES || depth > UBLK_QUEUE_DEPTH) {
|
||||
ublk_err("%s: invalid nr_queues or depth queues %u depth %u\n",
|
||||
__func__, nr_queues, depth);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* default to 1:1 threads:queues if nthreads is unspecified */
|
||||
|
|
@ -1136,30 +1138,37 @@ static int __cmd_dev_add(const struct dev_ctx *ctx)
|
|||
if (nthreads > UBLK_MAX_THREADS) {
|
||||
ublk_err("%s: %u is too many threads (max %u)\n",
|
||||
__func__, nthreads, UBLK_MAX_THREADS);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (nthreads != nr_queues && !ctx->per_io_tasks) {
|
||||
ublk_err("%s: threads %u must be same as queues %u if "
|
||||
"not using per_io_tasks\n",
|
||||
__func__, nthreads, nr_queues);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev = ublk_ctrl_init();
|
||||
if (!dev) {
|
||||
ublk_err("%s: can't alloc dev id %d, type %s\n",
|
||||
__func__, dev_id, tgt_type);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* kernel doesn't support get_features */
|
||||
ret = ublk_ctrl_get_features(dev, &features);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
if (ret < 0) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(features & UBLK_F_CMD_IOCTL_ENCODE))
|
||||
return -ENOTSUP;
|
||||
if (!(features & UBLK_F_CMD_IOCTL_ENCODE)) {
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
info = &dev->dev_info;
|
||||
info->dev_id = ctx->dev_id;
|
||||
|
|
@ -1200,7 +1209,8 @@ static int __cmd_dev_add(const struct dev_ctx *ctx)
|
|||
fail:
|
||||
if (ret < 0)
|
||||
ublk_send_dev_event(ctx, dev, -1);
|
||||
ublk_ctrl_deinit(dev);
|
||||
if (dev)
|
||||
ublk_ctrl_deinit(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1262,6 +1272,8 @@ static int cmd_dev_add(struct dev_ctx *ctx)
|
|||
shmctl(ctx->_shmid, IPC_RMID, NULL);
|
||||
/* wait for child and detach from it */
|
||||
wait(NULL);
|
||||
if (exit_code == EXIT_FAILURE)
|
||||
ublk_err("%s: command failed\n", __func__);
|
||||
exit(exit_code);
|
||||
} else {
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user