Commit bb848d20 authored by Stefan Metzmacher's avatar Stefan Metzmacher Committed by Steve French
Browse files

smb: client: port and use the wait_for_credits logic used by server



This simplifies the logic and prepares the use of
smbdirect_send_batch in order to make sure
all messages in a multi fragment send are grouped
together.

We'll add the smbdirect_send_batch processin
in a later patch.

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: default avatarStefan Metzmacher <metze@samba.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 8bfe3fd3
Loading
Loading
Loading
Loading
+43 −27
Original line number Diff line number Diff line
@@ -1137,6 +1137,44 @@ static int smbd_post_send(struct smbdirect_socket *sc,
	return rc;
}

static int wait_for_credits(struct smbdirect_socket *sc,
			    wait_queue_head_t *waitq, atomic_t *total_credits,
			    int needed)
{
	int ret;

	do {
		if (atomic_sub_return(needed, total_credits) >= 0)
			return 0;

		atomic_add(needed, total_credits);
		ret = wait_event_interruptible(*waitq,
					       atomic_read(total_credits) >= needed ||
					       sc->status != SMBDIRECT_SOCKET_CONNECTED);

		if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
			return -ENOTCONN;
		else if (ret < 0)
			return ret;
	} while (true);
}

static int wait_for_send_lcredit(struct smbdirect_socket *sc)
{
	return wait_for_credits(sc,
				&sc->send_io.lcredits.wait_queue,
				&sc->send_io.lcredits.count,
				1);
}

static int wait_for_send_credits(struct smbdirect_socket *sc)
{
	return wait_for_credits(sc,
				&sc->send_io.credits.wait_queue,
				&sc->send_io.credits.count,
				1);
}

static int smbd_post_send_iter(struct smbdirect_socket *sc,
			       struct iov_iter *iter,
			       int *_remaining_data_length)
@@ -1149,41 +1187,19 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
	struct smbdirect_data_transfer *packet;
	int new_credits = 0;

wait_lcredit:
	/* Wait for local send credits */
	rc = wait_event_interruptible(sc->send_io.lcredits.wait_queue,
		atomic_read(&sc->send_io.lcredits.count) > 0 ||
		sc->status != SMBDIRECT_SOCKET_CONNECTED);
	if (rc)
		goto err_wait_lcredit;

	if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
		log_outgoing(ERR, "disconnected not sending on wait_credit\n");
	rc = wait_for_send_lcredit(sc);
	if (rc) {
		log_outgoing(ERR, "disconnected not sending on wait_lcredit\n");
		rc = -EAGAIN;
		goto err_wait_lcredit;
	}
	if (unlikely(atomic_dec_return(&sc->send_io.lcredits.count) < 0)) {
		atomic_inc(&sc->send_io.lcredits.count);
		goto wait_lcredit;
	}

wait_credit:
	/* Wait for send credits. A SMBD packet needs one credit */
	rc = wait_event_interruptible(sc->send_io.credits.wait_queue,
		atomic_read(&sc->send_io.credits.count) > 0 ||
		sc->status != SMBDIRECT_SOCKET_CONNECTED);
	if (rc)
		goto err_wait_credit;

	if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
	rc = wait_for_send_credits(sc);
	if (rc) {
		log_outgoing(ERR, "disconnected not sending on wait_credit\n");
		rc = -EAGAIN;
		goto err_wait_credit;
	}
	if (unlikely(atomic_dec_return(&sc->send_io.credits.count) < 0)) {
		atomic_inc(&sc->send_io.credits.count);
		goto wait_credit;
	}

	request = mempool_alloc(sc->send_io.mem.pool, GFP_KERNEL);
	if (!request) {