Skip to content

Commit ddbdc86

Browse files
hcleesmfrench
authored andcommitted
ksmbd: smbd: introduce read/write credits for RDMA read/write
SMB2_READ/SMB2_WRITE request has to be granted the number of rw credits, the pages the request wants to transfer / the maximum pages which can be registered with one MR to read and write a file. And allocate enough RDMA resources for the maximum number of rw credits allowed by ksmbd. Signed-off-by: Hyunchul Lee <[email protected]> Acked-by: Namjae Jeon <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 1807abc commit ddbdc86

File tree

1 file changed

+71
-49
lines changed

1 file changed

+71
-49
lines changed

fs/ksmbd/transport_rdma.c

Lines changed: 71 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,7 @@ static int smb_direct_max_fragmented_recv_size = 1024 * 1024;
8080
/* The maximum single-message size which can be received */
8181
static int smb_direct_max_receive_size = 8192;
8282

83-
static int smb_direct_max_read_write_size = 524224;
84-
85-
static int smb_direct_max_outstanding_rw_ops = 8;
83+
static int smb_direct_max_read_write_size = 8 * 1024 * 1024;
8684

8785
static LIST_HEAD(smb_direct_device_list);
8886
static DEFINE_RWLOCK(smb_direct_device_lock);
@@ -147,10 +145,12 @@ struct smb_direct_transport {
147145
atomic_t send_credits;
148146
spinlock_t lock_new_recv_credits;
149147
int new_recv_credits;
150-
atomic_t rw_avail_ops;
148+
int max_rw_credits;
149+
int pages_per_rw_credit;
150+
atomic_t rw_credits;
151151

152152
wait_queue_head_t wait_send_credits;
153-
wait_queue_head_t wait_rw_avail_ops;
153+
wait_queue_head_t wait_rw_credits;
154154

155155
mempool_t *sendmsg_mempool;
156156
struct kmem_cache *sendmsg_cache;
@@ -377,7 +377,7 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
377377
t->reassembly_queue_length = 0;
378378
init_waitqueue_head(&t->wait_reassembly_queue);
379379
init_waitqueue_head(&t->wait_send_credits);
380-
init_waitqueue_head(&t->wait_rw_avail_ops);
380+
init_waitqueue_head(&t->wait_rw_credits);
381381

382382
spin_lock_init(&t->receive_credit_lock);
383383
spin_lock_init(&t->recvmsg_queue_lock);
@@ -983,18 +983,19 @@ static int smb_direct_flush_send_list(struct smb_direct_transport *t,
983983
}
984984

985985
static int wait_for_credits(struct smb_direct_transport *t,
986-
wait_queue_head_t *waitq, atomic_t *credits)
986+
wait_queue_head_t *waitq, atomic_t *total_credits,
987+
int needed)
987988
{
988989
int ret;
989990

990991
do {
991-
if (atomic_dec_return(credits) >= 0)
992+
if (atomic_sub_return(needed, total_credits) >= 0)
992993
return 0;
993994

994-
atomic_inc(credits);
995+
atomic_add(needed, total_credits);
995996
ret = wait_event_interruptible(*waitq,
996-
atomic_read(credits) > 0 ||
997-
t->status != SMB_DIRECT_CS_CONNECTED);
997+
atomic_read(total_credits) >= needed ||
998+
t->status != SMB_DIRECT_CS_CONNECTED);
998999

9991000
if (t->status != SMB_DIRECT_CS_CONNECTED)
10001001
return -ENOTCONN;
@@ -1015,7 +1016,19 @@ static int wait_for_send_credits(struct smb_direct_transport *t,
10151016
return ret;
10161017
}
10171018

1018-
return wait_for_credits(t, &t->wait_send_credits, &t->send_credits);
1019+
return wait_for_credits(t, &t->wait_send_credits, &t->send_credits, 1);
1020+
}
1021+
1022+
static int wait_for_rw_credits(struct smb_direct_transport *t, int credits)
1023+
{
1024+
return wait_for_credits(t, &t->wait_rw_credits, &t->rw_credits, credits);
1025+
}
1026+
1027+
static int calc_rw_credits(struct smb_direct_transport *t,
1028+
char *buf, unsigned int len)
1029+
{
1030+
return DIV_ROUND_UP(get_buf_page_count(buf, len),
1031+
t->pages_per_rw_credit);
10191032
}
10201033

10211034
static int smb_direct_create_header(struct smb_direct_transport *t,
@@ -1331,8 +1344,8 @@ static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
13311344
smb_direct_disconnect_rdma_connection(t);
13321345
}
13331346

1334-
if (atomic_inc_return(&t->rw_avail_ops) > 0)
1335-
wake_up(&t->wait_rw_avail_ops);
1347+
if (atomic_inc_return(&t->rw_credits) > 0)
1348+
wake_up(&t->wait_rw_credits);
13361349

13371350
rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
13381351
msg->sg_list, msg->sgt.nents, dir);
@@ -1363,16 +1376,18 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
13631376
struct ib_send_wr *first_wr = NULL;
13641377
u32 remote_key = le32_to_cpu(desc[0].token);
13651378
u64 remote_offset = le64_to_cpu(desc[0].offset);
1379+
int credits_needed;
13661380

1367-
ret = wait_for_credits(t, &t->wait_rw_avail_ops, &t->rw_avail_ops);
1381+
credits_needed = calc_rw_credits(t, buf, buf_len);
1382+
ret = wait_for_rw_credits(t, credits_needed);
13681383
if (ret < 0)
13691384
return ret;
13701385

13711386
/* TODO: mempool */
13721387
msg = kmalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
13731388
sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
13741389
if (!msg) {
1375-
atomic_inc(&t->rw_avail_ops);
1390+
atomic_add(credits_needed, &t->rw_credits);
13761391
return -ENOMEM;
13771392
}
13781393

@@ -1381,7 +1396,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
13811396
get_buf_page_count(buf, buf_len),
13821397
msg->sg_list, SG_CHUNK_SIZE);
13831398
if (ret) {
1384-
atomic_inc(&t->rw_avail_ops);
1399+
atomic_add(credits_needed, &t->rw_credits);
13851400
kfree(msg);
13861401
return -ENOMEM;
13871402
}
@@ -1417,7 +1432,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
14171432
return 0;
14181433

14191434
err:
1420-
atomic_inc(&t->rw_avail_ops);
1435+
atomic_add(credits_needed, &t->rw_credits);
14211436
if (first_wr)
14221437
rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
14231438
msg->sg_list, msg->sgt.nents,
@@ -1642,11 +1657,19 @@ static int smb_direct_prepare_negotiation(struct smb_direct_transport *t)
16421657
return ret;
16431658
}
16441659

1660+
static unsigned int smb_direct_get_max_fr_pages(struct smb_direct_transport *t)
1661+
{
1662+
return min_t(unsigned int,
1663+
t->cm_id->device->attrs.max_fast_reg_page_list_len,
1664+
256);
1665+
}
1666+
16451667
static int smb_direct_init_params(struct smb_direct_transport *t,
16461668
struct ib_qp_cap *cap)
16471669
{
16481670
struct ib_device *device = t->cm_id->device;
1649-
int max_send_sges, max_pages, max_rw_wrs, max_send_wrs;
1671+
int max_send_sges, max_rw_wrs, max_send_wrs;
1672+
unsigned int max_sge_per_wr, wrs_per_credit;
16501673

16511674
/* need 2 more sge. because a SMB_DIRECT header will be mapped,
16521675
* and maybe a send buffer could be not page aligned.
@@ -1658,25 +1681,31 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
16581681
return -EINVAL;
16591682
}
16601683

1661-
/*
1662-
* allow smb_direct_max_outstanding_rw_ops of in-flight RDMA
1663-
* read/writes. HCA guarantees at least max_send_sge of sges for
1664-
* a RDMA read/write work request, and if memory registration is used,
1665-
* we need reg_mr, local_inv wrs for each read/write.
1684+
/* Calculate the number of work requests for RDMA R/W.
1685+
* The maximum number of pages which can be registered
1686+
* with one Memory region can be transferred with one
1687+
* R/W credit. And at least 4 work requests for each credit
1688+
* are needed for MR registration, RDMA R/W, local & remote
1689+
* MR invalidation.
16661690
*/
16671691
t->max_rdma_rw_size = smb_direct_max_read_write_size;
1668-
max_pages = DIV_ROUND_UP(t->max_rdma_rw_size, PAGE_SIZE) + 1;
1669-
max_rw_wrs = DIV_ROUND_UP(max_pages, SMB_DIRECT_MAX_SEND_SGES);
1670-
max_rw_wrs += rdma_rw_mr_factor(device, t->cm_id->port_num,
1671-
max_pages) * 2;
1672-
max_rw_wrs *= smb_direct_max_outstanding_rw_ops;
1692+
t->pages_per_rw_credit = smb_direct_get_max_fr_pages(t);
1693+
t->max_rw_credits = DIV_ROUND_UP(t->max_rdma_rw_size,
1694+
(t->pages_per_rw_credit - 1) *
1695+
PAGE_SIZE);
1696+
1697+
max_sge_per_wr = min_t(unsigned int, device->attrs.max_send_sge,
1698+
device->attrs.max_sge_rd);
1699+
wrs_per_credit = max_t(unsigned int, 4,
1700+
DIV_ROUND_UP(t->pages_per_rw_credit,
1701+
max_sge_per_wr) + 1);
1702+
max_rw_wrs = t->max_rw_credits * wrs_per_credit;
16731703

16741704
max_send_wrs = smb_direct_send_credit_target + max_rw_wrs;
16751705
if (max_send_wrs > device->attrs.max_cqe ||
16761706
max_send_wrs > device->attrs.max_qp_wr) {
1677-
pr_err("consider lowering send_credit_target = %d, or max_outstanding_rw_ops = %d\n",
1678-
smb_direct_send_credit_target,
1679-
smb_direct_max_outstanding_rw_ops);
1707+
pr_err("consider lowering send_credit_target = %d\n",
1708+
smb_direct_send_credit_target);
16801709
pr_err("Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
16811710
device->attrs.max_cqe, device->attrs.max_qp_wr);
16821711
return -EINVAL;
@@ -1711,20 +1740,18 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
17111740

17121741
t->send_credit_target = smb_direct_send_credit_target;
17131742
atomic_set(&t->send_credits, 0);
1714-
atomic_set(&t->rw_avail_ops, smb_direct_max_outstanding_rw_ops);
1743+
atomic_set(&t->rw_credits, t->max_rw_credits);
17151744

17161745
t->max_send_size = smb_direct_max_send_size;
17171746
t->max_recv_size = smb_direct_max_receive_size;
17181747
t->max_fragmented_recv_size = smb_direct_max_fragmented_recv_size;
17191748

17201749
cap->max_send_wr = max_send_wrs;
17211750
cap->max_recv_wr = t->recv_credit_max;
1722-
cap->max_send_sge = SMB_DIRECT_MAX_SEND_SGES;
1751+
cap->max_send_sge = max_sge_per_wr;
17231752
cap->max_recv_sge = SMB_DIRECT_MAX_RECV_SGES;
17241753
cap->max_inline_data = 0;
1725-
cap->max_rdma_ctxs =
1726-
rdma_rw_mr_factor(device, t->cm_id->port_num, max_pages) *
1727-
smb_direct_max_outstanding_rw_ops;
1754+
cap->max_rdma_ctxs = t->max_rw_credits;
17281755
return 0;
17291756
}
17301757

@@ -1817,7 +1844,8 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
18171844
}
18181845

18191846
t->send_cq = ib_alloc_cq(t->cm_id->device, t,
1820-
t->send_credit_target, 0, IB_POLL_WORKQUEUE);
1847+
smb_direct_send_credit_target + cap->max_rdma_ctxs,
1848+
0, IB_POLL_WORKQUEUE);
18211849
if (IS_ERR(t->send_cq)) {
18221850
pr_err("Can't create RDMA send CQ\n");
18231851
ret = PTR_ERR(t->send_cq);
@@ -1826,8 +1854,7 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
18261854
}
18271855

18281856
t->recv_cq = ib_alloc_cq(t->cm_id->device, t,
1829-
cap->max_send_wr + cap->max_rdma_ctxs,
1830-
0, IB_POLL_WORKQUEUE);
1857+
t->recv_credit_max, 0, IB_POLL_WORKQUEUE);
18311858
if (IS_ERR(t->recv_cq)) {
18321859
pr_err("Can't create RDMA recv CQ\n");
18331860
ret = PTR_ERR(t->recv_cq);
@@ -1856,17 +1883,12 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
18561883

18571884
pages_per_rw = DIV_ROUND_UP(t->max_rdma_rw_size, PAGE_SIZE) + 1;
18581885
if (pages_per_rw > t->cm_id->device->attrs.max_sgl_rd) {
1859-
int pages_per_mr, mr_count;
1860-
1861-
pages_per_mr = min_t(int, pages_per_rw,
1862-
t->cm_id->device->attrs.max_fast_reg_page_list_len);
1863-
mr_count = DIV_ROUND_UP(pages_per_rw, pages_per_mr) *
1864-
atomic_read(&t->rw_avail_ops);
1865-
ret = ib_mr_pool_init(t->qp, &t->qp->rdma_mrs, mr_count,
1866-
IB_MR_TYPE_MEM_REG, pages_per_mr, 0);
1886+
ret = ib_mr_pool_init(t->qp, &t->qp->rdma_mrs,
1887+
t->max_rw_credits, IB_MR_TYPE_MEM_REG,
1888+
t->pages_per_rw_credit, 0);
18671889
if (ret) {
18681890
pr_err("failed to init mr pool count %d pages %d\n",
1869-
mr_count, pages_per_mr);
1891+
t->max_rw_credits, t->pages_per_rw_credit);
18701892
goto err;
18711893
}
18721894
}

0 commit comments

Comments
 (0)