mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 20:46:48 +02:00
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: 5fb9b459b3 ("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>
This commit is contained in:
parent
9da82dc73c
commit
9911b1ed18
|
|
@ -618,6 +618,7 @@ static void smbd_post_send_credits(struct work_struct *work)
|
|||
struct smbdirect_recv_io *response;
|
||||
struct smbdirect_socket *sc =
|
||||
container_of(work, struct smbdirect_socket, recv_io.posted.refill_work);
|
||||
int posted = 0;
|
||||
|
||||
if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
|
||||
return;
|
||||
|
|
@ -640,9 +641,12 @@ static void smbd_post_send_credits(struct work_struct *work)
|
|||
}
|
||||
|
||||
atomic_inc(&sc->recv_io.posted.count);
|
||||
posted += 1;
|
||||
}
|
||||
}
|
||||
|
||||
atomic_add(posted, &sc->recv_io.credits.available);
|
||||
|
||||
/* Promptly send an immediate packet as defined in [MS-SMBD] 3.1.1.1 */
|
||||
if (atomic_read(&sc->recv_io.credits.count) <
|
||||
sc->recv_io.credits.target - 1) {
|
||||
|
|
@ -1033,19 +1037,38 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
|
|||
*/
|
||||
static int manage_credits_prior_sending(struct smbdirect_socket *sc)
|
||||
{
|
||||
int missing;
|
||||
int available;
|
||||
int new_credits;
|
||||
|
||||
if (atomic_read(&sc->recv_io.credits.count) >= sc->recv_io.credits.target)
|
||||
return 0;
|
||||
|
||||
new_credits = atomic_read(&sc->recv_io.posted.count);
|
||||
if (new_credits == 0)
|
||||
missing = (int)sc->recv_io.credits.target - atomic_read(&sc->recv_io.credits.count);
|
||||
available = atomic_xchg(&sc->recv_io.credits.available, 0);
|
||||
new_credits = (u16)min3(U16_MAX, missing, available);
|
||||
if (new_credits <= 0) {
|
||||
/*
|
||||
* If credits are available, but not granted
|
||||
* we need to re-add them again.
|
||||
*/
|
||||
if (available)
|
||||
atomic_add(available, &sc->recv_io.credits.available);
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_credits -= atomic_read(&sc->recv_io.credits.count);
|
||||
if (new_credits <= 0)
|
||||
return 0;
|
||||
if (new_credits < available) {
|
||||
/*
|
||||
* Readd the remaining available again.
|
||||
*/
|
||||
available -= new_credits;
|
||||
atomic_add(available, &sc->recv_io.credits.available);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember we granted the credits
|
||||
*/
|
||||
atomic_add(new_credits, &sc->recv_io.credits.count);
|
||||
return new_credits;
|
||||
}
|
||||
|
||||
|
|
@ -1217,7 +1240,6 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
|
|||
packet->credits_requested = cpu_to_le16(sp->send_credit_target);
|
||||
|
||||
new_credits = manage_credits_prior_sending(sc);
|
||||
atomic_add(new_credits, &sc->recv_io.credits.count);
|
||||
packet->credits_granted = cpu_to_le16(new_credits);
|
||||
|
||||
packet->flags = 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user