From: Joanne Koong Date: Tue, 20 Jan 2026 22:44:47 +0000 (-0800) Subject: fuse: simplify logic in fuse_notify_store() and fuse_retrieve() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=25307ca50b815c14a21f82fc5b10e8a621af32ad;p=thirdparty%2Flinux.git fuse: simplify logic in fuse_notify_store() and fuse_retrieve() Simplify the folio parsing logic in fuse_notify_store() and fuse_retrieve(). In particular, calculate the index by tracking pos, which allows us to remove calculating nr_pages, and use "pos" in place of outarg's offset field. Suggested-by: Jingbo Xu Signed-off-by: Joanne Koong Reviewed-by: Jingbo Xu Reviewed-by: Darrick J. Wong Signed-off-by: Miklos Szeredi --- diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 8e23ec84ec8a9..18622bf805d6f 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1767,10 +1767,9 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, struct address_space *mapping; u64 nodeid; int err; - pgoff_t index; - unsigned int offset; unsigned int num; loff_t file_size; + loff_t pos; loff_t end; if (size < sizeof(outarg)) @@ -1787,7 +1786,8 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, return -EINVAL; nodeid = outarg.nodeid; - num = min(outarg.size, MAX_LFS_FILESIZE - outarg.offset); + pos = outarg.offset; + num = min(outarg.size, MAX_LFS_FILESIZE - pos); down_read(&fc->killsb); @@ -1797,10 +1797,8 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, goto out_up_killsb; mapping = inode->i_mapping; - index = outarg.offset >> PAGE_SHIFT; - offset = outarg.offset & ~PAGE_MASK; file_size = i_size_read(inode); - end = outarg.offset + num; + end = pos + num; if (end > file_size) { file_size = end; fuse_write_update_attr(inode, file_size, num); @@ -1810,19 +1808,18 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, struct folio *folio; unsigned int folio_offset; unsigned int nr_bytes; - unsigned int nr_pages; + pgoff_t index = pos >> PAGE_SHIFT; folio = filemap_grab_folio(mapping, index); err = PTR_ERR(folio); if (IS_ERR(folio)) goto out_iput; - folio_offset = ((index - folio->index) << PAGE_SHIFT) + offset; + folio_offset = offset_in_folio(folio, pos); nr_bytes = min(num, folio_size(folio) - folio_offset); - nr_pages = (offset + nr_bytes + PAGE_SIZE - 1) >> PAGE_SHIFT; err = fuse_copy_folio(cs, &folio, folio_offset, nr_bytes, 0); - if (!folio_test_uptodate(folio) && !err && offset == 0 && + if (!folio_test_uptodate(folio) && !err && folio_offset == 0 && (nr_bytes == folio_size(folio) || file_size == end)) { folio_zero_segment(folio, nr_bytes, folio_size(folio)); folio_mark_uptodate(folio); @@ -1833,9 +1830,8 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, if (err) goto out_iput; + pos += nr_bytes; num -= nr_bytes; - offset = 0; - index += nr_pages; } err = 0; @@ -1867,7 +1863,6 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode, { int err; struct address_space *mapping = inode->i_mapping; - pgoff_t index; loff_t file_size; unsigned int num; unsigned int offset; @@ -1878,15 +1873,16 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode, size_t args_size = sizeof(*ra); struct fuse_args_pages *ap; struct fuse_args *args; + loff_t pos = outarg->offset; - offset = outarg->offset & ~PAGE_MASK; + offset = offset_in_page(pos); file_size = i_size_read(inode); num = min(outarg->size, fc->max_write); - if (outarg->offset > file_size) + if (pos > file_size) num = 0; - else if (num > file_size - outarg->offset) - num = file_size - outarg->offset; + else if (num > file_size - pos) + num = file_size - pos; num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; num_pages = min(num_pages, fc->max_pages); @@ -1909,31 +1905,27 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode, args->in_pages = true; args->end = fuse_retrieve_end; - index = outarg->offset >> PAGE_SHIFT; - while (num && ap->num_folios < num_pages) { struct folio *folio; unsigned int folio_offset; unsigned int nr_bytes; - unsigned int nr_pages; + pgoff_t index = pos >> PAGE_SHIFT; folio = filemap_get_folio(mapping, index); if (IS_ERR(folio)) break; - folio_offset = ((index - folio->index) << PAGE_SHIFT) + offset; + folio_offset = offset_in_folio(folio, pos); nr_bytes = min(folio_size(folio) - folio_offset, num); - nr_pages = (offset + nr_bytes + PAGE_SIZE - 1) >> PAGE_SHIFT; ap->folios[ap->num_folios] = folio; ap->descs[ap->num_folios].offset = folio_offset; ap->descs[ap->num_folios].length = nr_bytes; ap->num_folios++; - offset = 0; + pos += nr_bytes; num -= nr_bytes; total_len += nr_bytes; - index += nr_pages; } ra->inarg.offset = outarg->offset; ra->inarg.size = total_len;