Large folios store a f2fs_folio_state pointer in folio->private, so page-private bits must be stored separately. Route page-private flags to a extra private_flags in f2fs_folio_state for large folios while preserving the existing encoding for order-0 folios.We also make PAGE_PRIVATE funcs aware of f2fs_folio_state.
Note there's and edge case when folio_set_f2fs_#name is called on a large folio before any f2fs_folio_state is attached. We may should alloc a f2fs_folio_state in that case, but it requires to move ffs_find_or_alloc to f2fs.h. For now I just let this case sliently return. Need more disscusion here. Signed-off-by: Nanzhe Zhao <[email protected]> --- fs/f2fs/f2fs.h | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 04a6310145c4..91f6d5fb9d20 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2045,6 +2045,7 @@ struct f2fs_sb_info { struct f2fs_folio_state { spinlock_t state_lock; unsigned int read_pages_pending; + unsigned long private_flags; unsigned long state[]; }; @@ -2618,9 +2619,15 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, #define PAGE_PRIVATE_GET_FUNC(name, flagname) \ static inline bool folio_test_f2fs_##name(const struct folio *folio) \ { \ - unsigned long priv = (unsigned long)folio->private; \ + unsigned long priv; \ unsigned long v = (1UL << PAGE_PRIVATE_NOT_POINTER) | \ (1UL << PAGE_PRIVATE_##flagname); \ + if (folio_test_large(folio) && folio->private) { \ + struct f2fs_folio_state *ffs = folio->private; \ + priv = ffs->private_flags; \ + } else { \ + priv = (unsigned long)folio->private; \ + } \ return (priv & v) == v; \ } \ static inline bool page_private_##name(struct page *page) \ @@ -2635,9 +2642,14 @@ static inline void folio_set_f2fs_##name(struct folio *folio) \ { \ unsigned long v = (1UL << PAGE_PRIVATE_NOT_POINTER) | \ (1UL << PAGE_PRIVATE_##flagname); \ - if (!folio->private) \ + if (!folio->private && !folio_test_large(folio)) \ folio_attach_private(folio, (void *)v); \ - else { \ + else if (folio_test_large(folio)) { \ + struct f2fs_folio_state *ffs = folio->private; \ + if (!ffs) \ + return; \ + ffs->private_flags |= v; \ + } else { \ v |= (unsigned long)folio->private; \ folio->private = (void *)v; \ } \ @@ -2653,13 +2665,17 @@ static inline void set_page_private_##name(struct page *page) \ #define PAGE_PRIVATE_CLEAR_FUNC(name, flagname) \ static inline void folio_clear_f2fs_##name(struct folio *folio) \ { \ - unsigned long v = (unsigned long)folio->private; \ - \ - v &= ~(1UL << PAGE_PRIVATE_##flagname); \ - if (v == (1UL << PAGE_PRIVATE_NOT_POINTER)) \ - folio_detach_private(folio); \ - else \ - folio->private = (void *)v; \ + if (folio_test_large(folio) && folio->private) { \ + struct f2fs_folio_state *ffs = folio->private; \ + ffs->private_flags &= ~(1UL << PAGE_PRIVATE_##flagname); \ + } else { \ + unsigned long v = (unsigned long)folio->private; \ + v &= ~(1UL << PAGE_PRIVATE_##flagname); \ + if (v == (1UL << PAGE_PRIVATE_NOT_POINTER)) \ + folio_detach_private(folio); \ + else \ + folio->private = (void *)v; \ + } \ } \ static inline void clear_page_private_##name(struct page *page) \ { \ -- 2.34.1 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
