History

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.

Caleb Sander Mateos committed 1 year ago

Commit 763ff021 parent 2da1e7b2 files · +32 −5Browse files

Unified · Split

2 files
  1. drivers/block/ublk_drv.c +22 −5
  2. include/uapi/linux/ublk_cmd.h +10 −0
drivers/block/ublk_drv.c+22−5
@@ -70,7 +70,8 @@ · 69 unmodified lines
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 \
@@ -2204,6 +2205,14 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, · 2127 unmodified lines
22042205 if (ret)
22052206 goto out;
22062207
2208+ /*
2209+ * io_buffer_unregister_bvec() doesn't access the ubq or io,
2210+ * so no need to validate the q_id, tag, or task
2211+ */
2212+ if (_IOC_NR(cmd_op) == UBLK_IO_UNREGISTER_IO_BUF)
2213+ return ublk_unregister_io_buf(cmd, ub, ub_cmd->addr,
2214+ issue_flags);
2215+
22072216 ret = -EINVAL;
22082217 if (ub_cmd->q_id >= ub->dev_info.nr_hw_queues)
22092218 goto out;
@@ -2224,8 +2233,17 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, · 14 unmodified lines
22242233 return -EIOCBQUEUED;
22252234 }
22262235
2227− if (READ_ONCE(io->task) != current)
2236+ if (READ_ONCE(io->task) != current) {
2237+ /*
2238+ * ublk_register_io_buf() accesses only the io's refcount,
2239+ * so can be handled on any task
2240+ */
2241+ if (_IOC_NR(cmd_op) == UBLK_IO_REGISTER_IO_BUF)
2242+ return ublk_register_io_buf(cmd, ubq, io, ub_cmd->addr,
2243+ issue_flags);
2244+
22282245 goto out;
2246+ }
22292247
22302248 /* there is pending io cmd, something must be wrong */
22312249 if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV)) {
@@ -2244,8 +2262,6 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, · 12 unmodified lines
22442262 switch (_IOC_NR(cmd_op)) {
22452263 case UBLK_IO_REGISTER_IO_BUF:
22462264 return ublk_register_io_buf(cmd, ubq, io, ub_cmd->addr, issue_flags);
2247− case UBLK_IO_UNREGISTER_IO_BUF:
2248− return ublk_unregister_io_buf(cmd, ub, ub_cmd->addr, issue_flags);
22492265 case UBLK_IO_COMMIT_AND_FETCH_REQ:
22502266 ret = ublk_commit_and_fetch(ubq, io, cmd, ub_cmd, issue_flags);
22512267 if (ret)
@@ -2961,7 +2977,8 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header) · 709 unmodified lines
29612977
29622978 ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE |
29632979 UBLK_F_URING_CMD_COMP_IN_TASK |
2964− UBLK_F_PER_IO_DAEMON;
2980+ UBLK_F_PER_IO_DAEMON |
2981+ UBLK_F_BUF_REG_OFF_DAEMON;
29652982
29662983 /* GET_DATA isn't needed any more with USER_COPY or ZERO COPY */
29672984 if (ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY |
include/uapi/linux/ublk_cmd.h+10−0
@@ -301,6 +301,16 @@ · 300 unmodified lines
301301 */
302302 #define UBLK_F_PER_IO_DAEMON (1ULL << 13)
303303
304+/*
305+ * If this feature is set, UBLK_U_IO_REGISTER_IO_BUF/UBLK_U_IO_UNREGISTER_IO_BUF
306+ * can be issued for an I/O on any task. q_id and tag are also ignored in
307+ * UBLK_U_IO_UNREGISTER_IO_BUF's ublksrv_io_cmd.
308+ * If it is unset, zero-copy buffers can only be registered and unregistered by
309+ * the I/O's daemon task. The q_id and tag of the registered buffer are required
310+ * in UBLK_U_IO_UNREGISTER_IO_BUF's ublksrv_io_cmd.
311+ */
312+#define UBLK_F_BUF_REG_OFF_DAEMON (1ULL << 14)
313+
304314 /* device state */
305315 #define UBLK_S_DEV_DEAD 0
306316 #define UBLK_S_DEV_LIVE 1