Skip to content

Commit 16367fe

Browse files
calebsanderkawasaki
authored andcommitted
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 <[email protected]> Signed-off-by: Caleb Sander Mateos <[email protected]>
1 parent 9ce5505 commit 16367fe

2 files changed

Lines changed: 30 additions & 15 deletions

File tree

drivers/block/ublk_drv.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@
7070
| UBLK_F_UPDATE_SIZE \
7171
| UBLK_F_AUTO_BUF_REG \
7272
| UBLK_F_QUIESCE \
73-
| UBLK_F_PER_IO_DAEMON)
73+
| UBLK_F_PER_IO_DAEMON \
74+
| UBLK_F_BUF_REG_OFF_DAEMON)
7475

7576
#define UBLK_F_ALL_RECOVERY_FLAGS (UBLK_F_USER_RECOVERY \
7677
| UBLK_F_USER_RECOVERY_REISSUE \
@@ -2020,16 +2021,6 @@ static int ublk_register_io_buf(struct io_uring_cmd *cmd,
20202021
return 0;
20212022
}
20222023

2023-
static int ublk_unregister_io_buf(struct io_uring_cmd *cmd,
2024-
const struct ublk_queue *ubq,
2025-
unsigned int index, unsigned int issue_flags)
2026-
{
2027-
if (!ublk_support_zero_copy(ubq))
2028-
return -EINVAL;
2029-
2030-
return io_buffer_unregister_bvec(cmd, index, issue_flags);
2031-
}
2032-
20332024
static int ublk_fetch(struct io_uring_cmd *cmd, struct ublk_queue *ubq,
20342025
struct ublk_io *io, __u64 buf_addr)
20352026
{
@@ -2186,6 +2177,14 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
21862177
if (ret)
21872178
goto out;
21882179

2180+
/*
2181+
* io_buffer_unregister_bvec() doesn't access the ubq or io,
2182+
* so no need to validate the q_id, tag, or task
2183+
*/
2184+
if (_IOC_NR(cmd_op) == UBLK_IO_UNREGISTER_IO_BUF)
2185+
return io_buffer_unregister_bvec(cmd, ub_cmd->addr,
2186+
issue_flags);
2187+
21892188
ret = -EINVAL;
21902189
if (ub_cmd->q_id >= ub->dev_info.nr_hw_queues)
21912190
goto out;
@@ -2206,8 +2205,17 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
22062205
return -EIOCBQUEUED;
22072206
}
22082207

2209-
if (READ_ONCE(io->task) != current)
2208+
if (READ_ONCE(io->task) != current) {
2209+
/*
2210+
* ublk_register_io_buf() accesses only the request, not io,
2211+
* so can be handled on any task
2212+
*/
2213+
if (_IOC_NR(cmd_op) == UBLK_IO_REGISTER_IO_BUF)
2214+
return ublk_register_io_buf(cmd, ubq, tag, ub_cmd->addr,
2215+
issue_flags);
2216+
22102217
goto out;
2218+
}
22112219

22122220
/* there is pending io cmd, something must be wrong */
22132221
if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV)) {
@@ -2226,8 +2234,6 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
22262234
switch (_IOC_NR(cmd_op)) {
22272235
case UBLK_IO_REGISTER_IO_BUF:
22282236
return ublk_register_io_buf(cmd, ubq, tag, ub_cmd->addr, issue_flags);
2229-
case UBLK_IO_UNREGISTER_IO_BUF:
2230-
return ublk_unregister_io_buf(cmd, ubq, ub_cmd->addr, issue_flags);
22312237
case UBLK_IO_COMMIT_AND_FETCH_REQ:
22322238
ret = ublk_commit_and_fetch(ubq, io, cmd, ub_cmd, issue_flags);
22332239
if (ret)
@@ -2920,7 +2926,8 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
29202926

29212927
ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE |
29222928
UBLK_F_URING_CMD_COMP_IN_TASK |
2923-
UBLK_F_PER_IO_DAEMON;
2929+
UBLK_F_PER_IO_DAEMON |
2930+
UBLK_F_BUF_REG_OFF_DAEMON;
29242931

29252932
/* GET_DATA isn't needed any more with USER_COPY or ZERO COPY */
29262933
if (ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY |

include/uapi/linux/ublk_cmd.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,14 @@
281281
*/
282282
#define UBLK_F_PER_IO_DAEMON (1ULL << 13)
283283

284+
/*
285+
* If this feature is set, UBLK_U_IO_REGISTER_IO_BUF/UBLK_U_IO_UNREGISTER_IO_BUF
286+
* can be issued for an I/O on any task.
287+
* If it is unset, zero-copy buffers can only be registered and unregistered by
288+
* the I/O's daemon task.
289+
*/
290+
#define UBLK_F_BUF_REG_OFF_DAEMON (1ULL << 14)
291+
284292
/* device state */
285293
#define UBLK_S_DEV_DEAD 0
286294
#define UBLK_S_DEV_LIVE 1

0 commit comments

Comments
 (0)