@@ -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 */
11561165static 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+
11831272static 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
12211329static 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
13571466static 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