Commit 906354c8 authored by Joanne Koong's avatar Joanne Koong Committed by Miklos Szeredi
Browse files

fuse: support large folios for readahead



Add support for folios larger than one page size for readahead.

Signed-off-by: default avatarJoanne Koong <joannelkoong@gmail.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent ff7c3ee4
Loading
Loading
Loading
Loading
+29 −9
Original line number Diff line number Diff line
@@ -876,14 +876,13 @@ static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
	fuse_io_free(ia);
}

static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file,
				unsigned int count)
{
	struct fuse_file *ff = file->private_data;
	struct fuse_mount *fm = ff->fm;
	struct fuse_args_pages *ap = &ia->ap;
	loff_t pos = folio_pos(ap->folios[0]);
	/* Currently, all folios in FUSE are one page */
	size_t count = ap->num_folios << PAGE_SHIFT;
	ssize_t res;
	int err;

@@ -918,6 +917,7 @@ static void fuse_readahead(struct readahead_control *rac)
	struct inode *inode = rac->mapping->host;
	struct fuse_conn *fc = get_fuse_conn(inode);
	unsigned int max_pages, nr_pages;
	struct folio *folio = NULL;

	if (fuse_is_bad(inode))
		return;
@@ -939,8 +939,8 @@ static void fuse_readahead(struct readahead_control *rac)
	while (nr_pages) {
		struct fuse_io_args *ia;
		struct fuse_args_pages *ap;
		struct folio *folio;
		unsigned cur_pages = min(max_pages, nr_pages);
		unsigned int pages = 0;

		if (fc->num_background >= fc->congestion_threshold &&
		    rac->ra->async_size >= readahead_count(rac))
@@ -952,10 +952,12 @@ static void fuse_readahead(struct readahead_control *rac)

		ia = fuse_io_alloc(NULL, cur_pages);
		if (!ia)
			return;
			break;
		ap = &ia->ap;

		while (ap->num_folios < cur_pages) {
		while (pages < cur_pages) {
			unsigned int folio_pages;

			/*
			 * This returns a folio with a ref held on it.
			 * The ref needs to be held until the request is
@@ -963,13 +965,31 @@ static void fuse_readahead(struct readahead_control *rac)
			 * fuse_try_move_page()) drops the ref after it's
			 * replaced in the page cache.
			 */
			if (!folio)
				folio =  __readahead_folio(rac);

			folio_pages = folio_nr_pages(folio);
			if (folio_pages > cur_pages - pages) {
				/*
				 * Large folios belonging to fuse will never
				 * have more pages than max_pages.
				 */
				WARN_ON(!pages);
				break;
			}

			ap->folios[ap->num_folios] = folio;
			ap->descs[ap->num_folios].length = folio_size(folio);
			ap->num_folios++;
			pages += folio_pages;
			folio = NULL;
		}
		fuse_send_readpages(ia, rac->file, pages << PAGE_SHIFT);
		nr_pages -= pages;
	}
		fuse_send_readpages(ia, rac->file);
		nr_pages -= cur_pages;
	if (folio) {
		folio_end_read(folio, false);
		folio_put(folio);
	}
}