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 <jefflexu@linux.alibaba.com>
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
Joanne Koong 2026-01-20 14:44:47 -08:00 committed by Miklos Szeredi
parent 65161470f9
commit 25307ca50b

View File

@ -1767,10 +1767,9 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
struct address_space *mapping; struct address_space *mapping;
u64 nodeid; u64 nodeid;
int err; int err;
pgoff_t index;
unsigned int offset;
unsigned int num; unsigned int num;
loff_t file_size; loff_t file_size;
loff_t pos;
loff_t end; loff_t end;
if (size < sizeof(outarg)) if (size < sizeof(outarg))
@ -1787,7 +1786,8 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
return -EINVAL; return -EINVAL;
nodeid = outarg.nodeid; 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); down_read(&fc->killsb);
@ -1797,10 +1797,8 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
goto out_up_killsb; goto out_up_killsb;
mapping = inode->i_mapping; mapping = inode->i_mapping;
index = outarg.offset >> PAGE_SHIFT;
offset = outarg.offset & ~PAGE_MASK;
file_size = i_size_read(inode); file_size = i_size_read(inode);
end = outarg.offset + num; end = pos + num;
if (end > file_size) { if (end > file_size) {
file_size = end; file_size = end;
fuse_write_update_attr(inode, file_size, num); 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; struct folio *folio;
unsigned int folio_offset; unsigned int folio_offset;
unsigned int nr_bytes; unsigned int nr_bytes;
unsigned int nr_pages; pgoff_t index = pos >> PAGE_SHIFT;
folio = filemap_grab_folio(mapping, index); folio = filemap_grab_folio(mapping, index);
err = PTR_ERR(folio); err = PTR_ERR(folio);
if (IS_ERR(folio)) if (IS_ERR(folio))
goto out_iput; 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_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); 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)) { (nr_bytes == folio_size(folio) || file_size == end)) {
folio_zero_segment(folio, nr_bytes, folio_size(folio)); folio_zero_segment(folio, nr_bytes, folio_size(folio));
folio_mark_uptodate(folio); folio_mark_uptodate(folio);
@ -1833,9 +1830,8 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
if (err) if (err)
goto out_iput; goto out_iput;
pos += nr_bytes;
num -= nr_bytes; num -= nr_bytes;
offset = 0;
index += nr_pages;
} }
err = 0; err = 0;
@ -1867,7 +1863,6 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
{ {
int err; int err;
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
pgoff_t index;
loff_t file_size; loff_t file_size;
unsigned int num; unsigned int num;
unsigned int offset; unsigned int offset;
@ -1878,15 +1873,16 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
size_t args_size = sizeof(*ra); size_t args_size = sizeof(*ra);
struct fuse_args_pages *ap; struct fuse_args_pages *ap;
struct fuse_args *args; 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); file_size = i_size_read(inode);
num = min(outarg->size, fc->max_write); num = min(outarg->size, fc->max_write);
if (outarg->offset > file_size) if (pos > file_size)
num = 0; num = 0;
else if (num > file_size - outarg->offset) else if (num > file_size - pos)
num = file_size - outarg->offset; num = file_size - pos;
num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
num_pages = min(num_pages, fc->max_pages); 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->in_pages = true;
args->end = fuse_retrieve_end; args->end = fuse_retrieve_end;
index = outarg->offset >> PAGE_SHIFT;
while (num && ap->num_folios < num_pages) { while (num && ap->num_folios < num_pages) {
struct folio *folio; struct folio *folio;
unsigned int folio_offset; unsigned int folio_offset;
unsigned int nr_bytes; unsigned int nr_bytes;
unsigned int nr_pages; pgoff_t index = pos >> PAGE_SHIFT;
folio = filemap_get_folio(mapping, index); folio = filemap_get_folio(mapping, index);
if (IS_ERR(folio)) if (IS_ERR(folio))
break; 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_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->folios[ap->num_folios] = folio;
ap->descs[ap->num_folios].offset = folio_offset; ap->descs[ap->num_folios].offset = folio_offset;
ap->descs[ap->num_folios].length = nr_bytes; ap->descs[ap->num_folios].length = nr_bytes;
ap->num_folios++; ap->num_folios++;
offset = 0; pos += nr_bytes;
num -= nr_bytes; num -= nr_bytes;
total_len += nr_bytes; total_len += nr_bytes;
index += nr_pages;
} }
ra->inarg.offset = outarg->offset; ra->inarg.offset = outarg->offset;
ra->inarg.size = total_len; ra->inarg.size = total_len;