smb: client: make use of smbdirect_connection_recvmsg()

This is basically the same as it was copied before...

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>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Stefan Metzmacher 2025-10-13 18:42:08 +02:00 committed by Steve French
parent 2cafcddbda
commit edb9e514f0

View File

@ -1580,137 +1580,8 @@ struct smbd_connection *smbd_get_connection(
int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
{
struct smbdirect_socket *sc = &info->socket;
struct smbdirect_recv_io *response;
struct smbdirect_data_transfer *data_transfer;
size_t size = iov_iter_count(&msg->msg_iter);
int to_copy, to_read, data_read, offset;
u32 data_length, remaining_data_length, data_offset;
int rc;
if (WARN_ON_ONCE(iov_iter_rw(&msg->msg_iter) == WRITE))
return -EINVAL; /* It's a bug in upper layer to get there */
again:
/*
* No need to hold the reassembly queue lock all the time as we are
* the only one reading from the front of the queue. The transport
* may add more entries to the back of the queue at the same time
*/
log_read(INFO, "size=%zd sc->recv_io.reassembly.data_length=%d\n", size,
sc->recv_io.reassembly.data_length);
if (sc->recv_io.reassembly.data_length >= size) {
int queue_length;
int queue_removed = 0;
unsigned long flags;
/*
* Need to make sure reassembly_data_length is read before
* reading reassembly_queue_length and calling
* smbdirect_connection_reassembly_first_recv_io. This call is lock free
* as we never read at the end of the queue which are being
* updated in SOFTIRQ as more data is received
*/
virt_rmb();
queue_length = sc->recv_io.reassembly.queue_length;
data_read = 0;
to_read = size;
offset = sc->recv_io.reassembly.first_entry_offset;
while (data_read < size) {
response = smbdirect_connection_reassembly_first_recv_io(sc);
data_transfer = smbdirect_recv_io_payload(response);
data_length = le32_to_cpu(data_transfer->data_length);
remaining_data_length =
le32_to_cpu(
data_transfer->remaining_data_length);
data_offset = le32_to_cpu(data_transfer->data_offset);
/*
* The upper layer expects RFC1002 length at the
* beginning of the payload. Return it to indicate
* the total length of the packet. This minimize the
* change to upper layer packet processing logic. This
* will be eventually remove when an intermediate
* transport layer is added
*/
if (response->first_segment && size == 4) {
unsigned int rfc1002_len =
data_length + remaining_data_length;
__be32 rfc1002_hdr = cpu_to_be32(rfc1002_len);
if (copy_to_iter(&rfc1002_hdr, sizeof(rfc1002_hdr),
&msg->msg_iter) != sizeof(rfc1002_hdr))
return -EFAULT;
data_read = 4;
response->first_segment = false;
log_read(INFO, "returning rfc1002 length %d\n",
rfc1002_len);
goto read_rfc1002_done;
}
to_copy = min_t(int, data_length - offset, to_read);
if (copy_to_iter((char *)data_transfer + data_offset + offset,
to_copy, &msg->msg_iter) != to_copy)
return -EFAULT;
/* move on to the next buffer? */
if (to_copy == data_length - offset) {
queue_length--;
/*
* No need to lock if we are not at the
* end of the queue
*/
if (queue_length)
list_del(&response->list);
else {
spin_lock_irqsave(
&sc->recv_io.reassembly.lock, flags);
list_del(&response->list);
spin_unlock_irqrestore(
&sc->recv_io.reassembly.lock, flags);
}
queue_removed++;
sc->statistics.dequeue_reassembly_queue++;
smbdirect_connection_put_recv_io(response);
offset = 0;
log_read(INFO, "smbdirect_connection_put_recv_io offset=0\n");
} else
offset += to_copy;
to_read -= to_copy;
data_read += to_copy;
log_read(INFO, "_get_first_reassembly memcpy %d bytes data_transfer_length-offset=%d after that to_read=%d data_read=%d offset=%d\n",
to_copy, data_length - offset,
to_read, data_read, offset);
}
spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
sc->recv_io.reassembly.data_length -= data_read;
sc->recv_io.reassembly.queue_length -= queue_removed;
spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
sc->recv_io.reassembly.first_entry_offset = offset;
log_read(INFO, "returning to thread data_read=%d reassembly_data_length=%d first_entry_offset=%d\n",
data_read, sc->recv_io.reassembly.data_length,
sc->recv_io.reassembly.first_entry_offset);
read_rfc1002_done:
return data_read;
}
log_read(INFO, "wait_event on more data\n");
rc = wait_event_interruptible(
sc->recv_io.reassembly.wait_queue,
sc->recv_io.reassembly.data_length >= size ||
sc->status != SMBDIRECT_SOCKET_CONNECTED);
/* Don't return any data if interrupted */
if (rc)
return rc;
if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
log_read(ERR, "disconnected\n");
return -ECONNABORTED;
}
goto again;
return smbdirect_connection_recvmsg(sc, msg, 0);
}
/*