Skip to content

Commit 0158e86

Browse files
metze-sambasmfrench
authored andcommitted
smb: server: make use of smbdirect_socket.send_io.lcredits.*
This introduces logic to prevent on overflow of the send submission queue with ib_post_send() easier. As we first get a local credit and then a remote credit before we mark us as pending. From reading the git history of the linux smbdirect implementations in client and server) it was seen that a peer granted more credits than we requested. I guess that only happened because of bugs in our implementation which was active as client and server. I guess Windows won't do that. So the local credits make sure we only use the amount of credits we asked for. Fixes: 0626e66 ("cifsd: add server handler for central processing and tranport layers") Cc: Namjae Jeon <[email protected]> Cc: Steve French <[email protected]> Cc: Tom Talpey <[email protected]> Cc: [email protected] Cc: [email protected] Signed-off-by: Stefan Metzmacher <[email protected]> Acked-by: Namjae Jeon <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent a902274 commit 0158e86

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

fs/smb/server/transport_rdma.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ static void smb_direct_disconnect_wake_up_all(struct smbdirect_socket *sc)
219219
* in order to notice the broken connection.
220220
*/
221221
wake_up_all(&sc->status_wait);
222+
wake_up_all(&sc->send_io.lcredits.wait_queue);
222223
wake_up_all(&sc->send_io.credits.wait_queue);
223224
wake_up_all(&sc->send_io.pending.zero_wait_queue);
224225
wake_up_all(&sc->recv_io.reassembly.wait_queue);
@@ -916,6 +917,7 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
916917
{
917918
struct smbdirect_send_io *sendmsg, *sibling, *next;
918919
struct smbdirect_socket *sc;
920+
int lcredits = 0;
919921

920922
sendmsg = container_of(wc->wr_cqe, struct smbdirect_send_io, cqe);
921923
sc = sendmsg->socket;
@@ -930,9 +932,11 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
930932
list_for_each_entry_safe(sibling, next, &sendmsg->sibling_list, sibling_list) {
931933
list_del_init(&sibling->sibling_list);
932934
smb_direct_free_sendmsg(sc, sibling);
935+
lcredits += 1;
933936
}
934937
/* Note this frees wc->wr_cqe, but not wc */
935938
smb_direct_free_sendmsg(sc, sendmsg);
939+
lcredits += 1;
936940

937941
if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
938942
pr_err("Send error. status='%s (%d)', opcode=%d\n",
@@ -942,6 +946,9 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
942946
return;
943947
}
944948

949+
atomic_add(lcredits, &sc->send_io.lcredits.count);
950+
wake_up(&sc->send_io.lcredits.wait_queue);
951+
945952
if (atomic_dec_and_test(&sc->send_io.pending.count))
946953
wake_up(&sc->send_io.pending.zero_wait_queue);
947954
}
@@ -1081,6 +1088,23 @@ static int wait_for_credits(struct smbdirect_socket *sc,
10811088
} while (true);
10821089
}
10831090

1091+
static int wait_for_send_lcredit(struct smbdirect_socket *sc,
1092+
struct smbdirect_send_batch *send_ctx)
1093+
{
1094+
if (send_ctx && (atomic_read(&sc->send_io.lcredits.count) <= 1)) {
1095+
int ret;
1096+
1097+
ret = smb_direct_flush_send_list(sc, send_ctx, false);
1098+
if (ret)
1099+
return ret;
1100+
}
1101+
1102+
return wait_for_credits(sc,
1103+
&sc->send_io.lcredits.wait_queue,
1104+
&sc->send_io.lcredits.count,
1105+
1);
1106+
}
1107+
10841108
static int wait_for_send_credits(struct smbdirect_socket *sc,
10851109
struct smbdirect_send_batch *send_ctx)
10861110
{
@@ -1268,20 +1292,22 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
12681292
int data_length;
12691293
struct scatterlist sg[SMBDIRECT_SEND_IO_MAX_SGE - 1];
12701294

1295+
ret = wait_for_send_lcredit(sc, send_ctx);
1296+
if (ret)
1297+
goto lcredit_failed;
1298+
12711299
ret = wait_for_send_credits(sc, send_ctx);
12721300
if (ret)
1273-
return ret;
1301+
goto credit_failed;
12741302

12751303
data_length = 0;
12761304
for (i = 0; i < niov; i++)
12771305
data_length += iov[i].iov_len;
12781306

12791307
ret = smb_direct_create_header(sc, data_length, remaining_data_length,
12801308
&msg);
1281-
if (ret) {
1282-
atomic_inc(&sc->send_io.credits.count);
1283-
return ret;
1284-
}
1309+
if (ret)
1310+
goto header_failed;
12851311

12861312
for (i = 0; i < niov; i++) {
12871313
struct ib_sge *sge;
@@ -1319,7 +1345,11 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
13191345
return 0;
13201346
err:
13211347
smb_direct_free_sendmsg(sc, msg);
1348+
header_failed:
13221349
atomic_inc(&sc->send_io.credits.count);
1350+
credit_failed:
1351+
atomic_inc(&sc->send_io.lcredits.count);
1352+
lcredit_failed:
13231353
return ret;
13241354
}
13251355

@@ -1897,6 +1927,8 @@ static int smb_direct_init_params(struct smbdirect_socket *sc)
18971927
return -EINVAL;
18981928
}
18991929

1930+
atomic_set(&sc->send_io.lcredits.count, sp->send_credit_target);
1931+
19001932
maxpages = DIV_ROUND_UP(sp->max_read_write_size, PAGE_SIZE);
19011933
sc->rw_io.credits.max = rdma_rw_mr_factor(sc->ib.dev,
19021934
sc->rdma.cm_id->port_num,

0 commit comments

Comments
 (0)