From: Jaegeuk Kim via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
To: Chao Yu <chao@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net
Subject: Re: [f2fs-dev] [PATCH v1 05/12] f2fs: cache: use meta cache
Date: Thu, 20 Aug 2026 05:11:07 +0000 [thread overview]
Message-ID: <aoaMa3N7mk5f4jz-@google.com> (raw)
In-Reply-To: <20260820031721.12218-6-chao@kernel.org>
On 08/20, Chao Yu via Linux-f2fs-devel wrote:
> This patch migrates F2FS meta block caching from the fake VFS inode
> page cache (sbi->meta_inode) to meta cache (sbi->meta_blocks).
>
> It converts CP, SIT, NAT, SSA, recovery, and GC metadata I/O paths to
> operate on struct f2fs_cached_block instead of folio, and removes
> sbi->meta_inode.
>
> Signed-off-by: Chao Yu <chao@kernel.org>
> ---
> fs/f2fs/cache.c | 2 +
> fs/f2fs/checkpoint.c | 394 ++++++++++++++++++----------------------
> fs/f2fs/compress.c | 4 +-
> fs/f2fs/data.c | 29 ++-
> fs/f2fs/debug.c | 12 +-
> fs/f2fs/f2fs.h | 81 +++------
> fs/f2fs/file.c | 4 +-
> fs/f2fs/gc.c | 134 +++++++-------
> fs/f2fs/inline.c | 9 +-
> fs/f2fs/inode.c | 9 +-
> fs/f2fs/node.c | 125 +++++++------
> fs/f2fs/node.h | 4 +-
> fs/f2fs/recovery.c | 198 ++++++++++----------
> fs/f2fs/segment.c | 201 ++++++++++----------
> fs/f2fs/segment.h | 31 +++-
> fs/f2fs/super.c | 31 +---
> include/linux/f2fs_fs.h | 1 -
> 17 files changed, 606 insertions(+), 663 deletions(-)
>
> diff --git a/fs/f2fs/cache.c b/fs/f2fs/cache.c
> index cb5b26046162..afef808e485a 100644
> --- a/fs/f2fs/cache.c
> +++ b/fs/f2fs/cache.c
> @@ -631,6 +631,8 @@ static int f2fs_cache_writeback_kthread(void *data)
> break;
> if (f2fs_cp_error(sbi))
> continue;
> +
> + f2fs_write_meta_caches(sbi);
> }
> return 0;
> }
> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> index 729d19680caf..1a7083540b82 100644
> --- a/fs/f2fs/checkpoint.c
> +++ b/fs/f2fs/checkpoint.c
> @@ -17,6 +17,7 @@
> #include <linux/delayacct.h>
> #include <linux/ioprio.h>
> #include <linux/math64.h>
> +#include <linux/freezer.h>
>
> #include "f2fs.h"
> #include "node.h"
> @@ -235,27 +236,27 @@ struct kmem_cache *f2fs_inode_entry_slab;
> /*
> * We guarantee no failure on the returned page.
> */
> -struct folio *f2fs_grab_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index)
> +struct f2fs_cached_block *f2fs_grab_meta_cache(struct f2fs_sb_info *sbi,
> + pgoff_t index)
> {
> - struct address_space *mapping = META_MAPPING(sbi);
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> repeat:
> - folio = f2fs_grab_cache_folio(mapping, index, false);
> - if (IS_ERR(folio)) {
> + entry = f2fs_grab_cache(META_CACHE(sbi), index,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(entry)) {
> cond_resched();
> goto repeat;
> }
> - f2fs_folio_wait_writeback(folio, META, true, true);
> - if (!folio_test_uptodate(folio))
> - folio_mark_uptodate(folio);
> - return folio;
> + f2fs_cache_wait_writeback(entry);
> + if (!f2fs_cache_test_uptodate(entry))
> + f2fs_cache_set_uptodate(entry);
> + return entry;
> }
>
> -static struct folio *__get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index,
> - bool is_meta)
> +static struct f2fs_cached_block *__get_meta_cache(struct f2fs_sb_info *sbi,
> + pgoff_t index, bool is_meta)
> {
> - struct address_space *mapping = META_MAPPING(sbi);
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> struct f2fs_io_info fio = {
> .sbi = sbi,
> .type = META,
> @@ -265,70 +266,75 @@ static struct folio *__get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index,
> .new_blkaddr = index,
> .encrypted_page = NULL,
> .is_por = !is_meta ? 1 : 0,
> + .is_cache = 1,
> };
> int err;
>
> if (unlikely(!is_meta))
> fio.op_flags &= ~REQ_META;
> repeat:
> - folio = f2fs_grab_cache_folio(mapping, index, false);
> - if (IS_ERR(folio)) {
> + entry = f2fs_grab_cache(META_CACHE(sbi), index,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(entry)) {
> cond_resched();
> goto repeat;
> }
> - if (folio_test_uptodate(folio))
> + if (f2fs_cache_test_uptodate(entry))
> goto out;
>
> - fio.folio = folio;
> + fio.cache_entry = entry;
>
> - err = f2fs_submit_page_bio(&fio);
> + err = f2fs_submit_cache_read(&fio);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> return ERR_PTR(err);
> }
>
> f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, F2FS_BLKSIZE);
>
> - folio_lock(folio);
> - if (unlikely(!is_meta_folio(folio))) {
> - f2fs_folio_put(folio, true);
> + f2fs_lock_cache(entry);
> + if (unlikely(!f2fs_is_meta_cache(entry))) {
> + f2fs_put_cache(entry, true);
> goto repeat;
> }
>
> - if (unlikely(!folio_test_uptodate(folio))) {
> - f2fs_handle_page_eio(sbi, folio, META);
> - f2fs_folio_put(folio, true);
> + if (unlikely(!f2fs_cache_test_uptodate(entry))) {
> + f2fs_handle_page_eio(sbi, entry->index, META);
> + f2fs_put_cache(entry, true);
> return ERR_PTR(-EIO);
> }
> out:
> - return folio;
> + return entry;
> }
>
> -struct folio *f2fs_get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index)
> +struct f2fs_cached_block *f2fs_get_meta_cache(struct f2fs_sb_info *sbi,
> + pgoff_t index)
> {
> - return __get_meta_folio(sbi, index, true);
> + return __get_meta_cache(sbi, index, true);
> }
>
> -struct folio *f2fs_get_meta_folio_retry(struct f2fs_sb_info *sbi, pgoff_t index)
> +struct f2fs_cached_block *f2fs_get_meta_cache_retry(struct f2fs_sb_info *sbi,
> + pgoff_t index)
> {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> int count = 0;
>
> retry:
> - folio = __get_meta_folio(sbi, index, true);
> - if (IS_ERR(folio)) {
> - if (PTR_ERR(folio) == -EIO &&
> + entry = __get_meta_cache(sbi, index, true);
> + if (IS_ERR(entry)) {
> + if (PTR_ERR(entry) == -EIO &&
> ++count <= DEFAULT_RETRY_IO_COUNT)
> goto retry;
> f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_META_PAGE);
> }
> - return folio;
> + return entry;
> }
>
> /* for POR only */
> -struct folio *f2fs_get_tmp_folio(struct f2fs_sb_info *sbi, pgoff_t index)
> +struct f2fs_cached_block *f2fs_get_tmp_cache(struct f2fs_sb_info *sbi,
> + pgoff_t index)
> {
> - return __get_meta_folio(sbi, index, false);
> + return __get_meta_cache(sbi, index, false);
> }
>
> static bool __is_bitmap_valid(struct f2fs_sb_info *sbi, block_t blkaddr,
> @@ -446,9 +452,10 @@ bool f2fs_is_valid_blkaddr_raw(struct f2fs_sb_info *sbi,
> /*
> * Readahead CP/NAT/SIT/SSA/POR pages
> */
> -int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> - int type, bool sync)
> +int f2fs_ra_meta_caches(struct f2fs_sb_info *sbi, block_t start,
> + int nrpages, int type, bool sync)
> {
> + struct f2fs_cached_block_list *cache = META_CACHE(sbi);
> block_t blkno = start;
> struct f2fs_io_info fio = {
> .sbi = sbi,
> @@ -458,6 +465,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> .encrypted_page = NULL,
> .in_list = 0,
> .is_por = (type == META_POR) ? 1 : 0,
> + .is_cache = 1,
> };
> struct blk_plug plug;
> int err;
> @@ -467,7 +475,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
>
> blk_start_plug(&plug);
> for (; nrpages-- > 0; blkno++) {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_is_valid_blkaddr(sbi, blkno, type))
> goto out;
> @@ -494,62 +502,58 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> fio.new_blkaddr = blkno;
> break;
> default:
> - BUG();
> + f2fs_bug_on(sbi, 1);
> }
>
> - folio = f2fs_grab_cache_folio(META_MAPPING(sbi),
> - fio.new_blkaddr, false);
> - if (IS_ERR(folio))
> + entry = f2fs_grab_cache(cache, fio.new_blkaddr,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(entry))
> continue;
> - if (folio_test_uptodate(folio)) {
> - f2fs_folio_put(folio, true);
> + if (f2fs_cache_test_uptodate(entry)) {
> + f2fs_put_cache(entry, true);
> continue;
> }
>
> - fio.folio = folio;
> - err = f2fs_submit_page_bio(&fio);
> - f2fs_folio_put(folio, err ? true : false);
> + fio.cache_entry = entry;
> + err = f2fs_submit_cache_read(&fio);
> + f2fs_put_cache(entry, err ? true : false);
>
> if (!err)
> f2fs_update_iostat(sbi, NULL, FS_META_READ_IO,
> - F2FS_BLKSIZE);
> + sbi->blocksize);
> }
> out:
> blk_finish_plug(&plug);
> return blkno - start;
> }
>
> -void f2fs_ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index,
> - unsigned int ra_blocks)
> +void f2fs_ra_meta_caches_cond(struct f2fs_sb_info *sbi, pgoff_t index,
> + unsigned int ra_blocks)
> {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> bool readahead = false;
>
> if (ra_blocks == RECOVERY_MIN_RA_BLOCKS)
> return;
>
> - folio = filemap_get_folio(META_MAPPING(sbi), index);
> - if (IS_ERR(folio) || !folio_test_uptodate(folio))
> + entry = f2fs_find_cache(META_CACHE(sbi), index);
> + if (IS_ERR(entry) || !f2fs_cache_test_uptodate(entry))
> readahead = true;
> - f2fs_folio_put(folio, false);
> + f2fs_put_cache(entry, false);
>
> if (readahead)
> - f2fs_ra_meta_pages(sbi, index, ra_blocks, META_POR, true);
> + f2fs_ra_meta_caches(sbi, index, ra_blocks, META_POR, true);
> }
>
> -static bool __f2fs_write_meta_folio(struct folio *folio,
> - struct writeback_control *wbc,
> +static bool __f2fs_write_meta_cache(struct f2fs_cached_block *entry,
> enum iostat_type io_type)
> {
> - struct f2fs_sb_info *sbi = F2FS_F_SB(folio);
> -
> - trace_f2fs_writepage(folio, META);
> + struct f2fs_sb_info *sbi = entry->cache->sbi;
>
> if (unlikely(f2fs_cp_error(sbi))) {
> if (is_sbi_flag_set(sbi, SBI_IS_CLOSE)) {
> - folio_clear_uptodate(folio);
> - dec_page_count(sbi, F2FS_DIRTY_META);
> - folio_unlock(folio);
> + f2fs_force_clear_cache_dirty(entry);
> + f2fs_unlock_cache(entry);
> return true;
> }
> goto redirty_out;
> @@ -557,10 +561,10 @@ static bool __f2fs_write_meta_folio(struct folio *folio,
> if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
> goto redirty_out;
>
> - f2fs_do_write_meta_page(sbi, folio, io_type);
> + f2fs_do_write_meta_cache(sbi, entry, io_type);
> dec_page_count(sbi, F2FS_DIRTY_META);
>
> - folio_unlock(folio);
> + f2fs_unlock_cache(entry);
>
> if (unlikely(f2fs_cp_error(sbi)))
> f2fs_submit_merged_write(sbi, META);
> @@ -568,101 +572,89 @@ static bool __f2fs_write_meta_folio(struct folio *folio,
> return true;
>
> redirty_out:
> - folio_redirty_for_writepage(wbc, folio);
> + f2fs_cache_set_dirty(entry);
> return false;
> }
>
> -static int f2fs_write_meta_pages(struct address_space *mapping,
> - struct writeback_control *wbc)
> +void f2fs_write_meta_caches(struct f2fs_sb_info *sbi)
> {
> - struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
> struct f2fs_lock_context lc;
> - long diff, written;
> + long nr_to_write = LONG_MAX;
>
> if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
> - goto skip_write;
> + return;
>
> - /* collect a number of dirty meta pages and write together */
> - if (wbc->sync_mode != WB_SYNC_ALL &&
> - get_pages(sbi, F2FS_DIRTY_META) <
> - nr_pages_to_skip(sbi, META))
> - goto skip_write;
> + /* collect a number of dirty meta caches and write together */
> + if (get_pages(sbi, F2FS_DIRTY_META) <
> + nr_pages_to_skip(sbi, META))
> + return;
>
> - /* if locked failed, cp will flush dirty pages instead */
> + /* if locked failed, cp will flush dirty caches instead */
> if (!f2fs_down_write_trylock_trace(&sbi->cp_global_sem, &lc))
> - goto skip_write;
> + return;
>
> - trace_f2fs_writepages(mapping->host, wbc, META);
> - diff = nr_pages_to_write(sbi, META, wbc);
> - written = f2fs_sync_meta_pages(sbi, wbc->nr_to_write, FS_META_IO);
> + nr_to_write = adjust_flush_cache_number(sbi, META);
> + f2fs_sync_meta_caches(sbi, nr_to_write, false, FS_META_IO);
> f2fs_up_write_trace(&sbi->cp_global_sem, &lc);
> - wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff);
> - return 0;
> -
> -skip_write:
> - wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_META);
> - trace_f2fs_writepages(mapping->host, wbc, META);
> - return 0;
> }
>
> -long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, long nr_to_write,
> - enum iostat_type io_type)
> +long f2fs_sync_meta_caches(struct f2fs_sb_info *sbi, long nr_to_write,
> + bool sync, enum iostat_type io_type)
> {
> - struct address_space *mapping = META_MAPPING(sbi);
> pgoff_t index = 0, prev = ULONG_MAX;
> - struct folio_batch fbatch;
> + struct f2fs_cached_block *entries[F2FS_ONSTACK_CACHES];
> long nwritten = 0;
> - int nr_folios;
> - struct writeback_control wbc = {};
> + int nr;
> struct blk_plug plug;
> -
> - folio_batch_init(&fbatch);
> + bool background = nr_to_write != LONG_MAX;
>
> blk_start_plug(&plug);
>
> - while ((nr_folios = filemap_get_folios_tag(mapping, &index,
> - (pgoff_t)-1,
> - PAGECACHE_TAG_DIRTY, &fbatch))) {
> + while ((nr = f2fs_cache_gang_lookup_tag(META_CACHE(sbi), entries,
> + &index, F2FS_ONSTACK_CACHES, F2FS_CACHE_TAG_DIRTY))) {
> int i;
>
> - for (i = 0; i < nr_folios; i++) {
> - struct folio *folio = fbatch.folios[i];
> + for (i = 0; i < nr; i++) {
> + struct f2fs_cached_block *entry = entries[i];
> +
> + if (background && unlikely(freezing(current))) {
> + f2fs_cache_gang_release(entries, nr);
> + goto stop;
> + }
>
> - if (nr_to_write != LONG_MAX && i != 0 &&
> - folio->index != prev +
> - folio_nr_pages(fbatch.folios[i-1])) {
> - folio_batch_release(&fbatch);
> + if (background && i != 0 &&
> + entry->index != prev + 1) {
> + f2fs_cache_gang_release(entries, nr);
> goto stop;
> }
>
> - folio_lock(folio);
> + f2fs_lock_cache(entry);
>
> - if (unlikely(!is_meta_folio(folio))) {
> + if (unlikely(!f2fs_is_meta_cache(entry))) {
> continue_unlock:
> - folio_unlock(folio);
> + f2fs_unlock_cache(entry);
> continue;
> }
> - if (!folio_test_dirty(folio)) {
> + if (!f2fs_cache_test_dirty(entry)) {
> /* someone wrote it for us */
> goto continue_unlock;
> }
>
> - f2fs_folio_wait_writeback(folio, META, true, true);
> + f2fs_cache_wait_writeback(entry);
>
> - if (!folio_clear_dirty_for_io(folio))
> + if (!f2fs_clear_cache_dirty(entry))
> goto continue_unlock;
>
> - if (!__f2fs_write_meta_folio(folio, &wbc,
> - io_type)) {
> - folio_unlock(folio);
> + if (!__f2fs_write_meta_cache(entry, io_type)) {
> + f2fs_unlock_cache(entry);
> break;
> }
> - nwritten += folio_nr_pages(folio);
> - prev = folio->index;
> + nwritten += sbi->blocksize;
> + prev = entry->index;
> if (unlikely(nwritten >= nr_to_write))
> break;
> }
> - folio_batch_release(&fbatch);
> + f2fs_cache_gang_release(entries, nr);
> cond_resched();
> }
> stop:
> @@ -674,29 +666,6 @@ long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, long nr_to_write,
> return nwritten;
> }
>
> -static bool f2fs_dirty_meta_folio(struct address_space *mapping,
> - struct folio *folio)
> -{
> - trace_f2fs_set_page_dirty(folio, META);
> -
> - if (!folio_test_uptodate(folio))
> - folio_mark_uptodate(folio);
> - if (filemap_dirty_folio(mapping, folio)) {
> - inc_page_count(F2FS_M_SB(mapping), F2FS_DIRTY_META);
> - folio_set_f2fs_reference(folio);
> - return true;
> - }
> - return false;
> -}
> -
> -const struct address_space_operations f2fs_meta_aops = {
> - .writepages = f2fs_write_meta_pages,
> - .dirty_folio = f2fs_dirty_meta_folio,
> - .invalidate_folio = f2fs_invalidate_folio,
> - .release_folio = f2fs_release_folio,
> - .migrate_folio = filemap_migrate_folio,
> -};
> -
> static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino,
> unsigned int devidx, int type)
> {
> @@ -1036,20 +1005,20 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
> start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi);
> orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi);
>
> - f2fs_ra_meta_pages(sbi, start_blk, orphan_blocks, META_CP, true);
> + f2fs_ra_meta_caches(sbi, start_blk, orphan_blocks, META_CP, true);
>
> for (i = 0; i < orphan_blocks; i++) {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> struct f2fs_orphan_block *orphan_blk;
> unsigned int entry_count;
>
> - folio = f2fs_get_meta_folio(sbi, start_blk + i);
> - if (IS_ERR(folio)) {
> - err = PTR_ERR(folio);
> + entry = f2fs_get_meta_cache(sbi, start_blk + i);
> + if (IS_ERR(entry)) {
> + err = PTR_ERR(entry);
> goto out;
> }
>
> - orphan_blk = folio_address(folio);
> + orphan_blk = cache_address(entry);
> entry_count = le32_to_cpu(orphan_blk->entry_count);
> if (entry_count > F2FS_ORPHANS_PER_BLOCK) {
> f2fs_err(sbi, "invalid orphan inode entry count %u",
> @@ -1057,7 +1026,7 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
> set_sbi_flag(sbi, SBI_NEED_FSCK);
> f2fs_handle_error(sbi, ERROR_INCONSISTENT_ORPHAN);
> err = -EFSCORRUPTED;
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> goto out;
> }
>
> @@ -1066,11 +1035,11 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
>
> err = recover_orphan_inode(sbi, ino);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> goto out;
> }
> }
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> }
> /* clear Orphan Flag */
> clear_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG);
> @@ -1087,9 +1056,9 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
> unsigned int nentries = 0;
> unsigned short index = 1;
> unsigned short orphan_blocks;
> - struct folio *folio = NULL;
> struct ino_entry *orphan = NULL;
> struct inode_management *im = &sbi->im[ORPHAN_INO];
> + struct f2fs_cached_block *entry = NULL;
>
> orphan_blocks = GET_ORPHAN_BLOCKS(im->ino_num);
>
> @@ -1102,9 +1071,9 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
>
> /* loop for each orphan inode entry and write them in journal block */
> list_for_each_entry(orphan, head, list) {
> - if (!folio) {
> - folio = f2fs_grab_meta_folio(sbi, start_blk++);
> - orphan_blk = folio_address(folio);
> + if (!entry) {
> + entry = f2fs_grab_meta_cache(sbi, start_blk++);
> + orphan_blk = (struct f2fs_orphan_block *)cache_address(entry);
> memset(orphan_blk, 0, sizeof(*orphan_blk));
> }
>
> @@ -1119,20 +1088,20 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
> orphan_blk->blk_addr = cpu_to_le16(index);
> orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
> orphan_blk->entry_count = cpu_to_le32(nentries);
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> index++;
> nentries = 0;
> - folio = NULL;
> + entry = NULL;
> }
> }
>
> - if (folio) {
> + if (entry) {
> orphan_blk->blk_addr = cpu_to_le16(index);
> orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
> orphan_blk->entry_count = cpu_to_le32(nentries);
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> }
> }
>
> @@ -1151,29 +1120,29 @@ static __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *ckpt)
> }
>
> static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
> - struct f2fs_checkpoint **cp_block, struct folio **cp_folio,
> + struct f2fs_checkpoint **cp_block, struct f2fs_cached_block **cp_entry,
> unsigned long long *version)
> {
> size_t crc_offset = 0;
> __u32 crc;
>
> - *cp_folio = f2fs_get_meta_folio(sbi, cp_addr);
> - if (IS_ERR(*cp_folio))
> - return PTR_ERR(*cp_folio);
> + *cp_entry = f2fs_get_meta_cache(sbi, cp_addr);
> + if (IS_ERR(*cp_entry))
> + return PTR_ERR(*cp_entry);
>
> - *cp_block = folio_address(*cp_folio);
> + *cp_block = (struct f2fs_checkpoint *)cache_address(*cp_entry);
>
> crc_offset = le32_to_cpu((*cp_block)->checksum_offset);
> if (crc_offset < CP_MIN_CHKSUM_OFFSET ||
> crc_offset > CP_CHKSUM_OFFSET) {
> - f2fs_folio_put(*cp_folio, true);
> + f2fs_put_cache(*cp_entry, true);
> f2fs_warn(sbi, "invalid crc_offset: %zu", crc_offset);
> return -EINVAL;
> }
>
> crc = f2fs_checkpoint_chksum(*cp_block);
> if (crc != cur_cp_crc(*cp_block)) {
> - f2fs_folio_put(*cp_folio, true);
> + f2fs_put_cache(*cp_entry, true);
> f2fs_warn(sbi, "invalid crc value");
> return -EINVAL;
> }
> @@ -1182,17 +1151,17 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
> return 0;
> }
>
> -static struct folio *validate_checkpoint(struct f2fs_sb_info *sbi,
> +static struct f2fs_cached_block *validate_checkpoint(struct f2fs_sb_info *sbi,
> block_t cp_addr, unsigned long long *version)
> {
> - struct folio *cp_folio_1 = NULL, *cp_folio_2 = NULL;
> + struct f2fs_cached_block *cp_entry_1 = NULL, *cp_entry_2 = NULL;
> struct f2fs_checkpoint *cp_block = NULL;
> unsigned long long cur_version = 0, pre_version = 0;
> unsigned int cp_blocks;
> int err;
>
> err = get_checkpoint_version(sbi, cp_addr, &cp_block,
> - &cp_folio_1, version);
> + &cp_entry_1, version);
> if (err)
> return NULL;
>
> @@ -1207,19 +1176,20 @@ static struct folio *validate_checkpoint(struct f2fs_sb_info *sbi,
>
> cp_addr += cp_blocks - 1;
> err = get_checkpoint_version(sbi, cp_addr, &cp_block,
> - &cp_folio_2, version);
> + &cp_entry_2, version);
> if (err)
> goto invalid_cp;
> cur_version = *version;
>
> if (cur_version == pre_version) {
> *version = cur_version;
> - f2fs_folio_put(cp_folio_2, true);
> - return cp_folio_1;
> + f2fs_put_cache(cp_entry_2, true);
> + return cp_entry_1;
> }
> - f2fs_folio_put(cp_folio_2, true);
> + f2fs_put_cache(cp_entry_2, true);
> invalid_cp:
> - f2fs_folio_put(cp_folio_1, true);
> + if (cp_entry_1)
> + f2fs_put_cache(cp_entry_1, true);
> return NULL;
> }
>
> @@ -1227,7 +1197,7 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
> {
> struct f2fs_checkpoint *cp_block;
> struct f2fs_super_block *fsb = sbi->raw_super;
> - struct folio *cp1, *cp2, *cur_folio;
> + struct f2fs_cached_block *cp1 = NULL, *cp2 = NULL, *cur_entry;
> unsigned long blk_size = sbi->blocksize;
> unsigned long long cp1_version = 0, cp2_version = 0;
> unsigned long long cp_start_blk_no;
> @@ -1254,22 +1224,22 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
>
> if (cp1 && cp2) {
> if (ver_after(cp2_version, cp1_version))
> - cur_folio = cp2;
> + cur_entry = cp2;
> else
> - cur_folio = cp1;
> + cur_entry = cp1;
> } else if (cp1) {
> - cur_folio = cp1;
> + cur_entry = cp1;
> } else if (cp2) {
> - cur_folio = cp2;
> + cur_entry = cp2;
> } else {
> err = -EFSCORRUPTED;
> goto fail_no_cp;
> }
>
> - cp_block = folio_address(cur_folio);
> + cp_block = (struct f2fs_checkpoint *)cache_address(cur_entry);
> memcpy(sbi->ckpt, cp_block, blk_size);
>
> - if (cur_folio == cp1)
> + if (cur_entry == cp1)
> sbi->cur_cp_pack = 1;
> else
> sbi->cur_cp_pack = 2;
> @@ -1284,30 +1254,35 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
> goto done;
>
> cp_blk_no = le32_to_cpu(fsb->cp_blkaddr);
> - if (cur_folio == cp2)
> + if (cur_entry == cp2)
> cp_blk_no += BIT(le32_to_cpu(fsb->log_blocks_per_seg));
>
> for (i = 1; i < cp_blks; i++) {
> + struct f2fs_cached_block *cur_entry_payload;
> void *sit_bitmap_ptr;
> unsigned char *ckpt = (unsigned char *)sbi->ckpt;
>
> - cur_folio = f2fs_get_meta_folio(sbi, cp_blk_no + i);
> - if (IS_ERR(cur_folio)) {
> - err = PTR_ERR(cur_folio);
> + cur_entry_payload = f2fs_get_meta_cache(sbi, cp_blk_no + i);
> + if (IS_ERR(cur_entry_payload)) {
> + err = PTR_ERR(cur_entry_payload);
> goto free_fail_no_cp;
> }
> - sit_bitmap_ptr = folio_address(cur_folio);
> + sit_bitmap_ptr = cache_address(cur_entry_payload);
> memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
> - f2fs_folio_put(cur_folio, true);
> + f2fs_put_cache(cur_entry_payload, true);
> }
> done:
> - f2fs_folio_put(cp1, true);
> - f2fs_folio_put(cp2, true);
> + if (cp1)
> + f2fs_put_cache(cp1, true);
In f2fs_put_cache(x, y),
if (!x)
return;
> + if (cp2)
> + f2fs_put_cache(cp2, true);
> return 0;
>
> free_fail_no_cp:
> - f2fs_folio_put(cp1, true);
> - f2fs_folio_put(cp2, true);
> + if (cp1)
> + f2fs_put_cache(cp1, true);
> + if (cp2)
> + f2fs_put_cache(cp2, true);
> fail_no_cp:
> kvfree(sbi->ckpt);
> return err;
> @@ -1621,7 +1596,7 @@ void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type)
> break;
>
> if (type == F2FS_DIRTY_META)
> - f2fs_sync_meta_pages(sbi, LONG_MAX, FS_CP_META_IO);
> + f2fs_sync_meta_caches(sbi, LONG_MAX, true, FS_META_IO);
> else if (type == F2FS_WB_CP_DATA)
> f2fs_submit_merged_write(sbi, DATA);
>
> @@ -1700,31 +1675,24 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> static void commit_checkpoint(struct f2fs_sb_info *sbi,
> void *src, block_t blk_addr)
> {
> - struct writeback_control wbc = {};
> -
> - /*
> - * filemap_get_folios_tag and folio_lock again will take
> - * some extra time. Therefore, f2fs_update_meta_pages and
> - * f2fs_sync_meta_pages are combined in this function.
> - */
> - struct folio *folio = f2fs_grab_meta_folio(sbi, blk_addr);
> + struct f2fs_cached_block *entry = f2fs_grab_meta_cache(sbi, blk_addr);
>
> - memcpy(folio_address(folio), src, PAGE_SIZE);
> + memcpy(cache_address(entry), src, F2FS_BLKSIZE);
>
> - folio_mark_dirty(folio);
> - if (unlikely(!folio_clear_dirty_for_io(folio)))
> + f2fs_mark_cache_dirty(entry);
> + if (unlikely(!f2fs_clear_cache_dirty(entry)))
> f2fs_bug_on(sbi, 1);
>
> /* writeout cp pack 2 page */
> - if (unlikely(!__f2fs_write_meta_folio(folio, &wbc, FS_CP_META_IO))) {
> + if (unlikely(!__f2fs_write_meta_cache(entry, FS_CP_META_IO))) {
> if (f2fs_cp_error(sbi)) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> return;
> }
> f2fs_bug_on(sbi, true);
> }
>
> - f2fs_folio_put(folio, false);
> + f2fs_put_cache(entry, false);
>
> /* submit checkpoint (with barrier if NOBARRIER is not set) */
> f2fs_submit_merged_write(sbi, META_FLUSH);
> @@ -1793,7 +1761,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> int err;
>
> /* Flush all the NAT/SIT pages */
> - f2fs_sync_meta_pages(sbi, LONG_MAX, FS_CP_META_IO);
> + f2fs_sync_meta_caches(sbi, LONG_MAX, true, FS_CP_META_IO);
>
> stat_cp_time(cpc, CP_TIME_SYNC_META);
>
> @@ -1892,7 +1860,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> }
>
> /* Here, we have one bio having CP pack except cp pack 2 page */
> - f2fs_sync_meta_pages(sbi, LONG_MAX, FS_CP_META_IO);
> + f2fs_sync_meta_caches(sbi, LONG_MAX, true, FS_CP_META_IO);
> stat_cp_time(cpc, CP_TIME_SYNC_CP_META);
>
> /* Wait for all dirty meta pages to be submitted for IO */
> @@ -1919,10 +1887,10 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> * used for migration of encrypted, verity or compressed inode's blocks.
> */
> if (f2fs_sb_has_encrypt(sbi) || f2fs_sb_has_verity(sbi) ||
> - f2fs_sb_has_compression(sbi))
> - f2fs_bug_on(sbi,
> - invalidate_inode_pages2_range(META_MAPPING(sbi),
> - MAIN_BLKADDR(sbi), MAX_BLKADDR(sbi) - 1));
> + f2fs_sb_has_compression(sbi)) {
> + f2fs_truncate_meta_caches(sbi, MAIN_BLKADDR(sbi),
> + MAX_BLKADDR(sbi) - MAIN_BLKADDR(sbi));
> + }
>
> f2fs_release_ino_entry(sbi, false);
>
> diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
> index 91855d91bbdd..bb749f6257a1 100644
> --- a/fs/f2fs/compress.c
> +++ b/fs/f2fs/compress.c
> @@ -1150,7 +1150,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
> f2fs_compress_ctx_add_page(cc, folio);
>
> if (!folio_test_uptodate(folio)) {
> - f2fs_handle_page_eio(sbi, folio, DATA);
> + f2fs_handle_page_eio(sbi, folio->index, DATA);
> release_and_retry:
> f2fs_put_rpages(cc);
> f2fs_unlock_rpages(cc, i + 1);
> @@ -1359,7 +1359,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
> fio.old_blkaddr = data_blkaddr(dn.inode, dn.node_folio,
> dn.ofs_in_node + i + 1);
>
> - /* wait for GCed page writeback via META_MAPPING */
> + /* wait for GCed page writeback via generic cache */
> f2fs_wait_on_block_writeback(inode, fio.old_blkaddr);
>
> if (fio.encrypted) {
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 110282bb8dcd..92c3293f0a1e 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -65,8 +65,7 @@ bool f2fs_is_cp_guaranteed(const struct folio *folio)
>
> inode = mapping->host;
>
> - if (inode->i_ino == F2FS_META_INO(sbi) ||
> - inode->i_ino == F2FS_NODE_INO(sbi) ||
> + if (inode->i_ino == F2FS_NODE_INO(sbi) ||
> S_ISDIR(inode->i_mode))
> return true;
>
> @@ -84,9 +83,6 @@ static enum count_type __read_io_type(struct folio *folio)
> struct inode *inode = mapping->host;
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
>
> - if (inode->i_ino == F2FS_META_INO(sbi))
> - return F2FS_RD_META;
> -
> if (inode->i_ino == F2FS_NODE_INO(sbi))
> return F2FS_RD_NODE;
> }
> @@ -1452,7 +1448,7 @@ static void f2fs_submit_page_read(struct inode *inode, struct fsverity_info *vi,
> bio = f2fs_grab_read_bio(inode, vi, blkaddr, 1, op_flags, folio->index,
> for_write);
>
> - /* wait for GCed page writeback via META_MAPPING */
> + /* wait for GCed page writeback via generic cache */
> f2fs_wait_on_block_writeback(inode, blkaddr);
>
> if (!bio_add_folio(bio, folio, PAGE_SIZE, 0))
> @@ -3110,7 +3106,7 @@ static void f2fs_readahead(struct readahead_control *rac)
> int f2fs_encrypt_one_page(struct f2fs_io_info *fio)
> {
> struct inode *inode = fio_inode(fio);
> - struct folio *mfolio;
> + struct f2fs_cached_block *entry;
> struct page *page;
>
> if (!f2fs_encrypted_file(inode))
> @@ -3126,12 +3122,13 @@ int f2fs_encrypt_one_page(struct f2fs_io_info *fio)
> if (IS_ERR(fio->encrypted_page))
> return PTR_ERR(fio->encrypted_page);
>
> - mfolio = filemap_lock_folio(META_MAPPING(fio->sbi), fio->old_blkaddr);
> - if (!IS_ERR(mfolio)) {
> - if (folio_test_uptodate(mfolio))
> - memcpy(folio_address(mfolio),
> - page_address(fio->encrypted_page), PAGE_SIZE);
> - f2fs_folio_put(mfolio, true);
> + entry = f2fs_find_cache(META_CACHE(fio->sbi), fio->old_blkaddr);
> + if (!IS_ERR(entry)) {
> + f2fs_lock_cache(entry);
> + if (f2fs_cache_test_uptodate(entry))
> + memcpy(cache_address(entry), page_address(fio->encrypted_page),
> + F2FS_BLKSIZE);
> + f2fs_put_cache(entry, true);
> }
> return 0;
> }
> @@ -3297,7 +3294,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
> goto out_writepage;
> }
>
> - /* wait for GCed page writeback via META_MAPPING */
> + /* wait for GCed page writeback via generic cache */
> if (fio->meta_gc)
> f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);
>
> @@ -4380,9 +4377,7 @@ void f2fs_invalidate_folio(struct folio *folio, size_t offset, size_t length)
> return;
>
> if (folio_test_dirty(folio)) {
> - if (inode->i_ino == F2FS_META_INO(sbi)) {
> - dec_page_count(sbi, F2FS_DIRTY_META);
> - } else if (inode->i_ino == F2FS_NODE_INO(sbi)) {
> + if (inode->i_ino == F2FS_NODE_INO(sbi)) {
> dec_page_count(sbi, F2FS_DIRTY_NODES);
> } else {
> inode_dec_dirty_pages(inode);
> diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
> index ff379aff4472..14059a50739c 100644
> --- a/fs/f2fs/debug.c
> +++ b/fs/f2fs/debug.c
> @@ -224,8 +224,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
> si->dirty_count = dirty_segments(sbi);
> if (sbi->node_inode)
> si->node_pages = NODE_MAPPING(sbi)->nrpages;
> - if (sbi->meta_inode)
> - si->meta_pages = META_MAPPING(sbi)->nrpages;
> + si->meta_caches = META_CACHE(sbi)->num_entries;
> #ifdef CONFIG_F2FS_FS_COMPRESSION
> if (sbi->compress_inode) {
> si->compress_pages = COMPRESS_MAPPING(sbi)->nrpages;
> @@ -388,11 +387,8 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
>
> si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
> }
> - if (sbi->meta_inode) {
> - unsigned long npages = META_MAPPING(sbi)->nrpages;
> -
> - si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
> - }
> + si->page_mem += (unsigned long long)META_CACHE(sbi)->num_entries << PAGE_SHIFT;
> + si->cache_mem += META_CACHE(sbi)->num_entries * sizeof(struct f2fs_cached_block);
> #ifdef CONFIG_F2FS_FS_COMPRESSION
> if (sbi->compress_inode) {
> unsigned long npages = COMPRESS_MAPPING(sbi)->nrpages;
> @@ -708,7 +704,7 @@ static int stat_show(struct seq_file *s, void *v)
> seq_printf(s, " - quota data: %4d in quota files:%4d\n",
> si->ndirty_qdata, si->nquota_files);
> seq_printf(s, " - meta: %4d in %4d\n",
> - si->ndirty_meta, si->meta_pages);
> + si->ndirty_meta, si->meta_caches);
> seq_printf(s, " - imeta: %4d\n",
> si->ndirty_imeta);
> seq_printf(s, " - fsync mark: %4lld\n",
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 6e20b3586f26..9a353dcd6658 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1828,7 +1828,6 @@ struct f2fs_sb_info {
> struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */
> int cur_cp_pack; /* remain current cp pack */
> spinlock_t cp_lock; /* for flag in ckpt */
> - struct inode *meta_inode; /* cache meta blocks */
> struct f2fs_rwsem cp_global_sem; /* checkpoint procedure lock */
> struct f2fs_rwsem cp_rwsem; /* blocking FS operations */
> struct f2fs_rwsem node_write; /* locking node writes */
> @@ -1873,7 +1872,6 @@ struct f2fs_sb_info {
> unsigned int blocksize; /* block size */
> unsigned int root_ino_num; /* root inode number*/
> unsigned int node_ino_num; /* node inode number*/
> - unsigned int meta_ino_num; /* meta inode number*/
> unsigned int log_blocks_per_seg; /* log2 blocks per segment */
> unsigned int blocks_per_seg; /* blocks per segment */
> unsigned int segs_per_sec; /* segments per section */
> @@ -2319,9 +2317,9 @@ static inline struct dirty_seglist_info *DIRTY_I(struct f2fs_sb_info *sbi)
> return (struct dirty_seglist_info *)(SM_I(sbi)->dirty_info);
> }
>
> -static inline struct address_space *META_MAPPING(struct f2fs_sb_info *sbi)
> +static inline bool f2fs_is_meta_cache(struct f2fs_cached_block *entry)
> {
> - return sbi->meta_inode->i_mapping;
> + return entry->cache && entry->cache == META_CACHE(entry->cache->sbi);
> }
>
> static inline struct address_space *NODE_MAPPING(struct f2fs_sb_info *sbi)
> @@ -2329,11 +2327,6 @@ static inline struct address_space *NODE_MAPPING(struct f2fs_sb_info *sbi)
> return sbi->node_inode->i_mapping;
> }
>
> -static inline bool is_meta_folio(struct folio *folio)
> -{
> - return folio->mapping == META_MAPPING(F2FS_F_SB(folio));
> -}
> -
> static inline bool is_node_folio(struct folio *folio)
> {
> return folio->mapping == NODE_MAPPING(F2FS_F_SB(folio));
> @@ -4057,9 +4050,9 @@ bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid);
> void f2fs_alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid);
> void f2fs_alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid);
> int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink);
> -int f2fs_recover_inline_xattr(struct inode *inode, struct folio *folio);
> -int f2fs_recover_xattr_data(struct inode *inode, struct folio *folio);
> -int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio);
> +int f2fs_recover_inline_xattr(struct inode *inode, struct f2fs_cached_block *entry);
> +int f2fs_recover_xattr_data(struct inode *inode, struct f2fs_cached_block *entry);
> +int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct f2fs_cached_block *entry);
> int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
> unsigned int segno, struct f2fs_summary_block *sum);
> int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
> @@ -4109,11 +4102,13 @@ int f2fs_allocate_new_segments(struct f2fs_sb_info *sbi);
> int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range);
> bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi,
> struct cp_control *cpc);
> -struct folio *f2fs_get_sum_folio(struct f2fs_sb_info *sbi, unsigned int segno);
> +struct f2fs_cached_block *f2fs_get_sum_cache(struct f2fs_sb_info *sbi,
> + unsigned int segno);
> void f2fs_update_meta_page(struct f2fs_sb_info *sbi, void *src,
> block_t blk_addr);
> -void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct folio *folio,
> - enum iostat_type io_type);
> +void f2fs_do_write_meta_cache(struct f2fs_sb_info *sbi,
> + struct f2fs_cached_block *entry,
> + enum iostat_type io_type);
> void f2fs_do_write_node_page(unsigned int nid, struct f2fs_io_info *fio);
> void f2fs_outplace_write_data(struct dnode_of_data *dn,
> struct f2fs_io_info *fio);
> @@ -4136,8 +4131,6 @@ void f2fs_update_device_state(struct f2fs_sb_info *sbi, nid_t ino,
> block_t blkaddr, unsigned int blkcnt);
> void f2fs_folio_wait_writeback(struct folio *folio, enum page_type type,
> bool ordered, bool locked);
> -#define f2fs_wait_on_page_writeback(page, type, ordered, locked) \
> - f2fs_folio_wait_writeback(page_folio(page), type, ordered, locked)
> void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr);
> void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
> block_t len);
> @@ -4203,20 +4196,21 @@ void f2fs_unlock_op(struct f2fs_sb_info *sbi, struct f2fs_lock_context *lc);
> void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io,
> unsigned char reason);
> void f2fs_flush_ckpt_thread(struct f2fs_sb_info *sbi);
> -struct folio *f2fs_grab_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index);
> -struct folio *f2fs_get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index);
> -struct folio *f2fs_get_meta_folio_retry(struct f2fs_sb_info *sbi, pgoff_t index);
> -struct folio *f2fs_get_tmp_folio(struct f2fs_sb_info *sbi, pgoff_t index);
> +struct f2fs_cached_block *f2fs_grab_meta_cache(struct f2fs_sb_info *sbi, pgoff_t index);
> +struct f2fs_cached_block *f2fs_get_meta_cache(struct f2fs_sb_info *sbi, pgoff_t index);
> +struct f2fs_cached_block *f2fs_get_meta_cache_retry(struct f2fs_sb_info *sbi, pgoff_t index);
> +struct f2fs_cached_block *f2fs_get_tmp_cache(struct f2fs_sb_info *sbi, pgoff_t index);
> bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
> block_t blkaddr, int type);
> bool f2fs_is_valid_blkaddr_raw(struct f2fs_sb_info *sbi,
> block_t blkaddr, int type);
> -int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> +int f2fs_ra_meta_caches(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> int type, bool sync);
> -void f2fs_ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index,
> +void f2fs_ra_meta_caches_cond(struct f2fs_sb_info *sbi, pgoff_t index,
> unsigned int ra_blocks);
> -long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, long nr_to_write,
> - enum iostat_type io_type);
> +void f2fs_write_meta_caches(struct f2fs_sb_info *sbi);
> +long f2fs_sync_meta_caches(struct f2fs_sb_info *sbi, long nr_to_write,
> + bool sync, enum iostat_type io_type);
> void f2fs_add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type);
> void f2fs_remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type);
> void f2fs_release_ino_entry(struct f2fs_sb_info *sbi, bool all);
> @@ -4403,7 +4397,7 @@ struct f2fs_stat_info {
> unsigned int bimodal, avg_vblocks;
> int util_free, util_valid, util_invalid;
> int rsvd_segs, overp_segs;
> - int dirty_count, node_pages, meta_pages, compress_pages;
> + int dirty_count, node_pages, meta_caches, compress_pages;
> int compress_page_hit;
> int prefree_count, free_segs, free_secs;
> int cp_call_count[MAX_CALL_TYPE], cp_count;
> @@ -4605,7 +4599,6 @@ extern const struct file_operations f2fs_file_operations;
> extern const struct inode_operations f2fs_file_inode_operations;
> extern const struct address_space_operations f2fs_dblock_aops;
> extern const struct address_space_operations f2fs_node_aops;
> -extern const struct address_space_operations f2fs_meta_aops;
> extern const struct inode_operations f2fs_dir_inode_operations;
> extern const struct inode_operations f2fs_symlink_inode_operations;
> extern const struct inode_operations f2fs_encrypted_symlink_inode_operations;
> @@ -4626,7 +4619,7 @@ int f2fs_convert_inline_folio(struct dnode_of_data *dn, struct folio *folio);
> int f2fs_convert_inline_inode(struct inode *inode);
> int f2fs_try_convert_inline_dir(struct inode *dir, struct dentry *dentry);
> int f2fs_write_inline_data(struct inode *inode, struct folio *folio);
> -int f2fs_recover_inline_data(struct inode *inode, struct folio *nfolio);
> +int f2fs_recover_inline_data(struct inode *inode, struct f2fs_cached_block *entry);
> struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir,
> const struct f2fs_filename *fname, struct folio **res_folio,
> bool use_hash);
> @@ -5186,10 +5179,8 @@ static inline void f2fs_schedule_timeout_killable(long timeout, bool io)
> }
>
> static inline void f2fs_handle_page_eio(struct f2fs_sb_info *sbi,
> - struct folio *folio, enum page_type type)
> + pgoff_t ofs, enum page_type type)
> {
> - pgoff_t ofs = folio->index;
> -
> if (unlikely(f2fs_cp_error(sbi)))
> return;
>
> @@ -5224,36 +5215,10 @@ static inline bool f2fs_is_readonly(struct f2fs_sb_info *sbi)
> return f2fs_sb_has_readonly(sbi) || f2fs_readonly(sbi->sb);
> }
>
> -static inline void f2fs_truncate_meta_inode_pages(struct f2fs_sb_info *sbi,
> - block_t blkaddr, unsigned int cnt)
> -{
> - bool need_submit = false;
> - int i = 0;
> -
> - do {
> - struct folio *folio;
> -
> - folio = filemap_get_folio(META_MAPPING(sbi), blkaddr + i);
> - if (!IS_ERR(folio)) {
> - if (folio_test_writeback(folio))
> - need_submit = true;
> - f2fs_folio_put(folio, false);
> - }
> - } while (++i < cnt && !need_submit);
> -
> - if (need_submit)
> - f2fs_submit_merged_write_cond(sbi, sbi->meta_inode,
> - NULL, 0, DATA);
> -
> - truncate_inode_pages_range(META_MAPPING(sbi),
> - F2FS_BLK_TO_BYTES((loff_t)blkaddr),
> - F2FS_BLK_END_BYTES((loff_t)(blkaddr + cnt - 1)));
> -}
> -
> static inline void f2fs_invalidate_internal_cache(struct f2fs_sb_info *sbi,
> block_t blkaddr, unsigned int len)
> {
> - f2fs_truncate_meta_inode_pages(sbi, blkaddr, len);
> + f2fs_truncate_meta_caches(sbi, blkaddr, len);
> f2fs_invalidate_compress_pages_range(sbi, blkaddr, len);
> }
>
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index a54b3ab52f1a..92daa41dd96d 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -214,7 +214,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
>
> f2fs_folio_wait_writeback(folio, DATA, false, true);
>
> - /* wait for GCed page writeback via META_MAPPING */
> + /* wait for GCed page writeback via generic cache */
> f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);
>
> /*
> @@ -2563,7 +2563,7 @@ int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,
> f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
> break;
> case F2FS_GOING_DOWN_METAFLUSH:
> - f2fs_sync_meta_pages(sbi, LONG_MAX, FS_META_IO);
> + f2fs_sync_meta_caches(sbi, LONG_MAX, true, FS_META_IO);
> f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
> break;
> case F2FS_GOING_DOWN_NEED_FSCK:
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index c4da2f31805b..54327cb2e27e 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -1066,7 +1066,7 @@ static int gc_node_segment(struct f2fs_sb_info *sbi,
> continue;
>
> if (phase == 0) {
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
> + f2fs_ra_meta_caches(sbi, NAT_BLOCK_OFFSET(nid), 1,
> META_NAT, true);
> continue;
> }
> @@ -1217,7 +1217,8 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
> struct address_space *mapping = inode->i_mapping;
> struct inode *atomic_inode = NULL;
> struct dnode_of_data dn;
> - struct folio *folio, *efolio;
> + struct folio *folio;
> + struct f2fs_cached_block *entry;
> struct f2fs_io_info fio = {
> .sbi = sbi,
> .ino = inode->i_ino,
> @@ -1227,6 +1228,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
> .op_flags = 0,
> .encrypted_page = NULL,
> .in_list = 0,
> + .is_cache = 1,
> };
> int err = 0;
>
> @@ -1285,22 +1287,21 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
>
> f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);
>
> - efolio = f2fs_filemap_get_folio(META_MAPPING(sbi), dn.data_blkaddr,
> - FGP_LOCK | FGP_CREAT, GFP_NOFS);
> - if (IS_ERR(efolio)) {
> - err = PTR_ERR(efolio);
> + entry = f2fs_grab_cache(META_CACHE(sbi), dn.data_blkaddr,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(entry)) {
> + err = PTR_ERR(entry);
> goto put_folio;
> }
>
> - fio.encrypted_page = &efolio->page;
> -
> - if (folio_test_uptodate(efolio))
> - goto put_encrypted_page;
> + if (f2fs_cache_test_uptodate(entry))
> + goto put_cache;
>
> - err = f2fs_submit_page_bio(&fio);
> + fio.cache_entry = entry;
> + err = f2fs_submit_cache_read(&fio);
> if (err)
> - goto put_encrypted_page;
> - f2fs_put_page(fio.encrypted_page, false);
> + goto put_cache;
> + f2fs_put_cache(entry, false);
> f2fs_folio_put(folio, true);
>
> f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE);
> @@ -1309,8 +1310,8 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
> if (atomic_inode)
> iput(atomic_inode);
> return 0;
> -put_encrypted_page:
> - f2fs_put_page(fio.encrypted_page, true);
> +put_cache:
> + f2fs_put_cache(entry, true);
> put_folio:
> f2fs_folio_put(folio, true);
> out_iput:
> @@ -1320,7 +1321,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
> }
>
> /*
> - * Move data block via META_MAPPING while keeping locked data page.
> + * Move data block via meta cache while keeping locked data page.
> * This can be used to move blocks, aka LBAs, directly on disk.
> */
> static int move_data_block(struct inode *inode, block_t bidx,
> @@ -1337,11 +1338,13 @@ static int move_data_block(struct inode *inode, block_t bidx,
> .op_flags = 0,
> .encrypted_page = NULL,
> .in_list = 0,
> + .is_cache = 1,
> };
> struct dnode_of_data dn;
> struct f2fs_summary sum;
> struct node_info ni;
> - struct folio *folio, *mfolio, *efolio;
> + struct folio *folio;
> + struct f2fs_cached_block *sentry, *tentry;
> block_t newaddr;
> int err = 0;
> bool lfs_mode = f2fs_lfs_mode(fio.sbi);
> @@ -1406,20 +1409,20 @@ static int move_data_block(struct inode *inode, block_t bidx,
> if (lfs_mode)
> f2fs_down_write(&fio.sbi->io_order_lock);
>
> - mfolio = f2fs_grab_cache_folio(META_MAPPING(fio.sbi),
> - fio.old_blkaddr, false);
> - if (IS_ERR(mfolio)) {
> - err = PTR_ERR(mfolio);
> + sentry = f2fs_grab_cache(META_CACHE(fio.sbi), fio.old_blkaddr,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(sentry)) {
> + err = PTR_ERR(sentry);
> goto up_out;
> }
>
> - fio.encrypted_page = folio_file_page(mfolio, fio.old_blkaddr);
> + fio.cache_entry = sentry;
>
> - /* read source block in mfolio */
> - if (!folio_test_uptodate(mfolio)) {
> - err = f2fs_submit_page_bio(&fio);
> + /* read source block in cache */
> + if (!f2fs_cache_test_uptodate(sentry)) {
> + err = f2fs_submit_cache_read(&fio);
> if (err) {
> - f2fs_folio_put(mfolio, true);
> + f2fs_put_cache(sentry, true);
> goto up_out;
> }
>
> @@ -1428,11 +1431,11 @@ static int move_data_block(struct inode *inode, block_t bidx,
> f2fs_update_iostat(fio.sbi, NULL, FS_GDATA_READ_IO,
> F2FS_BLKSIZE);
>
> - folio_lock(mfolio);
> - if (unlikely(!is_meta_folio(mfolio) ||
> - !folio_test_uptodate(mfolio))) {
> + f2fs_lock_cache(sentry);
> + if (unlikely(!f2fs_is_meta_cache(sentry) ||
> + !f2fs_cache_test_uptodate(sentry))) {
> err = -EIO;
> - f2fs_folio_put(mfolio, true);
> + f2fs_put_cache(sentry, true);
> goto up_out;
> }
> }
> @@ -1443,46 +1446,45 @@ static int move_data_block(struct inode *inode, block_t bidx,
> err = f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
> &sum, type, NULL);
> if (err) {
> - f2fs_folio_put(mfolio, true);
> + f2fs_put_cache(sentry, true);
> /* filesystem should shutdown, no need to recovery block */
> goto up_out;
> }
>
> - efolio = f2fs_filemap_get_folio(META_MAPPING(fio.sbi), newaddr,
> - FGP_LOCK | FGP_CREAT, GFP_NOFS);
> - if (IS_ERR(efolio)) {
> - err = PTR_ERR(efolio);
> - f2fs_folio_put(mfolio, true);
> + tentry = f2fs_grab_cache(META_CACHE(fio.sbi), newaddr,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(tentry)) {
> + err = PTR_ERR(tentry);
> + f2fs_put_cache(sentry, true);
> goto recover_block;
> }
>
> - fio.encrypted_page = &efolio->page;
> + fio.cache_entry = tentry;
>
> /* write target block */
> - f2fs_wait_on_page_writeback(fio.encrypted_page, DATA, true, true);
> - memcpy(page_address(fio.encrypted_page),
> - folio_address(mfolio), PAGE_SIZE);
> - f2fs_folio_put(mfolio, true);
> + f2fs_cache_wait_writeback_cond(tentry, DATA);
> + memcpy(cache_address(tentry), cache_address(sentry), PAGE_SIZE);
> + f2fs_put_cache(sentry, true);
>
> f2fs_invalidate_internal_cache(fio.sbi, fio.old_blkaddr, 1);
>
> - set_page_dirty(fio.encrypted_page);
> - if (clear_page_dirty_for_io(fio.encrypted_page))
> + f2fs_mark_cache_dirty(tentry);
> + if (f2fs_clear_cache_dirty(tentry))
> dec_page_count(fio.sbi, F2FS_DIRTY_META);
>
> - set_page_writeback(fio.encrypted_page);
> + f2fs_start_cache_writeback(tentry);
>
> fio.op = REQ_OP_WRITE;
> fio.op_flags = REQ_SYNC;
> fio.new_blkaddr = newaddr;
> - f2fs_submit_page_write(&fio);
> + f2fs_submit_cache_write(&fio);
>
> f2fs_update_iostat(fio.sbi, NULL, FS_GC_DATA_IO, F2FS_BLKSIZE);
>
> f2fs_update_data_blkaddr(&dn, newaddr);
> set_inode_flag(inode, FI_APPEND_WRITE);
>
> - f2fs_put_page(fio.encrypted_page, true);
> + f2fs_put_cache(tentry, true);
> recover_block:
> if (err)
> f2fs_do_replace_block(fio.sbi, &sum, newaddr, fio.old_blkaddr,
> @@ -1614,7 +1616,7 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
> continue;
>
> if (phase == 0) {
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
> + f2fs_ra_meta_caches(sbi, NAT_BLOCK_OFFSET(nid), 1,
> META_NAT, true);
> continue;
> }
> @@ -1818,28 +1820,31 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, sbi->sums_per_block);
> /* readahead multi ssa blocks those have contiguous address */
> if (__is_large_section(sbi))
> - f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
> + f2fs_ra_meta_caches(sbi, GET_SUM_BLOCK(sbi, segno),
> sum_blk_cnt, META_SSA, true);
>
> /* reference all summary page */
> while (segno < end_segno) {
> - struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno);
> + struct f2fs_cached_block *sum_entry =
> + f2fs_get_sum_cache(sbi, segno);
>
> segno += sbi->sums_per_block;
> - if (IS_ERR(sum_folio)) {
> - int err = PTR_ERR(sum_folio);
> + if (IS_ERR(sum_entry)) {
> + int err = PTR_ERR(sum_entry);
>
> end_segno = segno - sbi->sums_per_block;
> segno = rounddown(start_segno, sbi->sums_per_block);
> while (segno < end_segno) {
> - sum_folio = filemap_get_folio(META_MAPPING(sbi),
> + sum_entry = f2fs_find_meta_cache(sbi,
> GET_SUM_BLOCK(sbi, segno));
> - folio_put_refs(sum_folio, 2);
> + f2fs_put_cache(sum_entry, false);
> + f2fs_put_cache(sum_entry, false);
> segno += sbi->sums_per_block;
> }
> return err;
> }
> - folio_unlock(sum_folio);
> + f2fs_unlock_cache(sum_entry);
> +
> }
>
> blk_start_plug(&plug);
> @@ -1847,11 +1852,16 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> segno = start_segno;
> while (segno < end_segno) {
> unsigned int cur_segno;
> + unsigned int block_end_segno;
>
> /* find segment summary of victim */
> - struct folio *sum_folio = filemap_get_folio(META_MAPPING(sbi),
> + struct f2fs_cached_block *sum_entry =
> + f2fs_find_meta_cache(sbi,
> GET_SUM_BLOCK(sbi, segno));
> - unsigned int block_end_segno = rounddown(segno, sbi->sums_per_block)
> +
> + f2fs_bug_on(sbi, IS_ERR(sum_entry));
> +
> + block_end_segno = rounddown(segno, sbi->sums_per_block)
> + sbi->sums_per_block;
>
> if (block_end_segno > end_segno)
> @@ -1864,8 +1874,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> goto next_block;
> }
>
> - if (!folio_test_uptodate(sum_folio) ||
> - unlikely(f2fs_cp_error(sbi)))
> + if (!f2fs_cache_test_uptodate(sum_entry) ||
> + unlikely(f2fs_cp_error(sbi)))
> goto next_block;
>
> for (cur_segno = segno; cur_segno < block_end_segno;
> @@ -1884,7 +1894,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> data_type = (type == SUM_TYPE_DATA) ? DATA : NODE;
> }
>
> - sum = SUM_BLK_PAGE_ADDR(sbi, sum_folio, cur_segno);
> + sum = SUM_BLK_ENTRY_ADDR(sbi, sum_entry, cur_segno);
> if (type != GET_SUM_TYPE(sum_footer(sbi, sum))) {
> f2fs_err(sbi, "Inconsistent segment (%u) type "
> "[%d, %d] in SIT and SSA",
> @@ -1926,12 +1936,14 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> cur_segno + 1 : NULL_SEGNO;
>
> if (unlikely(freezing(current))) {
> - folio_put_refs(sum_folio, 2);
> + f2fs_put_cache(sum_entry, false);
> + f2fs_put_cache(sum_entry, false);
> goto stop;
> }
> }
> next_block:
> - folio_put_refs(sum_folio, 2);
> + f2fs_put_cache(sum_entry, false);
> + f2fs_put_cache(sum_entry, false);
> segno = block_end_segno;
> }
>
> diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
> index aec06fb4fd76..2156fb1fc57d 100644
> --- a/fs/f2fs/inline.c
> +++ b/fs/f2fs/inline.c
> @@ -294,7 +294,7 @@ int f2fs_write_inline_data(struct inode *inode, struct folio *folio)
> return 0;
> }
>
> -int f2fs_recover_inline_data(struct inode *inode, struct folio *nfolio)
> +int f2fs_recover_inline_data(struct inode *inode, struct f2fs_cached_block *entry)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> struct f2fs_inode *ri = NULL;
> @@ -308,12 +308,13 @@ int f2fs_recover_inline_data(struct inode *inode, struct folio *nfolio)
> * x o -> remove data blocks, and then recover inline_data
> * x x -> recover data blocks
> */
> - if (IS_INODE(nfolio))
> - ri = F2FS_INODE(nfolio);
> + if (IS_INODE(cache_folio(entry)))
> + ri = &CACHED_NODE(entry)->i;
>
> if (f2fs_has_inline_data(inode) &&
> ri && (ri->i_inline & F2FS_INLINE_DATA)) {
> struct folio *ifolio;
> +
> process_inline:
> ifolio = f2fs_get_inode_folio(sbi, inode->i_ino);
> if (IS_ERR(ifolio))
> @@ -321,7 +322,7 @@ int f2fs_recover_inline_data(struct inode *inode, struct folio *nfolio)
>
> f2fs_folio_wait_writeback(ifolio, NODE, true, true);
>
> - src_addr = inline_data_addr(inode, nfolio);
> + src_addr = inline_data_addr(inode, cache_folio(entry));
> dst_addr = inline_data_addr(inode, ifolio);
> memcpy(dst_addr, src_addr, MAX_INLINE_DATA(inode));
>
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index bac1e360d966..c533da4d4d70 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -577,7 +577,7 @@ static int do_read_inode(struct inode *inode)
>
> static bool is_meta_ino(struct f2fs_sb_info *sbi, unsigned int ino)
> {
> - if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi))
> + if (ino == F2FS_NODE_INO(sbi))
> return true;
> #ifdef CONFIG_F2FS_FS_COMPRESSION
> if (test_opt(sbi, COMPRESS_CACHE) && ino == F2FS_COMPRESS_INO(sbi))
> @@ -624,9 +624,6 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
> if (ino == F2FS_NODE_INO(sbi)) {
> inode->i_mapping->a_ops = &f2fs_node_aops;
> mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
> - } else if (ino == F2FS_META_INO(sbi)) {
> - inode->i_mapping->a_ops = &f2fs_meta_aops;
> - mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
> } else if (ino == F2FS_COMPRESS_INO(sbi)) {
> #ifdef CONFIG_F2FS_FS_COMPRESSION
> inode->i_mapping->a_ops = &f2fs_compress_aops;
> @@ -824,8 +821,7 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
>
> - if (inode->i_ino == F2FS_NODE_INO(sbi) ||
> - inode->i_ino == F2FS_META_INO(sbi))
> + if (inode->i_ino == F2FS_NODE_INO(sbi))
> return 0;
>
> /*
> @@ -919,7 +915,6 @@ static bool f2fs_pre_evict_inode(struct inode *inode)
> f2fs_invalidate_compress_pages(sbi, inode->i_ino);
>
> if (inode->i_ino == F2FS_NODE_INO(sbi) ||
> - inode->i_ino == F2FS_META_INO(sbi) ||
> inode->i_ino == F2FS_COMPRESS_INO(sbi))
> return true;
>
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 46bea52e35c3..398c58fc6cad 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -140,38 +140,36 @@ static void clear_node_folio_dirty(struct folio *folio)
> folio_clear_uptodate(folio);
> }
>
> -static struct folio *get_current_nat_folio(struct f2fs_sb_info *sbi, nid_t nid)
> +static struct f2fs_cached_block *get_current_nat_cache(struct f2fs_sb_info *sbi,
> + nid_t nid)
> {
> - return f2fs_get_meta_folio_retry(sbi, current_nat_addr(sbi, nid));
> + return f2fs_get_meta_cache_retry(sbi, current_nat_addr(sbi, nid));
> }
>
> -static struct folio *get_next_nat_folio(struct f2fs_sb_info *sbi, nid_t nid)
> +static struct f2fs_cached_block *get_next_nat_cache(struct f2fs_sb_info *sbi,
> + nid_t nid)
> {
> - struct folio *src_folio;
> - struct folio *dst_folio;
> + struct f2fs_cached_block *src_entry;
> + struct f2fs_cached_block *dst_entry;
> pgoff_t dst_off;
> - void *src_addr;
> - void *dst_addr;
> struct f2fs_nm_info *nm_i = NM_I(sbi);
>
> dst_off = next_nat_addr(sbi, current_nat_addr(sbi, nid));
>
> /* get current nat block page with lock */
> - src_folio = get_current_nat_folio(sbi, nid);
> - if (IS_ERR(src_folio))
> - return src_folio;
> - dst_folio = f2fs_grab_meta_folio(sbi, dst_off);
> - f2fs_bug_on(sbi, folio_test_dirty(src_folio));
> -
> - src_addr = folio_address(src_folio);
> - dst_addr = folio_address(dst_folio);
> - memcpy(dst_addr, src_addr, PAGE_SIZE);
> - folio_mark_dirty(dst_folio);
> - f2fs_folio_put(src_folio, true);
> + src_entry = get_current_nat_cache(sbi, nid);
> + if (IS_ERR(src_entry))
> + return src_entry;
> + dst_entry = f2fs_grab_meta_cache(sbi, dst_off);
> + f2fs_bug_on(sbi, f2fs_cache_test_dirty(src_entry));
> +
> + memcpy(cache_address(dst_entry), cache_address(src_entry), sbi->blocksize);
> + f2fs_mark_cache_dirty(dst_entry);
> + f2fs_put_cache(src_entry, true);
>
> set_to_next_nat(nm_i, nid);
>
> - return dst_folio;
> + return dst_entry;
> }
>
> static struct nat_entry *__alloc_nat_entry(struct f2fs_sb_info *sbi,
> @@ -575,7 +573,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
> struct f2fs_journal *journal = curseg->journal;
> nid_t start_nid = START_NID(nid);
> struct f2fs_nat_block *nat_blk;
> - struct folio *folio = NULL;
> + struct f2fs_cached_block *entry = NULL;
> struct f2fs_nat_entry ne;
> struct nat_entry *e;
> pgoff_t index;
> @@ -629,14 +627,14 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
> index = current_nat_addr(sbi, nid);
> f2fs_up_read(&nm_i->nat_tree_lock);
>
> - folio = f2fs_get_meta_folio(sbi, index);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + entry = f2fs_get_meta_cache(sbi, index);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
>
> - nat_blk = folio_address(folio);
> + nat_blk = cache_address(entry);
> ne = nat_blk->entries[nid - start_nid];
> node_info_from_raw_nat(ni, &ne);
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> sanity_check:
> if (__is_valid_data_blkaddr(ni->blk_addr) &&
> !f2fs_is_valid_blkaddr(sbi, ni->blk_addr,
> @@ -1622,7 +1620,7 @@ static struct folio *__get_node_folio(struct f2fs_sb_info *sbi, pgoff_t nid,
> out_put_err:
> /* ENOENT comes from read_node_folio which is not an error. */
> if (err != -ENOENT)
> - f2fs_handle_page_eio(sbi, folio, NODE);
> + f2fs_handle_page_eio(sbi, folio->index, NODE);
> f2fs_folio_put(folio, true);
> return ERR_PTR(err);
> }
> @@ -2598,6 +2596,7 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
> bool sync, bool mount)
> {
> struct f2fs_nm_info *nm_i = NM_I(sbi);
> + struct f2fs_cached_block *entry = NULL;
> int i = 0, ret;
> nid_t nid = nm_i->next_scan_nid;
>
> @@ -2623,7 +2622,7 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
> }
>
> /* readahead nat pages to be scanned */
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
> + f2fs_ra_meta_caches(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
> META_NAT, true);
>
> f2fs_down_read(&nm_i->nat_tree_lock);
> @@ -2631,14 +2630,14 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
> while (1) {
> if (!test_bit_le(NAT_BLOCK_OFFSET(nid),
> nm_i->nat_block_bitmap)) {
> - struct folio *folio = get_current_nat_folio(sbi, nid);
> + entry = get_current_nat_cache(sbi, nid);
>
> - if (IS_ERR(folio)) {
> - ret = PTR_ERR(folio);
> + if (IS_ERR(entry)) {
> + ret = PTR_ERR(entry);
> } else {
> - ret = scan_nat_page(sbi, folio_address(folio),
> + ret = scan_nat_page(sbi, cache_address(entry),
> nid);
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> }
>
> if (ret) {
> @@ -2671,7 +2670,7 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
>
> f2fs_up_read(&nm_i->nat_tree_lock);
>
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
> + f2fs_ra_meta_caches(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
> nm_i->ra_nid_pages, META_NAT, false);
>
> return 0;
> @@ -2826,7 +2825,7 @@ int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink)
> return nr - nr_shrink;
> }
>
> -int f2fs_recover_inline_xattr(struct inode *inode, struct folio *folio)
> +int f2fs_recover_inline_xattr(struct inode *inode, struct f2fs_cached_block *entry)
> {
> void *src_addr, *dst_addr;
> size_t inline_size;
> @@ -2837,7 +2836,7 @@ int f2fs_recover_inline_xattr(struct inode *inode, struct folio *folio)
> if (IS_ERR(ifolio))
> return PTR_ERR(ifolio);
>
> - ri = F2FS_INODE(folio);
> + ri = &CACHED_NODE(entry)->i;
> if (ri->i_inline & F2FS_INLINE_XATTR) {
> if (!f2fs_has_inline_xattr(inode)) {
> set_inode_flag(inode, FI_INLINE_XATTR);
> @@ -2852,7 +2851,7 @@ int f2fs_recover_inline_xattr(struct inode *inode, struct folio *folio)
> }
>
> dst_addr = inline_xattr_addr(inode, ifolio);
> - src_addr = inline_xattr_addr(inode, folio);
> + src_addr = inline_xattr_addr(inode, cache_folio(entry));
> inline_size = inline_xattr_size(inode);
>
> f2fs_folio_wait_writeback(ifolio, NODE, true, true);
> @@ -2863,7 +2862,7 @@ int f2fs_recover_inline_xattr(struct inode *inode, struct folio *folio)
> return 0;
> }
>
> -int f2fs_recover_xattr_data(struct inode *inode, struct folio *folio)
> +int f2fs_recover_xattr_data(struct inode *inode, struct f2fs_cached_block *entry)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid;
> @@ -2901,8 +2900,8 @@ int f2fs_recover_xattr_data(struct inode *inode, struct folio *folio)
> f2fs_update_inode_page(inode);
>
> /* 3: update and set xattr node page dirty */
> - if (folio) {
> - memcpy(F2FS_NODE(xfolio), F2FS_NODE(folio),
> + if (entry) {
> + memcpy(F2FS_NODE(xfolio), CACHED_NODE(entry),
> VALID_XATTR_BLOCK_SIZE);
> folio_mark_dirty(xfolio);
> }
> @@ -2911,10 +2910,10 @@ int f2fs_recover_xattr_data(struct inode *inode, struct folio *folio)
> return 0;
> }
>
> -int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio)
> +int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct f2fs_cached_block *entry)
> {
> struct f2fs_inode *src, *dst;
> - nid_t ino = ino_of_node(folio);
> + nid_t ino = ino_of_node(cache_folio(entry));
> struct node_info old_ni, new_ni;
> struct folio *ifolio;
> int err;
> @@ -2940,7 +2939,7 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio)
> fill_node_footer(ifolio, ino, ino, 0, true);
> set_cold_node(ifolio, false);
>
> - src = F2FS_INODE(folio);
> + src = &CACHED_NODE(entry)->i;
> dst = F2FS_INODE(ifolio);
>
> memcpy(dst, src, offsetof(struct f2fs_inode, i_ext));
> @@ -2999,24 +2998,24 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
> nrpages = bio_max_segs(last_offset - i);
>
> /* readahead node pages */
> - f2fs_ra_meta_pages(sbi, addr, nrpages, META_POR, true);
> + f2fs_ra_meta_caches(sbi, addr, nrpages, META_POR, true);
>
> for (idx = addr; idx < addr + nrpages; idx++) {
> - struct folio *folio = f2fs_get_tmp_folio(sbi, idx);
> + struct f2fs_cached_block *entry =
> + f2fs_get_tmp_cache(sbi, idx);
>
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
>
> - rn = F2FS_NODE(folio);
> + rn = CACHED_NODE(entry);
> sum_entry->nid = rn->footer.nid;
> sum_entry->version = 0;
> sum_entry->ofs_in_node = 0;
> sum_entry++;
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> }
>
> - invalidate_mapping_pages(META_MAPPING(sbi), addr,
> - addr + nrpages);
> + f2fs_truncate_meta_caches(sbi, addr, nrpages);
> }
> return 0;
> }
> @@ -3126,7 +3125,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> bool to_journal = true;
> struct f2fs_nat_block *nat_blk;
> struct nat_entry *ne, *cur;
> - struct folio *folio = NULL;
> + struct f2fs_cached_block *entry = NULL;
>
> /*
> * there are two steps to flush nat entries:
> @@ -3140,11 +3139,11 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> if (to_journal) {
> down_write(&curseg->journal_rwsem);
> } else {
> - folio = get_next_nat_folio(sbi, start_nid);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + entry = get_next_nat_cache(sbi, start_nid);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
>
> - nat_blk = folio_address(folio);
> + nat_blk = cache_address(entry);
> f2fs_bug_on(sbi, !nat_blk);
> }
>
> @@ -3181,7 +3180,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> up_write(&curseg->journal_rwsem);
> } else {
> __update_nat_bits(sbi, start_nid, nat_blk);
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> }
>
> /* Allow dirty nats by node block allocation in write_begin */
> @@ -3252,7 +3251,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> __has_cursum_space(sbi, journal,
> entry_count, NAT_JOURNAL))
> continue;
> - f2fs_ra_meta_pages(sbi, set->set, 1, META_NAT, true);
> + f2fs_ra_meta_caches(sbi, set->set, 1, META_NAT, true);
> }
> /* flush dirty nats in nat entry set */
> list_for_each_entry_safe(set, tmp, &sets, set_list) {
> @@ -3288,15 +3287,15 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
> nat_bits_addr = __start_cp_addr(sbi) + BLKS_PER_SEG(sbi) -
> nm_i->nat_bits_blocks;
> for (i = 0; i < nm_i->nat_bits_blocks; i++) {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> - folio = f2fs_get_meta_folio(sbi, nat_bits_addr++);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + entry = f2fs_get_meta_cache(sbi, nat_bits_addr++);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
>
> memcpy(nm_i->nat_bits + F2FS_BLK_TO_BYTES(i),
> - folio_address(folio), F2FS_BLKSIZE);
> - f2fs_folio_put(folio, true);
> + cache_address(entry), F2FS_BLKSIZE);
> + f2fs_put_cache(entry, true);
> }
>
> cp_ver |= (cur_cp_crc(ckpt) << 32);
> diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
> index 5e114f352099..de8dcd5d4392 100644
> --- a/fs/f2fs/node.h
> +++ b/fs/f2fs/node.h
> @@ -311,9 +311,9 @@ static inline void fill_node_footer_blkaddr(struct folio *folio, block_t blkaddr
> rn->footer.next_blkaddr = cpu_to_le32(blkaddr);
> }
>
> -static inline bool is_recoverable_dnode(const struct folio *folio)
> +static inline bool is_recoverable_dnode(struct f2fs_sb_info *sbi, const struct folio *folio)
> {
> - struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_F_SB(folio));
> + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
> __u64 cp_ver = cur_cp_version(ckpt);
>
> /* Don't care crc part, if fsck.f2fs sets it. */
> diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
> index aaa5227739c8..5cb56b4c1879 100644
> --- a/fs/f2fs/recovery.c
> +++ b/fs/f2fs/recovery.c
> @@ -182,33 +182,33 @@ static const char *recover_printable_name(struct inode *inode,
> return raw->i_name;
> }
>
> -static int recover_dentry(struct inode *inode, struct folio *ifolio,
> +static int recover_dentry(struct inode *inode, struct f2fs_cached_block *entry,
> struct list_head *dir_list)
> {
> - struct f2fs_inode *raw_inode = F2FS_INODE(ifolio);
> + struct f2fs_inode *raw_inode = &CACHED_NODE(entry)->i;
> nid_t pino = le32_to_cpu(raw_inode->i_pino);
> struct f2fs_dir_entry *de;
> struct f2fs_filename fname;
> struct qstr usr_fname;
> struct folio *folio;
> struct inode *dir, *einode;
> - struct fsync_inode_entry *entry;
> + struct fsync_inode_entry *fsync_entry;
> int err = 0;
> const char *name;
> int name_len;
>
> - entry = get_fsync_inode(dir_list, pino);
> - if (!entry) {
> - entry = add_fsync_inode(F2FS_I_SB(inode), dir_list,
> + fsync_entry = get_fsync_inode(dir_list, pino);
> + if (!fsync_entry) {
> + fsync_entry = add_fsync_inode(F2FS_I_SB(inode), dir_list,
> pino, false);
> - if (IS_ERR(entry)) {
> - dir = ERR_CAST(entry);
> - err = PTR_ERR(entry);
> + if (IS_ERR(fsync_entry)) {
> + dir = ERR_CAST(fsync_entry);
> + err = PTR_ERR(fsync_entry);
> goto out;
> }
> }
>
> - dir = entry->inode;
> + dir = fsync_entry->inode;
> err = init_recovered_filename(dir, inode, raw_inode, &fname, &usr_fname);
> if (err)
> goto out;
> @@ -256,14 +256,14 @@ static int recover_dentry(struct inode *inode, struct folio *ifolio,
> out:
> name = recover_printable_name(inode, raw_inode, &name_len);
> f2fs_notice(F2FS_I_SB(inode), "%s: ino = %x, name = %.*s, dir = %llu, err = %d",
> - __func__, ino_of_node(ifolio), name_len, name,
> + __func__, ino_of_node(cache_folio(entry)), name_len, name,
> IS_ERR(dir) ? 0 : dir->i_ino, err);
> return err;
> }
>
> -static int recover_quota_data(struct inode *inode, struct folio *folio)
> +static int recover_quota_data(struct inode *inode, struct f2fs_cached_block *entry)
> {
> - struct f2fs_inode *raw = F2FS_INODE(folio);
> + struct f2fs_inode *raw = &CACHED_NODE(entry)->i;
> struct iattr attr;
> uid_t i_uid = le32_to_cpu(raw->i_uid);
> gid_t i_gid = le32_to_cpu(raw->i_gid);
> @@ -300,9 +300,9 @@ static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri)
> clear_inode_flag(inode, FI_DATA_EXIST);
> }
>
> -static int recover_inode(struct inode *inode, struct folio *folio)
> +static int recover_inode(struct inode *inode, struct f2fs_cached_block *entry)
> {
> - struct f2fs_inode *raw = F2FS_INODE(folio);
> + struct f2fs_inode *raw = &CACHED_NODE(entry)->i;
> struct f2fs_inode_info *fi = F2FS_I(inode);
> const char *name;
> int name_len;
> @@ -310,7 +310,7 @@ static int recover_inode(struct inode *inode, struct folio *folio)
>
> inode->i_mode = le16_to_cpu(raw->i_mode);
>
> - err = recover_quota_data(inode, folio);
> + err = recover_quota_data(inode, entry);
> if (err)
> return err;
>
> @@ -357,7 +357,7 @@ static int recover_inode(struct inode *inode, struct folio *folio)
> name = recover_printable_name(inode, raw, &name_len);
>
> f2fs_notice(F2FS_I_SB(inode), "%s: ino = %x, name = %.*s, inline = %x",
> - __func__, ino_of_node(folio), name_len, name,
> + __func__, ino_of_node(cache_folio(entry)), name_len, name,
> raw->i_inline);
> return 0;
> }
> @@ -386,30 +386,30 @@ static int sanity_check_node_chain(struct f2fs_sb_info *sbi, block_t blkaddr,
> return 0;
>
> for (i = 0; i < 2; i++) {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_is_valid_blkaddr(sbi, *blkaddr_fast, META_POR)) {
> *is_detecting = false;
> return 0;
> }
>
> - folio = f2fs_get_tmp_folio(sbi, *blkaddr_fast);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + entry = f2fs_get_tmp_cache(sbi, *blkaddr_fast);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
>
> - if (!is_recoverable_dnode(folio)) {
> - f2fs_folio_put(folio, true);
> + if (!is_recoverable_dnode(sbi, cache_folio(entry))) {
> + f2fs_put_cache(entry, true);
> *is_detecting = false;
> return 0;
> }
>
> ra_blocks = adjust_por_ra_blocks(sbi, ra_blocks, *blkaddr_fast,
> - next_blkaddr_of_node(folio));
> + next_blkaddr_of_node(cache_folio(entry)));
>
> - *blkaddr_fast = next_blkaddr_of_node(folio);
> - f2fs_folio_put(folio, true);
> + *blkaddr_fast = next_blkaddr_of_node(cache_folio(entry));
> + f2fs_put_cache(entry, true);
>
> - f2fs_ra_meta_pages_cond(sbi, *blkaddr_fast, ra_blocks);
> + f2fs_ra_meta_caches_cond(sbi, *blkaddr_fast, ra_blocks);
> }
>
> if (*blkaddr_fast == blkaddr) {
> @@ -434,45 +434,47 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
> blkaddr_fast = blkaddr;
>
> while (1) {
> - struct fsync_inode_entry *entry;
> - struct folio *folio;
> + struct fsync_inode_entry *fsync_entry;
> + struct f2fs_cached_block *entry;
> + struct f2fs_node *rn;
>
> if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
> return 0;
>
> - folio = f2fs_get_tmp_folio(sbi, blkaddr);
> - if (IS_ERR(folio)) {
> - err = PTR_ERR(folio);
> + entry = f2fs_get_tmp_cache(sbi, blkaddr);
> + if (IS_ERR(entry)) {
> + err = PTR_ERR(entry);
> break;
> }
> + rn = CACHED_NODE(entry);
>
> - if (!is_recoverable_dnode(folio)) {
> - f2fs_folio_put(folio, true);
> + if (!is_recoverable_dnode(sbi, cache_folio(entry))) {
> + f2fs_put_cache(entry, true);
> break;
> }
>
> - if (!is_fsync_dnode(folio))
> + if (!is_fsync_dnode(cache_folio(entry)))
> goto next;
>
> - entry = get_fsync_inode(head, ino_of_node(folio));
> - if (!entry) {
> + fsync_entry = get_fsync_inode(head, ino_of_node(cache_folio(entry)));
> + if (!fsync_entry) {
> bool quota_inode = false;
>
> if (!check_only &&
> - IS_INODE(folio) &&
> - is_dent_dnode(folio)) {
> - err = f2fs_recover_inode_page(sbi, folio);
> + IS_INODE(cache_folio(entry)) &&
> + is_dent_dnode(cache_folio(entry))) {
> + err = f2fs_recover_inode_page(sbi, entry);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> break;
> }
> quota_inode = true;
> }
>
> - entry = add_fsync_inode(sbi, head, ino_of_node(folio),
> + fsync_entry = add_fsync_inode(sbi, head, ino_of_node(cache_folio(entry)),
> quota_inode);
> - if (IS_ERR(entry)) {
> - err = PTR_ERR(entry);
> + if (IS_ERR(fsync_entry)) {
> + err = PTR_ERR(fsync_entry);
> /*
> * CP | dnode(F) | inode(DF)
> * For this case, we should not give up now.
> @@ -482,18 +484,18 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
> *new_inode = true;
> goto next;
> }
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> break;
> }
> }
> - entry->blkaddr = blkaddr;
> + fsync_entry->blkaddr = blkaddr;
>
> - if (IS_INODE(folio) && is_dent_dnode(folio))
> - entry->last_dentry = blkaddr;
> + if (IS_INODE(cache_folio(entry)) && is_dent_dnode(cache_folio(entry)))
> + fsync_entry->last_dentry = blkaddr;
> next:
> /* check next segment */
> - blkaddr = next_blkaddr_of_node(folio);
> - f2fs_folio_put(folio, true);
> + blkaddr = next_blkaddr_of_node(cache_folio(entry));
> + f2fs_put_cache(entry, true);
>
> err = sanity_check_node_chain(sbi, blkaddr, &blkaddr_fast,
> &is_detecting);
> @@ -519,7 +521,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
> unsigned short blkoff = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
> struct f2fs_summary_block *sum_node;
> struct f2fs_summary sum;
> - struct folio *sum_folio, *node_folio;
> + struct f2fs_cached_block *entry = NULL;
> + struct folio *node_folio;
> struct dnode_of_data tdn = *dn;
> nid_t ino, nid;
> struct inode *inode;
> @@ -541,12 +544,12 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
> }
> }
>
> - sum_folio = f2fs_get_sum_folio(sbi, segno);
> - if (IS_ERR(sum_folio))
> - return PTR_ERR(sum_folio);
> - sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, segno);
> + entry = f2fs_get_sum_cache(sbi, segno);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
> + sum_node = SUM_BLK_ENTRY_ADDR(sbi, entry, segno);
> sum = sum_entries(sum_node)[blkoff];
> - f2fs_folio_put(sum_folio, true);
> + f2fs_put_cache(entry, true);
> got_it:
> /* Use the locked dnode page and inode */
> nid = le32_to_cpu(sum.nid);
> @@ -645,7 +648,7 @@ static int f2fs_reserve_new_block_retry(struct dnode_of_data *dn)
> }
>
> static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> - struct folio *folio)
> + struct f2fs_cached_block *entry)
> {
> struct dnode_of_data dn;
> struct node_info ni;
> @@ -653,19 +656,19 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> int err = 0, recovered = 0;
>
> /* step 1: recover xattr */
> - if (IS_INODE(folio)) {
> - err = f2fs_recover_inline_xattr(inode, folio);
> + if (IS_INODE(cache_folio(entry))) {
> + err = f2fs_recover_inline_xattr(inode, entry);
> if (err)
> goto out;
> - } else if (f2fs_has_xattr_block(ofs_of_node(folio))) {
> - err = f2fs_recover_xattr_data(inode, folio);
> + } else if (f2fs_has_xattr_block(ofs_of_node(cache_folio(entry)))) {
> + err = f2fs_recover_xattr_data(inode, entry);
> if (!err)
> recovered++;
> goto out;
> }
>
> /* step 2: recover inline data */
> - err = f2fs_recover_inline_data(inode, folio);
> + err = f2fs_recover_inline_data(inode, entry);
> if (err) {
> if (err == 1)
> err = 0;
> @@ -673,8 +676,8 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> }
>
> /* step 3: recover data indices */
> - start = f2fs_start_bidx_of_node(ofs_of_node(folio), inode);
> - end = start + ADDRS_PER_PAGE(folio, inode);
> + start = f2fs_start_bidx_of_node(ofs_of_node(cache_folio(entry)), inode);
> + end = start + addrs_per_page(inode, IS_INODE(cache_folio(entry)));
>
> set_new_dnode(&dn, inode, NULL, NULL, 0);
> retry_dn:
> @@ -693,12 +696,12 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> if (err)
> goto err;
>
> - f2fs_bug_on(sbi, ni.ino != ino_of_node(folio));
> + f2fs_bug_on(sbi, ni.ino != ino_of_node(cache_folio(entry)));
>
> - if (ofs_of_node(dn.node_folio) != ofs_of_node(folio)) {
> + if (ofs_of_node(dn.node_folio) != ofs_of_node(cache_folio(entry))) {
> f2fs_warn(sbi, "Inconsistent ofs_of_node, ino:%llu, ofs:%u, %u",
> inode->i_ino, ofs_of_node(dn.node_folio),
> - ofs_of_node(folio));
> + ofs_of_node(cache_folio(entry)));
> err = -EFSCORRUPTED;
> f2fs_handle_error(sbi, ERROR_INCONSISTENT_FOOTER);
> fserror_report_file_metadata(dn.inode, err, GFP_NOFS);
> @@ -709,7 +712,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> block_t src, dest;
>
> src = f2fs_data_blkaddr(&dn);
> - dest = data_blkaddr(dn.inode, folio, dn.ofs_in_node);
> + dest = data_blkaddr(dn.inode, cache_folio(entry), dn.ofs_in_node);
>
> if (__is_valid_data_blkaddr(src) &&
> !f2fs_is_valid_blkaddr(sbi, src, META_POR)) {
> @@ -784,16 +787,16 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> }
> }
>
> - copy_node_footer(dn.node_folio, folio);
> + copy_node_footer(dn.node_folio, cache_folio(entry));
> fill_node_footer(dn.node_folio, dn.nid, ni.ino,
> - ofs_of_node(folio), false);
> + ofs_of_node(cache_folio(entry)), false);
> folio_mark_dirty(dn.node_folio);
> err:
> f2fs_put_dnode(&dn);
> out:
> f2fs_notice(sbi, "recover_data: ino = %llx, nid = %x (i_size: %s), "
> "range (%u, %u), recovered = %d, err = %d",
> - inode->i_ino, nid_of_node(folio),
> + inode->i_ino, nid_of_node(cache_folio(entry)),
> file_keep_isize(inode) ? "keep" : "recover",
> start, end, recovered, err);
> return err;
> @@ -820,26 +823,26 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
> blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
>
> while (1) {
> - struct fsync_inode_entry *entry;
> - struct folio *folio;
> + struct fsync_inode_entry *fsync_entry;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
> break;
>
> - folio = f2fs_get_tmp_folio(sbi, blkaddr);
> - if (IS_ERR(folio)) {
> - err = PTR_ERR(folio);
> + entry = f2fs_get_tmp_cache(sbi, blkaddr);
> + if (IS_ERR(entry)) {
> + err = PTR_ERR(entry);
> break;
> }
>
> - if (!is_recoverable_dnode(folio)) {
> - f2fs_folio_put(folio, true);
> + if (!is_recoverable_dnode(sbi, cache_folio(entry))) {
> + f2fs_put_cache(entry, true);
> break;
> }
> recoverable_dnode++;
>
> - entry = get_fsync_inode(inode_list, ino_of_node(folio));
> - if (!entry)
> + fsync_entry = get_fsync_inode(inode_list, ino_of_node(cache_folio(entry)));
> + if (!fsync_entry)
> goto next;
> fsynced_dnode++;
> /*
> @@ -847,40 +850,40 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
> * In this case, we can lose the latest inode(x).
> * So, call recover_inode for the inode update.
> */
> - if (IS_INODE(folio)) {
> - err = recover_inode(entry->inode, folio);
> + if (IS_INODE(cache_folio(entry))) {
> + err = recover_inode(fsync_entry->inode, entry);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> break;
> }
> recovered_inode++;
> }
> - if (entry->last_dentry == blkaddr) {
> - err = recover_dentry(entry->inode, folio, dir_list);
> + if (fsync_entry->last_dentry == blkaddr) {
> + err = recover_dentry(fsync_entry->inode, entry, dir_list);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> break;
> }
> recovered_dentry++;
> }
> - err = do_recover_data(sbi, entry->inode, folio);
> + err = do_recover_data(sbi, fsync_entry->inode, entry);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> break;
> }
> recovered_dnode++;
>
> - if (entry->blkaddr == blkaddr)
> - list_move_tail(&entry->list, tmp_inode_list);
> + if (fsync_entry->blkaddr == blkaddr)
> + list_move_tail(&fsync_entry->list, tmp_inode_list);
> next:
> ra_blocks = adjust_por_ra_blocks(sbi, ra_blocks, blkaddr,
> - next_blkaddr_of_node(folio));
> + next_blkaddr_of_node(cache_folio(entry)));
>
> /* check next segment */
> - blkaddr = next_blkaddr_of_node(folio);
> - f2fs_folio_put(folio, true);
> + blkaddr = next_blkaddr_of_node(cache_folio(entry));
> + f2fs_put_cache(entry, true);
>
> - f2fs_ra_meta_pages_cond(sbi, blkaddr, ra_blocks);
> + f2fs_ra_meta_caches_cond(sbi, blkaddr, ra_blocks);
> total_dnode++;
> }
> if (!err)
> @@ -937,12 +940,11 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
> destroy_fsync_dnodes(&tmp_inode_list, err);
>
> /* truncate meta pages to be used by the recovery */
> - truncate_inode_pages_range(META_MAPPING(sbi),
> - (loff_t)MAIN_BLKADDR(sbi) << PAGE_SHIFT, -1);
> -
> + f2fs_truncate_meta_caches(sbi, MAIN_BLKADDR(sbi),
> + MAX_BLKADDR(sbi) - MAIN_BLKADDR(sbi));
> if (err) {
> truncate_inode_pages_final(NODE_MAPPING(sbi));
> - truncate_inode_pages_final(META_MAPPING(sbi));
> + f2fs_truncate_meta_caches(sbi, 0, ULONG_MAX);
> }
>
> /*
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 56decf9c691c..cbb3a8c9f4ab 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2774,63 +2774,62 @@ int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)
> return 3;
> }
>
> -/*
> - * Caller should put this summary folio
> - */
> -struct folio *f2fs_get_sum_folio(struct f2fs_sb_info *sbi, unsigned int segno)
> +
> +struct f2fs_cached_block *f2fs_get_sum_cache(struct f2fs_sb_info *sbi,
> + unsigned int segno)
> {
> if (unlikely(f2fs_cp_error(sbi)))
> return ERR_PTR(-EIO);
> - return f2fs_get_meta_folio_retry(sbi, GET_SUM_BLOCK(sbi, segno));
> + return f2fs_get_meta_cache_retry(sbi, GET_SUM_BLOCK(sbi, segno));
> }
>
> void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
> void *src, block_t blk_addr)
> {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_sb_has_packed_ssa(sbi))
> - folio = f2fs_grab_meta_folio(sbi, blk_addr);
> + entry = f2fs_grab_meta_cache(sbi, blk_addr);
> else
> - folio = f2fs_get_meta_folio_retry(sbi, blk_addr);
> + entry = f2fs_get_meta_cache_retry(sbi, blk_addr);
>
> - if (IS_ERR(folio))
> + if (IS_ERR(entry))
> return;
>
> - memcpy(folio_address(folio), src, PAGE_SIZE);
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + memcpy(cache_address(entry), src, sbi->blocksize);
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> }
>
> static void write_sum_page(struct f2fs_sb_info *sbi,
> struct f2fs_summary_block *sum_blk, unsigned int segno)
> {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_sb_has_packed_ssa(sbi))
> return f2fs_update_meta_page(sbi, (void *)sum_blk,
> GET_SUM_BLOCK(sbi, segno));
>
> - folio = f2fs_get_sum_folio(sbi, segno);
> - if (IS_ERR(folio))
> + entry = f2fs_get_sum_cache(sbi, GET_SUM_BLOCK(sbi, segno));
> + if (IS_ERR(entry))
> return;
>
> - memcpy(SUM_BLK_PAGE_ADDR(sbi, folio, segno), sum_blk,
> + memcpy(SUM_BLK_ENTRY_ADDR(sbi, entry, segno), sum_blk,
> sbi->sum_blocksize);
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> }
>
> static void write_current_sum_page(struct f2fs_sb_info *sbi,
> int type, block_t blk_addr)
> {
> struct curseg_info *curseg = CURSEG_I(sbi, type);
> - struct folio *folio = f2fs_grab_meta_folio(sbi, blk_addr);
> + struct f2fs_cached_block *entry = f2fs_grab_meta_cache(sbi, blk_addr);
> struct f2fs_summary_block *src = curseg->sum_blk;
> struct f2fs_summary_block *dst;
>
> - dst = folio_address(folio);
> - memset(dst, 0, PAGE_SIZE);
> + dst = cache_address(entry);
> + memset(dst, 0, sbi->blocksize);
>
> mutex_lock(&curseg->curseg_mutex);
>
> @@ -2843,8 +2842,8 @@ static void write_current_sum_page(struct f2fs_sb_info *sbi,
>
> mutex_unlock(&curseg->curseg_mutex);
>
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> }
>
> static int is_next_segment_free(struct f2fs_sb_info *sbi,
> @@ -3160,7 +3159,7 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type)
> struct curseg_info *curseg = CURSEG_I(sbi, type);
> unsigned int new_segno = curseg->next_segno;
> struct f2fs_summary_block *sum_node;
> - struct folio *sum_folio;
> + struct f2fs_cached_block *entry = NULL;
>
> if (curseg->inited)
> write_sum_page(sbi, curseg->sum_blk, curseg->segno);
> @@ -3176,15 +3175,15 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type)
> curseg->alloc_type = SSR;
> curseg->next_blkoff = __next_free_blkoff(sbi, curseg->segno, 0);
>
> - sum_folio = f2fs_get_sum_folio(sbi, new_segno);
> - if (IS_ERR(sum_folio)) {
> + entry = f2fs_get_sum_cache(sbi, new_segno);
> + if (IS_ERR(entry)) {
> /* GC won't be able to use stale summary pages by cp_error */
> memset(curseg->sum_blk, 0, sbi->sum_entry_size);
> - return PTR_ERR(sum_folio);
> + return PTR_ERR(entry);
> }
> - sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, new_segno);
> + sum_node = SUM_BLK_ENTRY_ADDR(sbi, entry, new_segno);
> memcpy(curseg->sum_blk, sum_node, sbi->sum_entry_size);
> - f2fs_folio_put(sum_folio, true);
> + f2fs_put_cache(entry, true);
> return 0;
> }
>
> @@ -4127,8 +4126,9 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
> f2fs_up_read(&fio->sbi->io_order_lock);
> }
>
> -void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct folio *folio,
> - enum iostat_type io_type)
> +void f2fs_do_write_meta_cache(struct f2fs_sb_info *sbi,
> + struct f2fs_cached_block *entry,
> + enum iostat_type io_type)
> {
> struct f2fs_io_info fio = {
> .sbi = sbi,
> @@ -4136,20 +4136,21 @@ void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct folio *folio,
> .temp = HOT,
> .op = REQ_OP_WRITE,
> .op_flags = REQ_SYNC | REQ_META | REQ_PRIO,
> - .old_blkaddr = folio->index,
> - .new_blkaddr = folio->index,
> - .folio = folio,
> + .old_blkaddr = entry->index,
> + .new_blkaddr = entry->index,
> .encrypted_page = NULL,
> .in_list = 0,
> + .cache_entry = entry,
> + .is_cache = 1,
> };
>
> - if (unlikely(folio->index >= MAIN_BLKADDR(sbi)))
> + if (unlikely(entry->index >= MAIN_BLKADDR(sbi)))
> fio.op_flags &= ~REQ_META;
>
> - folio_start_writeback(folio);
> - f2fs_submit_page_write(&fio);
> + f2fs_start_cache_writeback(entry);
> + f2fs_submit_cache_write(&fio);
>
> - stat_inc_meta_count(sbi, folio->index);
> + stat_inc_meta_count(sbi, entry->index);
> f2fs_update_iostat(sbi, NULL, io_type, F2FS_BLKSIZE);
> }
>
> @@ -4206,7 +4207,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
> }
>
> if (fio->meta_gc)
> - f2fs_truncate_meta_inode_pages(sbi, fio->new_blkaddr, 1);
> + f2fs_truncate_meta_caches(sbi, fio->new_blkaddr, 1);
>
> stat_inc_inplace_blocks(fio->sbi);
>
> @@ -4372,7 +4373,7 @@ void f2fs_folio_wait_writeback(struct folio *folio, enum page_type type,
> void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> - struct folio *cfolio;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_meta_inode_gc_required(inode))
> return;
> @@ -4380,11 +4381,12 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr)
> if (!__is_valid_data_blkaddr(blkaddr))
> return;
>
> - cfolio = filemap_lock_folio(META_MAPPING(sbi), blkaddr);
> - if (!IS_ERR(cfolio)) {
> - f2fs_folio_wait_writeback(cfolio, DATA, true, true);
> - f2fs_folio_put(cfolio, true);
> - }
> + entry = f2fs_find_cache(META_CACHE(sbi), blkaddr);
> + if (IS_ERR(entry))
> + return;
> + f2fs_lock_cache(entry);
> + f2fs_cache_wait_writeback_cond(entry, DATA);
> + f2fs_put_cache(entry, true);
> }
>
> void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
> @@ -4399,7 +4401,7 @@ void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
> for (i = 0; i < len; i++)
> f2fs_wait_on_block_writeback(inode, blkaddr + i);
>
> - f2fs_truncate_meta_inode_pages(sbi, blkaddr, len);
> + f2fs_truncate_meta_caches(sbi, blkaddr, len);
> }
>
> static int read_compacted_summaries(struct f2fs_sb_info *sbi)
> @@ -4407,16 +4409,16 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
> struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
> struct curseg_info *seg_i;
> unsigned char *kaddr;
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> block_t start;
> int i, j, offset;
>
> start = start_sum_block(sbi);
>
> - folio = f2fs_get_meta_folio(sbi, start++);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> - kaddr = folio_address(folio);
> + entry = f2fs_get_meta_cache(sbi, start++);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
> + kaddr = cache_address(entry);
>
> /* Step 1: restore nat cache */
> seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
> @@ -4453,16 +4455,16 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
> SUM_FOOTER_SIZE)
> continue;
>
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
>
> - folio = f2fs_get_meta_folio(sbi, start++);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> - kaddr = folio_address(folio);
> + entry = f2fs_get_meta_cache(sbi, start++);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
> + kaddr = cache_address(entry);
> offset = 0;
> }
> }
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> return 0;
> }
>
> @@ -4471,7 +4473,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
> struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
> struct f2fs_summary_block *sum;
> struct curseg_info *curseg;
> - struct folio *new;
> + struct f2fs_cached_block *entry;
> unsigned short blk_off;
> unsigned int segno = 0;
> block_t blk_addr = 0;
> @@ -4498,10 +4500,10 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
> blk_addr = GET_SUM_BLOCK(sbi, segno);
> }
>
> - new = f2fs_get_meta_folio(sbi, blk_addr);
> - if (IS_ERR(new))
> - return PTR_ERR(new);
> - sum = folio_address(new);
> + entry = f2fs_get_meta_cache(sbi, blk_addr);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
> + sum = cache_address(entry);
>
> if (IS_NODESEG(type)) {
> if (__exist_node_summaries(sbi)) {
> @@ -4538,7 +4540,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
> curseg->next_blkoff = blk_off;
> mutex_unlock(&curseg->curseg_mutex);
> out:
> - f2fs_folio_put(new, true);
> + f2fs_put_cache(entry, true);
> return err;
> }
>
> @@ -4553,8 +4555,8 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
> int npages = f2fs_npages_for_summary_flush(sbi, true);
>
> if (npages >= 2)
> - f2fs_ra_meta_pages(sbi, start_sum_block(sbi), npages,
> - META_CP, true);
> + f2fs_ra_meta_caches(sbi, start_sum_block(sbi),
> + npages, META_CP, true);
>
> /* restore for compacted data summary */
> err = read_compacted_summaries(sbi);
> @@ -4564,7 +4566,7 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
> }
>
> if (__exist_node_summaries(sbi))
> - f2fs_ra_meta_pages(sbi,
> + f2fs_ra_meta_caches(sbi,
> sum_blk_addr(sbi, NR_CURSEG_PERSIST_TYPE, type),
> NR_CURSEG_PERSIST_TYPE - type, META_CP, true);
>
> @@ -4587,16 +4589,16 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
>
> static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
> {
> - struct folio *folio;
> + struct f2fs_cached_block *entry = NULL;
> unsigned char *kaddr;
> struct f2fs_summary *summary;
> struct curseg_info *seg_i;
> int written_size = 0;
> int i, j;
>
> - folio = f2fs_grab_meta_folio(sbi, blkaddr++);
> - kaddr = folio_address(folio);
> - memset(kaddr, 0, PAGE_SIZE);
> + entry = f2fs_grab_meta_cache(sbi, blkaddr++);
> + kaddr = cache_address(entry);
> + memset(kaddr, 0, sbi->blocksize);
>
> /* Step 1: write nat cache */
> seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
> @@ -4612,10 +4614,10 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
> for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
> seg_i = CURSEG_I(sbi, i);
> for (j = 0; j < f2fs_curseg_valid_blocks(sbi, i); j++) {
> - if (!folio) {
> - folio = f2fs_grab_meta_folio(sbi, blkaddr++);
> - kaddr = folio_address(folio);
> - memset(kaddr, 0, PAGE_SIZE);
> + if (!entry) {
> + entry = f2fs_grab_meta_cache(sbi, blkaddr++);
> + kaddr = cache_address(entry);
> + memset(kaddr, 0, sbi->blocksize);
> written_size = 0;
> }
> summary = (struct f2fs_summary *)(kaddr + written_size);
> @@ -4626,14 +4628,14 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
> SUM_FOOTER_SIZE)
> continue;
>
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> - folio = NULL;
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> + entry = NULL;
> }
> }
> - if (folio) {
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + if (entry) {
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> }
> }
>
> @@ -4687,29 +4689,29 @@ int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi,
> return -1;
> }
>
> -static struct folio *get_current_sit_folio(struct f2fs_sb_info *sbi,
> +static struct f2fs_cached_block *get_current_sit_cache(struct f2fs_sb_info *sbi,
> unsigned int segno)
> {
> - return f2fs_get_meta_folio(sbi, current_sit_addr(sbi, segno));
> + return f2fs_get_meta_cache(sbi, current_sit_addr(sbi, segno));
> }
>
> -static struct folio *get_next_sit_folio(struct f2fs_sb_info *sbi,
> +static struct f2fs_cached_block *get_next_sit_cache(struct f2fs_sb_info *sbi,
> unsigned int start)
> {
> struct sit_info *sit_i = SIT_I(sbi);
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> pgoff_t src_off, dst_off;
>
> src_off = current_sit_addr(sbi, start);
> dst_off = next_sit_addr(sbi, src_off);
>
> - folio = f2fs_grab_meta_folio(sbi, dst_off);
> - seg_info_to_sit_folio(sbi, folio, start);
> + entry = f2fs_grab_meta_cache(sbi, dst_off);
> + seg_info_to_sit_block(sbi, entry, start);
>
> - folio_mark_dirty(folio);
> + f2fs_mark_cache_dirty(entry);
> set_to_next_sit(sit_i, start);
>
> - return folio;
> + return entry;
> }
>
> static struct sit_entry_set *grab_sit_entry_set(void)
> @@ -4839,8 +4841,9 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> * #2, flush sit entries to sit page.
> */
> list_for_each_entry_safe(ses, tmp, head, set_list) {
> - struct folio *folio = NULL;
> + struct f2fs_cached_block *entry = NULL;
> struct f2fs_sit_block *raw_sit = NULL;
> +
> unsigned int start_segno = ses->start_segno;
> unsigned int end = min(start_segno + SIT_ENTRY_PER_BLOCK,
> (unsigned long)MAIN_SEGS(sbi));
> @@ -4854,8 +4857,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> if (to_journal) {
> down_write(&curseg->journal_rwsem);
> } else {
> - folio = get_next_sit_folio(sbi, start_segno);
> - raw_sit = folio_address(folio);
> + entry = get_next_sit_cache(sbi, start_segno);
> + raw_sit = cache_address(entry);
> }
>
> /* flush dirty sit entries in region of current sit set */
> @@ -4900,7 +4903,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> if (to_journal)
> up_write(&curseg->journal_rwsem);
> else
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
>
> f2fs_bug_on(sbi, ses->entry_cnt);
> release_sit_entry_set(ses);
> @@ -5091,7 +5094,7 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
> block_t sit_valid_blocks[2] = {0, 0};
>
> do {
> - readed = f2fs_ra_meta_pages(sbi, start_blk, BIO_MAX_VECS,
> + readed = f2fs_ra_meta_caches(sbi, start_blk, BIO_MAX_VECS,
> META_SIT, true);
>
> start = start_blk * sit_i->sents_per_block;
> @@ -5099,15 +5102,15 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
>
> for (; start < end && start < MAIN_SEGS(sbi); start++) {
> struct f2fs_sit_block *sit_blk;
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> se = &sit_i->sentries[start];
> - folio = get_current_sit_folio(sbi, start);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> - sit_blk = folio_address(folio);
> + entry = get_current_sit_cache(sbi, start);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
> + sit_blk = cache_address(entry);
> sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)];
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
>
> err = check_block_count(sbi, start, &sit);
> if (err)
> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> index db1079169a23..fff35c63a00f 100644
> --- a/fs/f2fs/segment.h
> +++ b/fs/f2fs/segment.h
> @@ -95,6 +95,8 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
> #define GET_SUM_BLKOFF(sbi, segno) (segno % (sbi)->sums_per_block)
> #define SUM_BLK_PAGE_ADDR(sbi, folio, segno) \
> (folio_address(folio) + GET_SUM_BLKOFF(sbi, segno) * (sbi)->sum_blocksize)
> +#define SUM_BLK_ENTRY_ADDR(sbi, entry, segno) \
> + (cache_address(entry) + GET_SUM_BLKOFF(sbi, segno) * (sbi)->sum_blocksize)
>
> #define GET_SUM_TYPE(footer) ((footer)->entry_type)
> #define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
> @@ -417,8 +419,8 @@ static inline void __seg_info_to_raw_sit(struct seg_entry *se,
> rs->mtime = cpu_to_le64(se->mtime);
> }
>
> -static inline void seg_info_to_sit_folio(struct f2fs_sb_info *sbi,
> - struct folio *folio, unsigned int start)
> +static inline void seg_info_to_sit_block(struct f2fs_sb_info *sbi,
> + struct f2fs_cached_block *entry, unsigned int start)
> {
> struct f2fs_sit_block *raw_sit;
> struct seg_entry *se;
> @@ -427,8 +429,8 @@ static inline void seg_info_to_sit_folio(struct f2fs_sb_info *sbi,
> (unsigned long)MAIN_SEGS(sbi));
> int i;
>
> - raw_sit = folio_address(folio);
> - memset(raw_sit, 0, PAGE_SIZE);
> + raw_sit = cache_address(entry);
> + memset(raw_sit, 0, sbi->blocksize);
> for (i = 0; i < end - start; i++) {
> rs = &raw_sit->entries[i];
> se = get_seg_entry(sbi, start + i);
> @@ -991,6 +993,27 @@ static inline int nr_pages_to_skip(struct f2fs_sb_info *sbi, int type)
> return 0;
> }
>
> +/*
> + * When writing cache asynchronously, align nr_to_write to BIO_MAX_VECS.
> + */
> +static inline long adjust_flush_cache_number(struct f2fs_sb_info *sbi, int type)
> +{
> + long nr_to_write;
> +
> + switch (type) {
> + case META:
> + nr_to_write = BIO_MAX_VECS;
> + break;
> + case NODE:
> + nr_to_write = BIO_MAX_VECS << 1;
> + break;
> + default:
> + f2fs_bug_on(sbi, 1);
> + return 0;
> + }
> + return nr_to_write;
> +}
> +
> /*
> * When writing pages, it'd better align nr_to_write for segment size.
> */
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 89affe72f4fc..d3dee9b7d999 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -1839,8 +1839,7 @@ static int f2fs_drop_inode(struct inode *inode)
> * drop useless meta/node dirty pages.
> */
> if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> - if (inode->i_ino == F2FS_NODE_INO(sbi) ||
> - inode->i_ino == F2FS_META_INO(sbi)) {
> + if (inode->i_ino == F2FS_NODE_INO(sbi)) {
> trace_f2fs_drop_inode(inode, 1);
> return 1;
> }
> @@ -1942,8 +1941,7 @@ static void f2fs_dirty_inode(struct inode *inode, int flags)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
>
> - if (inode->i_ino == F2FS_NODE_INO(sbi) ||
> - inode->i_ino == F2FS_META_INO(sbi))
> + if (inode->i_ino == F2FS_NODE_INO(sbi))
> return;
>
> if (is_inode_flag_set(inode, FI_AUTO_RECOVER))
> @@ -2039,9 +2037,10 @@ static void f2fs_put_super(struct super_block *sb)
>
> f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA);
>
> - if (err || f2fs_cp_error(sbi)) {
> + if (err || f2fs_cp_error(sbi) ||
> + unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> truncate_inode_pages_final(NODE_MAPPING(sbi));
> - truncate_inode_pages_final(META_MAPPING(sbi));
> + f2fs_truncate_meta_caches(sbi, 0, ULONG_MAX);
> }
>
> f2fs_bug_on(sbi, sbi->fsync_node_num);
> @@ -2051,9 +2050,6 @@ static void f2fs_put_super(struct super_block *sb)
> iput(sbi->node_inode);
> sbi->node_inode = NULL;
>
> - iput(sbi->meta_inode);
> - sbi->meta_inode = NULL;
> -
> f2fs_destroy_cache(META_CACHE(sbi));
>
> /* Should check the page counts after dropping all node/meta pages */
> @@ -4383,7 +4379,6 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
> sbi->allocate_section_policy = ALLOCATE_FORWARD_NOHINT;
> F2FS_ROOT_INO(sbi) = le32_to_cpu(raw_super->root_ino);
> F2FS_NODE_INO(sbi) = le32_to_cpu(raw_super->node_ino);
> - F2FS_META_INO(sbi) = le32_to_cpu(raw_super->meta_ino);
> sbi->cur_victim_sec = NULL_SECNO;
> sbi->gc_mode = GC_NORMAL;
> sbi->next_victim_seg[BG_GC] = NULL_SEGNO;
> @@ -5224,18 +5219,10 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
> if (err)
> goto free_page_array_cache;
>
> - /* get an inode for meta space */
> - sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
> - if (IS_ERR(sbi->meta_inode)) {
> - f2fs_err(sbi, "Failed to read F2FS meta data inode");
> - err = PTR_ERR(sbi->meta_inode);
> - goto free_meta_cache;
> - }
> -
> err = f2fs_get_valid_checkpoint(sbi);
> if (err) {
> f2fs_err(sbi, "Failed to get valid F2FS checkpoint");
> - goto free_meta_inode;
> + goto free_meta_cache;
> }
>
> if (__is_set_ckpt_flags(F2FS_CKPT(sbi), CP_QUOTA_NEED_FSCK_FLAG))
> @@ -5529,7 +5516,7 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
> * followed by f2fs_write_checkpoint() through f2fs_write_node_pages(), which
> * falls into an infinite loop in f2fs_sync_meta_pages().
> */
> - truncate_inode_pages_final(META_MAPPING(sbi));
> + f2fs_truncate_meta_caches(sbi, 0, ULONG_MAX);
> /* evict some inodes being cached by GC */
> evict_inodes(sb);
> f2fs_unregister_sysfs(sbi);
> @@ -5559,10 +5546,6 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
> free_devices:
> destroy_device_list(sbi);
> kvfree(sbi->ckpt);
> -free_meta_inode:
> - make_bad_inode(sbi->meta_inode);
> - iput(sbi->meta_inode);
> - sbi->meta_inode = NULL;
> free_meta_cache:
> f2fs_destroy_cache(META_CACHE(sbi));
> free_page_array_cache:
> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> index bb2b6cd5d507..0c027d00a1ea 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -35,7 +35,6 @@
>
> #define F2FS_ROOT_INO(sbi) ((sbi)->root_ino_num)
> #define F2FS_NODE_INO(sbi) ((sbi)->node_ino_num)
> -#define F2FS_META_INO(sbi) ((sbi)->meta_ino_num)
> #define F2FS_COMPRESS_INO(sbi) (NM_I(sbi)->max_nid)
>
> #define F2FS_MAX_QUOTAS 3
> --
> 2.49.0
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
WARNING: multiple messages have this Message-ID (diff)
From: Jaegeuk Kim <jaegeuk@kernel.org>
To: Chao Yu <chao@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net
Subject: Re: [f2fs-dev] [PATCH v1 05/12] f2fs: cache: use meta cache
Date: Thu, 20 Aug 2026 05:11:07 +0000 [thread overview]
Message-ID: <aoaMa3N7mk5f4jz-@google.com> (raw)
In-Reply-To: <20260820031721.12218-6-chao@kernel.org>
On 08/20, Chao Yu via Linux-f2fs-devel wrote:
> This patch migrates F2FS meta block caching from the fake VFS inode
> page cache (sbi->meta_inode) to meta cache (sbi->meta_blocks).
>
> It converts CP, SIT, NAT, SSA, recovery, and GC metadata I/O paths to
> operate on struct f2fs_cached_block instead of folio, and removes
> sbi->meta_inode.
>
> Signed-off-by: Chao Yu <chao@kernel.org>
> ---
> fs/f2fs/cache.c | 2 +
> fs/f2fs/checkpoint.c | 394 ++++++++++++++++++----------------------
> fs/f2fs/compress.c | 4 +-
> fs/f2fs/data.c | 29 ++-
> fs/f2fs/debug.c | 12 +-
> fs/f2fs/f2fs.h | 81 +++------
> fs/f2fs/file.c | 4 +-
> fs/f2fs/gc.c | 134 +++++++-------
> fs/f2fs/inline.c | 9 +-
> fs/f2fs/inode.c | 9 +-
> fs/f2fs/node.c | 125 +++++++------
> fs/f2fs/node.h | 4 +-
> fs/f2fs/recovery.c | 198 ++++++++++----------
> fs/f2fs/segment.c | 201 ++++++++++----------
> fs/f2fs/segment.h | 31 +++-
> fs/f2fs/super.c | 31 +---
> include/linux/f2fs_fs.h | 1 -
> 17 files changed, 606 insertions(+), 663 deletions(-)
>
> diff --git a/fs/f2fs/cache.c b/fs/f2fs/cache.c
> index cb5b26046162..afef808e485a 100644
> --- a/fs/f2fs/cache.c
> +++ b/fs/f2fs/cache.c
> @@ -631,6 +631,8 @@ static int f2fs_cache_writeback_kthread(void *data)
> break;
> if (f2fs_cp_error(sbi))
> continue;
> +
> + f2fs_write_meta_caches(sbi);
> }
> return 0;
> }
> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> index 729d19680caf..1a7083540b82 100644
> --- a/fs/f2fs/checkpoint.c
> +++ b/fs/f2fs/checkpoint.c
> @@ -17,6 +17,7 @@
> #include <linux/delayacct.h>
> #include <linux/ioprio.h>
> #include <linux/math64.h>
> +#include <linux/freezer.h>
>
> #include "f2fs.h"
> #include "node.h"
> @@ -235,27 +236,27 @@ struct kmem_cache *f2fs_inode_entry_slab;
> /*
> * We guarantee no failure on the returned page.
> */
> -struct folio *f2fs_grab_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index)
> +struct f2fs_cached_block *f2fs_grab_meta_cache(struct f2fs_sb_info *sbi,
> + pgoff_t index)
> {
> - struct address_space *mapping = META_MAPPING(sbi);
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> repeat:
> - folio = f2fs_grab_cache_folio(mapping, index, false);
> - if (IS_ERR(folio)) {
> + entry = f2fs_grab_cache(META_CACHE(sbi), index,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(entry)) {
> cond_resched();
> goto repeat;
> }
> - f2fs_folio_wait_writeback(folio, META, true, true);
> - if (!folio_test_uptodate(folio))
> - folio_mark_uptodate(folio);
> - return folio;
> + f2fs_cache_wait_writeback(entry);
> + if (!f2fs_cache_test_uptodate(entry))
> + f2fs_cache_set_uptodate(entry);
> + return entry;
> }
>
> -static struct folio *__get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index,
> - bool is_meta)
> +static struct f2fs_cached_block *__get_meta_cache(struct f2fs_sb_info *sbi,
> + pgoff_t index, bool is_meta)
> {
> - struct address_space *mapping = META_MAPPING(sbi);
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> struct f2fs_io_info fio = {
> .sbi = sbi,
> .type = META,
> @@ -265,70 +266,75 @@ static struct folio *__get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index,
> .new_blkaddr = index,
> .encrypted_page = NULL,
> .is_por = !is_meta ? 1 : 0,
> + .is_cache = 1,
> };
> int err;
>
> if (unlikely(!is_meta))
> fio.op_flags &= ~REQ_META;
> repeat:
> - folio = f2fs_grab_cache_folio(mapping, index, false);
> - if (IS_ERR(folio)) {
> + entry = f2fs_grab_cache(META_CACHE(sbi), index,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(entry)) {
> cond_resched();
> goto repeat;
> }
> - if (folio_test_uptodate(folio))
> + if (f2fs_cache_test_uptodate(entry))
> goto out;
>
> - fio.folio = folio;
> + fio.cache_entry = entry;
>
> - err = f2fs_submit_page_bio(&fio);
> + err = f2fs_submit_cache_read(&fio);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> return ERR_PTR(err);
> }
>
> f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, F2FS_BLKSIZE);
>
> - folio_lock(folio);
> - if (unlikely(!is_meta_folio(folio))) {
> - f2fs_folio_put(folio, true);
> + f2fs_lock_cache(entry);
> + if (unlikely(!f2fs_is_meta_cache(entry))) {
> + f2fs_put_cache(entry, true);
> goto repeat;
> }
>
> - if (unlikely(!folio_test_uptodate(folio))) {
> - f2fs_handle_page_eio(sbi, folio, META);
> - f2fs_folio_put(folio, true);
> + if (unlikely(!f2fs_cache_test_uptodate(entry))) {
> + f2fs_handle_page_eio(sbi, entry->index, META);
> + f2fs_put_cache(entry, true);
> return ERR_PTR(-EIO);
> }
> out:
> - return folio;
> + return entry;
> }
>
> -struct folio *f2fs_get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index)
> +struct f2fs_cached_block *f2fs_get_meta_cache(struct f2fs_sb_info *sbi,
> + pgoff_t index)
> {
> - return __get_meta_folio(sbi, index, true);
> + return __get_meta_cache(sbi, index, true);
> }
>
> -struct folio *f2fs_get_meta_folio_retry(struct f2fs_sb_info *sbi, pgoff_t index)
> +struct f2fs_cached_block *f2fs_get_meta_cache_retry(struct f2fs_sb_info *sbi,
> + pgoff_t index)
> {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> int count = 0;
>
> retry:
> - folio = __get_meta_folio(sbi, index, true);
> - if (IS_ERR(folio)) {
> - if (PTR_ERR(folio) == -EIO &&
> + entry = __get_meta_cache(sbi, index, true);
> + if (IS_ERR(entry)) {
> + if (PTR_ERR(entry) == -EIO &&
> ++count <= DEFAULT_RETRY_IO_COUNT)
> goto retry;
> f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_META_PAGE);
> }
> - return folio;
> + return entry;
> }
>
> /* for POR only */
> -struct folio *f2fs_get_tmp_folio(struct f2fs_sb_info *sbi, pgoff_t index)
> +struct f2fs_cached_block *f2fs_get_tmp_cache(struct f2fs_sb_info *sbi,
> + pgoff_t index)
> {
> - return __get_meta_folio(sbi, index, false);
> + return __get_meta_cache(sbi, index, false);
> }
>
> static bool __is_bitmap_valid(struct f2fs_sb_info *sbi, block_t blkaddr,
> @@ -446,9 +452,10 @@ bool f2fs_is_valid_blkaddr_raw(struct f2fs_sb_info *sbi,
> /*
> * Readahead CP/NAT/SIT/SSA/POR pages
> */
> -int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> - int type, bool sync)
> +int f2fs_ra_meta_caches(struct f2fs_sb_info *sbi, block_t start,
> + int nrpages, int type, bool sync)
> {
> + struct f2fs_cached_block_list *cache = META_CACHE(sbi);
> block_t blkno = start;
> struct f2fs_io_info fio = {
> .sbi = sbi,
> @@ -458,6 +465,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> .encrypted_page = NULL,
> .in_list = 0,
> .is_por = (type == META_POR) ? 1 : 0,
> + .is_cache = 1,
> };
> struct blk_plug plug;
> int err;
> @@ -467,7 +475,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
>
> blk_start_plug(&plug);
> for (; nrpages-- > 0; blkno++) {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_is_valid_blkaddr(sbi, blkno, type))
> goto out;
> @@ -494,62 +502,58 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> fio.new_blkaddr = blkno;
> break;
> default:
> - BUG();
> + f2fs_bug_on(sbi, 1);
> }
>
> - folio = f2fs_grab_cache_folio(META_MAPPING(sbi),
> - fio.new_blkaddr, false);
> - if (IS_ERR(folio))
> + entry = f2fs_grab_cache(cache, fio.new_blkaddr,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(entry))
> continue;
> - if (folio_test_uptodate(folio)) {
> - f2fs_folio_put(folio, true);
> + if (f2fs_cache_test_uptodate(entry)) {
> + f2fs_put_cache(entry, true);
> continue;
> }
>
> - fio.folio = folio;
> - err = f2fs_submit_page_bio(&fio);
> - f2fs_folio_put(folio, err ? true : false);
> + fio.cache_entry = entry;
> + err = f2fs_submit_cache_read(&fio);
> + f2fs_put_cache(entry, err ? true : false);
>
> if (!err)
> f2fs_update_iostat(sbi, NULL, FS_META_READ_IO,
> - F2FS_BLKSIZE);
> + sbi->blocksize);
> }
> out:
> blk_finish_plug(&plug);
> return blkno - start;
> }
>
> -void f2fs_ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index,
> - unsigned int ra_blocks)
> +void f2fs_ra_meta_caches_cond(struct f2fs_sb_info *sbi, pgoff_t index,
> + unsigned int ra_blocks)
> {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> bool readahead = false;
>
> if (ra_blocks == RECOVERY_MIN_RA_BLOCKS)
> return;
>
> - folio = filemap_get_folio(META_MAPPING(sbi), index);
> - if (IS_ERR(folio) || !folio_test_uptodate(folio))
> + entry = f2fs_find_cache(META_CACHE(sbi), index);
> + if (IS_ERR(entry) || !f2fs_cache_test_uptodate(entry))
> readahead = true;
> - f2fs_folio_put(folio, false);
> + f2fs_put_cache(entry, false);
>
> if (readahead)
> - f2fs_ra_meta_pages(sbi, index, ra_blocks, META_POR, true);
> + f2fs_ra_meta_caches(sbi, index, ra_blocks, META_POR, true);
> }
>
> -static bool __f2fs_write_meta_folio(struct folio *folio,
> - struct writeback_control *wbc,
> +static bool __f2fs_write_meta_cache(struct f2fs_cached_block *entry,
> enum iostat_type io_type)
> {
> - struct f2fs_sb_info *sbi = F2FS_F_SB(folio);
> -
> - trace_f2fs_writepage(folio, META);
> + struct f2fs_sb_info *sbi = entry->cache->sbi;
>
> if (unlikely(f2fs_cp_error(sbi))) {
> if (is_sbi_flag_set(sbi, SBI_IS_CLOSE)) {
> - folio_clear_uptodate(folio);
> - dec_page_count(sbi, F2FS_DIRTY_META);
> - folio_unlock(folio);
> + f2fs_force_clear_cache_dirty(entry);
> + f2fs_unlock_cache(entry);
> return true;
> }
> goto redirty_out;
> @@ -557,10 +561,10 @@ static bool __f2fs_write_meta_folio(struct folio *folio,
> if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
> goto redirty_out;
>
> - f2fs_do_write_meta_page(sbi, folio, io_type);
> + f2fs_do_write_meta_cache(sbi, entry, io_type);
> dec_page_count(sbi, F2FS_DIRTY_META);
>
> - folio_unlock(folio);
> + f2fs_unlock_cache(entry);
>
> if (unlikely(f2fs_cp_error(sbi)))
> f2fs_submit_merged_write(sbi, META);
> @@ -568,101 +572,89 @@ static bool __f2fs_write_meta_folio(struct folio *folio,
> return true;
>
> redirty_out:
> - folio_redirty_for_writepage(wbc, folio);
> + f2fs_cache_set_dirty(entry);
> return false;
> }
>
> -static int f2fs_write_meta_pages(struct address_space *mapping,
> - struct writeback_control *wbc)
> +void f2fs_write_meta_caches(struct f2fs_sb_info *sbi)
> {
> - struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
> struct f2fs_lock_context lc;
> - long diff, written;
> + long nr_to_write = LONG_MAX;
>
> if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
> - goto skip_write;
> + return;
>
> - /* collect a number of dirty meta pages and write together */
> - if (wbc->sync_mode != WB_SYNC_ALL &&
> - get_pages(sbi, F2FS_DIRTY_META) <
> - nr_pages_to_skip(sbi, META))
> - goto skip_write;
> + /* collect a number of dirty meta caches and write together */
> + if (get_pages(sbi, F2FS_DIRTY_META) <
> + nr_pages_to_skip(sbi, META))
> + return;
>
> - /* if locked failed, cp will flush dirty pages instead */
> + /* if locked failed, cp will flush dirty caches instead */
> if (!f2fs_down_write_trylock_trace(&sbi->cp_global_sem, &lc))
> - goto skip_write;
> + return;
>
> - trace_f2fs_writepages(mapping->host, wbc, META);
> - diff = nr_pages_to_write(sbi, META, wbc);
> - written = f2fs_sync_meta_pages(sbi, wbc->nr_to_write, FS_META_IO);
> + nr_to_write = adjust_flush_cache_number(sbi, META);
> + f2fs_sync_meta_caches(sbi, nr_to_write, false, FS_META_IO);
> f2fs_up_write_trace(&sbi->cp_global_sem, &lc);
> - wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff);
> - return 0;
> -
> -skip_write:
> - wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_META);
> - trace_f2fs_writepages(mapping->host, wbc, META);
> - return 0;
> }
>
> -long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, long nr_to_write,
> - enum iostat_type io_type)
> +long f2fs_sync_meta_caches(struct f2fs_sb_info *sbi, long nr_to_write,
> + bool sync, enum iostat_type io_type)
> {
> - struct address_space *mapping = META_MAPPING(sbi);
> pgoff_t index = 0, prev = ULONG_MAX;
> - struct folio_batch fbatch;
> + struct f2fs_cached_block *entries[F2FS_ONSTACK_CACHES];
> long nwritten = 0;
> - int nr_folios;
> - struct writeback_control wbc = {};
> + int nr;
> struct blk_plug plug;
> -
> - folio_batch_init(&fbatch);
> + bool background = nr_to_write != LONG_MAX;
>
> blk_start_plug(&plug);
>
> - while ((nr_folios = filemap_get_folios_tag(mapping, &index,
> - (pgoff_t)-1,
> - PAGECACHE_TAG_DIRTY, &fbatch))) {
> + while ((nr = f2fs_cache_gang_lookup_tag(META_CACHE(sbi), entries,
> + &index, F2FS_ONSTACK_CACHES, F2FS_CACHE_TAG_DIRTY))) {
> int i;
>
> - for (i = 0; i < nr_folios; i++) {
> - struct folio *folio = fbatch.folios[i];
> + for (i = 0; i < nr; i++) {
> + struct f2fs_cached_block *entry = entries[i];
> +
> + if (background && unlikely(freezing(current))) {
> + f2fs_cache_gang_release(entries, nr);
> + goto stop;
> + }
>
> - if (nr_to_write != LONG_MAX && i != 0 &&
> - folio->index != prev +
> - folio_nr_pages(fbatch.folios[i-1])) {
> - folio_batch_release(&fbatch);
> + if (background && i != 0 &&
> + entry->index != prev + 1) {
> + f2fs_cache_gang_release(entries, nr);
> goto stop;
> }
>
> - folio_lock(folio);
> + f2fs_lock_cache(entry);
>
> - if (unlikely(!is_meta_folio(folio))) {
> + if (unlikely(!f2fs_is_meta_cache(entry))) {
> continue_unlock:
> - folio_unlock(folio);
> + f2fs_unlock_cache(entry);
> continue;
> }
> - if (!folio_test_dirty(folio)) {
> + if (!f2fs_cache_test_dirty(entry)) {
> /* someone wrote it for us */
> goto continue_unlock;
> }
>
> - f2fs_folio_wait_writeback(folio, META, true, true);
> + f2fs_cache_wait_writeback(entry);
>
> - if (!folio_clear_dirty_for_io(folio))
> + if (!f2fs_clear_cache_dirty(entry))
> goto continue_unlock;
>
> - if (!__f2fs_write_meta_folio(folio, &wbc,
> - io_type)) {
> - folio_unlock(folio);
> + if (!__f2fs_write_meta_cache(entry, io_type)) {
> + f2fs_unlock_cache(entry);
> break;
> }
> - nwritten += folio_nr_pages(folio);
> - prev = folio->index;
> + nwritten += sbi->blocksize;
> + prev = entry->index;
> if (unlikely(nwritten >= nr_to_write))
> break;
> }
> - folio_batch_release(&fbatch);
> + f2fs_cache_gang_release(entries, nr);
> cond_resched();
> }
> stop:
> @@ -674,29 +666,6 @@ long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, long nr_to_write,
> return nwritten;
> }
>
> -static bool f2fs_dirty_meta_folio(struct address_space *mapping,
> - struct folio *folio)
> -{
> - trace_f2fs_set_page_dirty(folio, META);
> -
> - if (!folio_test_uptodate(folio))
> - folio_mark_uptodate(folio);
> - if (filemap_dirty_folio(mapping, folio)) {
> - inc_page_count(F2FS_M_SB(mapping), F2FS_DIRTY_META);
> - folio_set_f2fs_reference(folio);
> - return true;
> - }
> - return false;
> -}
> -
> -const struct address_space_operations f2fs_meta_aops = {
> - .writepages = f2fs_write_meta_pages,
> - .dirty_folio = f2fs_dirty_meta_folio,
> - .invalidate_folio = f2fs_invalidate_folio,
> - .release_folio = f2fs_release_folio,
> - .migrate_folio = filemap_migrate_folio,
> -};
> -
> static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino,
> unsigned int devidx, int type)
> {
> @@ -1036,20 +1005,20 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
> start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi);
> orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi);
>
> - f2fs_ra_meta_pages(sbi, start_blk, orphan_blocks, META_CP, true);
> + f2fs_ra_meta_caches(sbi, start_blk, orphan_blocks, META_CP, true);
>
> for (i = 0; i < orphan_blocks; i++) {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> struct f2fs_orphan_block *orphan_blk;
> unsigned int entry_count;
>
> - folio = f2fs_get_meta_folio(sbi, start_blk + i);
> - if (IS_ERR(folio)) {
> - err = PTR_ERR(folio);
> + entry = f2fs_get_meta_cache(sbi, start_blk + i);
> + if (IS_ERR(entry)) {
> + err = PTR_ERR(entry);
> goto out;
> }
>
> - orphan_blk = folio_address(folio);
> + orphan_blk = cache_address(entry);
> entry_count = le32_to_cpu(orphan_blk->entry_count);
> if (entry_count > F2FS_ORPHANS_PER_BLOCK) {
> f2fs_err(sbi, "invalid orphan inode entry count %u",
> @@ -1057,7 +1026,7 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
> set_sbi_flag(sbi, SBI_NEED_FSCK);
> f2fs_handle_error(sbi, ERROR_INCONSISTENT_ORPHAN);
> err = -EFSCORRUPTED;
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> goto out;
> }
>
> @@ -1066,11 +1035,11 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
>
> err = recover_orphan_inode(sbi, ino);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> goto out;
> }
> }
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> }
> /* clear Orphan Flag */
> clear_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG);
> @@ -1087,9 +1056,9 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
> unsigned int nentries = 0;
> unsigned short index = 1;
> unsigned short orphan_blocks;
> - struct folio *folio = NULL;
> struct ino_entry *orphan = NULL;
> struct inode_management *im = &sbi->im[ORPHAN_INO];
> + struct f2fs_cached_block *entry = NULL;
>
> orphan_blocks = GET_ORPHAN_BLOCKS(im->ino_num);
>
> @@ -1102,9 +1071,9 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
>
> /* loop for each orphan inode entry and write them in journal block */
> list_for_each_entry(orphan, head, list) {
> - if (!folio) {
> - folio = f2fs_grab_meta_folio(sbi, start_blk++);
> - orphan_blk = folio_address(folio);
> + if (!entry) {
> + entry = f2fs_grab_meta_cache(sbi, start_blk++);
> + orphan_blk = (struct f2fs_orphan_block *)cache_address(entry);
> memset(orphan_blk, 0, sizeof(*orphan_blk));
> }
>
> @@ -1119,20 +1088,20 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
> orphan_blk->blk_addr = cpu_to_le16(index);
> orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
> orphan_blk->entry_count = cpu_to_le32(nentries);
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> index++;
> nentries = 0;
> - folio = NULL;
> + entry = NULL;
> }
> }
>
> - if (folio) {
> + if (entry) {
> orphan_blk->blk_addr = cpu_to_le16(index);
> orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
> orphan_blk->entry_count = cpu_to_le32(nentries);
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> }
> }
>
> @@ -1151,29 +1120,29 @@ static __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *ckpt)
> }
>
> static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
> - struct f2fs_checkpoint **cp_block, struct folio **cp_folio,
> + struct f2fs_checkpoint **cp_block, struct f2fs_cached_block **cp_entry,
> unsigned long long *version)
> {
> size_t crc_offset = 0;
> __u32 crc;
>
> - *cp_folio = f2fs_get_meta_folio(sbi, cp_addr);
> - if (IS_ERR(*cp_folio))
> - return PTR_ERR(*cp_folio);
> + *cp_entry = f2fs_get_meta_cache(sbi, cp_addr);
> + if (IS_ERR(*cp_entry))
> + return PTR_ERR(*cp_entry);
>
> - *cp_block = folio_address(*cp_folio);
> + *cp_block = (struct f2fs_checkpoint *)cache_address(*cp_entry);
>
> crc_offset = le32_to_cpu((*cp_block)->checksum_offset);
> if (crc_offset < CP_MIN_CHKSUM_OFFSET ||
> crc_offset > CP_CHKSUM_OFFSET) {
> - f2fs_folio_put(*cp_folio, true);
> + f2fs_put_cache(*cp_entry, true);
> f2fs_warn(sbi, "invalid crc_offset: %zu", crc_offset);
> return -EINVAL;
> }
>
> crc = f2fs_checkpoint_chksum(*cp_block);
> if (crc != cur_cp_crc(*cp_block)) {
> - f2fs_folio_put(*cp_folio, true);
> + f2fs_put_cache(*cp_entry, true);
> f2fs_warn(sbi, "invalid crc value");
> return -EINVAL;
> }
> @@ -1182,17 +1151,17 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
> return 0;
> }
>
> -static struct folio *validate_checkpoint(struct f2fs_sb_info *sbi,
> +static struct f2fs_cached_block *validate_checkpoint(struct f2fs_sb_info *sbi,
> block_t cp_addr, unsigned long long *version)
> {
> - struct folio *cp_folio_1 = NULL, *cp_folio_2 = NULL;
> + struct f2fs_cached_block *cp_entry_1 = NULL, *cp_entry_2 = NULL;
> struct f2fs_checkpoint *cp_block = NULL;
> unsigned long long cur_version = 0, pre_version = 0;
> unsigned int cp_blocks;
> int err;
>
> err = get_checkpoint_version(sbi, cp_addr, &cp_block,
> - &cp_folio_1, version);
> + &cp_entry_1, version);
> if (err)
> return NULL;
>
> @@ -1207,19 +1176,20 @@ static struct folio *validate_checkpoint(struct f2fs_sb_info *sbi,
>
> cp_addr += cp_blocks - 1;
> err = get_checkpoint_version(sbi, cp_addr, &cp_block,
> - &cp_folio_2, version);
> + &cp_entry_2, version);
> if (err)
> goto invalid_cp;
> cur_version = *version;
>
> if (cur_version == pre_version) {
> *version = cur_version;
> - f2fs_folio_put(cp_folio_2, true);
> - return cp_folio_1;
> + f2fs_put_cache(cp_entry_2, true);
> + return cp_entry_1;
> }
> - f2fs_folio_put(cp_folio_2, true);
> + f2fs_put_cache(cp_entry_2, true);
> invalid_cp:
> - f2fs_folio_put(cp_folio_1, true);
> + if (cp_entry_1)
> + f2fs_put_cache(cp_entry_1, true);
> return NULL;
> }
>
> @@ -1227,7 +1197,7 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
> {
> struct f2fs_checkpoint *cp_block;
> struct f2fs_super_block *fsb = sbi->raw_super;
> - struct folio *cp1, *cp2, *cur_folio;
> + struct f2fs_cached_block *cp1 = NULL, *cp2 = NULL, *cur_entry;
> unsigned long blk_size = sbi->blocksize;
> unsigned long long cp1_version = 0, cp2_version = 0;
> unsigned long long cp_start_blk_no;
> @@ -1254,22 +1224,22 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
>
> if (cp1 && cp2) {
> if (ver_after(cp2_version, cp1_version))
> - cur_folio = cp2;
> + cur_entry = cp2;
> else
> - cur_folio = cp1;
> + cur_entry = cp1;
> } else if (cp1) {
> - cur_folio = cp1;
> + cur_entry = cp1;
> } else if (cp2) {
> - cur_folio = cp2;
> + cur_entry = cp2;
> } else {
> err = -EFSCORRUPTED;
> goto fail_no_cp;
> }
>
> - cp_block = folio_address(cur_folio);
> + cp_block = (struct f2fs_checkpoint *)cache_address(cur_entry);
> memcpy(sbi->ckpt, cp_block, blk_size);
>
> - if (cur_folio == cp1)
> + if (cur_entry == cp1)
> sbi->cur_cp_pack = 1;
> else
> sbi->cur_cp_pack = 2;
> @@ -1284,30 +1254,35 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
> goto done;
>
> cp_blk_no = le32_to_cpu(fsb->cp_blkaddr);
> - if (cur_folio == cp2)
> + if (cur_entry == cp2)
> cp_blk_no += BIT(le32_to_cpu(fsb->log_blocks_per_seg));
>
> for (i = 1; i < cp_blks; i++) {
> + struct f2fs_cached_block *cur_entry_payload;
> void *sit_bitmap_ptr;
> unsigned char *ckpt = (unsigned char *)sbi->ckpt;
>
> - cur_folio = f2fs_get_meta_folio(sbi, cp_blk_no + i);
> - if (IS_ERR(cur_folio)) {
> - err = PTR_ERR(cur_folio);
> + cur_entry_payload = f2fs_get_meta_cache(sbi, cp_blk_no + i);
> + if (IS_ERR(cur_entry_payload)) {
> + err = PTR_ERR(cur_entry_payload);
> goto free_fail_no_cp;
> }
> - sit_bitmap_ptr = folio_address(cur_folio);
> + sit_bitmap_ptr = cache_address(cur_entry_payload);
> memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
> - f2fs_folio_put(cur_folio, true);
> + f2fs_put_cache(cur_entry_payload, true);
> }
> done:
> - f2fs_folio_put(cp1, true);
> - f2fs_folio_put(cp2, true);
> + if (cp1)
> + f2fs_put_cache(cp1, true);
In f2fs_put_cache(x, y),
if (!x)
return;
> + if (cp2)
> + f2fs_put_cache(cp2, true);
> return 0;
>
> free_fail_no_cp:
> - f2fs_folio_put(cp1, true);
> - f2fs_folio_put(cp2, true);
> + if (cp1)
> + f2fs_put_cache(cp1, true);
> + if (cp2)
> + f2fs_put_cache(cp2, true);
> fail_no_cp:
> kvfree(sbi->ckpt);
> return err;
> @@ -1621,7 +1596,7 @@ void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type)
> break;
>
> if (type == F2FS_DIRTY_META)
> - f2fs_sync_meta_pages(sbi, LONG_MAX, FS_CP_META_IO);
> + f2fs_sync_meta_caches(sbi, LONG_MAX, true, FS_META_IO);
> else if (type == F2FS_WB_CP_DATA)
> f2fs_submit_merged_write(sbi, DATA);
>
> @@ -1700,31 +1675,24 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> static void commit_checkpoint(struct f2fs_sb_info *sbi,
> void *src, block_t blk_addr)
> {
> - struct writeback_control wbc = {};
> -
> - /*
> - * filemap_get_folios_tag and folio_lock again will take
> - * some extra time. Therefore, f2fs_update_meta_pages and
> - * f2fs_sync_meta_pages are combined in this function.
> - */
> - struct folio *folio = f2fs_grab_meta_folio(sbi, blk_addr);
> + struct f2fs_cached_block *entry = f2fs_grab_meta_cache(sbi, blk_addr);
>
> - memcpy(folio_address(folio), src, PAGE_SIZE);
> + memcpy(cache_address(entry), src, F2FS_BLKSIZE);
>
> - folio_mark_dirty(folio);
> - if (unlikely(!folio_clear_dirty_for_io(folio)))
> + f2fs_mark_cache_dirty(entry);
> + if (unlikely(!f2fs_clear_cache_dirty(entry)))
> f2fs_bug_on(sbi, 1);
>
> /* writeout cp pack 2 page */
> - if (unlikely(!__f2fs_write_meta_folio(folio, &wbc, FS_CP_META_IO))) {
> + if (unlikely(!__f2fs_write_meta_cache(entry, FS_CP_META_IO))) {
> if (f2fs_cp_error(sbi)) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> return;
> }
> f2fs_bug_on(sbi, true);
> }
>
> - f2fs_folio_put(folio, false);
> + f2fs_put_cache(entry, false);
>
> /* submit checkpoint (with barrier if NOBARRIER is not set) */
> f2fs_submit_merged_write(sbi, META_FLUSH);
> @@ -1793,7 +1761,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> int err;
>
> /* Flush all the NAT/SIT pages */
> - f2fs_sync_meta_pages(sbi, LONG_MAX, FS_CP_META_IO);
> + f2fs_sync_meta_caches(sbi, LONG_MAX, true, FS_CP_META_IO);
>
> stat_cp_time(cpc, CP_TIME_SYNC_META);
>
> @@ -1892,7 +1860,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> }
>
> /* Here, we have one bio having CP pack except cp pack 2 page */
> - f2fs_sync_meta_pages(sbi, LONG_MAX, FS_CP_META_IO);
> + f2fs_sync_meta_caches(sbi, LONG_MAX, true, FS_CP_META_IO);
> stat_cp_time(cpc, CP_TIME_SYNC_CP_META);
>
> /* Wait for all dirty meta pages to be submitted for IO */
> @@ -1919,10 +1887,10 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> * used for migration of encrypted, verity or compressed inode's blocks.
> */
> if (f2fs_sb_has_encrypt(sbi) || f2fs_sb_has_verity(sbi) ||
> - f2fs_sb_has_compression(sbi))
> - f2fs_bug_on(sbi,
> - invalidate_inode_pages2_range(META_MAPPING(sbi),
> - MAIN_BLKADDR(sbi), MAX_BLKADDR(sbi) - 1));
> + f2fs_sb_has_compression(sbi)) {
> + f2fs_truncate_meta_caches(sbi, MAIN_BLKADDR(sbi),
> + MAX_BLKADDR(sbi) - MAIN_BLKADDR(sbi));
> + }
>
> f2fs_release_ino_entry(sbi, false);
>
> diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
> index 91855d91bbdd..bb749f6257a1 100644
> --- a/fs/f2fs/compress.c
> +++ b/fs/f2fs/compress.c
> @@ -1150,7 +1150,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
> f2fs_compress_ctx_add_page(cc, folio);
>
> if (!folio_test_uptodate(folio)) {
> - f2fs_handle_page_eio(sbi, folio, DATA);
> + f2fs_handle_page_eio(sbi, folio->index, DATA);
> release_and_retry:
> f2fs_put_rpages(cc);
> f2fs_unlock_rpages(cc, i + 1);
> @@ -1359,7 +1359,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
> fio.old_blkaddr = data_blkaddr(dn.inode, dn.node_folio,
> dn.ofs_in_node + i + 1);
>
> - /* wait for GCed page writeback via META_MAPPING */
> + /* wait for GCed page writeback via generic cache */
> f2fs_wait_on_block_writeback(inode, fio.old_blkaddr);
>
> if (fio.encrypted) {
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 110282bb8dcd..92c3293f0a1e 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -65,8 +65,7 @@ bool f2fs_is_cp_guaranteed(const struct folio *folio)
>
> inode = mapping->host;
>
> - if (inode->i_ino == F2FS_META_INO(sbi) ||
> - inode->i_ino == F2FS_NODE_INO(sbi) ||
> + if (inode->i_ino == F2FS_NODE_INO(sbi) ||
> S_ISDIR(inode->i_mode))
> return true;
>
> @@ -84,9 +83,6 @@ static enum count_type __read_io_type(struct folio *folio)
> struct inode *inode = mapping->host;
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
>
> - if (inode->i_ino == F2FS_META_INO(sbi))
> - return F2FS_RD_META;
> -
> if (inode->i_ino == F2FS_NODE_INO(sbi))
> return F2FS_RD_NODE;
> }
> @@ -1452,7 +1448,7 @@ static void f2fs_submit_page_read(struct inode *inode, struct fsverity_info *vi,
> bio = f2fs_grab_read_bio(inode, vi, blkaddr, 1, op_flags, folio->index,
> for_write);
>
> - /* wait for GCed page writeback via META_MAPPING */
> + /* wait for GCed page writeback via generic cache */
> f2fs_wait_on_block_writeback(inode, blkaddr);
>
> if (!bio_add_folio(bio, folio, PAGE_SIZE, 0))
> @@ -3110,7 +3106,7 @@ static void f2fs_readahead(struct readahead_control *rac)
> int f2fs_encrypt_one_page(struct f2fs_io_info *fio)
> {
> struct inode *inode = fio_inode(fio);
> - struct folio *mfolio;
> + struct f2fs_cached_block *entry;
> struct page *page;
>
> if (!f2fs_encrypted_file(inode))
> @@ -3126,12 +3122,13 @@ int f2fs_encrypt_one_page(struct f2fs_io_info *fio)
> if (IS_ERR(fio->encrypted_page))
> return PTR_ERR(fio->encrypted_page);
>
> - mfolio = filemap_lock_folio(META_MAPPING(fio->sbi), fio->old_blkaddr);
> - if (!IS_ERR(mfolio)) {
> - if (folio_test_uptodate(mfolio))
> - memcpy(folio_address(mfolio),
> - page_address(fio->encrypted_page), PAGE_SIZE);
> - f2fs_folio_put(mfolio, true);
> + entry = f2fs_find_cache(META_CACHE(fio->sbi), fio->old_blkaddr);
> + if (!IS_ERR(entry)) {
> + f2fs_lock_cache(entry);
> + if (f2fs_cache_test_uptodate(entry))
> + memcpy(cache_address(entry), page_address(fio->encrypted_page),
> + F2FS_BLKSIZE);
> + f2fs_put_cache(entry, true);
> }
> return 0;
> }
> @@ -3297,7 +3294,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
> goto out_writepage;
> }
>
> - /* wait for GCed page writeback via META_MAPPING */
> + /* wait for GCed page writeback via generic cache */
> if (fio->meta_gc)
> f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);
>
> @@ -4380,9 +4377,7 @@ void f2fs_invalidate_folio(struct folio *folio, size_t offset, size_t length)
> return;
>
> if (folio_test_dirty(folio)) {
> - if (inode->i_ino == F2FS_META_INO(sbi)) {
> - dec_page_count(sbi, F2FS_DIRTY_META);
> - } else if (inode->i_ino == F2FS_NODE_INO(sbi)) {
> + if (inode->i_ino == F2FS_NODE_INO(sbi)) {
> dec_page_count(sbi, F2FS_DIRTY_NODES);
> } else {
> inode_dec_dirty_pages(inode);
> diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
> index ff379aff4472..14059a50739c 100644
> --- a/fs/f2fs/debug.c
> +++ b/fs/f2fs/debug.c
> @@ -224,8 +224,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
> si->dirty_count = dirty_segments(sbi);
> if (sbi->node_inode)
> si->node_pages = NODE_MAPPING(sbi)->nrpages;
> - if (sbi->meta_inode)
> - si->meta_pages = META_MAPPING(sbi)->nrpages;
> + si->meta_caches = META_CACHE(sbi)->num_entries;
> #ifdef CONFIG_F2FS_FS_COMPRESSION
> if (sbi->compress_inode) {
> si->compress_pages = COMPRESS_MAPPING(sbi)->nrpages;
> @@ -388,11 +387,8 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
>
> si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
> }
> - if (sbi->meta_inode) {
> - unsigned long npages = META_MAPPING(sbi)->nrpages;
> -
> - si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
> - }
> + si->page_mem += (unsigned long long)META_CACHE(sbi)->num_entries << PAGE_SHIFT;
> + si->cache_mem += META_CACHE(sbi)->num_entries * sizeof(struct f2fs_cached_block);
> #ifdef CONFIG_F2FS_FS_COMPRESSION
> if (sbi->compress_inode) {
> unsigned long npages = COMPRESS_MAPPING(sbi)->nrpages;
> @@ -708,7 +704,7 @@ static int stat_show(struct seq_file *s, void *v)
> seq_printf(s, " - quota data: %4d in quota files:%4d\n",
> si->ndirty_qdata, si->nquota_files);
> seq_printf(s, " - meta: %4d in %4d\n",
> - si->ndirty_meta, si->meta_pages);
> + si->ndirty_meta, si->meta_caches);
> seq_printf(s, " - imeta: %4d\n",
> si->ndirty_imeta);
> seq_printf(s, " - fsync mark: %4lld\n",
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 6e20b3586f26..9a353dcd6658 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1828,7 +1828,6 @@ struct f2fs_sb_info {
> struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */
> int cur_cp_pack; /* remain current cp pack */
> spinlock_t cp_lock; /* for flag in ckpt */
> - struct inode *meta_inode; /* cache meta blocks */
> struct f2fs_rwsem cp_global_sem; /* checkpoint procedure lock */
> struct f2fs_rwsem cp_rwsem; /* blocking FS operations */
> struct f2fs_rwsem node_write; /* locking node writes */
> @@ -1873,7 +1872,6 @@ struct f2fs_sb_info {
> unsigned int blocksize; /* block size */
> unsigned int root_ino_num; /* root inode number*/
> unsigned int node_ino_num; /* node inode number*/
> - unsigned int meta_ino_num; /* meta inode number*/
> unsigned int log_blocks_per_seg; /* log2 blocks per segment */
> unsigned int blocks_per_seg; /* blocks per segment */
> unsigned int segs_per_sec; /* segments per section */
> @@ -2319,9 +2317,9 @@ static inline struct dirty_seglist_info *DIRTY_I(struct f2fs_sb_info *sbi)
> return (struct dirty_seglist_info *)(SM_I(sbi)->dirty_info);
> }
>
> -static inline struct address_space *META_MAPPING(struct f2fs_sb_info *sbi)
> +static inline bool f2fs_is_meta_cache(struct f2fs_cached_block *entry)
> {
> - return sbi->meta_inode->i_mapping;
> + return entry->cache && entry->cache == META_CACHE(entry->cache->sbi);
> }
>
> static inline struct address_space *NODE_MAPPING(struct f2fs_sb_info *sbi)
> @@ -2329,11 +2327,6 @@ static inline struct address_space *NODE_MAPPING(struct f2fs_sb_info *sbi)
> return sbi->node_inode->i_mapping;
> }
>
> -static inline bool is_meta_folio(struct folio *folio)
> -{
> - return folio->mapping == META_MAPPING(F2FS_F_SB(folio));
> -}
> -
> static inline bool is_node_folio(struct folio *folio)
> {
> return folio->mapping == NODE_MAPPING(F2FS_F_SB(folio));
> @@ -4057,9 +4050,9 @@ bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid);
> void f2fs_alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid);
> void f2fs_alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid);
> int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink);
> -int f2fs_recover_inline_xattr(struct inode *inode, struct folio *folio);
> -int f2fs_recover_xattr_data(struct inode *inode, struct folio *folio);
> -int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio);
> +int f2fs_recover_inline_xattr(struct inode *inode, struct f2fs_cached_block *entry);
> +int f2fs_recover_xattr_data(struct inode *inode, struct f2fs_cached_block *entry);
> +int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct f2fs_cached_block *entry);
> int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
> unsigned int segno, struct f2fs_summary_block *sum);
> int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
> @@ -4109,11 +4102,13 @@ int f2fs_allocate_new_segments(struct f2fs_sb_info *sbi);
> int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range);
> bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi,
> struct cp_control *cpc);
> -struct folio *f2fs_get_sum_folio(struct f2fs_sb_info *sbi, unsigned int segno);
> +struct f2fs_cached_block *f2fs_get_sum_cache(struct f2fs_sb_info *sbi,
> + unsigned int segno);
> void f2fs_update_meta_page(struct f2fs_sb_info *sbi, void *src,
> block_t blk_addr);
> -void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct folio *folio,
> - enum iostat_type io_type);
> +void f2fs_do_write_meta_cache(struct f2fs_sb_info *sbi,
> + struct f2fs_cached_block *entry,
> + enum iostat_type io_type);
> void f2fs_do_write_node_page(unsigned int nid, struct f2fs_io_info *fio);
> void f2fs_outplace_write_data(struct dnode_of_data *dn,
> struct f2fs_io_info *fio);
> @@ -4136,8 +4131,6 @@ void f2fs_update_device_state(struct f2fs_sb_info *sbi, nid_t ino,
> block_t blkaddr, unsigned int blkcnt);
> void f2fs_folio_wait_writeback(struct folio *folio, enum page_type type,
> bool ordered, bool locked);
> -#define f2fs_wait_on_page_writeback(page, type, ordered, locked) \
> - f2fs_folio_wait_writeback(page_folio(page), type, ordered, locked)
> void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr);
> void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
> block_t len);
> @@ -4203,20 +4196,21 @@ void f2fs_unlock_op(struct f2fs_sb_info *sbi, struct f2fs_lock_context *lc);
> void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io,
> unsigned char reason);
> void f2fs_flush_ckpt_thread(struct f2fs_sb_info *sbi);
> -struct folio *f2fs_grab_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index);
> -struct folio *f2fs_get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index);
> -struct folio *f2fs_get_meta_folio_retry(struct f2fs_sb_info *sbi, pgoff_t index);
> -struct folio *f2fs_get_tmp_folio(struct f2fs_sb_info *sbi, pgoff_t index);
> +struct f2fs_cached_block *f2fs_grab_meta_cache(struct f2fs_sb_info *sbi, pgoff_t index);
> +struct f2fs_cached_block *f2fs_get_meta_cache(struct f2fs_sb_info *sbi, pgoff_t index);
> +struct f2fs_cached_block *f2fs_get_meta_cache_retry(struct f2fs_sb_info *sbi, pgoff_t index);
> +struct f2fs_cached_block *f2fs_get_tmp_cache(struct f2fs_sb_info *sbi, pgoff_t index);
> bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
> block_t blkaddr, int type);
> bool f2fs_is_valid_blkaddr_raw(struct f2fs_sb_info *sbi,
> block_t blkaddr, int type);
> -int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> +int f2fs_ra_meta_caches(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> int type, bool sync);
> -void f2fs_ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index,
> +void f2fs_ra_meta_caches_cond(struct f2fs_sb_info *sbi, pgoff_t index,
> unsigned int ra_blocks);
> -long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, long nr_to_write,
> - enum iostat_type io_type);
> +void f2fs_write_meta_caches(struct f2fs_sb_info *sbi);
> +long f2fs_sync_meta_caches(struct f2fs_sb_info *sbi, long nr_to_write,
> + bool sync, enum iostat_type io_type);
> void f2fs_add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type);
> void f2fs_remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type);
> void f2fs_release_ino_entry(struct f2fs_sb_info *sbi, bool all);
> @@ -4403,7 +4397,7 @@ struct f2fs_stat_info {
> unsigned int bimodal, avg_vblocks;
> int util_free, util_valid, util_invalid;
> int rsvd_segs, overp_segs;
> - int dirty_count, node_pages, meta_pages, compress_pages;
> + int dirty_count, node_pages, meta_caches, compress_pages;
> int compress_page_hit;
> int prefree_count, free_segs, free_secs;
> int cp_call_count[MAX_CALL_TYPE], cp_count;
> @@ -4605,7 +4599,6 @@ extern const struct file_operations f2fs_file_operations;
> extern const struct inode_operations f2fs_file_inode_operations;
> extern const struct address_space_operations f2fs_dblock_aops;
> extern const struct address_space_operations f2fs_node_aops;
> -extern const struct address_space_operations f2fs_meta_aops;
> extern const struct inode_operations f2fs_dir_inode_operations;
> extern const struct inode_operations f2fs_symlink_inode_operations;
> extern const struct inode_operations f2fs_encrypted_symlink_inode_operations;
> @@ -4626,7 +4619,7 @@ int f2fs_convert_inline_folio(struct dnode_of_data *dn, struct folio *folio);
> int f2fs_convert_inline_inode(struct inode *inode);
> int f2fs_try_convert_inline_dir(struct inode *dir, struct dentry *dentry);
> int f2fs_write_inline_data(struct inode *inode, struct folio *folio);
> -int f2fs_recover_inline_data(struct inode *inode, struct folio *nfolio);
> +int f2fs_recover_inline_data(struct inode *inode, struct f2fs_cached_block *entry);
> struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir,
> const struct f2fs_filename *fname, struct folio **res_folio,
> bool use_hash);
> @@ -5186,10 +5179,8 @@ static inline void f2fs_schedule_timeout_killable(long timeout, bool io)
> }
>
> static inline void f2fs_handle_page_eio(struct f2fs_sb_info *sbi,
> - struct folio *folio, enum page_type type)
> + pgoff_t ofs, enum page_type type)
> {
> - pgoff_t ofs = folio->index;
> -
> if (unlikely(f2fs_cp_error(sbi)))
> return;
>
> @@ -5224,36 +5215,10 @@ static inline bool f2fs_is_readonly(struct f2fs_sb_info *sbi)
> return f2fs_sb_has_readonly(sbi) || f2fs_readonly(sbi->sb);
> }
>
> -static inline void f2fs_truncate_meta_inode_pages(struct f2fs_sb_info *sbi,
> - block_t blkaddr, unsigned int cnt)
> -{
> - bool need_submit = false;
> - int i = 0;
> -
> - do {
> - struct folio *folio;
> -
> - folio = filemap_get_folio(META_MAPPING(sbi), blkaddr + i);
> - if (!IS_ERR(folio)) {
> - if (folio_test_writeback(folio))
> - need_submit = true;
> - f2fs_folio_put(folio, false);
> - }
> - } while (++i < cnt && !need_submit);
> -
> - if (need_submit)
> - f2fs_submit_merged_write_cond(sbi, sbi->meta_inode,
> - NULL, 0, DATA);
> -
> - truncate_inode_pages_range(META_MAPPING(sbi),
> - F2FS_BLK_TO_BYTES((loff_t)blkaddr),
> - F2FS_BLK_END_BYTES((loff_t)(blkaddr + cnt - 1)));
> -}
> -
> static inline void f2fs_invalidate_internal_cache(struct f2fs_sb_info *sbi,
> block_t blkaddr, unsigned int len)
> {
> - f2fs_truncate_meta_inode_pages(sbi, blkaddr, len);
> + f2fs_truncate_meta_caches(sbi, blkaddr, len);
> f2fs_invalidate_compress_pages_range(sbi, blkaddr, len);
> }
>
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index a54b3ab52f1a..92daa41dd96d 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -214,7 +214,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
>
> f2fs_folio_wait_writeback(folio, DATA, false, true);
>
> - /* wait for GCed page writeback via META_MAPPING */
> + /* wait for GCed page writeback via generic cache */
> f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);
>
> /*
> @@ -2563,7 +2563,7 @@ int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,
> f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
> break;
> case F2FS_GOING_DOWN_METAFLUSH:
> - f2fs_sync_meta_pages(sbi, LONG_MAX, FS_META_IO);
> + f2fs_sync_meta_caches(sbi, LONG_MAX, true, FS_META_IO);
> f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
> break;
> case F2FS_GOING_DOWN_NEED_FSCK:
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index c4da2f31805b..54327cb2e27e 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -1066,7 +1066,7 @@ static int gc_node_segment(struct f2fs_sb_info *sbi,
> continue;
>
> if (phase == 0) {
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
> + f2fs_ra_meta_caches(sbi, NAT_BLOCK_OFFSET(nid), 1,
> META_NAT, true);
> continue;
> }
> @@ -1217,7 +1217,8 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
> struct address_space *mapping = inode->i_mapping;
> struct inode *atomic_inode = NULL;
> struct dnode_of_data dn;
> - struct folio *folio, *efolio;
> + struct folio *folio;
> + struct f2fs_cached_block *entry;
> struct f2fs_io_info fio = {
> .sbi = sbi,
> .ino = inode->i_ino,
> @@ -1227,6 +1228,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
> .op_flags = 0,
> .encrypted_page = NULL,
> .in_list = 0,
> + .is_cache = 1,
> };
> int err = 0;
>
> @@ -1285,22 +1287,21 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
>
> f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);
>
> - efolio = f2fs_filemap_get_folio(META_MAPPING(sbi), dn.data_blkaddr,
> - FGP_LOCK | FGP_CREAT, GFP_NOFS);
> - if (IS_ERR(efolio)) {
> - err = PTR_ERR(efolio);
> + entry = f2fs_grab_cache(META_CACHE(sbi), dn.data_blkaddr,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(entry)) {
> + err = PTR_ERR(entry);
> goto put_folio;
> }
>
> - fio.encrypted_page = &efolio->page;
> -
> - if (folio_test_uptodate(efolio))
> - goto put_encrypted_page;
> + if (f2fs_cache_test_uptodate(entry))
> + goto put_cache;
>
> - err = f2fs_submit_page_bio(&fio);
> + fio.cache_entry = entry;
> + err = f2fs_submit_cache_read(&fio);
> if (err)
> - goto put_encrypted_page;
> - f2fs_put_page(fio.encrypted_page, false);
> + goto put_cache;
> + f2fs_put_cache(entry, false);
> f2fs_folio_put(folio, true);
>
> f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE);
> @@ -1309,8 +1310,8 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
> if (atomic_inode)
> iput(atomic_inode);
> return 0;
> -put_encrypted_page:
> - f2fs_put_page(fio.encrypted_page, true);
> +put_cache:
> + f2fs_put_cache(entry, true);
> put_folio:
> f2fs_folio_put(folio, true);
> out_iput:
> @@ -1320,7 +1321,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
> }
>
> /*
> - * Move data block via META_MAPPING while keeping locked data page.
> + * Move data block via meta cache while keeping locked data page.
> * This can be used to move blocks, aka LBAs, directly on disk.
> */
> static int move_data_block(struct inode *inode, block_t bidx,
> @@ -1337,11 +1338,13 @@ static int move_data_block(struct inode *inode, block_t bidx,
> .op_flags = 0,
> .encrypted_page = NULL,
> .in_list = 0,
> + .is_cache = 1,
> };
> struct dnode_of_data dn;
> struct f2fs_summary sum;
> struct node_info ni;
> - struct folio *folio, *mfolio, *efolio;
> + struct folio *folio;
> + struct f2fs_cached_block *sentry, *tentry;
> block_t newaddr;
> int err = 0;
> bool lfs_mode = f2fs_lfs_mode(fio.sbi);
> @@ -1406,20 +1409,20 @@ static int move_data_block(struct inode *inode, block_t bidx,
> if (lfs_mode)
> f2fs_down_write(&fio.sbi->io_order_lock);
>
> - mfolio = f2fs_grab_cache_folio(META_MAPPING(fio.sbi),
> - fio.old_blkaddr, false);
> - if (IS_ERR(mfolio)) {
> - err = PTR_ERR(mfolio);
> + sentry = f2fs_grab_cache(META_CACHE(fio.sbi), fio.old_blkaddr,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(sentry)) {
> + err = PTR_ERR(sentry);
> goto up_out;
> }
>
> - fio.encrypted_page = folio_file_page(mfolio, fio.old_blkaddr);
> + fio.cache_entry = sentry;
>
> - /* read source block in mfolio */
> - if (!folio_test_uptodate(mfolio)) {
> - err = f2fs_submit_page_bio(&fio);
> + /* read source block in cache */
> + if (!f2fs_cache_test_uptodate(sentry)) {
> + err = f2fs_submit_cache_read(&fio);
> if (err) {
> - f2fs_folio_put(mfolio, true);
> + f2fs_put_cache(sentry, true);
> goto up_out;
> }
>
> @@ -1428,11 +1431,11 @@ static int move_data_block(struct inode *inode, block_t bidx,
> f2fs_update_iostat(fio.sbi, NULL, FS_GDATA_READ_IO,
> F2FS_BLKSIZE);
>
> - folio_lock(mfolio);
> - if (unlikely(!is_meta_folio(mfolio) ||
> - !folio_test_uptodate(mfolio))) {
> + f2fs_lock_cache(sentry);
> + if (unlikely(!f2fs_is_meta_cache(sentry) ||
> + !f2fs_cache_test_uptodate(sentry))) {
> err = -EIO;
> - f2fs_folio_put(mfolio, true);
> + f2fs_put_cache(sentry, true);
> goto up_out;
> }
> }
> @@ -1443,46 +1446,45 @@ static int move_data_block(struct inode *inode, block_t bidx,
> err = f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
> &sum, type, NULL);
> if (err) {
> - f2fs_folio_put(mfolio, true);
> + f2fs_put_cache(sentry, true);
> /* filesystem should shutdown, no need to recovery block */
> goto up_out;
> }
>
> - efolio = f2fs_filemap_get_folio(META_MAPPING(fio.sbi), newaddr,
> - FGP_LOCK | FGP_CREAT, GFP_NOFS);
> - if (IS_ERR(efolio)) {
> - err = PTR_ERR(efolio);
> - f2fs_folio_put(mfolio, true);
> + tentry = f2fs_grab_cache(META_CACHE(fio.sbi), newaddr,
> + F2FS_CACHE_LOCK_CREATE);
> + if (IS_ERR(tentry)) {
> + err = PTR_ERR(tentry);
> + f2fs_put_cache(sentry, true);
> goto recover_block;
> }
>
> - fio.encrypted_page = &efolio->page;
> + fio.cache_entry = tentry;
>
> /* write target block */
> - f2fs_wait_on_page_writeback(fio.encrypted_page, DATA, true, true);
> - memcpy(page_address(fio.encrypted_page),
> - folio_address(mfolio), PAGE_SIZE);
> - f2fs_folio_put(mfolio, true);
> + f2fs_cache_wait_writeback_cond(tentry, DATA);
> + memcpy(cache_address(tentry), cache_address(sentry), PAGE_SIZE);
> + f2fs_put_cache(sentry, true);
>
> f2fs_invalidate_internal_cache(fio.sbi, fio.old_blkaddr, 1);
>
> - set_page_dirty(fio.encrypted_page);
> - if (clear_page_dirty_for_io(fio.encrypted_page))
> + f2fs_mark_cache_dirty(tentry);
> + if (f2fs_clear_cache_dirty(tentry))
> dec_page_count(fio.sbi, F2FS_DIRTY_META);
>
> - set_page_writeback(fio.encrypted_page);
> + f2fs_start_cache_writeback(tentry);
>
> fio.op = REQ_OP_WRITE;
> fio.op_flags = REQ_SYNC;
> fio.new_blkaddr = newaddr;
> - f2fs_submit_page_write(&fio);
> + f2fs_submit_cache_write(&fio);
>
> f2fs_update_iostat(fio.sbi, NULL, FS_GC_DATA_IO, F2FS_BLKSIZE);
>
> f2fs_update_data_blkaddr(&dn, newaddr);
> set_inode_flag(inode, FI_APPEND_WRITE);
>
> - f2fs_put_page(fio.encrypted_page, true);
> + f2fs_put_cache(tentry, true);
> recover_block:
> if (err)
> f2fs_do_replace_block(fio.sbi, &sum, newaddr, fio.old_blkaddr,
> @@ -1614,7 +1616,7 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
> continue;
>
> if (phase == 0) {
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
> + f2fs_ra_meta_caches(sbi, NAT_BLOCK_OFFSET(nid), 1,
> META_NAT, true);
> continue;
> }
> @@ -1818,28 +1820,31 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, sbi->sums_per_block);
> /* readahead multi ssa blocks those have contiguous address */
> if (__is_large_section(sbi))
> - f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
> + f2fs_ra_meta_caches(sbi, GET_SUM_BLOCK(sbi, segno),
> sum_blk_cnt, META_SSA, true);
>
> /* reference all summary page */
> while (segno < end_segno) {
> - struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno);
> + struct f2fs_cached_block *sum_entry =
> + f2fs_get_sum_cache(sbi, segno);
>
> segno += sbi->sums_per_block;
> - if (IS_ERR(sum_folio)) {
> - int err = PTR_ERR(sum_folio);
> + if (IS_ERR(sum_entry)) {
> + int err = PTR_ERR(sum_entry);
>
> end_segno = segno - sbi->sums_per_block;
> segno = rounddown(start_segno, sbi->sums_per_block);
> while (segno < end_segno) {
> - sum_folio = filemap_get_folio(META_MAPPING(sbi),
> + sum_entry = f2fs_find_meta_cache(sbi,
> GET_SUM_BLOCK(sbi, segno));
> - folio_put_refs(sum_folio, 2);
> + f2fs_put_cache(sum_entry, false);
> + f2fs_put_cache(sum_entry, false);
> segno += sbi->sums_per_block;
> }
> return err;
> }
> - folio_unlock(sum_folio);
> + f2fs_unlock_cache(sum_entry);
> +
> }
>
> blk_start_plug(&plug);
> @@ -1847,11 +1852,16 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> segno = start_segno;
> while (segno < end_segno) {
> unsigned int cur_segno;
> + unsigned int block_end_segno;
>
> /* find segment summary of victim */
> - struct folio *sum_folio = filemap_get_folio(META_MAPPING(sbi),
> + struct f2fs_cached_block *sum_entry =
> + f2fs_find_meta_cache(sbi,
> GET_SUM_BLOCK(sbi, segno));
> - unsigned int block_end_segno = rounddown(segno, sbi->sums_per_block)
> +
> + f2fs_bug_on(sbi, IS_ERR(sum_entry));
> +
> + block_end_segno = rounddown(segno, sbi->sums_per_block)
> + sbi->sums_per_block;
>
> if (block_end_segno > end_segno)
> @@ -1864,8 +1874,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> goto next_block;
> }
>
> - if (!folio_test_uptodate(sum_folio) ||
> - unlikely(f2fs_cp_error(sbi)))
> + if (!f2fs_cache_test_uptodate(sum_entry) ||
> + unlikely(f2fs_cp_error(sbi)))
> goto next_block;
>
> for (cur_segno = segno; cur_segno < block_end_segno;
> @@ -1884,7 +1894,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> data_type = (type == SUM_TYPE_DATA) ? DATA : NODE;
> }
>
> - sum = SUM_BLK_PAGE_ADDR(sbi, sum_folio, cur_segno);
> + sum = SUM_BLK_ENTRY_ADDR(sbi, sum_entry, cur_segno);
> if (type != GET_SUM_TYPE(sum_footer(sbi, sum))) {
> f2fs_err(sbi, "Inconsistent segment (%u) type "
> "[%d, %d] in SIT and SSA",
> @@ -1926,12 +1936,14 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> cur_segno + 1 : NULL_SEGNO;
>
> if (unlikely(freezing(current))) {
> - folio_put_refs(sum_folio, 2);
> + f2fs_put_cache(sum_entry, false);
> + f2fs_put_cache(sum_entry, false);
> goto stop;
> }
> }
> next_block:
> - folio_put_refs(sum_folio, 2);
> + f2fs_put_cache(sum_entry, false);
> + f2fs_put_cache(sum_entry, false);
> segno = block_end_segno;
> }
>
> diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
> index aec06fb4fd76..2156fb1fc57d 100644
> --- a/fs/f2fs/inline.c
> +++ b/fs/f2fs/inline.c
> @@ -294,7 +294,7 @@ int f2fs_write_inline_data(struct inode *inode, struct folio *folio)
> return 0;
> }
>
> -int f2fs_recover_inline_data(struct inode *inode, struct folio *nfolio)
> +int f2fs_recover_inline_data(struct inode *inode, struct f2fs_cached_block *entry)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> struct f2fs_inode *ri = NULL;
> @@ -308,12 +308,13 @@ int f2fs_recover_inline_data(struct inode *inode, struct folio *nfolio)
> * x o -> remove data blocks, and then recover inline_data
> * x x -> recover data blocks
> */
> - if (IS_INODE(nfolio))
> - ri = F2FS_INODE(nfolio);
> + if (IS_INODE(cache_folio(entry)))
> + ri = &CACHED_NODE(entry)->i;
>
> if (f2fs_has_inline_data(inode) &&
> ri && (ri->i_inline & F2FS_INLINE_DATA)) {
> struct folio *ifolio;
> +
> process_inline:
> ifolio = f2fs_get_inode_folio(sbi, inode->i_ino);
> if (IS_ERR(ifolio))
> @@ -321,7 +322,7 @@ int f2fs_recover_inline_data(struct inode *inode, struct folio *nfolio)
>
> f2fs_folio_wait_writeback(ifolio, NODE, true, true);
>
> - src_addr = inline_data_addr(inode, nfolio);
> + src_addr = inline_data_addr(inode, cache_folio(entry));
> dst_addr = inline_data_addr(inode, ifolio);
> memcpy(dst_addr, src_addr, MAX_INLINE_DATA(inode));
>
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index bac1e360d966..c533da4d4d70 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -577,7 +577,7 @@ static int do_read_inode(struct inode *inode)
>
> static bool is_meta_ino(struct f2fs_sb_info *sbi, unsigned int ino)
> {
> - if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi))
> + if (ino == F2FS_NODE_INO(sbi))
> return true;
> #ifdef CONFIG_F2FS_FS_COMPRESSION
> if (test_opt(sbi, COMPRESS_CACHE) && ino == F2FS_COMPRESS_INO(sbi))
> @@ -624,9 +624,6 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
> if (ino == F2FS_NODE_INO(sbi)) {
> inode->i_mapping->a_ops = &f2fs_node_aops;
> mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
> - } else if (ino == F2FS_META_INO(sbi)) {
> - inode->i_mapping->a_ops = &f2fs_meta_aops;
> - mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
> } else if (ino == F2FS_COMPRESS_INO(sbi)) {
> #ifdef CONFIG_F2FS_FS_COMPRESSION
> inode->i_mapping->a_ops = &f2fs_compress_aops;
> @@ -824,8 +821,7 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
>
> - if (inode->i_ino == F2FS_NODE_INO(sbi) ||
> - inode->i_ino == F2FS_META_INO(sbi))
> + if (inode->i_ino == F2FS_NODE_INO(sbi))
> return 0;
>
> /*
> @@ -919,7 +915,6 @@ static bool f2fs_pre_evict_inode(struct inode *inode)
> f2fs_invalidate_compress_pages(sbi, inode->i_ino);
>
> if (inode->i_ino == F2FS_NODE_INO(sbi) ||
> - inode->i_ino == F2FS_META_INO(sbi) ||
> inode->i_ino == F2FS_COMPRESS_INO(sbi))
> return true;
>
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 46bea52e35c3..398c58fc6cad 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -140,38 +140,36 @@ static void clear_node_folio_dirty(struct folio *folio)
> folio_clear_uptodate(folio);
> }
>
> -static struct folio *get_current_nat_folio(struct f2fs_sb_info *sbi, nid_t nid)
> +static struct f2fs_cached_block *get_current_nat_cache(struct f2fs_sb_info *sbi,
> + nid_t nid)
> {
> - return f2fs_get_meta_folio_retry(sbi, current_nat_addr(sbi, nid));
> + return f2fs_get_meta_cache_retry(sbi, current_nat_addr(sbi, nid));
> }
>
> -static struct folio *get_next_nat_folio(struct f2fs_sb_info *sbi, nid_t nid)
> +static struct f2fs_cached_block *get_next_nat_cache(struct f2fs_sb_info *sbi,
> + nid_t nid)
> {
> - struct folio *src_folio;
> - struct folio *dst_folio;
> + struct f2fs_cached_block *src_entry;
> + struct f2fs_cached_block *dst_entry;
> pgoff_t dst_off;
> - void *src_addr;
> - void *dst_addr;
> struct f2fs_nm_info *nm_i = NM_I(sbi);
>
> dst_off = next_nat_addr(sbi, current_nat_addr(sbi, nid));
>
> /* get current nat block page with lock */
> - src_folio = get_current_nat_folio(sbi, nid);
> - if (IS_ERR(src_folio))
> - return src_folio;
> - dst_folio = f2fs_grab_meta_folio(sbi, dst_off);
> - f2fs_bug_on(sbi, folio_test_dirty(src_folio));
> -
> - src_addr = folio_address(src_folio);
> - dst_addr = folio_address(dst_folio);
> - memcpy(dst_addr, src_addr, PAGE_SIZE);
> - folio_mark_dirty(dst_folio);
> - f2fs_folio_put(src_folio, true);
> + src_entry = get_current_nat_cache(sbi, nid);
> + if (IS_ERR(src_entry))
> + return src_entry;
> + dst_entry = f2fs_grab_meta_cache(sbi, dst_off);
> + f2fs_bug_on(sbi, f2fs_cache_test_dirty(src_entry));
> +
> + memcpy(cache_address(dst_entry), cache_address(src_entry), sbi->blocksize);
> + f2fs_mark_cache_dirty(dst_entry);
> + f2fs_put_cache(src_entry, true);
>
> set_to_next_nat(nm_i, nid);
>
> - return dst_folio;
> + return dst_entry;
> }
>
> static struct nat_entry *__alloc_nat_entry(struct f2fs_sb_info *sbi,
> @@ -575,7 +573,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
> struct f2fs_journal *journal = curseg->journal;
> nid_t start_nid = START_NID(nid);
> struct f2fs_nat_block *nat_blk;
> - struct folio *folio = NULL;
> + struct f2fs_cached_block *entry = NULL;
> struct f2fs_nat_entry ne;
> struct nat_entry *e;
> pgoff_t index;
> @@ -629,14 +627,14 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
> index = current_nat_addr(sbi, nid);
> f2fs_up_read(&nm_i->nat_tree_lock);
>
> - folio = f2fs_get_meta_folio(sbi, index);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + entry = f2fs_get_meta_cache(sbi, index);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
>
> - nat_blk = folio_address(folio);
> + nat_blk = cache_address(entry);
> ne = nat_blk->entries[nid - start_nid];
> node_info_from_raw_nat(ni, &ne);
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> sanity_check:
> if (__is_valid_data_blkaddr(ni->blk_addr) &&
> !f2fs_is_valid_blkaddr(sbi, ni->blk_addr,
> @@ -1622,7 +1620,7 @@ static struct folio *__get_node_folio(struct f2fs_sb_info *sbi, pgoff_t nid,
> out_put_err:
> /* ENOENT comes from read_node_folio which is not an error. */
> if (err != -ENOENT)
> - f2fs_handle_page_eio(sbi, folio, NODE);
> + f2fs_handle_page_eio(sbi, folio->index, NODE);
> f2fs_folio_put(folio, true);
> return ERR_PTR(err);
> }
> @@ -2598,6 +2596,7 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
> bool sync, bool mount)
> {
> struct f2fs_nm_info *nm_i = NM_I(sbi);
> + struct f2fs_cached_block *entry = NULL;
> int i = 0, ret;
> nid_t nid = nm_i->next_scan_nid;
>
> @@ -2623,7 +2622,7 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
> }
>
> /* readahead nat pages to be scanned */
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
> + f2fs_ra_meta_caches(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
> META_NAT, true);
>
> f2fs_down_read(&nm_i->nat_tree_lock);
> @@ -2631,14 +2630,14 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
> while (1) {
> if (!test_bit_le(NAT_BLOCK_OFFSET(nid),
> nm_i->nat_block_bitmap)) {
> - struct folio *folio = get_current_nat_folio(sbi, nid);
> + entry = get_current_nat_cache(sbi, nid);
>
> - if (IS_ERR(folio)) {
> - ret = PTR_ERR(folio);
> + if (IS_ERR(entry)) {
> + ret = PTR_ERR(entry);
> } else {
> - ret = scan_nat_page(sbi, folio_address(folio),
> + ret = scan_nat_page(sbi, cache_address(entry),
> nid);
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> }
>
> if (ret) {
> @@ -2671,7 +2670,7 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
>
> f2fs_up_read(&nm_i->nat_tree_lock);
>
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
> + f2fs_ra_meta_caches(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
> nm_i->ra_nid_pages, META_NAT, false);
>
> return 0;
> @@ -2826,7 +2825,7 @@ int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink)
> return nr - nr_shrink;
> }
>
> -int f2fs_recover_inline_xattr(struct inode *inode, struct folio *folio)
> +int f2fs_recover_inline_xattr(struct inode *inode, struct f2fs_cached_block *entry)
> {
> void *src_addr, *dst_addr;
> size_t inline_size;
> @@ -2837,7 +2836,7 @@ int f2fs_recover_inline_xattr(struct inode *inode, struct folio *folio)
> if (IS_ERR(ifolio))
> return PTR_ERR(ifolio);
>
> - ri = F2FS_INODE(folio);
> + ri = &CACHED_NODE(entry)->i;
> if (ri->i_inline & F2FS_INLINE_XATTR) {
> if (!f2fs_has_inline_xattr(inode)) {
> set_inode_flag(inode, FI_INLINE_XATTR);
> @@ -2852,7 +2851,7 @@ int f2fs_recover_inline_xattr(struct inode *inode, struct folio *folio)
> }
>
> dst_addr = inline_xattr_addr(inode, ifolio);
> - src_addr = inline_xattr_addr(inode, folio);
> + src_addr = inline_xattr_addr(inode, cache_folio(entry));
> inline_size = inline_xattr_size(inode);
>
> f2fs_folio_wait_writeback(ifolio, NODE, true, true);
> @@ -2863,7 +2862,7 @@ int f2fs_recover_inline_xattr(struct inode *inode, struct folio *folio)
> return 0;
> }
>
> -int f2fs_recover_xattr_data(struct inode *inode, struct folio *folio)
> +int f2fs_recover_xattr_data(struct inode *inode, struct f2fs_cached_block *entry)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid;
> @@ -2901,8 +2900,8 @@ int f2fs_recover_xattr_data(struct inode *inode, struct folio *folio)
> f2fs_update_inode_page(inode);
>
> /* 3: update and set xattr node page dirty */
> - if (folio) {
> - memcpy(F2FS_NODE(xfolio), F2FS_NODE(folio),
> + if (entry) {
> + memcpy(F2FS_NODE(xfolio), CACHED_NODE(entry),
> VALID_XATTR_BLOCK_SIZE);
> folio_mark_dirty(xfolio);
> }
> @@ -2911,10 +2910,10 @@ int f2fs_recover_xattr_data(struct inode *inode, struct folio *folio)
> return 0;
> }
>
> -int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio)
> +int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct f2fs_cached_block *entry)
> {
> struct f2fs_inode *src, *dst;
> - nid_t ino = ino_of_node(folio);
> + nid_t ino = ino_of_node(cache_folio(entry));
> struct node_info old_ni, new_ni;
> struct folio *ifolio;
> int err;
> @@ -2940,7 +2939,7 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio)
> fill_node_footer(ifolio, ino, ino, 0, true);
> set_cold_node(ifolio, false);
>
> - src = F2FS_INODE(folio);
> + src = &CACHED_NODE(entry)->i;
> dst = F2FS_INODE(ifolio);
>
> memcpy(dst, src, offsetof(struct f2fs_inode, i_ext));
> @@ -2999,24 +2998,24 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
> nrpages = bio_max_segs(last_offset - i);
>
> /* readahead node pages */
> - f2fs_ra_meta_pages(sbi, addr, nrpages, META_POR, true);
> + f2fs_ra_meta_caches(sbi, addr, nrpages, META_POR, true);
>
> for (idx = addr; idx < addr + nrpages; idx++) {
> - struct folio *folio = f2fs_get_tmp_folio(sbi, idx);
> + struct f2fs_cached_block *entry =
> + f2fs_get_tmp_cache(sbi, idx);
>
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
>
> - rn = F2FS_NODE(folio);
> + rn = CACHED_NODE(entry);
> sum_entry->nid = rn->footer.nid;
> sum_entry->version = 0;
> sum_entry->ofs_in_node = 0;
> sum_entry++;
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> }
>
> - invalidate_mapping_pages(META_MAPPING(sbi), addr,
> - addr + nrpages);
> + f2fs_truncate_meta_caches(sbi, addr, nrpages);
> }
> return 0;
> }
> @@ -3126,7 +3125,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> bool to_journal = true;
> struct f2fs_nat_block *nat_blk;
> struct nat_entry *ne, *cur;
> - struct folio *folio = NULL;
> + struct f2fs_cached_block *entry = NULL;
>
> /*
> * there are two steps to flush nat entries:
> @@ -3140,11 +3139,11 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> if (to_journal) {
> down_write(&curseg->journal_rwsem);
> } else {
> - folio = get_next_nat_folio(sbi, start_nid);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + entry = get_next_nat_cache(sbi, start_nid);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
>
> - nat_blk = folio_address(folio);
> + nat_blk = cache_address(entry);
> f2fs_bug_on(sbi, !nat_blk);
> }
>
> @@ -3181,7 +3180,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> up_write(&curseg->journal_rwsem);
> } else {
> __update_nat_bits(sbi, start_nid, nat_blk);
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> }
>
> /* Allow dirty nats by node block allocation in write_begin */
> @@ -3252,7 +3251,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> __has_cursum_space(sbi, journal,
> entry_count, NAT_JOURNAL))
> continue;
> - f2fs_ra_meta_pages(sbi, set->set, 1, META_NAT, true);
> + f2fs_ra_meta_caches(sbi, set->set, 1, META_NAT, true);
> }
> /* flush dirty nats in nat entry set */
> list_for_each_entry_safe(set, tmp, &sets, set_list) {
> @@ -3288,15 +3287,15 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
> nat_bits_addr = __start_cp_addr(sbi) + BLKS_PER_SEG(sbi) -
> nm_i->nat_bits_blocks;
> for (i = 0; i < nm_i->nat_bits_blocks; i++) {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> - folio = f2fs_get_meta_folio(sbi, nat_bits_addr++);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + entry = f2fs_get_meta_cache(sbi, nat_bits_addr++);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
>
> memcpy(nm_i->nat_bits + F2FS_BLK_TO_BYTES(i),
> - folio_address(folio), F2FS_BLKSIZE);
> - f2fs_folio_put(folio, true);
> + cache_address(entry), F2FS_BLKSIZE);
> + f2fs_put_cache(entry, true);
> }
>
> cp_ver |= (cur_cp_crc(ckpt) << 32);
> diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
> index 5e114f352099..de8dcd5d4392 100644
> --- a/fs/f2fs/node.h
> +++ b/fs/f2fs/node.h
> @@ -311,9 +311,9 @@ static inline void fill_node_footer_blkaddr(struct folio *folio, block_t blkaddr
> rn->footer.next_blkaddr = cpu_to_le32(blkaddr);
> }
>
> -static inline bool is_recoverable_dnode(const struct folio *folio)
> +static inline bool is_recoverable_dnode(struct f2fs_sb_info *sbi, const struct folio *folio)
> {
> - struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_F_SB(folio));
> + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
> __u64 cp_ver = cur_cp_version(ckpt);
>
> /* Don't care crc part, if fsck.f2fs sets it. */
> diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
> index aaa5227739c8..5cb56b4c1879 100644
> --- a/fs/f2fs/recovery.c
> +++ b/fs/f2fs/recovery.c
> @@ -182,33 +182,33 @@ static const char *recover_printable_name(struct inode *inode,
> return raw->i_name;
> }
>
> -static int recover_dentry(struct inode *inode, struct folio *ifolio,
> +static int recover_dentry(struct inode *inode, struct f2fs_cached_block *entry,
> struct list_head *dir_list)
> {
> - struct f2fs_inode *raw_inode = F2FS_INODE(ifolio);
> + struct f2fs_inode *raw_inode = &CACHED_NODE(entry)->i;
> nid_t pino = le32_to_cpu(raw_inode->i_pino);
> struct f2fs_dir_entry *de;
> struct f2fs_filename fname;
> struct qstr usr_fname;
> struct folio *folio;
> struct inode *dir, *einode;
> - struct fsync_inode_entry *entry;
> + struct fsync_inode_entry *fsync_entry;
> int err = 0;
> const char *name;
> int name_len;
>
> - entry = get_fsync_inode(dir_list, pino);
> - if (!entry) {
> - entry = add_fsync_inode(F2FS_I_SB(inode), dir_list,
> + fsync_entry = get_fsync_inode(dir_list, pino);
> + if (!fsync_entry) {
> + fsync_entry = add_fsync_inode(F2FS_I_SB(inode), dir_list,
> pino, false);
> - if (IS_ERR(entry)) {
> - dir = ERR_CAST(entry);
> - err = PTR_ERR(entry);
> + if (IS_ERR(fsync_entry)) {
> + dir = ERR_CAST(fsync_entry);
> + err = PTR_ERR(fsync_entry);
> goto out;
> }
> }
>
> - dir = entry->inode;
> + dir = fsync_entry->inode;
> err = init_recovered_filename(dir, inode, raw_inode, &fname, &usr_fname);
> if (err)
> goto out;
> @@ -256,14 +256,14 @@ static int recover_dentry(struct inode *inode, struct folio *ifolio,
> out:
> name = recover_printable_name(inode, raw_inode, &name_len);
> f2fs_notice(F2FS_I_SB(inode), "%s: ino = %x, name = %.*s, dir = %llu, err = %d",
> - __func__, ino_of_node(ifolio), name_len, name,
> + __func__, ino_of_node(cache_folio(entry)), name_len, name,
> IS_ERR(dir) ? 0 : dir->i_ino, err);
> return err;
> }
>
> -static int recover_quota_data(struct inode *inode, struct folio *folio)
> +static int recover_quota_data(struct inode *inode, struct f2fs_cached_block *entry)
> {
> - struct f2fs_inode *raw = F2FS_INODE(folio);
> + struct f2fs_inode *raw = &CACHED_NODE(entry)->i;
> struct iattr attr;
> uid_t i_uid = le32_to_cpu(raw->i_uid);
> gid_t i_gid = le32_to_cpu(raw->i_gid);
> @@ -300,9 +300,9 @@ static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri)
> clear_inode_flag(inode, FI_DATA_EXIST);
> }
>
> -static int recover_inode(struct inode *inode, struct folio *folio)
> +static int recover_inode(struct inode *inode, struct f2fs_cached_block *entry)
> {
> - struct f2fs_inode *raw = F2FS_INODE(folio);
> + struct f2fs_inode *raw = &CACHED_NODE(entry)->i;
> struct f2fs_inode_info *fi = F2FS_I(inode);
> const char *name;
> int name_len;
> @@ -310,7 +310,7 @@ static int recover_inode(struct inode *inode, struct folio *folio)
>
> inode->i_mode = le16_to_cpu(raw->i_mode);
>
> - err = recover_quota_data(inode, folio);
> + err = recover_quota_data(inode, entry);
> if (err)
> return err;
>
> @@ -357,7 +357,7 @@ static int recover_inode(struct inode *inode, struct folio *folio)
> name = recover_printable_name(inode, raw, &name_len);
>
> f2fs_notice(F2FS_I_SB(inode), "%s: ino = %x, name = %.*s, inline = %x",
> - __func__, ino_of_node(folio), name_len, name,
> + __func__, ino_of_node(cache_folio(entry)), name_len, name,
> raw->i_inline);
> return 0;
> }
> @@ -386,30 +386,30 @@ static int sanity_check_node_chain(struct f2fs_sb_info *sbi, block_t blkaddr,
> return 0;
>
> for (i = 0; i < 2; i++) {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_is_valid_blkaddr(sbi, *blkaddr_fast, META_POR)) {
> *is_detecting = false;
> return 0;
> }
>
> - folio = f2fs_get_tmp_folio(sbi, *blkaddr_fast);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> + entry = f2fs_get_tmp_cache(sbi, *blkaddr_fast);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
>
> - if (!is_recoverable_dnode(folio)) {
> - f2fs_folio_put(folio, true);
> + if (!is_recoverable_dnode(sbi, cache_folio(entry))) {
> + f2fs_put_cache(entry, true);
> *is_detecting = false;
> return 0;
> }
>
> ra_blocks = adjust_por_ra_blocks(sbi, ra_blocks, *blkaddr_fast,
> - next_blkaddr_of_node(folio));
> + next_blkaddr_of_node(cache_folio(entry)));
>
> - *blkaddr_fast = next_blkaddr_of_node(folio);
> - f2fs_folio_put(folio, true);
> + *blkaddr_fast = next_blkaddr_of_node(cache_folio(entry));
> + f2fs_put_cache(entry, true);
>
> - f2fs_ra_meta_pages_cond(sbi, *blkaddr_fast, ra_blocks);
> + f2fs_ra_meta_caches_cond(sbi, *blkaddr_fast, ra_blocks);
> }
>
> if (*blkaddr_fast == blkaddr) {
> @@ -434,45 +434,47 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
> blkaddr_fast = blkaddr;
>
> while (1) {
> - struct fsync_inode_entry *entry;
> - struct folio *folio;
> + struct fsync_inode_entry *fsync_entry;
> + struct f2fs_cached_block *entry;
> + struct f2fs_node *rn;
>
> if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
> return 0;
>
> - folio = f2fs_get_tmp_folio(sbi, blkaddr);
> - if (IS_ERR(folio)) {
> - err = PTR_ERR(folio);
> + entry = f2fs_get_tmp_cache(sbi, blkaddr);
> + if (IS_ERR(entry)) {
> + err = PTR_ERR(entry);
> break;
> }
> + rn = CACHED_NODE(entry);
>
> - if (!is_recoverable_dnode(folio)) {
> - f2fs_folio_put(folio, true);
> + if (!is_recoverable_dnode(sbi, cache_folio(entry))) {
> + f2fs_put_cache(entry, true);
> break;
> }
>
> - if (!is_fsync_dnode(folio))
> + if (!is_fsync_dnode(cache_folio(entry)))
> goto next;
>
> - entry = get_fsync_inode(head, ino_of_node(folio));
> - if (!entry) {
> + fsync_entry = get_fsync_inode(head, ino_of_node(cache_folio(entry)));
> + if (!fsync_entry) {
> bool quota_inode = false;
>
> if (!check_only &&
> - IS_INODE(folio) &&
> - is_dent_dnode(folio)) {
> - err = f2fs_recover_inode_page(sbi, folio);
> + IS_INODE(cache_folio(entry)) &&
> + is_dent_dnode(cache_folio(entry))) {
> + err = f2fs_recover_inode_page(sbi, entry);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> break;
> }
> quota_inode = true;
> }
>
> - entry = add_fsync_inode(sbi, head, ino_of_node(folio),
> + fsync_entry = add_fsync_inode(sbi, head, ino_of_node(cache_folio(entry)),
> quota_inode);
> - if (IS_ERR(entry)) {
> - err = PTR_ERR(entry);
> + if (IS_ERR(fsync_entry)) {
> + err = PTR_ERR(fsync_entry);
> /*
> * CP | dnode(F) | inode(DF)
> * For this case, we should not give up now.
> @@ -482,18 +484,18 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
> *new_inode = true;
> goto next;
> }
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> break;
> }
> }
> - entry->blkaddr = blkaddr;
> + fsync_entry->blkaddr = blkaddr;
>
> - if (IS_INODE(folio) && is_dent_dnode(folio))
> - entry->last_dentry = blkaddr;
> + if (IS_INODE(cache_folio(entry)) && is_dent_dnode(cache_folio(entry)))
> + fsync_entry->last_dentry = blkaddr;
> next:
> /* check next segment */
> - blkaddr = next_blkaddr_of_node(folio);
> - f2fs_folio_put(folio, true);
> + blkaddr = next_blkaddr_of_node(cache_folio(entry));
> + f2fs_put_cache(entry, true);
>
> err = sanity_check_node_chain(sbi, blkaddr, &blkaddr_fast,
> &is_detecting);
> @@ -519,7 +521,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
> unsigned short blkoff = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
> struct f2fs_summary_block *sum_node;
> struct f2fs_summary sum;
> - struct folio *sum_folio, *node_folio;
> + struct f2fs_cached_block *entry = NULL;
> + struct folio *node_folio;
> struct dnode_of_data tdn = *dn;
> nid_t ino, nid;
> struct inode *inode;
> @@ -541,12 +544,12 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
> }
> }
>
> - sum_folio = f2fs_get_sum_folio(sbi, segno);
> - if (IS_ERR(sum_folio))
> - return PTR_ERR(sum_folio);
> - sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, segno);
> + entry = f2fs_get_sum_cache(sbi, segno);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
> + sum_node = SUM_BLK_ENTRY_ADDR(sbi, entry, segno);
> sum = sum_entries(sum_node)[blkoff];
> - f2fs_folio_put(sum_folio, true);
> + f2fs_put_cache(entry, true);
> got_it:
> /* Use the locked dnode page and inode */
> nid = le32_to_cpu(sum.nid);
> @@ -645,7 +648,7 @@ static int f2fs_reserve_new_block_retry(struct dnode_of_data *dn)
> }
>
> static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> - struct folio *folio)
> + struct f2fs_cached_block *entry)
> {
> struct dnode_of_data dn;
> struct node_info ni;
> @@ -653,19 +656,19 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> int err = 0, recovered = 0;
>
> /* step 1: recover xattr */
> - if (IS_INODE(folio)) {
> - err = f2fs_recover_inline_xattr(inode, folio);
> + if (IS_INODE(cache_folio(entry))) {
> + err = f2fs_recover_inline_xattr(inode, entry);
> if (err)
> goto out;
> - } else if (f2fs_has_xattr_block(ofs_of_node(folio))) {
> - err = f2fs_recover_xattr_data(inode, folio);
> + } else if (f2fs_has_xattr_block(ofs_of_node(cache_folio(entry)))) {
> + err = f2fs_recover_xattr_data(inode, entry);
> if (!err)
> recovered++;
> goto out;
> }
>
> /* step 2: recover inline data */
> - err = f2fs_recover_inline_data(inode, folio);
> + err = f2fs_recover_inline_data(inode, entry);
> if (err) {
> if (err == 1)
> err = 0;
> @@ -673,8 +676,8 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> }
>
> /* step 3: recover data indices */
> - start = f2fs_start_bidx_of_node(ofs_of_node(folio), inode);
> - end = start + ADDRS_PER_PAGE(folio, inode);
> + start = f2fs_start_bidx_of_node(ofs_of_node(cache_folio(entry)), inode);
> + end = start + addrs_per_page(inode, IS_INODE(cache_folio(entry)));
>
> set_new_dnode(&dn, inode, NULL, NULL, 0);
> retry_dn:
> @@ -693,12 +696,12 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> if (err)
> goto err;
>
> - f2fs_bug_on(sbi, ni.ino != ino_of_node(folio));
> + f2fs_bug_on(sbi, ni.ino != ino_of_node(cache_folio(entry)));
>
> - if (ofs_of_node(dn.node_folio) != ofs_of_node(folio)) {
> + if (ofs_of_node(dn.node_folio) != ofs_of_node(cache_folio(entry))) {
> f2fs_warn(sbi, "Inconsistent ofs_of_node, ino:%llu, ofs:%u, %u",
> inode->i_ino, ofs_of_node(dn.node_folio),
> - ofs_of_node(folio));
> + ofs_of_node(cache_folio(entry)));
> err = -EFSCORRUPTED;
> f2fs_handle_error(sbi, ERROR_INCONSISTENT_FOOTER);
> fserror_report_file_metadata(dn.inode, err, GFP_NOFS);
> @@ -709,7 +712,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> block_t src, dest;
>
> src = f2fs_data_blkaddr(&dn);
> - dest = data_blkaddr(dn.inode, folio, dn.ofs_in_node);
> + dest = data_blkaddr(dn.inode, cache_folio(entry), dn.ofs_in_node);
>
> if (__is_valid_data_blkaddr(src) &&
> !f2fs_is_valid_blkaddr(sbi, src, META_POR)) {
> @@ -784,16 +787,16 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> }
> }
>
> - copy_node_footer(dn.node_folio, folio);
> + copy_node_footer(dn.node_folio, cache_folio(entry));
> fill_node_footer(dn.node_folio, dn.nid, ni.ino,
> - ofs_of_node(folio), false);
> + ofs_of_node(cache_folio(entry)), false);
> folio_mark_dirty(dn.node_folio);
> err:
> f2fs_put_dnode(&dn);
> out:
> f2fs_notice(sbi, "recover_data: ino = %llx, nid = %x (i_size: %s), "
> "range (%u, %u), recovered = %d, err = %d",
> - inode->i_ino, nid_of_node(folio),
> + inode->i_ino, nid_of_node(cache_folio(entry)),
> file_keep_isize(inode) ? "keep" : "recover",
> start, end, recovered, err);
> return err;
> @@ -820,26 +823,26 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
> blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
>
> while (1) {
> - struct fsync_inode_entry *entry;
> - struct folio *folio;
> + struct fsync_inode_entry *fsync_entry;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
> break;
>
> - folio = f2fs_get_tmp_folio(sbi, blkaddr);
> - if (IS_ERR(folio)) {
> - err = PTR_ERR(folio);
> + entry = f2fs_get_tmp_cache(sbi, blkaddr);
> + if (IS_ERR(entry)) {
> + err = PTR_ERR(entry);
> break;
> }
>
> - if (!is_recoverable_dnode(folio)) {
> - f2fs_folio_put(folio, true);
> + if (!is_recoverable_dnode(sbi, cache_folio(entry))) {
> + f2fs_put_cache(entry, true);
> break;
> }
> recoverable_dnode++;
>
> - entry = get_fsync_inode(inode_list, ino_of_node(folio));
> - if (!entry)
> + fsync_entry = get_fsync_inode(inode_list, ino_of_node(cache_folio(entry)));
> + if (!fsync_entry)
> goto next;
> fsynced_dnode++;
> /*
> @@ -847,40 +850,40 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
> * In this case, we can lose the latest inode(x).
> * So, call recover_inode for the inode update.
> */
> - if (IS_INODE(folio)) {
> - err = recover_inode(entry->inode, folio);
> + if (IS_INODE(cache_folio(entry))) {
> + err = recover_inode(fsync_entry->inode, entry);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> break;
> }
> recovered_inode++;
> }
> - if (entry->last_dentry == blkaddr) {
> - err = recover_dentry(entry->inode, folio, dir_list);
> + if (fsync_entry->last_dentry == blkaddr) {
> + err = recover_dentry(fsync_entry->inode, entry, dir_list);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> break;
> }
> recovered_dentry++;
> }
> - err = do_recover_data(sbi, entry->inode, folio);
> + err = do_recover_data(sbi, fsync_entry->inode, entry);
> if (err) {
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> break;
> }
> recovered_dnode++;
>
> - if (entry->blkaddr == blkaddr)
> - list_move_tail(&entry->list, tmp_inode_list);
> + if (fsync_entry->blkaddr == blkaddr)
> + list_move_tail(&fsync_entry->list, tmp_inode_list);
> next:
> ra_blocks = adjust_por_ra_blocks(sbi, ra_blocks, blkaddr,
> - next_blkaddr_of_node(folio));
> + next_blkaddr_of_node(cache_folio(entry)));
>
> /* check next segment */
> - blkaddr = next_blkaddr_of_node(folio);
> - f2fs_folio_put(folio, true);
> + blkaddr = next_blkaddr_of_node(cache_folio(entry));
> + f2fs_put_cache(entry, true);
>
> - f2fs_ra_meta_pages_cond(sbi, blkaddr, ra_blocks);
> + f2fs_ra_meta_caches_cond(sbi, blkaddr, ra_blocks);
> total_dnode++;
> }
> if (!err)
> @@ -937,12 +940,11 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
> destroy_fsync_dnodes(&tmp_inode_list, err);
>
> /* truncate meta pages to be used by the recovery */
> - truncate_inode_pages_range(META_MAPPING(sbi),
> - (loff_t)MAIN_BLKADDR(sbi) << PAGE_SHIFT, -1);
> -
> + f2fs_truncate_meta_caches(sbi, MAIN_BLKADDR(sbi),
> + MAX_BLKADDR(sbi) - MAIN_BLKADDR(sbi));
> if (err) {
> truncate_inode_pages_final(NODE_MAPPING(sbi));
> - truncate_inode_pages_final(META_MAPPING(sbi));
> + f2fs_truncate_meta_caches(sbi, 0, ULONG_MAX);
> }
>
> /*
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 56decf9c691c..cbb3a8c9f4ab 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2774,63 +2774,62 @@ int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)
> return 3;
> }
>
> -/*
> - * Caller should put this summary folio
> - */
> -struct folio *f2fs_get_sum_folio(struct f2fs_sb_info *sbi, unsigned int segno)
> +
> +struct f2fs_cached_block *f2fs_get_sum_cache(struct f2fs_sb_info *sbi,
> + unsigned int segno)
> {
> if (unlikely(f2fs_cp_error(sbi)))
> return ERR_PTR(-EIO);
> - return f2fs_get_meta_folio_retry(sbi, GET_SUM_BLOCK(sbi, segno));
> + return f2fs_get_meta_cache_retry(sbi, GET_SUM_BLOCK(sbi, segno));
> }
>
> void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
> void *src, block_t blk_addr)
> {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_sb_has_packed_ssa(sbi))
> - folio = f2fs_grab_meta_folio(sbi, blk_addr);
> + entry = f2fs_grab_meta_cache(sbi, blk_addr);
> else
> - folio = f2fs_get_meta_folio_retry(sbi, blk_addr);
> + entry = f2fs_get_meta_cache_retry(sbi, blk_addr);
>
> - if (IS_ERR(folio))
> + if (IS_ERR(entry))
> return;
>
> - memcpy(folio_address(folio), src, PAGE_SIZE);
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + memcpy(cache_address(entry), src, sbi->blocksize);
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> }
>
> static void write_sum_page(struct f2fs_sb_info *sbi,
> struct f2fs_summary_block *sum_blk, unsigned int segno)
> {
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_sb_has_packed_ssa(sbi))
> return f2fs_update_meta_page(sbi, (void *)sum_blk,
> GET_SUM_BLOCK(sbi, segno));
>
> - folio = f2fs_get_sum_folio(sbi, segno);
> - if (IS_ERR(folio))
> + entry = f2fs_get_sum_cache(sbi, GET_SUM_BLOCK(sbi, segno));
> + if (IS_ERR(entry))
> return;
>
> - memcpy(SUM_BLK_PAGE_ADDR(sbi, folio, segno), sum_blk,
> + memcpy(SUM_BLK_ENTRY_ADDR(sbi, entry, segno), sum_blk,
> sbi->sum_blocksize);
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> }
>
> static void write_current_sum_page(struct f2fs_sb_info *sbi,
> int type, block_t blk_addr)
> {
> struct curseg_info *curseg = CURSEG_I(sbi, type);
> - struct folio *folio = f2fs_grab_meta_folio(sbi, blk_addr);
> + struct f2fs_cached_block *entry = f2fs_grab_meta_cache(sbi, blk_addr);
> struct f2fs_summary_block *src = curseg->sum_blk;
> struct f2fs_summary_block *dst;
>
> - dst = folio_address(folio);
> - memset(dst, 0, PAGE_SIZE);
> + dst = cache_address(entry);
> + memset(dst, 0, sbi->blocksize);
>
> mutex_lock(&curseg->curseg_mutex);
>
> @@ -2843,8 +2842,8 @@ static void write_current_sum_page(struct f2fs_sb_info *sbi,
>
> mutex_unlock(&curseg->curseg_mutex);
>
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> }
>
> static int is_next_segment_free(struct f2fs_sb_info *sbi,
> @@ -3160,7 +3159,7 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type)
> struct curseg_info *curseg = CURSEG_I(sbi, type);
> unsigned int new_segno = curseg->next_segno;
> struct f2fs_summary_block *sum_node;
> - struct folio *sum_folio;
> + struct f2fs_cached_block *entry = NULL;
>
> if (curseg->inited)
> write_sum_page(sbi, curseg->sum_blk, curseg->segno);
> @@ -3176,15 +3175,15 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type)
> curseg->alloc_type = SSR;
> curseg->next_blkoff = __next_free_blkoff(sbi, curseg->segno, 0);
>
> - sum_folio = f2fs_get_sum_folio(sbi, new_segno);
> - if (IS_ERR(sum_folio)) {
> + entry = f2fs_get_sum_cache(sbi, new_segno);
> + if (IS_ERR(entry)) {
> /* GC won't be able to use stale summary pages by cp_error */
> memset(curseg->sum_blk, 0, sbi->sum_entry_size);
> - return PTR_ERR(sum_folio);
> + return PTR_ERR(entry);
> }
> - sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, new_segno);
> + sum_node = SUM_BLK_ENTRY_ADDR(sbi, entry, new_segno);
> memcpy(curseg->sum_blk, sum_node, sbi->sum_entry_size);
> - f2fs_folio_put(sum_folio, true);
> + f2fs_put_cache(entry, true);
> return 0;
> }
>
> @@ -4127,8 +4126,9 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
> f2fs_up_read(&fio->sbi->io_order_lock);
> }
>
> -void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct folio *folio,
> - enum iostat_type io_type)
> +void f2fs_do_write_meta_cache(struct f2fs_sb_info *sbi,
> + struct f2fs_cached_block *entry,
> + enum iostat_type io_type)
> {
> struct f2fs_io_info fio = {
> .sbi = sbi,
> @@ -4136,20 +4136,21 @@ void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct folio *folio,
> .temp = HOT,
> .op = REQ_OP_WRITE,
> .op_flags = REQ_SYNC | REQ_META | REQ_PRIO,
> - .old_blkaddr = folio->index,
> - .new_blkaddr = folio->index,
> - .folio = folio,
> + .old_blkaddr = entry->index,
> + .new_blkaddr = entry->index,
> .encrypted_page = NULL,
> .in_list = 0,
> + .cache_entry = entry,
> + .is_cache = 1,
> };
>
> - if (unlikely(folio->index >= MAIN_BLKADDR(sbi)))
> + if (unlikely(entry->index >= MAIN_BLKADDR(sbi)))
> fio.op_flags &= ~REQ_META;
>
> - folio_start_writeback(folio);
> - f2fs_submit_page_write(&fio);
> + f2fs_start_cache_writeback(entry);
> + f2fs_submit_cache_write(&fio);
>
> - stat_inc_meta_count(sbi, folio->index);
> + stat_inc_meta_count(sbi, entry->index);
> f2fs_update_iostat(sbi, NULL, io_type, F2FS_BLKSIZE);
> }
>
> @@ -4206,7 +4207,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
> }
>
> if (fio->meta_gc)
> - f2fs_truncate_meta_inode_pages(sbi, fio->new_blkaddr, 1);
> + f2fs_truncate_meta_caches(sbi, fio->new_blkaddr, 1);
>
> stat_inc_inplace_blocks(fio->sbi);
>
> @@ -4372,7 +4373,7 @@ void f2fs_folio_wait_writeback(struct folio *folio, enum page_type type,
> void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> - struct folio *cfolio;
> + struct f2fs_cached_block *entry;
>
> if (!f2fs_meta_inode_gc_required(inode))
> return;
> @@ -4380,11 +4381,12 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr)
> if (!__is_valid_data_blkaddr(blkaddr))
> return;
>
> - cfolio = filemap_lock_folio(META_MAPPING(sbi), blkaddr);
> - if (!IS_ERR(cfolio)) {
> - f2fs_folio_wait_writeback(cfolio, DATA, true, true);
> - f2fs_folio_put(cfolio, true);
> - }
> + entry = f2fs_find_cache(META_CACHE(sbi), blkaddr);
> + if (IS_ERR(entry))
> + return;
> + f2fs_lock_cache(entry);
> + f2fs_cache_wait_writeback_cond(entry, DATA);
> + f2fs_put_cache(entry, true);
> }
>
> void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
> @@ -4399,7 +4401,7 @@ void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
> for (i = 0; i < len; i++)
> f2fs_wait_on_block_writeback(inode, blkaddr + i);
>
> - f2fs_truncate_meta_inode_pages(sbi, blkaddr, len);
> + f2fs_truncate_meta_caches(sbi, blkaddr, len);
> }
>
> static int read_compacted_summaries(struct f2fs_sb_info *sbi)
> @@ -4407,16 +4409,16 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
> struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
> struct curseg_info *seg_i;
> unsigned char *kaddr;
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> block_t start;
> int i, j, offset;
>
> start = start_sum_block(sbi);
>
> - folio = f2fs_get_meta_folio(sbi, start++);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> - kaddr = folio_address(folio);
> + entry = f2fs_get_meta_cache(sbi, start++);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
> + kaddr = cache_address(entry);
>
> /* Step 1: restore nat cache */
> seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
> @@ -4453,16 +4455,16 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
> SUM_FOOTER_SIZE)
> continue;
>
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
>
> - folio = f2fs_get_meta_folio(sbi, start++);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> - kaddr = folio_address(folio);
> + entry = f2fs_get_meta_cache(sbi, start++);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
> + kaddr = cache_address(entry);
> offset = 0;
> }
> }
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
> return 0;
> }
>
> @@ -4471,7 +4473,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
> struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
> struct f2fs_summary_block *sum;
> struct curseg_info *curseg;
> - struct folio *new;
> + struct f2fs_cached_block *entry;
> unsigned short blk_off;
> unsigned int segno = 0;
> block_t blk_addr = 0;
> @@ -4498,10 +4500,10 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
> blk_addr = GET_SUM_BLOCK(sbi, segno);
> }
>
> - new = f2fs_get_meta_folio(sbi, blk_addr);
> - if (IS_ERR(new))
> - return PTR_ERR(new);
> - sum = folio_address(new);
> + entry = f2fs_get_meta_cache(sbi, blk_addr);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
> + sum = cache_address(entry);
>
> if (IS_NODESEG(type)) {
> if (__exist_node_summaries(sbi)) {
> @@ -4538,7 +4540,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
> curseg->next_blkoff = blk_off;
> mutex_unlock(&curseg->curseg_mutex);
> out:
> - f2fs_folio_put(new, true);
> + f2fs_put_cache(entry, true);
> return err;
> }
>
> @@ -4553,8 +4555,8 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
> int npages = f2fs_npages_for_summary_flush(sbi, true);
>
> if (npages >= 2)
> - f2fs_ra_meta_pages(sbi, start_sum_block(sbi), npages,
> - META_CP, true);
> + f2fs_ra_meta_caches(sbi, start_sum_block(sbi),
> + npages, META_CP, true);
>
> /* restore for compacted data summary */
> err = read_compacted_summaries(sbi);
> @@ -4564,7 +4566,7 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
> }
>
> if (__exist_node_summaries(sbi))
> - f2fs_ra_meta_pages(sbi,
> + f2fs_ra_meta_caches(sbi,
> sum_blk_addr(sbi, NR_CURSEG_PERSIST_TYPE, type),
> NR_CURSEG_PERSIST_TYPE - type, META_CP, true);
>
> @@ -4587,16 +4589,16 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
>
> static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
> {
> - struct folio *folio;
> + struct f2fs_cached_block *entry = NULL;
> unsigned char *kaddr;
> struct f2fs_summary *summary;
> struct curseg_info *seg_i;
> int written_size = 0;
> int i, j;
>
> - folio = f2fs_grab_meta_folio(sbi, blkaddr++);
> - kaddr = folio_address(folio);
> - memset(kaddr, 0, PAGE_SIZE);
> + entry = f2fs_grab_meta_cache(sbi, blkaddr++);
> + kaddr = cache_address(entry);
> + memset(kaddr, 0, sbi->blocksize);
>
> /* Step 1: write nat cache */
> seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
> @@ -4612,10 +4614,10 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
> for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
> seg_i = CURSEG_I(sbi, i);
> for (j = 0; j < f2fs_curseg_valid_blocks(sbi, i); j++) {
> - if (!folio) {
> - folio = f2fs_grab_meta_folio(sbi, blkaddr++);
> - kaddr = folio_address(folio);
> - memset(kaddr, 0, PAGE_SIZE);
> + if (!entry) {
> + entry = f2fs_grab_meta_cache(sbi, blkaddr++);
> + kaddr = cache_address(entry);
> + memset(kaddr, 0, sbi->blocksize);
> written_size = 0;
> }
> summary = (struct f2fs_summary *)(kaddr + written_size);
> @@ -4626,14 +4628,14 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
> SUM_FOOTER_SIZE)
> continue;
>
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> - folio = NULL;
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> + entry = NULL;
> }
> }
> - if (folio) {
> - folio_mark_dirty(folio);
> - f2fs_folio_put(folio, true);
> + if (entry) {
> + f2fs_mark_cache_dirty(entry);
> + f2fs_put_cache(entry, true);
> }
> }
>
> @@ -4687,29 +4689,29 @@ int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi,
> return -1;
> }
>
> -static struct folio *get_current_sit_folio(struct f2fs_sb_info *sbi,
> +static struct f2fs_cached_block *get_current_sit_cache(struct f2fs_sb_info *sbi,
> unsigned int segno)
> {
> - return f2fs_get_meta_folio(sbi, current_sit_addr(sbi, segno));
> + return f2fs_get_meta_cache(sbi, current_sit_addr(sbi, segno));
> }
>
> -static struct folio *get_next_sit_folio(struct f2fs_sb_info *sbi,
> +static struct f2fs_cached_block *get_next_sit_cache(struct f2fs_sb_info *sbi,
> unsigned int start)
> {
> struct sit_info *sit_i = SIT_I(sbi);
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
> pgoff_t src_off, dst_off;
>
> src_off = current_sit_addr(sbi, start);
> dst_off = next_sit_addr(sbi, src_off);
>
> - folio = f2fs_grab_meta_folio(sbi, dst_off);
> - seg_info_to_sit_folio(sbi, folio, start);
> + entry = f2fs_grab_meta_cache(sbi, dst_off);
> + seg_info_to_sit_block(sbi, entry, start);
>
> - folio_mark_dirty(folio);
> + f2fs_mark_cache_dirty(entry);
> set_to_next_sit(sit_i, start);
>
> - return folio;
> + return entry;
> }
>
> static struct sit_entry_set *grab_sit_entry_set(void)
> @@ -4839,8 +4841,9 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> * #2, flush sit entries to sit page.
> */
> list_for_each_entry_safe(ses, tmp, head, set_list) {
> - struct folio *folio = NULL;
> + struct f2fs_cached_block *entry = NULL;
> struct f2fs_sit_block *raw_sit = NULL;
> +
> unsigned int start_segno = ses->start_segno;
> unsigned int end = min(start_segno + SIT_ENTRY_PER_BLOCK,
> (unsigned long)MAIN_SEGS(sbi));
> @@ -4854,8 +4857,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> if (to_journal) {
> down_write(&curseg->journal_rwsem);
> } else {
> - folio = get_next_sit_folio(sbi, start_segno);
> - raw_sit = folio_address(folio);
> + entry = get_next_sit_cache(sbi, start_segno);
> + raw_sit = cache_address(entry);
> }
>
> /* flush dirty sit entries in region of current sit set */
> @@ -4900,7 +4903,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> if (to_journal)
> up_write(&curseg->journal_rwsem);
> else
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
>
> f2fs_bug_on(sbi, ses->entry_cnt);
> release_sit_entry_set(ses);
> @@ -5091,7 +5094,7 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
> block_t sit_valid_blocks[2] = {0, 0};
>
> do {
> - readed = f2fs_ra_meta_pages(sbi, start_blk, BIO_MAX_VECS,
> + readed = f2fs_ra_meta_caches(sbi, start_blk, BIO_MAX_VECS,
> META_SIT, true);
>
> start = start_blk * sit_i->sents_per_block;
> @@ -5099,15 +5102,15 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
>
> for (; start < end && start < MAIN_SEGS(sbi); start++) {
> struct f2fs_sit_block *sit_blk;
> - struct folio *folio;
> + struct f2fs_cached_block *entry;
>
> se = &sit_i->sentries[start];
> - folio = get_current_sit_folio(sbi, start);
> - if (IS_ERR(folio))
> - return PTR_ERR(folio);
> - sit_blk = folio_address(folio);
> + entry = get_current_sit_cache(sbi, start);
> + if (IS_ERR(entry))
> + return PTR_ERR(entry);
> + sit_blk = cache_address(entry);
> sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)];
> - f2fs_folio_put(folio, true);
> + f2fs_put_cache(entry, true);
>
> err = check_block_count(sbi, start, &sit);
> if (err)
> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> index db1079169a23..fff35c63a00f 100644
> --- a/fs/f2fs/segment.h
> +++ b/fs/f2fs/segment.h
> @@ -95,6 +95,8 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
> #define GET_SUM_BLKOFF(sbi, segno) (segno % (sbi)->sums_per_block)
> #define SUM_BLK_PAGE_ADDR(sbi, folio, segno) \
> (folio_address(folio) + GET_SUM_BLKOFF(sbi, segno) * (sbi)->sum_blocksize)
> +#define SUM_BLK_ENTRY_ADDR(sbi, entry, segno) \
> + (cache_address(entry) + GET_SUM_BLKOFF(sbi, segno) * (sbi)->sum_blocksize)
>
> #define GET_SUM_TYPE(footer) ((footer)->entry_type)
> #define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
> @@ -417,8 +419,8 @@ static inline void __seg_info_to_raw_sit(struct seg_entry *se,
> rs->mtime = cpu_to_le64(se->mtime);
> }
>
> -static inline void seg_info_to_sit_folio(struct f2fs_sb_info *sbi,
> - struct folio *folio, unsigned int start)
> +static inline void seg_info_to_sit_block(struct f2fs_sb_info *sbi,
> + struct f2fs_cached_block *entry, unsigned int start)
> {
> struct f2fs_sit_block *raw_sit;
> struct seg_entry *se;
> @@ -427,8 +429,8 @@ static inline void seg_info_to_sit_folio(struct f2fs_sb_info *sbi,
> (unsigned long)MAIN_SEGS(sbi));
> int i;
>
> - raw_sit = folio_address(folio);
> - memset(raw_sit, 0, PAGE_SIZE);
> + raw_sit = cache_address(entry);
> + memset(raw_sit, 0, sbi->blocksize);
> for (i = 0; i < end - start; i++) {
> rs = &raw_sit->entries[i];
> se = get_seg_entry(sbi, start + i);
> @@ -991,6 +993,27 @@ static inline int nr_pages_to_skip(struct f2fs_sb_info *sbi, int type)
> return 0;
> }
>
> +/*
> + * When writing cache asynchronously, align nr_to_write to BIO_MAX_VECS.
> + */
> +static inline long adjust_flush_cache_number(struct f2fs_sb_info *sbi, int type)
> +{
> + long nr_to_write;
> +
> + switch (type) {
> + case META:
> + nr_to_write = BIO_MAX_VECS;
> + break;
> + case NODE:
> + nr_to_write = BIO_MAX_VECS << 1;
> + break;
> + default:
> + f2fs_bug_on(sbi, 1);
> + return 0;
> + }
> + return nr_to_write;
> +}
> +
> /*
> * When writing pages, it'd better align nr_to_write for segment size.
> */
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 89affe72f4fc..d3dee9b7d999 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -1839,8 +1839,7 @@ static int f2fs_drop_inode(struct inode *inode)
> * drop useless meta/node dirty pages.
> */
> if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> - if (inode->i_ino == F2FS_NODE_INO(sbi) ||
> - inode->i_ino == F2FS_META_INO(sbi)) {
> + if (inode->i_ino == F2FS_NODE_INO(sbi)) {
> trace_f2fs_drop_inode(inode, 1);
> return 1;
> }
> @@ -1942,8 +1941,7 @@ static void f2fs_dirty_inode(struct inode *inode, int flags)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
>
> - if (inode->i_ino == F2FS_NODE_INO(sbi) ||
> - inode->i_ino == F2FS_META_INO(sbi))
> + if (inode->i_ino == F2FS_NODE_INO(sbi))
> return;
>
> if (is_inode_flag_set(inode, FI_AUTO_RECOVER))
> @@ -2039,9 +2037,10 @@ static void f2fs_put_super(struct super_block *sb)
>
> f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA);
>
> - if (err || f2fs_cp_error(sbi)) {
> + if (err || f2fs_cp_error(sbi) ||
> + unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> truncate_inode_pages_final(NODE_MAPPING(sbi));
> - truncate_inode_pages_final(META_MAPPING(sbi));
> + f2fs_truncate_meta_caches(sbi, 0, ULONG_MAX);
> }
>
> f2fs_bug_on(sbi, sbi->fsync_node_num);
> @@ -2051,9 +2050,6 @@ static void f2fs_put_super(struct super_block *sb)
> iput(sbi->node_inode);
> sbi->node_inode = NULL;
>
> - iput(sbi->meta_inode);
> - sbi->meta_inode = NULL;
> -
> f2fs_destroy_cache(META_CACHE(sbi));
>
> /* Should check the page counts after dropping all node/meta pages */
> @@ -4383,7 +4379,6 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
> sbi->allocate_section_policy = ALLOCATE_FORWARD_NOHINT;
> F2FS_ROOT_INO(sbi) = le32_to_cpu(raw_super->root_ino);
> F2FS_NODE_INO(sbi) = le32_to_cpu(raw_super->node_ino);
> - F2FS_META_INO(sbi) = le32_to_cpu(raw_super->meta_ino);
> sbi->cur_victim_sec = NULL_SECNO;
> sbi->gc_mode = GC_NORMAL;
> sbi->next_victim_seg[BG_GC] = NULL_SEGNO;
> @@ -5224,18 +5219,10 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
> if (err)
> goto free_page_array_cache;
>
> - /* get an inode for meta space */
> - sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
> - if (IS_ERR(sbi->meta_inode)) {
> - f2fs_err(sbi, "Failed to read F2FS meta data inode");
> - err = PTR_ERR(sbi->meta_inode);
> - goto free_meta_cache;
> - }
> -
> err = f2fs_get_valid_checkpoint(sbi);
> if (err) {
> f2fs_err(sbi, "Failed to get valid F2FS checkpoint");
> - goto free_meta_inode;
> + goto free_meta_cache;
> }
>
> if (__is_set_ckpt_flags(F2FS_CKPT(sbi), CP_QUOTA_NEED_FSCK_FLAG))
> @@ -5529,7 +5516,7 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
> * followed by f2fs_write_checkpoint() through f2fs_write_node_pages(), which
> * falls into an infinite loop in f2fs_sync_meta_pages().
> */
> - truncate_inode_pages_final(META_MAPPING(sbi));
> + f2fs_truncate_meta_caches(sbi, 0, ULONG_MAX);
> /* evict some inodes being cached by GC */
> evict_inodes(sb);
> f2fs_unregister_sysfs(sbi);
> @@ -5559,10 +5546,6 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
> free_devices:
> destroy_device_list(sbi);
> kvfree(sbi->ckpt);
> -free_meta_inode:
> - make_bad_inode(sbi->meta_inode);
> - iput(sbi->meta_inode);
> - sbi->meta_inode = NULL;
> free_meta_cache:
> f2fs_destroy_cache(META_CACHE(sbi));
> free_page_array_cache:
> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> index bb2b6cd5d507..0c027d00a1ea 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -35,7 +35,6 @@
>
> #define F2FS_ROOT_INO(sbi) ((sbi)->root_ino_num)
> #define F2FS_NODE_INO(sbi) ((sbi)->node_ino_num)
> -#define F2FS_META_INO(sbi) ((sbi)->meta_ino_num)
> #define F2FS_COMPRESS_INO(sbi) (NM_I(sbi)->max_nid)
>
> #define F2FS_MAX_QUOTAS 3
> --
> 2.49.0
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
next prev parent reply other threads:[~2026-08-20 5:11 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 3:17 [PATCH v1 00/12] f2fs: introduce metadata cache Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
2026-08-20 3:17 ` [PATCH v1 01/12] f2fs: cache: implement " Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
2026-08-20 5:08 ` Jaegeuk Kim via Linux-f2fs-devel
2026-08-20 5:08 ` Jaegeuk Kim
2026-08-20 5:13 ` Chao Yu via Linux-f2fs-devel
2026-08-20 5:13 ` Chao Yu
2026-08-20 3:17 ` [PATCH v1 02/12] f2fs: cache: initialize meta cache Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
2026-08-20 3:17 ` [PATCH v1 03/12] f2fs: cache: introduce shrinker Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
2026-08-20 3:17 ` [PATCH v1 04/12] f2fs: cache: introduce writeback thread Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
2026-08-20 5:09 ` Jaegeuk Kim via Linux-f2fs-devel
2026-08-20 5:09 ` Jaegeuk Kim
2026-08-20 3:17 ` [f2fs-dev] [PATCH v1 05/12] f2fs: cache: use meta cache Chao Yu via Linux-f2fs-devel
2026-08-20 3:17 ` Chao Yu
2026-08-20 5:11 ` Jaegeuk Kim via Linux-f2fs-devel [this message]
2026-08-20 5:11 ` [f2fs-dev] " Jaegeuk Kim
2026-08-20 3:17 ` [PATCH v1 06/12] f2fs: cache: initialize node cache Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
2026-08-20 3:17 ` [f2fs-dev] [PATCH v1 07/12] f2fs: cache: use " Chao Yu via Linux-f2fs-devel
2026-08-20 3:17 ` Chao Yu
2026-08-20 3:17 ` [PATCH v1 08/12] f2fs: cache: initialize compress cache Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
2026-08-20 3:17 ` [PATCH v1 09/12] f2fs: cache: use " Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
2026-08-20 3:17 ` [PATCH v1 10/12] f2fs: cache: support fault injection Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
2026-08-20 3:17 ` [PATCH v1 11/12] f2fs: cache: introduce tracepoints Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
2026-08-20 3:17 ` [PATCH v1 12/12] f2fs: cache: show per-cache usage in debugfs Chao Yu
2026-08-20 3:17 ` [f2fs-dev] " Chao Yu via Linux-f2fs-devel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aoaMa3N7mk5f4jz-@google.com \
--to=linux-f2fs-devel@lists.sourceforge.net \
--cc=chao@kernel.org \
--cc=jaegeuk@kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.