Skip to content

Commit 99c1e4e

Browse files
Ming Leiaxboe
authored andcommitted
ublk: register buffer to local io_uring with provided buf index via UBLK_F_AUTO_BUF_REG
Add UBLK_F_AUTO_BUF_REG for supporting to register buffer automatically to local io_uring context with provided buffer index. Add UAPI structure `struct ublk_auto_buf_reg` for holding user parameter to register request buffer automatically, one 'flags' field is defined, and there is still 32bit available for future extension, such as, adding one io_ring FD field for registering buffer to external io_uring. `struct ublk_auto_buf_reg` is populated from ublk uring_cmd's sqe->addr, and all existing ublk commands are data-less, so it is just fine to reuse sqe->addr for this purpose. Signed-off-by: Ming Lei <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 9e6b475 commit 99c1e4e

File tree

2 files changed

+113
-7
lines changed

2 files changed

+113
-7
lines changed

drivers/block/ublk_drv.c

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@
6666
| UBLK_F_USER_COPY \
6767
| UBLK_F_ZONED \
6868
| UBLK_F_USER_RECOVERY_FAIL_IO \
69-
| UBLK_F_UPDATE_SIZE)
69+
| UBLK_F_UPDATE_SIZE \
70+
| UBLK_F_AUTO_BUF_REG)
7071

7172
#define UBLK_F_ALL_RECOVERY_FLAGS (UBLK_F_USER_RECOVERY \
7273
| UBLK_F_USER_RECOVERY_REISSUE \
@@ -80,6 +81,9 @@
8081

8182
struct ublk_rq_data {
8283
refcount_t ref;
84+
85+
/* for auto-unregister buffer in case of UBLK_F_AUTO_BUF_REG */
86+
u16 buf_index;
8387
};
8488

8589
struct ublk_uring_cmd_pdu {
@@ -101,6 +105,9 @@ struct ublk_uring_cmd_pdu {
101105
* setup in ublk uring_cmd handler
102106
*/
103107
struct ublk_queue *ubq;
108+
109+
struct ublk_auto_buf_reg buf;
110+
104111
u16 tag;
105112
};
106113

@@ -630,7 +637,7 @@ static inline bool ublk_support_zero_copy(const struct ublk_queue *ubq)
630637

631638
static inline bool ublk_support_auto_buf_reg(const struct ublk_queue *ubq)
632639
{
633-
return false;
640+
return ubq->flags & UBLK_F_AUTO_BUF_REG;
634641
}
635642

636643
static inline bool ublk_support_user_copy(const struct ublk_queue *ubq)
@@ -1178,17 +1185,20 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq,
11781185
static bool ublk_auto_buf_reg(struct request *req, struct ublk_io *io,
11791186
unsigned int issue_flags)
11801187
{
1188+
struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(io->cmd);
11811189
struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
11821190
int ret;
11831191

1184-
ret = io_buffer_register_bvec(io->cmd, req, ublk_io_release, 0,
1185-
issue_flags);
1192+
ret = io_buffer_register_bvec(io->cmd, req, ublk_io_release,
1193+
pdu->buf.index, issue_flags);
11861194
if (ret) {
11871195
blk_mq_end_request(req, BLK_STS_IOERR);
11881196
return false;
11891197
}
11901198
/* one extra reference is dropped by ublk_io_release */
11911199
refcount_set(&data->ref, 2);
1200+
/* store buffer index in request payload */
1201+
data->buf_index = pdu->buf.index;
11921202
io->flags |= UBLK_IO_FLAG_AUTO_BUF_REG;
11931203
return true;
11941204
}
@@ -1952,6 +1962,18 @@ static inline void ublk_prep_cancel(struct io_uring_cmd *cmd,
19521962
io_uring_cmd_mark_cancelable(cmd, issue_flags);
19531963
}
19541964

1965+
static inline int ublk_set_auto_buf_reg(struct io_uring_cmd *cmd)
1966+
{
1967+
struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
1968+
1969+
pdu->buf = ublk_sqe_addr_to_auto_buf_reg(READ_ONCE(cmd->sqe->addr));
1970+
1971+
if (pdu->buf.reserved0 || pdu->buf.reserved1)
1972+
return -EINVAL;
1973+
1974+
return 0;
1975+
}
1976+
19551977
static void ublk_io_release(void *priv)
19561978
{
19571979
struct request *rq = priv;
@@ -2034,6 +2056,12 @@ static int ublk_fetch(struct io_uring_cmd *cmd, struct ublk_queue *ubq,
20342056
goto out;
20352057
}
20362058

2059+
if (ublk_support_auto_buf_reg(ubq)) {
2060+
ret = ublk_set_auto_buf_reg(cmd);
2061+
if (ret)
2062+
return ret;
2063+
}
2064+
20372065
ublk_fill_io_cmd(io, cmd, buf_addr);
20382066
ublk_mark_io_ready(ub, ubq);
20392067
out:
@@ -2065,11 +2093,20 @@ static int ublk_commit_and_fetch(const struct ublk_queue *ubq,
20652093
}
20662094

20672095
if (ublk_support_auto_buf_reg(ubq)) {
2096+
int ret;
2097+
20682098
if (io->flags & UBLK_IO_FLAG_AUTO_BUF_REG) {
2069-
WARN_ON_ONCE(io_buffer_unregister_bvec(cmd, 0,
2099+
struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
2100+
2101+
WARN_ON_ONCE(io_buffer_unregister_bvec(cmd,
2102+
data->buf_index,
20702103
issue_flags));
20712104
io->flags &= ~UBLK_IO_FLAG_AUTO_BUF_REG;
20722105
}
2106+
2107+
ret = ublk_set_auto_buf_reg(cmd);
2108+
if (ret)
2109+
return ret;
20732110
}
20742111

20752112
ublk_fill_io_cmd(io, cmd, ub_cmd->addr);
@@ -2791,8 +2828,11 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
27912828
* For USER_COPY, we depends on userspace to fill request
27922829
* buffer by pwrite() to ublk char device, which can't be
27932830
* used for unprivileged device
2831+
*
2832+
* Same with zero copy or auto buffer register.
27942833
*/
2795-
if (info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY))
2834+
if (info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY |
2835+
UBLK_F_AUTO_BUF_REG))
27962836
return -EINVAL;
27972837
}
27982838

@@ -2850,7 +2890,8 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
28502890
UBLK_F_URING_CMD_COMP_IN_TASK;
28512891

28522892
/* GET_DATA isn't needed any more with USER_COPY or ZERO COPY */
2853-
if (ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY))
2893+
if (ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY |
2894+
UBLK_F_AUTO_BUF_REG))
28542895
ub->dev_info.flags &= ~UBLK_F_NEED_GET_DATA;
28552896

28562897
/*
@@ -3377,6 +3418,7 @@ static int __init ublk_init(void)
33773418

33783419
BUILD_BUG_ON((u64)UBLKSRV_IO_BUF_OFFSET +
33793420
UBLKSRV_IO_BUF_TOTAL_SIZE < UBLKSRV_IO_BUF_OFFSET);
3421+
BUILD_BUG_ON(sizeof(struct ublk_auto_buf_reg) != 8);
33803422

33813423
init_waitqueue_head(&ublk_idr_wq);
33823424

include/uapi/linux/ublk_cmd.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,29 @@
219219
*/
220220
#define UBLK_F_UPDATE_SIZE (1ULL << 10)
221221

222+
/*
223+
* request buffer is registered automatically to uring_cmd's io_uring
224+
* context before delivering this io command to ublk server, meantime
225+
* it is un-registered automatically when completing this io command.
226+
*
227+
* For using this feature:
228+
*
229+
* - ublk server has to create sparse buffer table
230+
*
231+
* - ublk server passes auto buf register data via uring_cmd's sqe->addr,
232+
* `struct ublk_auto_buf_reg` is populated from sqe->addr, please see
233+
* the definition of ublk_sqe_addr_to_auto_buf_reg()
234+
*
235+
* - pass buffer index from `ublk_auto_buf_reg.index`
236+
*
237+
* - all reserved fields in `ublk_auto_buf_reg` need to be zeroed
238+
*
239+
* This way avoids extra cost from two uring_cmd, but also simplifies backend
240+
* implementation, such as, the dependency on IO_REGISTER_IO_BUF and
241+
* IO_UNREGISTER_IO_BUF becomes not necessary.
242+
*/
243+
#define UBLK_F_AUTO_BUF_REG (1ULL << 11)
244+
222245
/* device state */
223246
#define UBLK_S_DEV_DEAD 0
224247
#define UBLK_S_DEV_LIVE 1
@@ -339,6 +362,47 @@ static inline __u32 ublksrv_get_flags(const struct ublksrv_io_desc *iod)
339362
return iod->op_flags >> 8;
340363
}
341364

365+
struct ublk_auto_buf_reg {
366+
/* index for registering the delivered request buffer */
367+
__u16 index;
368+
__u16 reserved0;
369+
370+
/*
371+
* io_ring FD can be passed via the reserve field in future for
372+
* supporting to register io buffer to external io_uring
373+
*/
374+
__u32 reserved1;
375+
};
376+
377+
/*
378+
* For UBLK_F_AUTO_BUF_REG, auto buffer register data is carried via
379+
* uring_cmd's sqe->addr:
380+
*
381+
* - bit0 ~ bit15: buffer index
382+
* - bit24 ~ bit31: reserved0
383+
* - bit32 ~ bit63: reserved1
384+
*/
385+
static inline struct ublk_auto_buf_reg ublk_sqe_addr_to_auto_buf_reg(
386+
__u64 sqe_addr)
387+
{
388+
struct ublk_auto_buf_reg reg = {
389+
.index = sqe_addr & 0xffff,
390+
.reserved0 = (sqe_addr >> 16) & 0xffff,
391+
.reserved1 = sqe_addr >> 32,
392+
};
393+
394+
return reg;
395+
}
396+
397+
static inline __u64
398+
ublk_auto_buf_reg_to_sqe_addr(const struct ublk_auto_buf_reg *buf)
399+
{
400+
__u64 addr = buf->index | (__u64)buf->reserved0 << 16 |
401+
(__u64)buf->reserved1 << 32;
402+
403+
return addr;
404+
}
405+
342406
/* issued to ublk driver via /dev/ublkcN */
343407
struct ublksrv_io_cmd {
344408
__u16 q_id;

0 commit comments

Comments
 (0)