Re: [PATCH v1 6/7] nfs: Optimize direct I/O to use folios for requests

"Anna Schumaker" <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.nfs
Message-ID <[email protected]>
Hi Pranjal,

On Wed, Jun 3, 2026, at 1:30 AM, Pranjal Shrivastava wrote:
> Optimize nfs_direct_extract_pages() to group contiguous pages from the
> same folio into single nfs_page structures. This effectively migrates
> NFS Direct I/O from being page-based to being folio-based.
>
> Reduce the number of nfs_page allocations and subsequent iterations
> by utilizing nfs_page_create_from_folio() to create aggregated
> requests.

I am seeing a LOT of failing xfstests after applying this patch (testing
against various NFS versions over TCP with AUTH_SYS):

+-------------+-----------+-------------+-------------+-------------+
|    testcase | tcp-sys-3 | tcp-sys-4.0 | tcp-sys-4.1 | tcp-sys-4.2 |
+-------------+-----------+-------------+-------------+-------------+
| generic/091 | failure   | failure     | failure     | failure     |
| generic/130 | failure   | failure     | failure     | failure     |
| generic/139 | skipped   | skipped     | skipped     | failure     |
| generic/143 | skipped   | skipped     | skipped     | failure     |
| generic/154 | skipped   | skipped     | skipped     | failure     |
| generic/155 | skipped   | skipped     | skipped     | failure     |
| generic/183 | skipped   | skipped     | skipped     | failure     |
| generic/188 | skipped   | skipped     | skipped     | failure     |
| generic/190 | skipped   | skipped     | skipped     | failure     |
| generic/196 | skipped   | skipped     | skipped     | failure     |
| generic/198 | failure   | failure     | failure     | failure     |
| generic/203 | skipped   | skipped     | skipped     | failure     |
| generic/214 | skipped   | skipped     | skipped     | failure     |
| generic/240 | failure   | failure     | failure     | failure     |
| generic/263 | failure   | failure     | failure     | failure     |
| generic/287 | skipped   | skipped     | skipped     | failure     |
| generic/290 | skipped   | skipped     | skipped     | failure     |
| generic/292 | skipped   | skipped     | skipped     | failure     |
| generic/330 | skipped   | skipped     | skipped     | failure     |
| generic/444 | failure   | skipped     | skipped     | skipped     |
| generic/450 | failure   | failure     | failure     | failure     |
| generic/451 | failure   | failure     | failure     | failure     |
| generic/586 | skipped   | skipped     | skipped     | failure     |
| generic/647 | failure   | failure     | failure     | failure     |
| generic/708 | failure   | failure     | failure     | failure     |
| generic/729 | failure   | failure     | failure     | failure     |
| generic/760 | failure   | failure     | failure     | failure     |
+-------------+-----------+-------------+-------------+-------------+

I'm curious if you've run xfstests against your changes, and if you
see the same failures?

Thanks,
Anna

>
> Signed-off-by: Pranjal Shrivastava <[email protected]>
> ---
>  fs/nfs/direct.c | 36 +++++++++++++++++++++++++++++-------
>  1 file changed, 29 insertions(+), 7 deletions(-)
>
> diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
> index 59002c150f23..93e1af9ec36b 100644
> --- a/fs/nfs/direct.c
> +++ b/fs/nfs/direct.c
> @@ -194,23 +194,45 @@ static ssize_t nfs_direct_extract_pages(struct 
> nfs_direct_req *dreq,
>  		return result;
> 
>  	npages = (result + pgbase + PAGE_SIZE - 1) >> PAGE_SHIFT;
> -	for (i = 0; i < npages; i++) {
> +	for (i = 0; i < npages; ) {
> +		unsigned int chunk_len, folio_offset;
> +		unsigned int nr_to_add = 1;
>  		struct nfs_page *req;
> -		unsigned int req_len = min_t(size_t, result - bytes, PAGE_SIZE - pgbase);
> +		struct folio *folio;
> 
> -		req = nfs_page_create_from_page(dreq->ctx, pagevec[i],
> -						pinned, pgbase, *pos,
> -						req_len);
> +		folio = page_folio(pagevec[i]);
> +		folio_offset = (folio_page_idx(folio, pagevec[i]) << PAGE_SHIFT) + pgbase;
> +		chunk_len = min_t(size_t, result - bytes, PAGE_SIZE - pgbase);
> +
> +		while (i + nr_to_add < npages) {
> +			struct page *next_page = pagevec[i + nr_to_add];
> +			struct page *prev_page = pagevec[i + nr_to_add - 1];
> +
> +			if (page_folio(next_page) != folio ||
> +			    next_page != prev_page + 1)
> +				break;
> +
> +			chunk_len += min_t(size_t, result - bytes - chunk_len, PAGE_SIZE);
> +			nr_to_add++;
> +		}
> +
> +		req = nfs_page_create_from_folio(dreq->ctx, folio,
> +						  pinned, folio_offset,
> +						  chunk_len);
>  		if (IS_ERR(req)) {
>  			if (!bytes)
>  				bytes = PTR_ERR(req);
>  			break;
>  		}
> 
> +		req->wb_index = *pos >> PAGE_SHIFT;
> +		req->wb_offset = *pos;
> +
>  		list_add_tail(&req->wb_list, list);
>  		pgbase = 0;
> -		bytes += req_len;
> -		*pos += req_len;
> +		bytes += chunk_len;
> +		*pos += chunk_len;
> +		i += nr_to_add;
>  	}
> 
>  	if (i < npages) {
> -- 
> 2.54.0.1013.g208068f2d8-goog
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.