Skip to content

Commit 73e4593

Browse files
calebsanderkawasaki
authored andcommitted
ublk: optimize UBLK_IO_REGISTER_IO_BUF on daemon task
ublk_register_io_buf() performs an expensive atomic refcount increment, as well as a lot of pointer chasing to look up the struct request. Create a separate ublk_daemon_register_io_buf() for the daemon task to call. Initialize ublk_rq_data's reference count to a large number, count the number of buffers registered on the daemon task nonatomically, and atomically subtract the large number minus the number of registered buffers in ublk_commit_and_fetch(). Also obtain the struct request directly from ublk_io's req field instead of looking it up on the tagset. Signed-off-by: Caleb Sander Mateos <[email protected]>
1 parent 16367fe commit 73e4593

1 file changed

Lines changed: 50 additions & 9 deletions

File tree

drivers/block/ublk_drv.c

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,16 @@
8383
UBLK_PARAM_TYPE_DEVT | UBLK_PARAM_TYPE_ZONED | \
8484
UBLK_PARAM_TYPE_DMA_ALIGN | UBLK_PARAM_TYPE_SEGMENT)
8585

86+
/*
87+
* Initialize refcount to a large number to include any registered buffers.
88+
* UBLK_IO_COMMIT_AND_FETCH_REQ will release these references minus those for
89+
* any buffers registered on the io daemon task.
90+
*/
91+
#define UBLK_REFCOUNT_INIT (REFCOUNT_MAX / 2)
92+
8693
struct ublk_rq_data {
8794
refcount_t ref;
95+
unsigned buffers_registered;
8896

8997
/* for auto-unregister buffer in case of UBLK_F_AUTO_BUF_REG */
9098
u16 buf_index;
@@ -679,7 +687,8 @@ static inline void ublk_init_req_ref(const struct ublk_queue *ubq,
679687
if (ublk_need_req_ref(ubq)) {
680688
struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
681689

682-
refcount_set(&data->ref, 1);
690+
refcount_set(&data->ref, UBLK_REFCOUNT_INIT);
691+
data->buffers_registered = 0;
683692
}
684693
}
685694

@@ -708,6 +717,15 @@ static inline void ublk_put_req_ref(const struct ublk_queue *ubq,
708717
}
709718
}
710719

720+
static inline void ublk_sub_req_ref(struct request *req)
721+
{
722+
struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
723+
unsigned sub_refs = UBLK_REFCOUNT_INIT - data->buffers_registered;
724+
725+
if (refcount_sub_and_test(sub_refs, &data->ref))
726+
__ublk_complete_rq(req);
727+
}
728+
711729
static inline bool ublk_need_get_data(const struct ublk_queue *ubq)
712730
{
713731
return ubq->flags & UBLK_F_NEED_GET_DATA;
@@ -1186,10 +1204,8 @@ static void ublk_auto_buf_reg_fallback(struct request *req)
11861204
{
11871205
const struct ublk_queue *ubq = req->mq_hctx->driver_data;
11881206
struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);
1189-
struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
11901207

11911208
iod->op_flags |= UBLK_IO_F_NEED_REG_BUF;
1192-
refcount_set(&data->ref, 1);
11931209
}
11941210

11951211
static bool ublk_auto_buf_reg(struct request *req, struct ublk_io *io,
@@ -1209,9 +1225,8 @@ static bool ublk_auto_buf_reg(struct request *req, struct ublk_io *io,
12091225
blk_mq_end_request(req, BLK_STS_IOERR);
12101226
return false;
12111227
}
1212-
/* one extra reference is dropped by ublk_io_release */
1213-
refcount_set(&data->ref, 2);
12141228

1229+
data->buffers_registered = 1;
12151230
data->buf_ctx_handle = io_uring_cmd_ctx_handle(io->cmd);
12161231
/* store buffer index in request payload */
12171232
data->buf_index = pdu->buf.index;
@@ -1223,10 +1238,10 @@ static bool ublk_prep_auto_buf_reg(struct ublk_queue *ubq,
12231238
struct request *req, struct ublk_io *io,
12241239
unsigned int issue_flags)
12251240
{
1241+
ublk_init_req_ref(ubq, req);
12261242
if (ublk_support_auto_buf_reg(ubq) && ublk_rq_has_data(req))
12271243
return ublk_auto_buf_reg(req, io, issue_flags);
12281244

1229-
ublk_init_req_ref(ubq, req);
12301245
return true;
12311246
}
12321247

@@ -2021,6 +2036,27 @@ static int ublk_register_io_buf(struct io_uring_cmd *cmd,
20212036
return 0;
20222037
}
20232038

2039+
static int ublk_daemon_register_io_buf(struct io_uring_cmd *cmd,
2040+
const struct ublk_queue *ubq,
2041+
const struct ublk_io *io,
2042+
unsigned index, unsigned issue_flags)
2043+
{
2044+
struct request *req = io->req;
2045+
struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
2046+
int ret;
2047+
2048+
if (!ublk_support_zero_copy(ubq) || !ublk_rq_has_data(req))
2049+
return -EINVAL;
2050+
2051+
ret = io_buffer_register_bvec(cmd, req, ublk_io_release, index,
2052+
issue_flags);
2053+
if (ret)
2054+
return ret;
2055+
2056+
data->buffers_registered++;
2057+
return 0;
2058+
}
2059+
20242060
static int ublk_fetch(struct io_uring_cmd *cmd, struct ublk_queue *ubq,
20252061
struct ublk_io *io, __u64 buf_addr)
20262062
{
@@ -2133,9 +2169,13 @@ static int ublk_commit_and_fetch(const struct ublk_queue *ubq,
21332169
if (req_op(req) == REQ_OP_ZONE_APPEND)
21342170
req->__sector = ub_cmd->zone_append_lba;
21352171

2136-
if (likely(!blk_should_fake_timeout(req->q)))
2137-
ublk_put_req_ref(ubq, req);
2172+
if (unlikely(blk_should_fake_timeout(req->q)))
2173+
return 0;
21382174

2175+
if (ublk_need_req_ref(ubq))
2176+
ublk_sub_req_ref(req);
2177+
else
2178+
__ublk_complete_rq(req);
21392179
return 0;
21402180
}
21412181

@@ -2233,7 +2273,8 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
22332273

22342274
switch (_IOC_NR(cmd_op)) {
22352275
case UBLK_IO_REGISTER_IO_BUF:
2236-
return ublk_register_io_buf(cmd, ubq, tag, ub_cmd->addr, issue_flags);
2276+
return ublk_daemon_register_io_buf(cmd, ubq, io, ub_cmd->addr,
2277+
issue_flags);
22372278
case UBLK_IO_COMMIT_AND_FETCH_REQ:
22382279
ret = ublk_commit_and_fetch(ubq, io, cmd, ub_cmd, issue_flags);
22392280
if (ret)

0 commit comments

Comments
 (0)