Skip to content

Commit 5a1328d

Browse files
Gioh Kimaxboe
authored andcommitted
block/rnbd-clt: Dynamically allocate sglist for rnbd_iu
The BMAX_SEGMENT static array for scatterlist is embedded in rnbd_iu structure to avoid memory allocation in hot IO path. In many cases, we do need only several sg entries because many IOs have only several segments. This patch change rnbd_iu to check the number of segments in the request and allocate sglist dynamically. For io path, use sg_alloc_table_chained to allocate sg list faster. First it makes two sg entries after pdu of request. The sg_alloc_table_chained uses the pre-allocated sg entries if the number of segments of the request is less than two. So it reduces the number of memory allocation. Signed-off-by: Gioh Kim <gi-oh.kim@cloud.ionos.com> Signed-off-by: Jack Wang <jinpu.wang@cloud.ionos.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 512c781 commit 5a1328d

File tree

2 files changed

+43
-27
lines changed

2 files changed

+43
-27
lines changed

drivers/block/rnbd/rnbd-clt.c

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ static void rnbd_softirq_done_fn(struct request *rq)
384384
struct rnbd_iu *iu;
385385

386386
iu = blk_mq_rq_to_pdu(rq);
387+
sg_free_table_chained(&iu->sgt, RNBD_INLINE_SG_CNT);
387388
rnbd_put_permit(sess, iu->permit);
388389
blk_mq_end_request(rq, errno_to_blk_status(iu->errno));
389390
}
@@ -477,7 +478,7 @@ static int send_msg_close(struct rnbd_clt_dev *dev, u32 device_id, bool wait)
477478
iu->buf = NULL;
478479
iu->dev = dev;
479480

480-
sg_mark_end(&iu->sglist[0]);
481+
sg_alloc_table(&iu->sgt, 1, GFP_KERNEL);
481482

482483
msg.hdr.type = cpu_to_le16(RNBD_MSG_CLOSE);
483484
msg.device_id = cpu_to_le32(device_id);
@@ -492,6 +493,7 @@ static int send_msg_close(struct rnbd_clt_dev *dev, u32 device_id, bool wait)
492493
err = errno;
493494
}
494495

496+
sg_free_table(&iu->sgt);
495497
rnbd_put_iu(sess, iu);
496498
return err;
497499
}
@@ -564,15 +566,16 @@ static int send_msg_open(struct rnbd_clt_dev *dev, bool wait)
564566
iu->buf = rsp;
565567
iu->dev = dev;
566568

567-
sg_init_one(iu->sglist, rsp, sizeof(*rsp));
569+
sg_alloc_table(&iu->sgt, 1, GFP_KERNEL);
570+
sg_init_one(iu->sgt.sgl, rsp, sizeof(*rsp));
568571

569572
msg.hdr.type = cpu_to_le16(RNBD_MSG_OPEN);
570573
msg.access_mode = dev->access_mode;
571574
strlcpy(msg.dev_name, dev->pathname, sizeof(msg.dev_name));
572575

573576
WARN_ON(!rnbd_clt_get_dev(dev));
574577
err = send_usr_msg(sess->rtrs, READ, iu,
575-
&vec, sizeof(*rsp), iu->sglist, 1,
578+
&vec, sizeof(*rsp), iu->sgt.sgl, 1,
576579
msg_open_conf, &errno, wait);
577580
if (err) {
578581
rnbd_clt_put_dev(dev);
@@ -582,6 +585,7 @@ static int send_msg_open(struct rnbd_clt_dev *dev, bool wait)
582585
err = errno;
583586
}
584587

588+
sg_free_table(&iu->sgt);
585589
rnbd_put_iu(sess, iu);
586590
return err;
587591
}
@@ -610,7 +614,8 @@ static int send_msg_sess_info(struct rnbd_clt_session *sess, bool wait)
610614
iu->buf = rsp;
611615
iu->sess = sess;
612616

613-
sg_init_one(iu->sglist, rsp, sizeof(*rsp));
617+
sg_alloc_table(&iu->sgt, 1, GFP_KERNEL);
618+
sg_init_one(iu->sgt.sgl, rsp, sizeof(*rsp));
614619

615620
msg.hdr.type = cpu_to_le16(RNBD_MSG_SESS_INFO);
616621
msg.ver = RNBD_PROTO_VER_MAJOR;
@@ -626,7 +631,7 @@ static int send_msg_sess_info(struct rnbd_clt_session *sess, bool wait)
626631
goto put_iu;
627632
}
628633
err = send_usr_msg(sess->rtrs, READ, iu,
629-
&vec, sizeof(*rsp), iu->sglist, 1,
634+
&vec, sizeof(*rsp), iu->sgt.sgl, 1,
630635
msg_sess_info_conf, &errno, wait);
631636
if (err) {
632637
rnbd_clt_put_sess(sess);
@@ -636,7 +641,7 @@ static int send_msg_sess_info(struct rnbd_clt_session *sess, bool wait)
636641
} else {
637642
err = errno;
638643
}
639-
644+
sg_free_table(&iu->sgt);
640645
rnbd_put_iu(sess, iu);
641646
return err;
642647
}
@@ -1016,11 +1021,10 @@ static int rnbd_client_xfer_request(struct rnbd_clt_dev *dev,
10161021
* See queue limits.
10171022
*/
10181023
if (req_op(rq) != REQ_OP_DISCARD)
1019-
sg_cnt = blk_rq_map_sg(dev->queue, rq, iu->sglist);
1024+
sg_cnt = blk_rq_map_sg(dev->queue, rq, iu->sgt.sgl);
10201025

10211026
if (sg_cnt == 0)
1022-
/* Do not forget to mark the end */
1023-
sg_mark_end(&iu->sglist[0]);
1027+
sg_mark_end(&iu->sgt.sgl[0]);
10241028

10251029
msg.hdr.type = cpu_to_le16(RNBD_MSG_IO);
10261030
msg.device_id = cpu_to_le32(dev->device_id);
@@ -1029,13 +1033,13 @@ static int rnbd_client_xfer_request(struct rnbd_clt_dev *dev,
10291033
.iov_base = &msg,
10301034
.iov_len = sizeof(msg)
10311035
};
1032-
size = rnbd_clt_get_sg_size(iu->sglist, sg_cnt);
1036+
size = rnbd_clt_get_sg_size(iu->sgt.sgl, sg_cnt);
10331037
req_ops = (struct rtrs_clt_req_ops) {
10341038
.priv = iu,
10351039
.conf_fn = msg_io_conf,
10361040
};
10371041
err = rtrs_clt_request(rq_data_dir(rq), &req_ops, rtrs, permit,
1038-
&vec, 1, size, iu->sglist, sg_cnt);
1042+
&vec, 1, size, iu->sgt.sgl, sg_cnt);
10391043
if (unlikely(err)) {
10401044
rnbd_clt_err_rl(dev, "RTRS failed to transfer IO, err: %d\n",
10411045
err);
@@ -1122,6 +1126,7 @@ static blk_status_t rnbd_queue_rq(struct blk_mq_hw_ctx *hctx,
11221126
struct rnbd_clt_dev *dev = rq->rq_disk->private_data;
11231127
struct rnbd_iu *iu = blk_mq_rq_to_pdu(rq);
11241128
int err;
1129+
blk_status_t ret = BLK_STS_IOERR;
11251130

11261131
if (unlikely(dev->dev_state != DEV_STATE_MAPPED))
11271132
return BLK_STS_IOERR;
@@ -1133,32 +1138,35 @@ static blk_status_t rnbd_queue_rq(struct blk_mq_hw_ctx *hctx,
11331138
return BLK_STS_RESOURCE;
11341139
}
11351140

1141+
iu->sgt.sgl = iu->first_sgl;
1142+
err = sg_alloc_table_chained(&iu->sgt,
1143+
/* Even-if the request has no segment,
1144+
* sglist must have one entry at least */
1145+
blk_rq_nr_phys_segments(rq) ? : 1,
1146+
iu->sgt.sgl,
1147+
RNBD_INLINE_SG_CNT);
1148+
if (err) {
1149+
rnbd_clt_err_rl(dev, "sg_alloc_table_chained ret=%d\n", err);
1150+
rnbd_clt_dev_kick_mq_queue(dev, hctx, 10/*ms*/);
1151+
rnbd_put_permit(dev->sess, iu->permit);
1152+
return BLK_STS_RESOURCE;
1153+
}
1154+
11361155
blk_mq_start_request(rq);
11371156
err = rnbd_client_xfer_request(dev, rq, iu);
11381157
if (likely(err == 0))
11391158
return BLK_STS_OK;
11401159
if (unlikely(err == -EAGAIN || err == -ENOMEM)) {
11411160
rnbd_clt_dev_kick_mq_queue(dev, hctx, 10/*ms*/);
1142-
rnbd_put_permit(dev->sess, iu->permit);
1143-
return BLK_STS_RESOURCE;
1161+
ret = BLK_STS_RESOURCE;
11441162
}
1145-
1163+
sg_free_table_chained(&iu->sgt, RNBD_INLINE_SG_CNT);
11461164
rnbd_put_permit(dev->sess, iu->permit);
1147-
return BLK_STS_IOERR;
1148-
}
1149-
1150-
static int rnbd_init_request(struct blk_mq_tag_set *set, struct request *rq,
1151-
unsigned int hctx_idx, unsigned int numa_node)
1152-
{
1153-
struct rnbd_iu *iu = blk_mq_rq_to_pdu(rq);
1154-
1155-
sg_init_table(iu->sglist, BMAX_SEGMENTS);
1156-
return 0;
1165+
return ret;
11571166
}
11581167

11591168
static struct blk_mq_ops rnbd_mq_ops = {
11601169
.queue_rq = rnbd_queue_rq,
1161-
.init_request = rnbd_init_request,
11621170
.complete = rnbd_softirq_done_fn,
11631171
};
11641172

@@ -1172,7 +1180,7 @@ static int setup_mq_tags(struct rnbd_clt_session *sess)
11721180
tag_set->numa_node = NUMA_NO_NODE;
11731181
tag_set->flags = BLK_MQ_F_SHOULD_MERGE |
11741182
BLK_MQ_F_TAG_QUEUE_SHARED;
1175-
tag_set->cmd_size = sizeof(struct rnbd_iu);
1183+
tag_set->cmd_size = sizeof(struct rnbd_iu) + RNBD_RDMA_SGL_SIZE;
11761184
tag_set->nr_hw_queues = num_online_cpus();
11771185

11781186
return blk_mq_alloc_tag_set(tag_set);

drivers/block/rnbd/rnbd-clt.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ struct rnbd_iu_comp {
4444
int errno;
4545
};
4646

47+
#ifdef CONFIG_ARCH_NO_SG_CHAIN
48+
#define RNBD_INLINE_SG_CNT 0
49+
#else
50+
#define RNBD_INLINE_SG_CNT 2
51+
#endif
52+
#define RNBD_RDMA_SGL_SIZE (sizeof(struct scatterlist) * RNBD_INLINE_SG_CNT)
53+
4754
struct rnbd_iu {
4855
union {
4956
struct request *rq; /* for block io */
@@ -56,11 +63,12 @@ struct rnbd_iu {
5663
/* use to send msg associated with a sess */
5764
struct rnbd_clt_session *sess;
5865
};
59-
struct scatterlist sglist[BMAX_SEGMENTS];
66+
struct sg_table sgt;
6067
struct work_struct work;
6168
int errno;
6269
struct rnbd_iu_comp comp;
6370
atomic_t refcount;
71+
struct scatterlist first_sgl[]; /* must be the last one */
6472
};
6573

6674
struct rnbd_cpu_qlist {

0 commit comments

Comments
 (0)