Re: [PATCH v5 10/11] fuse: optimize direct io large folios processing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 4/26/25 02:08, Joanne Koong wrote:
> Optimize processing folios larger than one page size for the direct io
> case. If contiguous pages are part of the same folio, collate the
> processing instead of processing each page in the folio separately.
> 
> Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx>
> Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>

Reviewed-by: Bernd Schubert <bschubert@xxxxxxx>

> ---
>  fs/fuse/file.c | 55 +++++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 41 insertions(+), 14 deletions(-)
> 
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index 9a31f2a516b9..61eaec1c993b 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -1490,7 +1490,8 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
>  	}
>  
>  	while (nbytes < *nbytesp && nr_pages < max_pages) {
> -		unsigned nfolios, i;
> +		struct folio *prev_folio = NULL;
> +		unsigned npages, i;
>  		size_t start;
>  
>  		ret = iov_iter_extract_pages(ii, &pages,
> @@ -1502,23 +1503,49 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
>  
>  		nbytes += ret;
>  
> -		nfolios = DIV_ROUND_UP(ret + start, PAGE_SIZE);
> +		npages = DIV_ROUND_UP(ret + start, PAGE_SIZE);
>  
> -		for (i = 0; i < nfolios; i++) {
> -			struct folio *folio = page_folio(pages[i]);
> -			unsigned int offset = start +
> -				(folio_page_idx(folio, pages[i]) << PAGE_SHIFT);
> -			unsigned int len = min_t(unsigned int, ret, PAGE_SIZE - start);
> +		/*
> +		 * We must check each extracted page. We can't assume every page
> +		 * in a large folio is used. For example, userspace may mmap() a
> +		 * file PROT_WRITE, MAP_PRIVATE, and then store to the middle of
> +		 * a large folio, in which case the extracted pages could be
> +		 *
> +		 * folio A page 0
> +		 * folio A page 1
> +		 * folio B page 0
> +		 * folio A page 3
> +		 *
> +		 * where folio A belongs to the file and folio B is an anonymous
> +		 * COW page.
> +		 */
> +		for (i = 0; i < npages && ret; i++) {
> +			struct folio *folio;
> +			unsigned int offset;
> +			unsigned int len;
> +
> +			WARN_ON(!pages[i]);
> +			folio = page_folio(pages[i]);
> +
> +			len = min_t(unsigned int, ret, PAGE_SIZE - start);
> +
> +			if (folio == prev_folio && pages[i] != pages[i - 1]) {
> +				WARN_ON(ap->folios[ap->num_folios - 1] != folio);
> +				ap->descs[ap->num_folios - 1].length += len;
> +				WARN_ON(ap->descs[ap->num_folios - 1].length > folio_size(folio));
> +			} else {
> +				offset = start + (folio_page_idx(folio, pages[i]) << PAGE_SHIFT);
> +				ap->descs[ap->num_folios].offset = offset;
> +				ap->descs[ap->num_folios].length = len;
> +				ap->folios[ap->num_folios] = folio;
> +				start = 0;
> +				ap->num_folios++;
> +				prev_folio = folio;
> +			}
>  
> -			ap->descs[ap->num_folios].offset = offset;
> -			ap->descs[ap->num_folios].length = len;
> -			ap->folios[ap->num_folios] = folio;
> -			start = 0;
>  			ret -= len;
> -			ap->num_folios++;
>  		}
> -
> -		nr_pages += nfolios;
> +		nr_pages += npages;
>  	}
>  	kfree(pages);
>  





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux