fs/isofs/compress.c | 74 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 32 deletions(-)
Store folios in the array that zisofs_read_folio() passes to
zisofs_fill_pages() and zisofs_uncompress_block(), use the folio APIs on
them, and grab the folios with __filemap_get_folio() instead of
grab_cache_page_nowait(). This removes six compound_head() calls, from
page_offset(), the three SetPageUptodate() calls, unlock_page() and
put_page(), and the last struct page usage in isofs.
grab_cache_page_nowait() passed FGP_NOFS as well, but FGP_NOWAIT already
prevents reclaim entirely, so leave it out, as FGP_NOFS is on its way
out [1].
Change poffset to be unsigned int rather than just unsigned while at
it.
[1] https://lore.kernel.org/linux-mm/20260830041901.2668-9-willy@infradead.org/
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
Convert the zisofs decompression path to folios. This removes the last
struct page usage in isofs and one of the three remaining callers of
grab_cache_page_nowait().
isofs never enables large folios, so the one page of zlib output per
array slot is unchanged.
Based on v7.3-rc2.
---
fs/isofs/compress.c | 74 ++++++++++++++++++++++++++++++-----------------------
1 file changed, 42 insertions(+), 32 deletions(-)
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
index f9869d62b850..d7fdebf4b787 100644
--- a/fs/isofs/compress.c
+++ b/fs/isofs/compress.c
@@ -39,7 +39,7 @@ static DEFINE_MUTEX(zisofs_zlib_lock);
*/
static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
loff_t block_end, int pcount,
- struct page **pages, unsigned poffset,
+ struct folio **folios, unsigned int poffset,
int *errp)
{
unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
@@ -66,11 +66,12 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
if (block_size == 0) {
for ( i = 0 ; i < pcount ; i++ ) {
unsigned int off = i ? 0 : poffset;
+ struct folio *folio = folios[i];
- if (!pages[i])
+ if (!folio)
continue;
- memzero_page(pages[i], off, PAGE_SIZE - off);
- SetPageUptodate(pages[i]);
+ folio_zero_range(folio, off, PAGE_SIZE - off);
+ folio_mark_uptodate(folio);
}
return (((loff_t)pcount) << PAGE_SHIFT) - poffset;
}
@@ -119,9 +120,11 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
while (curpage < pcount && curbh < haveblocks &&
zerr != Z_STREAM_END) {
+ struct folio *folio = folios[curpage];
+
if (!stream.avail_out) {
- if (pages[curpage]) {
- stream.next_out = kmap_local_page(pages[curpage])
+ if (folio) {
+ stream.next_out = kmap_local_folio(folio, 0)
+ poffset;
stream.avail_out = PAGE_SIZE - poffset;
poffset = 0;
@@ -173,9 +176,9 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
if (!stream.avail_out) {
/* This page completed */
- if (pages[curpage]) {
- flush_dcache_page(pages[curpage]);
- SetPageUptodate(pages[curpage]);
+ if (folio) {
+ flush_dcache_folio(folio);
+ folio_mark_uptodate(folio);
}
if (stream.next_out != (unsigned char *)zisofs_sink_page) {
kunmap_local(stream.next_out);
@@ -206,7 +209,7 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
* fills in other pages if we have data for them.
*/
static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
- struct page **pages)
+ struct folio **folios)
{
loff_t start_off, end_off;
loff_t block_start, block_end;
@@ -221,14 +224,14 @@ static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
int err;
loff_t ret;
- BUG_ON(!pages[full_page]);
+ BUG_ON(!folios[full_page]);
/*
* We want to read at least 'full_page' page. Because we have to
* uncompress the whole compression block anyway, fill the surrounding
* pages with the data we have anyway...
*/
- start_off = page_offset(pages[full_page]);
+ start_off = folio_pos(folios[full_page]);
end_off = min_t(loff_t, start_off + PAGE_SIZE, inode->i_size);
cstart_block = start_off >> zisofs_block_shift;
@@ -267,9 +270,9 @@ static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
}
err = 0;
ret = zisofs_uncompress_block(inode, block_start, block_end,
- pcount, pages, poffset, &err);
+ pcount, folios, poffset, &err);
poffset += ret;
- pages += poffset >> PAGE_SHIFT;
+ folios += poffset >> PAGE_SHIFT;
pcount -= poffset >> PAGE_SHIFT;
full_page -= poffset >> PAGE_SHIFT;
poffset &= ~PAGE_MASK;
@@ -289,9 +292,11 @@ static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
cstart_block++;
}
- if (poffset && *pages) {
- memzero_page(*pages, poffset, PAGE_SIZE - poffset);
- SetPageUptodate(*pages);
+ if (poffset && *folios) {
+ struct folio *folio = *folios;
+
+ folio_zero_range(folio, poffset, PAGE_SIZE - poffset);
+ folio_mark_uptodate(folio);
}
brelse(bh);
return 0;
@@ -312,7 +317,7 @@ static int zisofs_read_folio(struct file *file, struct folio *folio)
unsigned int zisofs_pages_per_cblock =
PAGE_SHIFT <= zisofs_block_shift ?
(1 << (zisofs_block_shift - PAGE_SHIFT)) : 0;
- struct page **pages;
+ struct folio **folios;
pgoff_t index = folio->index, end_index;
end_index = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -336,33 +341,38 @@ static int zisofs_read_folio(struct file *file, struct folio *folio)
full_page = 0;
pcount = 1;
}
- pages = kzalloc_objs(*pages,
- max_t(unsigned int, zisofs_pages_per_cblock, 1));
- if (!pages) {
+ folios = kzalloc_objs(*folios,
+ max_t(unsigned int, zisofs_pages_per_cblock, 1));
+ if (!folios) {
folio_unlock(folio);
return -ENOMEM;
}
- pages[full_page] = &folio->page;
+ folios[full_page] = folio;
for (i = 0; i < pcount; i++, index++) {
- if (i != full_page)
- pages[i] = grab_cache_page_nowait(mapping, index);
+ if (i == full_page)
+ continue;
+ folios[i] = __filemap_get_folio(mapping, index,
+ FGP_LOCK | FGP_CREAT | FGP_NOWAIT,
+ mapping_gfp_mask(mapping));
+ if (IS_ERR(folios[i]))
+ folios[i] = NULL;
}
- err = zisofs_fill_pages(inode, full_page, pcount, pages);
+ err = zisofs_fill_pages(inode, full_page, pcount, folios);
- /* Release any residual pages, do not SetPageUptodate */
+ /* Release any residual folios, do not mark them uptodate */
for (i = 0; i < pcount; i++) {
- if (pages[i]) {
- flush_dcache_page(pages[i]);
- unlock_page(pages[i]);
+ if (folios[i]) {
+ flush_dcache_folio(folios[i]);
+ folio_unlock(folios[i]);
if (i != full_page)
- put_page(pages[i]);
+ folio_put(folios[i]);
}
- }
+ }
/* At this point, err contains 0 or -EIO depending on the "critical" page */
- kfree(pages);
+ kfree(folios);
return err;
}
---
base-commit: df2908090cda368b01ff43709f51890076c56157
change-id: 20260906-isofs-zisofs-folio-5b1621d694e4
Best regards,
--
Tal Zussman <tz2294@columbia.edu>
On Sun 06-09-26 22:14:59, Tal Zussman wrote:
> Store folios in the array that zisofs_read_folio() passes to
> zisofs_fill_pages() and zisofs_uncompress_block(), use the folio APIs on
> them, and grab the folios with __filemap_get_folio() instead of
> grab_cache_page_nowait(). This removes six compound_head() calls, from
> page_offset(), the three SetPageUptodate() calls, unlock_page() and
> put_page(), and the last struct page usage in isofs.
>
> grab_cache_page_nowait() passed FGP_NOFS as well, but FGP_NOWAIT already
> prevents reclaim entirely, so leave it out, as FGP_NOFS is on its way
> out [1].
>
> Change poffset to be unsigned int rather than just unsigned while at
> it.
>
> [1] https://lore.kernel.org/linux-mm/20260830041901.2668-9-willy@infradead.org/
>
> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Thanks for the conversion! The patch looks mostly good, some smaller
comments below:
> @@ -66,11 +66,12 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
> if (block_size == 0) {
> for ( i = 0 ; i < pcount ; i++ ) {
> unsigned int off = i ? 0 : poffset;
> + struct folio *folio = folios[i];
>
> - if (!pages[i])
> + if (!folio)
> continue;
> - memzero_page(pages[i], off, PAGE_SIZE - off);
> - SetPageUptodate(pages[i]);
> + folio_zero_range(folio, off, PAGE_SIZE - off);
^^ perhaps
"folio_size(folio) - off" here?
> + folio_mark_uptodate(folio);
> }
> return (((loff_t)pcount) << PAGE_SHIFT) - poffset;
> }
...
> @@ -119,9 +120,11 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
>
> while (curpage < pcount && curbh < haveblocks &&
> zerr != Z_STREAM_END) {
> + struct folio *folio = folios[curpage];
> +
> if (!stream.avail_out) {
> - if (pages[curpage]) {
> - stream.next_out = kmap_local_page(pages[curpage])
> + if (folio) {
> + stream.next_out = kmap_local_folio(folio, 0)
> + poffset;
^^^ this is just:
kmap_local_folio(folio, poffset);
> stream.avail_out = PAGE_SIZE - poffset;
And this would be probably more idiomatic as "folio_size(folio) - poffset"
after the conversion.
...
> @@ -289,9 +292,11 @@ static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
> cstart_block++;
> }
>
> - if (poffset && *pages) {
> - memzero_page(*pages, poffset, PAGE_SIZE - poffset);
> - SetPageUptodate(*pages);
> + if (poffset && *folios) {
> + struct folio *folio = *folios;
> +
> + folio_zero_range(folio, poffset, PAGE_SIZE - poffset);
^^^ again
folio_size(folio) here?
> + folio_mark_uptodate(folio);
> }
> brelse(bh);
> return 0;
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
On 9/7/26 12:34 PM, Jan Kara wrote:
> On Sun 06-09-26 22:14:59, Tal Zussman wrote:
>> Store folios in the array that zisofs_read_folio() passes to
>> zisofs_fill_pages() and zisofs_uncompress_block(), use the folio APIs on
>> them, and grab the folios with __filemap_get_folio() instead of
>> grab_cache_page_nowait(). This removes six compound_head() calls, from
>> page_offset(), the three SetPageUptodate() calls, unlock_page() and
>> put_page(), and the last struct page usage in isofs.
>>
>> grab_cache_page_nowait() passed FGP_NOFS as well, but FGP_NOWAIT already
>> prevents reclaim entirely, so leave it out, as FGP_NOFS is on its way
>> out [1].
>>
>> Change poffset to be unsigned int rather than just unsigned while at
>> it.
>>
>> [1] https://lore.kernel.org/linux-mm/20260830041901.2668-9-willy@infradead.org/
>>
>> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
>
> Thanks for the conversion! The patch looks mostly good, some smaller
> comments below:
>
Thanks! Will adjust all of these and send v2.
>> @@ -66,11 +66,12 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
>> if (block_size == 0) {
>> for ( i = 0 ; i < pcount ; i++ ) {
>> unsigned int off = i ? 0 : poffset;
>> + struct folio *folio = folios[i];
>>
>> - if (!pages[i])
>> + if (!folio)
>> continue;
>> - memzero_page(pages[i], off, PAGE_SIZE - off);
>> - SetPageUptodate(pages[i]);
>> + folio_zero_range(folio, off, PAGE_SIZE - off);
> ^^ perhaps
> "folio_size(folio) - off" here?
>
>> + folio_mark_uptodate(folio);
>> }
>> return (((loff_t)pcount) << PAGE_SHIFT) - poffset;
>> }
> ...
>> @@ -119,9 +120,11 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
>>
>> while (curpage < pcount && curbh < haveblocks &&
>> zerr != Z_STREAM_END) {
>> + struct folio *folio = folios[curpage];
>> +
>> if (!stream.avail_out) {
>> - if (pages[curpage]) {
>> - stream.next_out = kmap_local_page(pages[curpage])
>> + if (folio) {
>> + stream.next_out = kmap_local_folio(folio, 0)
>> + poffset;
> ^^^ this is just:
> kmap_local_folio(folio, poffset);
>
>> stream.avail_out = PAGE_SIZE - poffset;
>
> And this would be probably more idiomatic as "folio_size(folio) - poffset"
> after the conversion.
>
> ...
>> @@ -289,9 +292,11 @@ static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
>> cstart_block++;
>> }
>>
>> - if (poffset && *pages) {
>> - memzero_page(*pages, poffset, PAGE_SIZE - poffset);
>> - SetPageUptodate(*pages);
>> + if (poffset && *folios) {
>> + struct folio *folio = *folios;
>> +
>> + folio_zero_range(folio, poffset, PAGE_SIZE - poffset);
> ^^^ again
> folio_size(folio) here?
>
>> + folio_mark_uptodate(folio);
>> }
>> brelse(bh);
>> return 0;
>
> Honza
> --
> Jan Kara <jack@suse.com>
> SUSE Labs, CR
>
© 2016 - 2026 Red Hat, Inc.