Message ID | 20241109001258.2216604-5-joannelkoong@gmail.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | fuse: support large folios | expand |
On Fri, Nov 8, 2024 at 4:13 PM Joanne Koong <joannelkoong@gmail.com> wrote: > > Add support for folios larger than one page size for non-writeback I'll change this naming from "non-writeback" to "writethrough" > writes. > > Signed-off-by: Joanne Koong <joannelkoong@gmail.com> > --- > fs/fuse/file.c | 29 ++++++++++++++++++----------- > 1 file changed, 18 insertions(+), 11 deletions(-) > > diff --git a/fs/fuse/file.c b/fs/fuse/file.c > index a89fdc55a40b..6ee23ab9b7f2 100644 > --- a/fs/fuse/file.c > +++ b/fs/fuse/file.c > @@ -1146,19 +1146,15 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, > num = min(num, max_pages << PAGE_SHIFT); > > ap->args.in_pages = true; > - ap->descs[0].offset = offset; > > while (num) { > size_t tmp; > struct folio *folio; > pgoff_t index = pos >> PAGE_SHIFT; > - unsigned int bytes = min(PAGE_SIZE - offset, num); > - > - again: > - err = -EFAULT; > - if (fault_in_iov_iter_readable(ii, bytes)) > - break; > + unsigned int bytes; > + unsigned int folio_offset; > > + again: > folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, > mapping_gfp_mask(mapping)); This __filemap_get_folio() call (and the one in fuse_write_begin() as well) needs to also set the order on the fgf flag to enable large folios, else all folios returned will be order 0. I'll fix this in v2. > if (IS_ERR(folio)) { > @@ -1166,10 +1162,20 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, > break; > } > > + folio_offset = ((index - folio->index) << PAGE_SHIFT) + offset; > + bytes = min(folio_size(folio) - folio_offset, num); > + > + err = -EFAULT; > + if (fault_in_iov_iter_readable(ii, bytes)) { > + folio_unlock(folio); > + folio_put(folio); > + break; > + } > + > if (mapping_writably_mapped(mapping)) > flush_dcache_folio(folio); > > - tmp = copy_folio_from_iter_atomic(folio, offset, bytes, ii); > + tmp = copy_folio_from_iter_atomic(folio, folio_offset, bytes, ii); > flush_dcache_folio(folio); > > if (!tmp) { > @@ -1180,6 +1186,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, > > err = 0; > ap->folios[ap->num_folios] = folio; > + ap->descs[ap->num_folios].offset = folio_offset; > ap->descs[ap->num_folios].length = tmp; > ap->num_folios++; > > @@ -1187,11 +1194,11 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, > pos += tmp; > num -= tmp; > offset += tmp; > - if (offset == PAGE_SIZE) > + if (offset == folio_size(folio)) > offset = 0; > > - /* If we copied full page, mark it uptodate */ > - if (tmp == PAGE_SIZE) > + /* If we copied full folio, mark it uptodate */ > + if (tmp == folio_size(folio)) > folio_mark_uptodate(folio); > > if (folio_test_uptodate(folio)) { > -- > 2.43.5 >
On Tue, Nov 12, 2024 at 9:32 AM Joanne Koong <joannelkoong@gmail.com> wrote: > > On Fri, Nov 8, 2024 at 4:13 PM Joanne Koong <joannelkoong@gmail.com> wrote: > > > > Add support for folios larger than one page size for non-writeback > > I'll change this naming from "non-writeback" to "writethrough" > > > writes. > > > > Signed-off-by: Joanne Koong <joannelkoong@gmail.com> > > --- > > fs/fuse/file.c | 29 ++++++++++++++++++----------- > > 1 file changed, 18 insertions(+), 11 deletions(-) > > > > diff --git a/fs/fuse/file.c b/fs/fuse/file.c > > index a89fdc55a40b..6ee23ab9b7f2 100644 > > --- a/fs/fuse/file.c > > +++ b/fs/fuse/file.c > > @@ -1146,19 +1146,15 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, > > num = min(num, max_pages << PAGE_SHIFT); > > > > ap->args.in_pages = true; > > - ap->descs[0].offset = offset; > > > > while (num) { > > size_t tmp; > > struct folio *folio; > > pgoff_t index = pos >> PAGE_SHIFT; > > - unsigned int bytes = min(PAGE_SIZE - offset, num); > > - > > - again: > > - err = -EFAULT; > > - if (fault_in_iov_iter_readable(ii, bytes)) > > - break; > > + unsigned int bytes; > > + unsigned int folio_offset; > > > > + again: > > folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, > > mapping_gfp_mask(mapping)); > > This __filemap_get_folio() call (and the one in fuse_write_begin() as > well) needs to also set the order on the fgf flag to enable large > folios, else all folios returned will be order 0. > > I'll fix this in v2. Ran some benchmarks and trying to get the largest folios possible from __filemap_get_folio() is an over-optimization and slows down writes significantly. I'll leave this as is for v2, and we could look into optimizing this in the future. > > > if (IS_ERR(folio)) { > > @@ -1166,10 +1162,20 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, > > break; > > } > > > > + folio_offset = ((index - folio->index) << PAGE_SHIFT) + offset; > > + bytes = min(folio_size(folio) - folio_offset, num); > > + > > + err = -EFAULT; > > + if (fault_in_iov_iter_readable(ii, bytes)) { > > + folio_unlock(folio); > > + folio_put(folio); > > + break; > > + } > > + > > if (mapping_writably_mapped(mapping)) > > flush_dcache_folio(folio); > > > > - tmp = copy_folio_from_iter_atomic(folio, offset, bytes, ii); > > + tmp = copy_folio_from_iter_atomic(folio, folio_offset, bytes, ii); > > flush_dcache_folio(folio); > > > > if (!tmp) { > > @@ -1180,6 +1186,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, > > > > err = 0; > > ap->folios[ap->num_folios] = folio; > > + ap->descs[ap->num_folios].offset = folio_offset; > > ap->descs[ap->num_folios].length = tmp; > > ap->num_folios++; > > > > @@ -1187,11 +1194,11 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, > > pos += tmp; > > num -= tmp; > > offset += tmp; > > - if (offset == PAGE_SIZE) > > + if (offset == folio_size(folio)) > > offset = 0; > > > > - /* If we copied full page, mark it uptodate */ > > - if (tmp == PAGE_SIZE) > > + /* If we copied full folio, mark it uptodate */ > > + if (tmp == folio_size(folio)) > > folio_mark_uptodate(folio); > > > > if (folio_test_uptodate(folio)) { > > -- > > 2.43.5 > >
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index a89fdc55a40b..6ee23ab9b7f2 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1146,19 +1146,15 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, num = min(num, max_pages << PAGE_SHIFT); ap->args.in_pages = true; - ap->descs[0].offset = offset; while (num) { size_t tmp; struct folio *folio; pgoff_t index = pos >> PAGE_SHIFT; - unsigned int bytes = min(PAGE_SIZE - offset, num); - - again: - err = -EFAULT; - if (fault_in_iov_iter_readable(ii, bytes)) - break; + unsigned int bytes; + unsigned int folio_offset; + again: folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, mapping_gfp_mask(mapping)); if (IS_ERR(folio)) { @@ -1166,10 +1162,20 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, break; } + folio_offset = ((index - folio->index) << PAGE_SHIFT) + offset; + bytes = min(folio_size(folio) - folio_offset, num); + + err = -EFAULT; + if (fault_in_iov_iter_readable(ii, bytes)) { + folio_unlock(folio); + folio_put(folio); + break; + } + if (mapping_writably_mapped(mapping)) flush_dcache_folio(folio); - tmp = copy_folio_from_iter_atomic(folio, offset, bytes, ii); + tmp = copy_folio_from_iter_atomic(folio, folio_offset, bytes, ii); flush_dcache_folio(folio); if (!tmp) { @@ -1180,6 +1186,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, err = 0; ap->folios[ap->num_folios] = folio; + ap->descs[ap->num_folios].offset = folio_offset; ap->descs[ap->num_folios].length = tmp; ap->num_folios++; @@ -1187,11 +1194,11 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, pos += tmp; num -= tmp; offset += tmp; - if (offset == PAGE_SIZE) + if (offset == folio_size(folio)) offset = 0; - /* If we copied full page, mark it uptodate */ - if (tmp == PAGE_SIZE) + /* If we copied full folio, mark it uptodate */ + if (tmp == folio_size(folio)) folio_mark_uptodate(folio); if (folio_test_uptodate(folio)) {
Add support for folios larger than one page size for non-writeback writes. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> --- fs/fuse/file.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-)