mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-12-22 12:17:45 +01:00
ublk: allow UBLK_IO_(UN)REGISTER_IO_BUF on any task
Currently, UBLK_IO_REGISTER_IO_BUF and UBLK_IO_UNREGISTER_IO_BUF are only permitted on the ublk_io's daemon task. But this restriction is unnecessary. ublk_register_io_buf() calls __ublk_check_and_get_req() to look up the request from the tagset and atomically take a reference on the request without accessing the ublk_io. ublk_unregister_io_buf() doesn't use the q_id or tag at all. So allow these opcodes even on tasks other than io->task. Handle UBLK_IO_UNREGISTER_IO_BUF before obtaining the ubq and io since the buffer index being unregistered is not necessarily related to the specified q_id and tag. Add a feature flag UBLK_F_BUF_REG_OFF_DAEMON that userspace can use to determine whether the kernel supports off-daemon buffer registration. Suggested-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> Reviewed-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20250620151008.3976463-10-csander@purestorage.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
committed by
Jens Axboe
parent
2da1e7bb3f
commit
763ff02ce2
@@ -70,7 +70,8 @@
|
||||
| UBLK_F_UPDATE_SIZE \
|
||||
| UBLK_F_AUTO_BUF_REG \
|
||||
| UBLK_F_QUIESCE \
|
||||
| UBLK_F_PER_IO_DAEMON)
|
||||
| UBLK_F_PER_IO_DAEMON \
|
||||
| UBLK_F_BUF_REG_OFF_DAEMON)
|
||||
|
||||
#define UBLK_F_ALL_RECOVERY_FLAGS (UBLK_F_USER_RECOVERY \
|
||||
| UBLK_F_USER_RECOVERY_REISSUE \
|
||||
@@ -2204,6 +2205,14 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* io_buffer_unregister_bvec() doesn't access the ubq or io,
|
||||
* so no need to validate the q_id, tag, or task
|
||||
*/
|
||||
if (_IOC_NR(cmd_op) == UBLK_IO_UNREGISTER_IO_BUF)
|
||||
return ublk_unregister_io_buf(cmd, ub, ub_cmd->addr,
|
||||
issue_flags);
|
||||
|
||||
ret = -EINVAL;
|
||||
if (ub_cmd->q_id >= ub->dev_info.nr_hw_queues)
|
||||
goto out;
|
||||
@@ -2224,8 +2233,17 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
|
||||
return -EIOCBQUEUED;
|
||||
}
|
||||
|
||||
if (READ_ONCE(io->task) != current)
|
||||
if (READ_ONCE(io->task) != current) {
|
||||
/*
|
||||
* ublk_register_io_buf() accesses only the io's refcount,
|
||||
* so can be handled on any task
|
||||
*/
|
||||
if (_IOC_NR(cmd_op) == UBLK_IO_REGISTER_IO_BUF)
|
||||
return ublk_register_io_buf(cmd, ubq, io, ub_cmd->addr,
|
||||
issue_flags);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* there is pending io cmd, something must be wrong */
|
||||
if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV)) {
|
||||
@@ -2244,8 +2262,6 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
|
||||
switch (_IOC_NR(cmd_op)) {
|
||||
case UBLK_IO_REGISTER_IO_BUF:
|
||||
return ublk_register_io_buf(cmd, ubq, io, ub_cmd->addr, issue_flags);
|
||||
case UBLK_IO_UNREGISTER_IO_BUF:
|
||||
return ublk_unregister_io_buf(cmd, ub, ub_cmd->addr, issue_flags);
|
||||
case UBLK_IO_COMMIT_AND_FETCH_REQ:
|
||||
ret = ublk_commit_and_fetch(ubq, io, cmd, ub_cmd, issue_flags);
|
||||
if (ret)
|
||||
@@ -2961,7 +2977,8 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
|
||||
|
||||
ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE |
|
||||
UBLK_F_URING_CMD_COMP_IN_TASK |
|
||||
UBLK_F_PER_IO_DAEMON;
|
||||
UBLK_F_PER_IO_DAEMON |
|
||||
UBLK_F_BUF_REG_OFF_DAEMON;
|
||||
|
||||
/* GET_DATA isn't needed any more with USER_COPY or ZERO COPY */
|
||||
if (ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY |
|
||||
|
||||
@@ -301,6 +301,16 @@
|
||||
*/
|
||||
#define UBLK_F_PER_IO_DAEMON (1ULL << 13)
|
||||
|
||||
/*
|
||||
* If this feature is set, UBLK_U_IO_REGISTER_IO_BUF/UBLK_U_IO_UNREGISTER_IO_BUF
|
||||
* can be issued for an I/O on any task. q_id and tag are also ignored in
|
||||
* UBLK_U_IO_UNREGISTER_IO_BUF's ublksrv_io_cmd.
|
||||
* If it is unset, zero-copy buffers can only be registered and unregistered by
|
||||
* the I/O's daemon task. The q_id and tag of the registered buffer are required
|
||||
* in UBLK_U_IO_UNREGISTER_IO_BUF's ublksrv_io_cmd.
|
||||
*/
|
||||
#define UBLK_F_BUF_REG_OFF_DAEMON (1ULL << 14)
|
||||
|
||||
/* device state */
|
||||
#define UBLK_S_DEV_DEAD 0
|
||||
#define UBLK_S_DEV_LIVE 1
|
||||
|
||||
Reference in New Issue
Block a user