From nobody Tue Dec 16 07:12:36 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 783242D879B for ; Wed, 25 Jun 2025 16:43:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750869814; cv=none; b=LDypPlzGjqYxj1pGdeXt/k2EnCOakdgwlDfN6WjEfNFbB9uQtkvb0wSxEhPvAVczsJVJRmXgNvJZ0hxqsv0Ri8Ddf/gG4aFYUwDujyqwXIfA+4c/mytScJQqtAn1yoM9GJRFYO2hYWMWz3uu8vCu95xRh10clnLOD8CYyl1mEc8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750869814; c=relaxed/simple; bh=0S7Wb2Ayru7zxU3qzn80qEG3N84qFnB6/qthu5wYMpo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ovOMb5AWqiPlA6BX1n+1gqw96uCA/RVkB3yiJ+ZZTQrZWXbDMZQjs6rLhrR1V5YwwCe3RNSdgv31jYvTQ7dk/Ib3Mk8lxK29UG78Bh45ejWoVa2dWi7dWerB5NaPP9Vk0zzs9sXh0RctXbiqv8j+jFb8T9ztgTZLIQkfp7uY1MY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=KkpEyf0F; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="KkpEyf0F" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1750869811; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4v+u+1rM8Ekf5NVVpiW18gc8WO84+L9XnF1ABQbI6tU=; b=KkpEyf0FKRzEJf0XWmwvQAiHuunu348L8x3GyRVGNfe2vOIqYvsI6DUpfQYoGWSkkCI9N6 6r6SvPQtjfd7EXEuSYWnR0YyGZ8zs1i52lpC3N5kpj6NXsG7RfeerzzvB+kL7Hwd5iVNvt hunHIGEwgOhZa+verns89dVpXGbdsv8= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-652-0vhc79CuOq6KNev3OCSRqw-1; Wed, 25 Jun 2025 12:43:26 -0400 X-MC-Unique: 0vhc79CuOq6KNev3OCSRqw-1 X-Mimecast-MFC-AGG-ID: 0vhc79CuOq6KNev3OCSRqw_1750869804 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 105CF1800268; Wed, 25 Jun 2025 16:43:24 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.81]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id EBC3A195608D; Wed, 25 Jun 2025 16:43:19 +0000 (UTC) From: David Howells To: Christian Brauner , Steve French Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Stefan Metzmacher , Steve French , Tom Talpey , Matthew Wilcox Subject: [PATCH v2 12/16] cifs: Fix reading into an ITER_FOLIOQ from the smbdirect code Date: Wed, 25 Jun 2025 17:42:07 +0100 Message-ID: <20250625164213.1408754-13-dhowells@redhat.com> In-Reply-To: <20250625164213.1408754-1-dhowells@redhat.com> References: <20250625164213.1408754-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" When performing a file read from RDMA, smbd_recv() prints an "Invalid msg type 4" error and fails the I/O. This is due to the switch-statement there not handling the ITER_FOLIOQ handed down from netfslib. Fix this by collapsing smbd_recv_buf() and smbd_recv_page() into smbd_recv() and just using copy_to_iter() instead of memcpy(). This future-proofs the function too, in case more ITER_* types are added. Fixes: ee4cdf7ba857 ("netfs: Speed up buffered reading") Reported-by: Stefan Metzmacher Signed-off-by: David Howells cc: Steve French cc: Tom Talpey cc: Paulo Alcantara (Red Hat) cc: Matthew Wilcox cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smbdirect.c | 114 +++++++------------------------------- 1 file changed, 19 insertions(+), 95 deletions(-) diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c index a976bcf61226..5fa46b2e682c 100644 --- a/fs/smb/client/smbdirect.c +++ b/fs/smb/client/smbdirect.c @@ -1770,35 +1770,39 @@ struct smbd_connection *smbd_get_connection( } =20 /* - * Receive data from receive reassembly queue + * Receive data from the transport's receive reassembly queue * All the incoming data packets are placed in reassembly queue - * buf: the buffer to read data into + * iter: the buffer to read data into * size: the length of data to read * return value: actual data read - * Note: this implementation copies the data from reassebmly queue to rece= ive + * + * Note: this implementation copies the data from reassembly queue to rece= ive * buffers used by upper layer. This is not the optimal code path. A bette= r way * to do it is to not have upper layer allocate its receive buffers but ra= ther * borrow the buffer from reassembly queue, and return it after data is * consumed. But this will require more changes to upper layer code, and a= lso * need to consider packet boundaries while they still being reassembled. */ -static int smbd_recv_buf(struct smbd_connection *info, char *buf, - unsigned int size) +int smbd_recv(struct smbd_connection *info, struct msghdr *msg) { struct smbdirect_socket *sc =3D &info->socket; struct smbd_response *response; struct smbdirect_data_transfer *data_transfer; + size_t size =3D iov_iter_count(&msg->msg_iter); int to_copy, to_read, data_read, offset; u32 data_length, remaining_data_length, data_offset; int rc; =20 + if (WARN_ON_ONCE(iov_iter_rw(&msg->msg_iter) =3D=3D 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=3D%d info->reassembly_data_length=3D%d\n", size, + log_read(INFO, "size=3D%zd info->reassembly_data_length=3D%d\n", size, info->reassembly_data_length); if (info->reassembly_data_length >=3D size) { int queue_length; @@ -1836,7 +1840,10 @@ static int smbd_recv_buf(struct smbd_connection *inf= o, char *buf, if (response->first_segment && size =3D=3D 4) { unsigned int rfc1002_len =3D data_length + remaining_data_length; - *((__be32 *)buf) =3D cpu_to_be32(rfc1002_len); + __be32 rfc1002_hdr =3D cpu_to_be32(rfc1002_len); + if (copy_to_iter(&rfc1002_hdr, sizeof(rfc1002_hdr), + &msg->msg_iter) !=3D sizeof(rfc1002_hdr)) + return -EFAULT; data_read =3D 4; response->first_segment =3D false; log_read(INFO, "returning rfc1002 length %d\n", @@ -1845,10 +1852,9 @@ static int smbd_recv_buf(struct smbd_connection *inf= o, char *buf, } =20 to_copy =3D min_t(int, data_length - offset, to_read); - memcpy( - buf + data_read, - (char *)data_transfer + data_offset + offset, - to_copy); + if (copy_to_iter((char *)data_transfer + data_offset + offset, + to_copy, &msg->msg_iter) !=3D to_copy) + return -EFAULT; =20 /* move on to the next buffer? */ if (to_copy =3D=3D data_length - offset) { @@ -1893,6 +1899,8 @@ static int smbd_recv_buf(struct smbd_connection *info= , char *buf, data_read, info->reassembly_data_length, info->first_entry_offset); read_rfc1002_done: + /* SMBDirect will read it all or nothing */ + msg->msg_iter.count =3D 0; return data_read; } =20 @@ -1913,90 +1921,6 @@ static int smbd_recv_buf(struct smbd_connection *inf= o, char *buf, goto again; } =20 -/* - * Receive a page from receive reassembly queue - * page: the page to read data into - * to_read: the length of data to read - * return value: actual data read - */ -static int smbd_recv_page(struct smbd_connection *info, - struct page *page, unsigned int page_offset, - unsigned int to_read) -{ - struct smbdirect_socket *sc =3D &info->socket; - int ret; - char *to_address; - void *page_address; - - /* make sure we have the page ready for read */ - ret =3D wait_event_interruptible( - info->wait_reassembly_queue, - info->reassembly_data_length >=3D to_read || - sc->status !=3D SMBDIRECT_SOCKET_CONNECTED); - if (ret) - return ret; - - /* now we can read from reassembly queue and not sleep */ - page_address =3D kmap_atomic(page); - to_address =3D (char *) page_address + page_offset; - - log_read(INFO, "reading from page=3D%p address=3D%p to_read=3D%d\n", - page, to_address, to_read); - - ret =3D smbd_recv_buf(info, to_address, to_read); - kunmap_atomic(page_address); - - return ret; -} - -/* - * Receive data from transport - * msg: a msghdr point to the buffer, can be ITER_KVEC or ITER_BVEC - * return: total bytes read, or 0. SMB Direct will not do partial read. - */ -int smbd_recv(struct smbd_connection *info, struct msghdr *msg) -{ - char *buf; - struct page *page; - unsigned int to_read, page_offset; - int rc; - - if (iov_iter_rw(&msg->msg_iter) =3D=3D WRITE) { - /* It's a bug in upper layer to get there */ - cifs_dbg(VFS, "Invalid msg iter dir %u\n", - iov_iter_rw(&msg->msg_iter)); - rc =3D -EINVAL; - goto out; - } - - switch (iov_iter_type(&msg->msg_iter)) { - case ITER_KVEC: - buf =3D msg->msg_iter.kvec->iov_base; - to_read =3D msg->msg_iter.kvec->iov_len; - rc =3D smbd_recv_buf(info, buf, to_read); - break; - - case ITER_BVEC: - page =3D msg->msg_iter.bvec->bv_page; - page_offset =3D msg->msg_iter.bvec->bv_offset; - to_read =3D msg->msg_iter.bvec->bv_len; - rc =3D smbd_recv_page(info, page, page_offset, to_read); - break; - - default: - /* It's a bug in upper layer to get there */ - cifs_dbg(VFS, "Invalid msg type %d\n", - iov_iter_type(&msg->msg_iter)); - rc =3D -EINVAL; - } - -out: - /* SMBDirect will read it all or nothing */ - if (rc > 0) - msg->msg_iter.count =3D 0; - return rc; -} - /* * Send data to transport * Each rqst is transported as a SMBDirect payload