Skip to content

Commit 566771a

Browse files
committed
Merge tag 'v6.18-rc2-smb-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: "smbdirect (RDMA) fixes in order avoid potential submission queue overflows: - free transport teardown fix - credit related fixes (five server related, one client related)" * tag 'v6.18-rc2-smb-server-fixes' of git://git.samba.org/ksmbd: smb: server: let free_transport() wait for SMBDIRECT_SOCKET_DISCONNECTED smb: client: make use of smbdirect_socket.send_io.lcredits.* smb: server: make use of smbdirect_socket.send_io.lcredits.* smb: server: simplify sibling_list handling in smb_direct_flush_send_list/send_done smb: server: smb_direct_disconnect_rdma_connection() already wakes all waiters on error smb: smbdirect: introduce smbdirect_socket.send_io.lcredits.* smb: server: allocate enough space for RW WRs and ib_drain_qp()
2 parents 53abe3e + dd6940f commit 566771a

File tree

3 files changed

+273
-151
lines changed

3 files changed

+273
-151
lines changed

fs/smb/client/smbdirect.c

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ static void smbd_disconnect_wake_up_all(struct smbdirect_socket *sc)
172172
* in order to notice the broken connection.
173173
*/
174174
wake_up_all(&sc->status_wait);
175+
wake_up_all(&sc->send_io.lcredits.wait_queue);
175176
wake_up_all(&sc->send_io.credits.wait_queue);
176177
wake_up_all(&sc->send_io.pending.dec_wait_queue);
177178
wake_up_all(&sc->send_io.pending.zero_wait_queue);
@@ -495,6 +496,7 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
495496
struct smbdirect_send_io *request =
496497
container_of(wc->wr_cqe, struct smbdirect_send_io, cqe);
497498
struct smbdirect_socket *sc = request->socket;
499+
int lcredits = 0;
498500

499501
log_rdma_send(INFO, "smbdirect_send_io 0x%p completed wc->status=%s\n",
500502
request, ib_wc_status_msg(wc->status));
@@ -504,22 +506,24 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
504506
request->sge[i].addr,
505507
request->sge[i].length,
506508
DMA_TO_DEVICE);
509+
mempool_free(request, sc->send_io.mem.pool);
510+
lcredits += 1;
507511

508512
if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
509513
if (wc->status != IB_WC_WR_FLUSH_ERR)
510514
log_rdma_send(ERR, "wc->status=%s wc->opcode=%d\n",
511515
ib_wc_status_msg(wc->status), wc->opcode);
512-
mempool_free(request, sc->send_io.mem.pool);
513516
smbd_disconnect_rdma_connection(sc);
514517
return;
515518
}
516519

520+
atomic_add(lcredits, &sc->send_io.lcredits.count);
521+
wake_up(&sc->send_io.lcredits.wait_queue);
522+
517523
if (atomic_dec_and_test(&sc->send_io.pending.count))
518524
wake_up(&sc->send_io.pending.zero_wait_queue);
519525

520526
wake_up(&sc->send_io.pending.dec_wait_queue);
521-
522-
mempool_free(request, sc->send_io.mem.pool);
523527
}
524528

525529
static void dump_smbdirect_negotiate_resp(struct smbdirect_negotiate_resp *resp)
@@ -567,6 +571,7 @@ static bool process_negotiation_response(
567571
log_rdma_event(ERR, "error: credits_granted==0\n");
568572
return false;
569573
}
574+
atomic_set(&sc->send_io.lcredits.count, sp->send_credit_target);
570575
atomic_set(&sc->send_io.credits.count, le16_to_cpu(packet->credits_granted));
571576

572577
if (le32_to_cpu(packet->preferred_send_size) > sp->max_recv_size) {
@@ -1114,6 +1119,24 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
11141119
struct smbdirect_data_transfer *packet;
11151120
int new_credits = 0;
11161121

1122+
wait_lcredit:
1123+
/* Wait for local send credits */
1124+
rc = wait_event_interruptible(sc->send_io.lcredits.wait_queue,
1125+
atomic_read(&sc->send_io.lcredits.count) > 0 ||
1126+
sc->status != SMBDIRECT_SOCKET_CONNECTED);
1127+
if (rc)
1128+
goto err_wait_lcredit;
1129+
1130+
if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
1131+
log_outgoing(ERR, "disconnected not sending on wait_credit\n");
1132+
rc = -EAGAIN;
1133+
goto err_wait_lcredit;
1134+
}
1135+
if (unlikely(atomic_dec_return(&sc->send_io.lcredits.count) < 0)) {
1136+
atomic_inc(&sc->send_io.lcredits.count);
1137+
goto wait_lcredit;
1138+
}
1139+
11171140
wait_credit:
11181141
/* Wait for send credits. A SMBD packet needs one credit */
11191142
rc = wait_event_interruptible(sc->send_io.credits.wait_queue,
@@ -1132,23 +1155,6 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
11321155
goto wait_credit;
11331156
}
11341157

1135-
wait_send_queue:
1136-
wait_event(sc->send_io.pending.dec_wait_queue,
1137-
atomic_read(&sc->send_io.pending.count) < sp->send_credit_target ||
1138-
sc->status != SMBDIRECT_SOCKET_CONNECTED);
1139-
1140-
if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
1141-
log_outgoing(ERR, "disconnected not sending on wait_send_queue\n");
1142-
rc = -EAGAIN;
1143-
goto err_wait_send_queue;
1144-
}
1145-
1146-
if (unlikely(atomic_inc_return(&sc->send_io.pending.count) >
1147-
sp->send_credit_target)) {
1148-
atomic_dec(&sc->send_io.pending.count);
1149-
goto wait_send_queue;
1150-
}
1151-
11521158
request = mempool_alloc(sc->send_io.mem.pool, GFP_KERNEL);
11531159
if (!request) {
11541160
rc = -ENOMEM;
@@ -1229,10 +1235,21 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
12291235
le32_to_cpu(packet->data_length),
12301236
le32_to_cpu(packet->remaining_data_length));
12311237

1238+
/*
1239+
* Now that we got a local and a remote credit
1240+
* we add us as pending
1241+
*/
1242+
atomic_inc(&sc->send_io.pending.count);
1243+
12321244
rc = smbd_post_send(sc, request);
12331245
if (!rc)
12341246
return 0;
12351247

1248+
if (atomic_dec_and_test(&sc->send_io.pending.count))
1249+
wake_up(&sc->send_io.pending.zero_wait_queue);
1250+
1251+
wake_up(&sc->send_io.pending.dec_wait_queue);
1252+
12361253
err_dma:
12371254
for (i = 0; i < request->num_sge; i++)
12381255
if (request->sge[i].addr)
@@ -1246,14 +1263,14 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
12461263
atomic_sub(new_credits, &sc->recv_io.credits.count);
12471264

12481265
err_alloc:
1249-
if (atomic_dec_and_test(&sc->send_io.pending.count))
1250-
wake_up(&sc->send_io.pending.zero_wait_queue);
1251-
1252-
err_wait_send_queue:
1253-
/* roll back send credits and pending */
12541266
atomic_inc(&sc->send_io.credits.count);
1267+
wake_up(&sc->send_io.credits.wait_queue);
12551268

12561269
err_wait_credit:
1270+
atomic_inc(&sc->send_io.lcredits.count);
1271+
wake_up(&sc->send_io.lcredits.wait_queue);
1272+
1273+
err_wait_lcredit:
12571274
return rc;
12581275
}
12591276

fs/smb/common/smbdirect/smbdirect_socket.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,15 @@ struct smbdirect_socket {
142142
} mem;
143143

144144
/*
145-
* The credit state for the send side
145+
* The local credit state for ib_post_send()
146+
*/
147+
struct {
148+
atomic_t count;
149+
wait_queue_head_t wait_queue;
150+
} lcredits;
151+
152+
/*
153+
* The remote credit state for the send side
146154
*/
147155
struct {
148156
atomic_t count;
@@ -337,6 +345,9 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
337345
INIT_DELAYED_WORK(&sc->idle.timer_work, __smbdirect_socket_disabled_work);
338346
disable_delayed_work_sync(&sc->idle.timer_work);
339347

348+
atomic_set(&sc->send_io.lcredits.count, 0);
349+
init_waitqueue_head(&sc->send_io.lcredits.wait_queue);
350+
340351
atomic_set(&sc->send_io.credits.count, 0);
341352
init_waitqueue_head(&sc->send_io.credits.wait_queue);
342353

0 commit comments

Comments
 (0)