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

Reply via email to