Skip to content

Commit 9911b1e

Browse files
metze-sambasmfrench
authored andcommitted
smb: client: make use of smbdirect_socket.recv_io.credits.available
The logic off managing recv credits by counting posted recv_io and granted credits is racy. That's because the peer might already consumed a credit, but between receiving the incoming recv at the hardware and processing the completion in the 'recv_done' functions we likely have a window where we grant credits, which don't really exist. So we better have a decicated counter for the available credits, which will be incremented when we posted new recv buffers and drained when we grant the credits to the peer. Fixes: 5fb9b45 ("smb: client: count the number of posted recv_io messages in order to calculated credits") 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 9da82dc commit 9911b1e

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

fs/smb/client/smbdirect.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ static void smbd_post_send_credits(struct work_struct *work)
618618
struct smbdirect_recv_io *response;
619619
struct smbdirect_socket *sc =
620620
container_of(work, struct smbdirect_socket, recv_io.posted.refill_work);
621+
int posted = 0;
621622

622623
if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
623624
return;
@@ -640,9 +641,12 @@ static void smbd_post_send_credits(struct work_struct *work)
640641
}
641642

642643
atomic_inc(&sc->recv_io.posted.count);
644+
posted += 1;
643645
}
644646
}
645647

648+
atomic_add(posted, &sc->recv_io.credits.available);
649+
646650
/* Promptly send an immediate packet as defined in [MS-SMBD] 3.1.1.1 */
647651
if (atomic_read(&sc->recv_io.credits.count) <
648652
sc->recv_io.credits.target - 1) {
@@ -1033,19 +1037,38 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
10331037
*/
10341038
static int manage_credits_prior_sending(struct smbdirect_socket *sc)
10351039
{
1040+
int missing;
1041+
int available;
10361042
int new_credits;
10371043

10381044
if (atomic_read(&sc->recv_io.credits.count) >= sc->recv_io.credits.target)
10391045
return 0;
10401046

1041-
new_credits = atomic_read(&sc->recv_io.posted.count);
1042-
if (new_credits == 0)
1047+
missing = (int)sc->recv_io.credits.target - atomic_read(&sc->recv_io.credits.count);
1048+
available = atomic_xchg(&sc->recv_io.credits.available, 0);
1049+
new_credits = (u16)min3(U16_MAX, missing, available);
1050+
if (new_credits <= 0) {
1051+
/*
1052+
* If credits are available, but not granted
1053+
* we need to re-add them again.
1054+
*/
1055+
if (available)
1056+
atomic_add(available, &sc->recv_io.credits.available);
10431057
return 0;
1058+
}
10441059

1045-
new_credits -= atomic_read(&sc->recv_io.credits.count);
1046-
if (new_credits <= 0)
1047-
return 0;
1060+
if (new_credits < available) {
1061+
/*
1062+
* Readd the remaining available again.
1063+
*/
1064+
available -= new_credits;
1065+
atomic_add(available, &sc->recv_io.credits.available);
1066+
}
10481067

1068+
/*
1069+
* Remember we granted the credits
1070+
*/
1071+
atomic_add(new_credits, &sc->recv_io.credits.count);
10491072
return new_credits;
10501073
}
10511074

@@ -1217,7 +1240,6 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
12171240
packet->credits_requested = cpu_to_le16(sp->send_credit_target);
12181241

12191242
new_credits = manage_credits_prior_sending(sc);
1220-
atomic_add(new_credits, &sc->recv_io.credits.count);
12211243
packet->credits_granted = cpu_to_le16(new_credits);
12221244

12231245
packet->flags = 0;

0 commit comments

Comments
 (0)