Skip to content

Commit 2c1ac39

Browse files
metze-sambasmfrench
authored andcommitted
smb: client: use smbdirect_send_batch processing
This will allow us to use similar logic as we have in the server soon, so that we can share common code later. Cc: <stable@vger.kernel.org> # 6.18.x Cc: Steve French <smfrench@gmail.com> Cc: Tom Talpey <tom@talpey.com> Cc: Long Li <longli@microsoft.com> Cc: Namjae Jeon <linkinjeon@kernel.org> Cc: linux-cifs@vger.kernel.org Cc: samba-technical@lists.samba.org Signed-off-by: Stefan Metzmacher <metze@samba.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent dc77da0 commit 2c1ac39

1 file changed

Lines changed: 135 additions & 14 deletions

File tree

fs/smb/client/smbdirect.c

Lines changed: 135 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -544,11 +544,20 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
544544
struct smbdirect_send_io *request =
545545
container_of(wc->wr_cqe, struct smbdirect_send_io, cqe);
546546
struct smbdirect_socket *sc = request->socket;
547+
struct smbdirect_send_io *sibling, *next;
547548
int lcredits = 0;
548549

549550
log_rdma_send(INFO, "smbdirect_send_io 0x%p completed wc->status=%s\n",
550551
request, ib_wc_status_msg(wc->status));
551552

553+
/*
554+
* Free possible siblings and then the main send_io
555+
*/
556+
list_for_each_entry_safe(sibling, next, &request->sibling_list, sibling_list) {
557+
list_del_init(&sibling->sibling_list);
558+
smbd_free_send_io(sibling);
559+
lcredits += 1;
560+
}
552561
/* Note this frees wc->wr_cqe, but not wc */
553562
smbd_free_send_io(request);
554563
lcredits += 1;
@@ -1154,7 +1163,8 @@ static int smbd_ib_post_send(struct smbdirect_socket *sc,
11541163

11551164
/* Post the send request */
11561165
static int smbd_post_send(struct smbdirect_socket *sc,
1157-
struct smbdirect_send_io *request)
1166+
struct smbdirect_send_batch *batch,
1167+
struct smbdirect_send_io *request)
11581168
{
11591169
int i;
11601170

@@ -1170,16 +1180,95 @@ static int smbd_post_send(struct smbdirect_socket *sc,
11701180
}
11711181

11721182
request->cqe.done = send_done;
1173-
11741183
request->wr.next = NULL;
1175-
request->wr.wr_cqe = &request->cqe;
11761184
request->wr.sg_list = request->sge;
11771185
request->wr.num_sge = request->num_sge;
11781186
request->wr.opcode = IB_WR_SEND;
1187+
1188+
if (batch) {
1189+
request->wr.wr_cqe = NULL;
1190+
request->wr.send_flags = 0;
1191+
if (!list_empty(&batch->msg_list)) {
1192+
struct smbdirect_send_io *last;
1193+
1194+
last = list_last_entry(&batch->msg_list,
1195+
struct smbdirect_send_io,
1196+
sibling_list);
1197+
last->wr.next = &request->wr;
1198+
}
1199+
list_add_tail(&request->sibling_list, &batch->msg_list);
1200+
batch->wr_cnt++;
1201+
return 0;
1202+
}
1203+
1204+
request->wr.wr_cqe = &request->cqe;
11791205
request->wr.send_flags = IB_SEND_SIGNALED;
11801206
return smbd_ib_post_send(sc, &request->wr);
11811207
}
11821208

1209+
static void smbd_send_batch_init(struct smbdirect_send_batch *batch,
1210+
bool need_invalidate_rkey,
1211+
unsigned int remote_key)
1212+
{
1213+
INIT_LIST_HEAD(&batch->msg_list);
1214+
batch->wr_cnt = 0;
1215+
batch->need_invalidate_rkey = need_invalidate_rkey;
1216+
batch->remote_key = remote_key;
1217+
}
1218+
1219+
static int smbd_send_batch_flush(struct smbdirect_socket *sc,
1220+
struct smbdirect_send_batch *batch,
1221+
bool is_last)
1222+
{
1223+
struct smbdirect_send_io *first, *last;
1224+
int ret = 0;
1225+
1226+
if (list_empty(&batch->msg_list))
1227+
return 0;
1228+
1229+
first = list_first_entry(&batch->msg_list,
1230+
struct smbdirect_send_io,
1231+
sibling_list);
1232+
last = list_last_entry(&batch->msg_list,
1233+
struct smbdirect_send_io,
1234+
sibling_list);
1235+
1236+
if (batch->need_invalidate_rkey) {
1237+
first->wr.opcode = IB_WR_SEND_WITH_INV;
1238+
first->wr.ex.invalidate_rkey = batch->remote_key;
1239+
batch->need_invalidate_rkey = false;
1240+
batch->remote_key = 0;
1241+
}
1242+
1243+
last->wr.send_flags = IB_SEND_SIGNALED;
1244+
last->wr.wr_cqe = &last->cqe;
1245+
1246+
/*
1247+
* Remove last from batch->msg_list
1248+
* and splice the rest of batch->msg_list
1249+
* to last->sibling_list.
1250+
*
1251+
* batch->msg_list is a valid empty list
1252+
* at the end.
1253+
*/
1254+
list_del_init(&last->sibling_list);
1255+
list_splice_tail_init(&batch->msg_list, &last->sibling_list);
1256+
batch->wr_cnt = 0;
1257+
1258+
ret = smbd_ib_post_send(sc, &first->wr);
1259+
if (ret) {
1260+
struct smbdirect_send_io *sibling, *next;
1261+
1262+
list_for_each_entry_safe(sibling, next, &last->sibling_list, sibling_list) {
1263+
list_del_init(&sibling->sibling_list);
1264+
smbd_free_send_io(sibling);
1265+
}
1266+
smbd_free_send_io(last);
1267+
}
1268+
1269+
return ret;
1270+
}
1271+
11831272
static int wait_for_credits(struct smbdirect_socket *sc,
11841273
wait_queue_head_t *waitq, atomic_t *total_credits,
11851274
int needed)
@@ -1202,23 +1291,43 @@ static int wait_for_credits(struct smbdirect_socket *sc,
12021291
} while (true);
12031292
}
12041293

1205-
static int wait_for_send_lcredit(struct smbdirect_socket *sc)
1294+
static int wait_for_send_lcredit(struct smbdirect_socket *sc,
1295+
struct smbdirect_send_batch *batch)
12061296
{
1297+
if (batch && (atomic_read(&sc->send_io.lcredits.count) <= 1)) {
1298+
int ret;
1299+
1300+
ret = smbd_send_batch_flush(sc, batch, false);
1301+
if (ret)
1302+
return ret;
1303+
}
1304+
12071305
return wait_for_credits(sc,
12081306
&sc->send_io.lcredits.wait_queue,
12091307
&sc->send_io.lcredits.count,
12101308
1);
12111309
}
12121310

1213-
static int wait_for_send_credits(struct smbdirect_socket *sc)
1311+
static int wait_for_send_credits(struct smbdirect_socket *sc,
1312+
struct smbdirect_send_batch *batch)
12141313
{
1314+
if (batch &&
1315+
(batch->wr_cnt >= 16 || atomic_read(&sc->send_io.credits.count) <= 1)) {
1316+
int ret;
1317+
1318+
ret = smbd_send_batch_flush(sc, batch, false);
1319+
if (ret)
1320+
return ret;
1321+
}
1322+
12151323
return wait_for_credits(sc,
12161324
&sc->send_io.credits.wait_queue,
12171325
&sc->send_io.credits.count,
12181326
1);
12191327
}
12201328

12211329
static int smbd_post_send_iter(struct smbdirect_socket *sc,
1330+
struct smbdirect_send_batch *batch,
12221331
struct iov_iter *iter,
12231332
int *_remaining_data_length)
12241333
{
@@ -1230,14 +1339,14 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
12301339
struct smbdirect_data_transfer *packet;
12311340
int new_credits = 0;
12321341

1233-
rc = wait_for_send_lcredit(sc);
1342+
rc = wait_for_send_lcredit(sc, batch);
12341343
if (rc) {
12351344
log_outgoing(ERR, "disconnected not sending on wait_lcredit\n");
12361345
rc = -EAGAIN;
12371346
goto err_wait_lcredit;
12381347
}
12391348

1240-
rc = wait_for_send_credits(sc);
1349+
rc = wait_for_send_credits(sc, batch);
12411350
if (rc) {
12421351
log_outgoing(ERR, "disconnected not sending on wait_credit\n");
12431352
rc = -EAGAIN;
@@ -1322,7 +1431,7 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
13221431
le32_to_cpu(packet->data_length),
13231432
le32_to_cpu(packet->remaining_data_length));
13241433

1325-
rc = smbd_post_send(sc, request);
1434+
rc = smbd_post_send(sc, batch, request);
13261435
if (!rc)
13271436
return 0;
13281437

@@ -1351,10 +1460,11 @@ static int smbd_post_send_empty(struct smbdirect_socket *sc)
13511460
int remaining_data_length = 0;
13521461

13531462
sc->statistics.send_empty++;
1354-
return smbd_post_send_iter(sc, NULL, &remaining_data_length);
1463+
return smbd_post_send_iter(sc, NULL, NULL, &remaining_data_length);
13551464
}
13561465

13571466
static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
1467+
struct smbdirect_send_batch *batch,
13581468
struct iov_iter *iter,
13591469
int *_remaining_data_length)
13601470
{
@@ -1367,7 +1477,7 @@ static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
13671477
*/
13681478

13691479
while (iov_iter_count(iter) > 0) {
1370-
rc = smbd_post_send_iter(sc, iter, _remaining_data_length);
1480+
rc = smbd_post_send_iter(sc, batch, iter, _remaining_data_length);
13711481
if (rc < 0)
13721482
break;
13731483
}
@@ -2289,8 +2399,10 @@ int smbd_send(struct TCP_Server_Info *server,
22892399
struct smbdirect_socket_parameters *sp = &sc->parameters;
22902400
struct smb_rqst *rqst;
22912401
struct iov_iter iter;
2402+
struct smbdirect_send_batch batch;
22922403
unsigned int remaining_data_length, klen;
22932404
int rc, i, rqst_idx;
2405+
int error = 0;
22942406

22952407
if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
22962408
return -EAGAIN;
@@ -2315,6 +2427,7 @@ int smbd_send(struct TCP_Server_Info *server,
23152427
num_rqst, remaining_data_length);
23162428

23172429
rqst_idx = 0;
2430+
smbd_send_batch_init(&batch, false, 0);
23182431
do {
23192432
rqst = &rqst_array[rqst_idx];
23202433

@@ -2333,20 +2446,28 @@ int smbd_send(struct TCP_Server_Info *server,
23332446
klen += rqst->rq_iov[i].iov_len;
23342447
iov_iter_kvec(&iter, ITER_SOURCE, rqst->rq_iov, rqst->rq_nvec, klen);
23352448

2336-
rc = smbd_post_send_full_iter(sc, &iter, &remaining_data_length);
2337-
if (rc < 0)
2449+
rc = smbd_post_send_full_iter(sc, &batch, &iter, &remaining_data_length);
2450+
if (rc < 0) {
2451+
error = rc;
23382452
break;
2453+
}
23392454

23402455
if (iov_iter_count(&rqst->rq_iter) > 0) {
23412456
/* And then the data pages if there are any */
2342-
rc = smbd_post_send_full_iter(sc, &rqst->rq_iter,
2457+
rc = smbd_post_send_full_iter(sc, &batch, &rqst->rq_iter,
23432458
&remaining_data_length);
2344-
if (rc < 0)
2459+
if (rc < 0) {
2460+
error = rc;
23452461
break;
2462+
}
23462463
}
23472464

23482465
} while (++rqst_idx < num_rqst);
23492466

2467+
rc = smbd_send_batch_flush(sc, &batch, true);
2468+
if (unlikely(!rc && error))
2469+
rc = error;
2470+
23502471
/*
23512472
* As an optimization, we don't wait for individual I/O to finish
23522473
* before sending the next one.

0 commit comments

Comments
 (0)