mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 07:33:19 +02:00
fuse: support large folios for readahead
Add support for folios larger than one page size for readahead. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
ff7c3ee484
commit
906354c87f
|
|
@ -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.
|
||||
*/
|
||||
folio = __readahead_folio(rac);
|
||||
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);
|
||||
nr_pages -= cur_pages;
|
||||
fuse_send_readpages(ia, rac->file, pages << PAGE_SHIFT);
|
||||
nr_pages -= pages;
|
||||
}
|
||||
if (folio) {
|
||||
folio_end_read(folio, false);
|
||||
folio_put(folio);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user