Skip to content

Commit 7a4f541

Browse files
joannekoongMiklos Szeredi
authored andcommitted
fuse: fix direct io folio offset and length calculation
For the direct io case, the pages from userspace may be part of a huge folio, even if all folios in the page cache for fuse are small. Fix the logic for calculating the offset and length of the folio for the direct io case, which currently incorrectly assumes that all folios encountered are one page size. Fixes: 3b97c36 ("fuse: convert direct io to use folios") Signed-off-by: Joanne Koong <[email protected]> Reviewed-by: Jingbo Xu <[email protected]> Reviewed-by: Bernd Schubert <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 40384c8 commit 7a4f541

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

fs/fuse/file.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,18 +1557,22 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
15571557

15581558
nbytes += ret;
15591559

1560-
ret += start;
1561-
/* Currently, all folios in FUSE are one page */
1562-
nfolios = DIV_ROUND_UP(ret, PAGE_SIZE);
1563-
1564-
ap->descs[ap->num_folios].offset = start;
1565-
fuse_folio_descs_length_init(ap->descs, ap->num_folios, nfolios);
1566-
for (i = 0; i < nfolios; i++)
1567-
ap->folios[i + ap->num_folios] = page_folio(pages[i]);
1568-
1569-
ap->num_folios += nfolios;
1570-
ap->descs[ap->num_folios - 1].length -=
1571-
(PAGE_SIZE - ret) & (PAGE_SIZE - 1);
1560+
nfolios = DIV_ROUND_UP(ret + start, PAGE_SIZE);
1561+
1562+
for (i = 0; i < nfolios; i++) {
1563+
struct folio *folio = page_folio(pages[i]);
1564+
unsigned int offset = start +
1565+
(folio_page_idx(folio, pages[i]) << PAGE_SHIFT);
1566+
unsigned int len = min_t(unsigned int, ret, PAGE_SIZE - start);
1567+
1568+
ap->descs[ap->num_folios].offset = offset;
1569+
ap->descs[ap->num_folios].length = len;
1570+
ap->folios[ap->num_folios] = folio;
1571+
start = 0;
1572+
ret -= len;
1573+
ap->num_folios++;
1574+
}
1575+
15721576
nr_pages += nfolios;
15731577
}
15741578
kfree(pages);

0 commit comments

Comments
 (0)