Skip to content

Commit 40f0e5d

Browse files
guixinliu1995keithbusch
authored andcommitted
nvmet-rdma: use sbitmap to replace rsp free list
We can use sbitmap to manage all the nvmet_rdma_rsp instead of using free lists and spinlock, and we can use an additional tag to determine whether the nvmet_rdma_rsp is extra allocated. In addition, performance has improved: 1. testing environment is local rxe rdma devie and mem-based backstore device. 2. fio command, test the average 5 times: fio -filename=/dev/nvme0n1 --ioengine=libaio -direct=1 -size=1G -name=1 -thread -runtime=60 -time_based -rw=read -numjobs=16 -iodepth=128 -bs=4k -group_reporting 3. Before: 241k IOPS, After: 256k IOPS, an increase of about 5%. Signed-off-by: Guixin Liu <[email protected]> Reviewed-by: Jens Axboe <[email protected]>
1 parent 782373b commit 40f0e5d

File tree

1 file changed

+27
-29
lines changed

1 file changed

+27
-29
lines changed

drivers/nvme/target/rdma.c

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939

4040
#define NVMET_RDMA_BACKLOG 128
4141

42+
#define NVMET_RDMA_DISCRETE_RSP_TAG -1
43+
4244
struct nvmet_rdma_srq;
4345

4446
struct nvmet_rdma_cmd {
@@ -75,7 +77,7 @@ struct nvmet_rdma_rsp {
7577
u32 invalidate_rkey;
7678

7779
struct list_head wait_list;
78-
struct list_head free_list;
80+
int tag;
7981
};
8082

8183
enum nvmet_rdma_queue_state {
@@ -98,8 +100,7 @@ struct nvmet_rdma_queue {
98100
struct nvmet_sq nvme_sq;
99101

100102
struct nvmet_rdma_rsp *rsps;
101-
struct list_head free_rsps;
102-
spinlock_t rsps_lock;
103+
struct sbitmap rsp_tags;
103104
struct nvmet_rdma_cmd *cmds;
104105

105106
struct work_struct release_work;
@@ -172,7 +173,8 @@ static void nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue);
172173
static void nvmet_rdma_free_rsp(struct nvmet_rdma_device *ndev,
173174
struct nvmet_rdma_rsp *r);
174175
static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev,
175-
struct nvmet_rdma_rsp *r);
176+
struct nvmet_rdma_rsp *r,
177+
int tag);
176178

177179
static const struct nvmet_fabrics_ops nvmet_rdma_ops;
178180

@@ -210,29 +212,25 @@ static inline bool nvmet_rdma_need_data_out(struct nvmet_rdma_rsp *rsp)
210212
static inline struct nvmet_rdma_rsp *
211213
nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue)
212214
{
213-
struct nvmet_rdma_rsp *rsp;
214-
unsigned long flags;
215+
struct nvmet_rdma_rsp *rsp = NULL;
216+
int tag;
215217

216-
spin_lock_irqsave(&queue->rsps_lock, flags);
217-
rsp = list_first_entry_or_null(&queue->free_rsps,
218-
struct nvmet_rdma_rsp, free_list);
219-
if (likely(rsp))
220-
list_del(&rsp->free_list);
221-
spin_unlock_irqrestore(&queue->rsps_lock, flags);
218+
tag = sbitmap_get(&queue->rsp_tags);
219+
if (tag >= 0)
220+
rsp = &queue->rsps[tag];
222221

223222
if (unlikely(!rsp)) {
224223
int ret;
225224

226225
rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
227226
if (unlikely(!rsp))
228227
return NULL;
229-
ret = nvmet_rdma_alloc_rsp(queue->dev, rsp);
228+
ret = nvmet_rdma_alloc_rsp(queue->dev, rsp,
229+
NVMET_RDMA_DISCRETE_RSP_TAG);
230230
if (unlikely(ret)) {
231231
kfree(rsp);
232232
return NULL;
233233
}
234-
235-
rsp->allocated = true;
236234
}
237235

238236
return rsp;
@@ -241,17 +239,13 @@ nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue)
241239
static inline void
242240
nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp)
243241
{
244-
unsigned long flags;
245-
246-
if (unlikely(rsp->allocated)) {
242+
if (unlikely(rsp->tag == NVMET_RDMA_DISCRETE_RSP_TAG)) {
247243
nvmet_rdma_free_rsp(rsp->queue->dev, rsp);
248244
kfree(rsp);
249245
return;
250246
}
251247

252-
spin_lock_irqsave(&rsp->queue->rsps_lock, flags);
253-
list_add_tail(&rsp->free_list, &rsp->queue->free_rsps);
254-
spin_unlock_irqrestore(&rsp->queue->rsps_lock, flags);
248+
sbitmap_clear_bit(&rsp->queue->rsp_tags, rsp->tag);
255249
}
256250

257251
static void nvmet_rdma_free_inline_pages(struct nvmet_rdma_device *ndev,
@@ -404,7 +398,7 @@ static void nvmet_rdma_free_cmds(struct nvmet_rdma_device *ndev,
404398
}
405399

406400
static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev,
407-
struct nvmet_rdma_rsp *r)
401+
struct nvmet_rdma_rsp *r, int tag)
408402
{
409403
/* NVMe CQE / RDMA SEND */
410404
r->req.cqe = kmalloc(sizeof(*r->req.cqe), GFP_KERNEL);
@@ -432,6 +426,7 @@ static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev,
432426
r->read_cqe.done = nvmet_rdma_read_data_done;
433427
/* Data Out / RDMA WRITE */
434428
r->write_cqe.done = nvmet_rdma_write_data_done;
429+
r->tag = tag;
435430

436431
return 0;
437432

@@ -454,21 +449,23 @@ nvmet_rdma_alloc_rsps(struct nvmet_rdma_queue *queue)
454449
{
455450
struct nvmet_rdma_device *ndev = queue->dev;
456451
int nr_rsps = queue->recv_queue_size * 2;
457-
int ret = -EINVAL, i;
452+
int ret = -ENOMEM, i;
453+
454+
if (sbitmap_init_node(&queue->rsp_tags, nr_rsps, -1, GFP_KERNEL,
455+
NUMA_NO_NODE, false, true))
456+
goto out;
458457

459458
queue->rsps = kcalloc(nr_rsps, sizeof(struct nvmet_rdma_rsp),
460459
GFP_KERNEL);
461460
if (!queue->rsps)
462-
goto out;
461+
goto out_free_sbitmap;
463462

464463
for (i = 0; i < nr_rsps; i++) {
465464
struct nvmet_rdma_rsp *rsp = &queue->rsps[i];
466465

467-
ret = nvmet_rdma_alloc_rsp(ndev, rsp);
466+
ret = nvmet_rdma_alloc_rsp(ndev, rsp, i);
468467
if (ret)
469468
goto out_free;
470-
471-
list_add_tail(&rsp->free_list, &queue->free_rsps);
472469
}
473470

474471
return 0;
@@ -477,6 +474,8 @@ nvmet_rdma_alloc_rsps(struct nvmet_rdma_queue *queue)
477474
while (--i >= 0)
478475
nvmet_rdma_free_rsp(ndev, &queue->rsps[i]);
479476
kfree(queue->rsps);
477+
out_free_sbitmap:
478+
sbitmap_free(&queue->rsp_tags);
480479
out:
481480
return ret;
482481
}
@@ -489,6 +488,7 @@ static void nvmet_rdma_free_rsps(struct nvmet_rdma_queue *queue)
489488
for (i = 0; i < nr_rsps; i++)
490489
nvmet_rdma_free_rsp(ndev, &queue->rsps[i]);
491490
kfree(queue->rsps);
491+
sbitmap_free(&queue->rsp_tags);
492492
}
493493

494494
static int nvmet_rdma_post_recv(struct nvmet_rdma_device *ndev,
@@ -1447,8 +1447,6 @@ nvmet_rdma_alloc_queue(struct nvmet_rdma_device *ndev,
14471447
INIT_LIST_HEAD(&queue->rsp_wait_list);
14481448
INIT_LIST_HEAD(&queue->rsp_wr_wait_list);
14491449
spin_lock_init(&queue->rsp_wr_wait_lock);
1450-
INIT_LIST_HEAD(&queue->free_rsps);
1451-
spin_lock_init(&queue->rsps_lock);
14521450
INIT_LIST_HEAD(&queue->queue_list);
14531451

14541452
queue->idx = ida_alloc(&nvmet_rdma_queue_ida, GFP_KERNEL);

0 commit comments

Comments
 (0)