[PATCH 17/26] cifs: Support ITER_BVECQ in smb_extract_iter_to_rdma()
David Howells <[email protected]> Thu, 26 Mar 2026 10:45:32 +0000
| Newsgroups | dev.linux.lists.v9fs,dev.linux.lists.netfs,org.kernel.vger.ceph-devel,org.kernel.vger.linux-cifs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-nfs,org.ozlabs.lists.linux-erofs |
|---|---|
| Message-ID | <[email protected]> |
Add support for ITER_BVECQ to smb_extract_iter_to_rdma(). Signed-off-by: David Howells <[email protected]> cc: Paulo Alcantara <[email protected]> cc: Matthew Wilcox <[email protected]> cc: Christoph Hellwig <[email protected]> cc: Steve French <[email protected]> cc: Shyam Prasad N <[email protected]> cc: Tom Talpey <[email protected]> cc: [email protected] cc: [email protected] cc: [email protected] --- fs/smb/client/smbdirect.c | 60 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c index c79304012b08..f8a6be83db98 100644 --- a/fs/smb/client/smbdirect.c +++ b/fs/smb/client/smbdirect.c @@ -3298,6 +3298,63 @@ static ssize_t smb_extract_folioq_to_rdma(struct iov_iter *iter, return ret; } +/* + * Extract memory fragments from a BVECQ-class iterator and add them to an RDMA + * list. The folios are not pinned. + */ +static ssize_t smb_extract_bvecq_to_rdma(struct iov_iter *iter, + struct smb_extract_to_rdma *rdma, + ssize_t maxsize) +{ + const struct bvecq *bq = iter->bvecq; + unsigned int slot = iter->bvecq_slot; + ssize_t ret = 0; + size_t offset = iter->iov_offset; + + if (slot >= bq->nr_slots) { + bq = bq->next; + if (WARN_ON_ONCE(!bq)) + return -EIO; + slot = 0; + } + + do { + struct bio_vec *bv = &bq->bv[slot]; + struct page *page = bv->bv_page; + size_t bsize = bv->bv_len; + + if (offset < bsize) { + size_t part = umin(maxsize, bsize - offset); + + if (!smb_set_sge(rdma, page, bv->bv_offset + offset, part)) + return -EIO; + + offset += part; + ret += part; + maxsize -= part; + } + + if (offset >= bsize) { + offset = 0; + slot++; + if (slot >= bq->nr_slots) { + if (!bq->next) { + WARN_ON_ONCE(ret < iter->count); + break; + } + bq = bq->next; + slot = 0; + } + } + } while (rdma->nr_sge < rdma->max_sge && maxsize > 0); + + iter->bvecq = bq; + iter->bvecq_slot = slot; + iter->iov_offset = offset; + iter->count -= ret; + return ret; +} + /* * Extract page fragments from up to the given amount of the source iterator * and build up an RDMA list that refers to all of those bits. The RDMA list @@ -3325,6 +3382,9 @@ static ssize_t smb_extract_iter_to_rdma(struct iov_iter *iter, size_t len, case ITER_FOLIOQ: ret = smb_extract_folioq_to_rdma(iter, rdma, len); break; + case ITER_BVECQ: + ret = smb_extract_bvecq_to_rdma(iter, rdma, len); + break; default: WARN_ON_ONCE(1); return -EIO;