Skip to content

Commit ee1b055

Browse files
hcleesmfrench
authored andcommitted
ksmbd: smbd: handle multiple Buffer descriptors
Make ksmbd handle multiple buffer descriptors when reading and writing files using SMB direct: Post the work requests of rdma_rw_ctx for RDMA read/write in smb_direct_rdma_xmit(), and the work request for the READ/WRITE response with a remote invalidation in smb_direct_writev(). Signed-off-by: Hyunchul Lee <[email protected]> Acked-by: Namjae Jeon <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 4e3edd0 commit ee1b055

File tree

2 files changed

+107
-62
lines changed

2 files changed

+107
-62
lines changed

fs/ksmbd/smb2pdu.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6133,11 +6133,8 @@ static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
61336133
le32_to_cpu(desc[i].length));
61346134
}
61356135
}
6136-
if (ch_count != 1) {
6137-
ksmbd_debug(RDMA, "RDMA multiple buffer descriptors %d are not supported yet\n",
6138-
ch_count);
6136+
if (!ch_count)
61396137
return -EINVAL;
6140-
}
61416138

61426139
work->need_invalidate_rkey =
61436140
(Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);

fs/ksmbd/transport_rdma.c

Lines changed: 106 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,9 @@ struct smb_direct_recvmsg {
206206
struct smb_direct_rdma_rw_msg {
207207
struct smb_direct_transport *t;
208208
struct ib_cqe cqe;
209+
int status;
209210
struct completion *completion;
211+
struct list_head list;
210212
struct rdma_rw_ctx rw_ctx;
211213
struct sg_table sgt;
212214
struct scatterlist sg_list[];
@@ -1311,6 +1313,16 @@ static int smb_direct_writev(struct ksmbd_transport *t,
13111313
return ret;
13121314
}
13131315

1316+
static void smb_direct_free_rdma_rw_msg(struct smb_direct_transport *t,
1317+
struct smb_direct_rdma_rw_msg *msg,
1318+
enum dma_data_direction dir)
1319+
{
1320+
rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
1321+
msg->sgt.sgl, msg->sgt.nents, dir);
1322+
sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
1323+
kfree(msg);
1324+
}
1325+
13141326
static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
13151327
enum dma_data_direction dir)
13161328
{
@@ -1319,19 +1331,14 @@ static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
13191331
struct smb_direct_transport *t = msg->t;
13201332

13211333
if (wc->status != IB_WC_SUCCESS) {
1334+
msg->status = -EIO;
13221335
pr_err("read/write error. opcode = %d, status = %s(%d)\n",
13231336
wc->opcode, ib_wc_status_msg(wc->status), wc->status);
1324-
smb_direct_disconnect_rdma_connection(t);
1337+
if (wc->status != IB_WC_WR_FLUSH_ERR)
1338+
smb_direct_disconnect_rdma_connection(t);
13251339
}
13261340

1327-
if (atomic_inc_return(&t->rw_credits) > 0)
1328-
wake_up(&t->wait_rw_credits);
1329-
1330-
rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
1331-
msg->sg_list, msg->sgt.nents, dir);
1332-
sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
13331341
complete(msg->completion);
1334-
kfree(msg);
13351342
}
13361343

13371344
static void read_done(struct ib_cq *cq, struct ib_wc *wc)
@@ -1350,75 +1357,116 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
13501357
unsigned int desc_len,
13511358
bool is_read)
13521359
{
1353-
struct smb_direct_rdma_rw_msg *msg;
1354-
int ret;
1360+
struct smb_direct_rdma_rw_msg *msg, *next_msg;
1361+
int i, ret;
13551362
DECLARE_COMPLETION_ONSTACK(completion);
1356-
struct ib_send_wr *first_wr = NULL;
1357-
u32 remote_key = le32_to_cpu(desc[0].token);
1358-
u64 remote_offset = le64_to_cpu(desc[0].offset);
1363+
struct ib_send_wr *first_wr;
1364+
LIST_HEAD(msg_list);
1365+
char *desc_buf;
13591366
int credits_needed;
1367+
unsigned int desc_buf_len;
1368+
size_t total_length = 0;
1369+
1370+
if (t->status != SMB_DIRECT_CS_CONNECTED)
1371+
return -ENOTCONN;
1372+
1373+
/* calculate needed credits */
1374+
credits_needed = 0;
1375+
desc_buf = buf;
1376+
for (i = 0; i < desc_len / sizeof(*desc); i++) {
1377+
desc_buf_len = le32_to_cpu(desc[i].length);
1378+
1379+
credits_needed += calc_rw_credits(t, desc_buf, desc_buf_len);
1380+
desc_buf += desc_buf_len;
1381+
total_length += desc_buf_len;
1382+
if (desc_buf_len == 0 || total_length > buf_len ||
1383+
total_length > t->max_rdma_rw_size)
1384+
return -EINVAL;
1385+
}
1386+
1387+
ksmbd_debug(RDMA, "RDMA %s, len %#x, needed credits %#x\n",
1388+
is_read ? "read" : "write", buf_len, credits_needed);
13601389

1361-
credits_needed = calc_rw_credits(t, buf, buf_len);
13621390
ret = wait_for_rw_credits(t, credits_needed);
13631391
if (ret < 0)
13641392
return ret;
13651393

1366-
/* TODO: mempool */
1367-
msg = kmalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
1368-
sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
1369-
if (!msg) {
1370-
atomic_add(credits_needed, &t->rw_credits);
1371-
return -ENOMEM;
1372-
}
1394+
/* build rdma_rw_ctx for each descriptor */
1395+
desc_buf = buf;
1396+
for (i = 0; i < desc_len / sizeof(*desc); i++) {
1397+
msg = kzalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
1398+
sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
1399+
if (!msg) {
1400+
ret = -ENOMEM;
1401+
goto out;
1402+
}
13731403

1374-
msg->sgt.sgl = &msg->sg_list[0];
1375-
ret = sg_alloc_table_chained(&msg->sgt,
1376-
get_buf_page_count(buf, buf_len),
1377-
msg->sg_list, SG_CHUNK_SIZE);
1378-
if (ret) {
1379-
atomic_add(credits_needed, &t->rw_credits);
1380-
kfree(msg);
1381-
return -ENOMEM;
1382-
}
1404+
desc_buf_len = le32_to_cpu(desc[i].length);
13831405

1384-
ret = get_sg_list(buf, buf_len, msg->sgt.sgl, msg->sgt.orig_nents);
1385-
if (ret <= 0) {
1386-
pr_err("failed to get pages\n");
1387-
goto err;
1388-
}
1406+
msg->t = t;
1407+
msg->cqe.done = is_read ? read_done : write_done;
1408+
msg->completion = &completion;
13891409

1390-
ret = rdma_rw_ctx_init(&msg->rw_ctx, t->qp, t->qp->port,
1391-
msg->sg_list, get_buf_page_count(buf, buf_len),
1392-
0, remote_offset, remote_key,
1393-
is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
1394-
if (ret < 0) {
1395-
pr_err("failed to init rdma_rw_ctx: %d\n", ret);
1396-
goto err;
1410+
msg->sgt.sgl = &msg->sg_list[0];
1411+
ret = sg_alloc_table_chained(&msg->sgt,
1412+
get_buf_page_count(desc_buf, desc_buf_len),
1413+
msg->sg_list, SG_CHUNK_SIZE);
1414+
if (ret) {
1415+
kfree(msg);
1416+
ret = -ENOMEM;
1417+
goto out;
1418+
}
1419+
1420+
ret = get_sg_list(desc_buf, desc_buf_len,
1421+
msg->sgt.sgl, msg->sgt.orig_nents);
1422+
if (ret < 0) {
1423+
sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
1424+
kfree(msg);
1425+
goto out;
1426+
}
1427+
1428+
ret = rdma_rw_ctx_init(&msg->rw_ctx, t->qp, t->qp->port,
1429+
msg->sgt.sgl,
1430+
get_buf_page_count(desc_buf, desc_buf_len),
1431+
0,
1432+
le64_to_cpu(desc[i].offset),
1433+
le32_to_cpu(desc[i].token),
1434+
is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
1435+
if (ret < 0) {
1436+
pr_err("failed to init rdma_rw_ctx: %d\n", ret);
1437+
sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
1438+
kfree(msg);
1439+
goto out;
1440+
}
1441+
1442+
list_add_tail(&msg->list, &msg_list);
1443+
desc_buf += desc_buf_len;
13971444
}
13981445

1399-
msg->t = t;
1400-
msg->cqe.done = is_read ? read_done : write_done;
1401-
msg->completion = &completion;
1402-
first_wr = rdma_rw_ctx_wrs(&msg->rw_ctx, t->qp, t->qp->port,
1403-
&msg->cqe, NULL);
1446+
/* concatenate work requests of rdma_rw_ctxs */
1447+
first_wr = NULL;
1448+
list_for_each_entry_reverse(msg, &msg_list, list) {
1449+
first_wr = rdma_rw_ctx_wrs(&msg->rw_ctx, t->qp, t->qp->port,
1450+
&msg->cqe, first_wr);
1451+
}
14041452

14051453
ret = ib_post_send(t->qp, first_wr, NULL);
14061454
if (ret) {
1407-
pr_err("failed to post send wr: %d\n", ret);
1408-
goto err;
1455+
pr_err("failed to post send wr for RDMA R/W: %d\n", ret);
1456+
goto out;
14091457
}
14101458

1459+
msg = list_last_entry(&msg_list, struct smb_direct_rdma_rw_msg, list);
14111460
wait_for_completion(&completion);
1412-
return 0;
1413-
1414-
err:
1461+
ret = msg->status;
1462+
out:
1463+
list_for_each_entry_safe(msg, next_msg, &msg_list, list) {
1464+
list_del(&msg->list);
1465+
smb_direct_free_rdma_rw_msg(t, msg,
1466+
is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
1467+
}
14151468
atomic_add(credits_needed, &t->rw_credits);
1416-
if (first_wr)
1417-
rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
1418-
msg->sg_list, msg->sgt.nents,
1419-
is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
1420-
sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
1421-
kfree(msg);
1469+
wake_up(&t->wait_rw_credits);
14221470
return ret;
14231471
}
14241472

0 commit comments

Comments
 (0)