Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

jfs: implement migrate_folio for jfs_metapage_aops

Add the missing migrate_folio operation to jfs_metapage_aops to fix
warnings during memory compaction. These warnings were introduced by
commit 7ee3647243e5 ("migrate: Remove call to ->writepage") which added
explicit warnings when filesystems don't implement migrate_folio.

System reports following warnings:
jfs_metapage_aops does not implement migrate_folio
WARNING: CPU: 0 PID: 6870 at mm/migrate.c:955 fallback_migrate_folio mm/migrate.c:953 [inline]
WARNING: CPU: 0 PID: 6870 at mm/migrate.c:955 move_to_new_folio+0x70e/0x840 mm/migrate.c:1007

Implement metapage_migrate_folio() which handles both single and multiple
metapages per page configurations.

[shivankg@amd.com: change comment style]
Link: https://lkml.kernel.org/r/1967593d-8084-4a4a-b384-35d5adc54eb4@amd.com
[akpm@linux-foundation.org: fix build]
[shivankg@amd.com: remove redundant NULL check in __metapage_migrate_folio()]
Link: https://lkml.kernel.org/r/a67db238-0ca6-4725-abb2-dc092de87e1b@amd.com
Link: https://lkml.kernel.org/r/20250430100150.279751-3-shivankg@amd.com
Fixes: 35474d52c605 ("jfs: Convert metapage_writepage to metapage_write_folio")
Signed-off-by: Shivank Garg <shivankg@amd.com>
Reported-by: syzbot+8bb6fd945af4e0ad9299@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/67faff52.050a0220.379d84.001b.GAE@google.com
Tested-by: syzbot+8bb6fd945af4e0ad9299@syzkaller.appspotmail.com
Cc: Alistair Popple <apopple@nvidia.com>
Cc: Dave Kleikamp <shaggy@kernel.org>
Cc: David Hildenbrand <david@redhat.com>
Cc: Donet Tom <donettom@linux.ibm.com>
Cc: Jane Chu <jane.chu@oracle.com>
Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Zi Yan <ziy@nvidia.com>
Cc: Dan Carpenter <dan.carpenter@linaro.org>
Cc: kernel test robot <lkp@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Shivank Garg and committed by
Andrew Morton
906d7ce3 86ebd502

+106
+106
fs/jfs/jfs_metapage.c
··· 15 15 #include <linux/mempool.h> 16 16 #include <linux/seq_file.h> 17 17 #include <linux/writeback.h> 18 + #include <linux/migrate.h> 18 19 #include "jfs_incore.h" 19 20 #include "jfs_superblock.h" 20 21 #include "jfs_filsys.h" ··· 152 151 handler(folio, anchor->status); 153 152 } 154 153 154 + #ifdef CONFIG_MIGRATION 155 + static int __metapage_migrate_folio(struct address_space *mapping, 156 + struct folio *dst, struct folio *src, 157 + enum migrate_mode mode) 158 + { 159 + struct meta_anchor *src_anchor = src->private; 160 + struct metapage *mps[MPS_PER_PAGE] = {0}; 161 + struct metapage *mp; 162 + int i, rc; 163 + 164 + for (i = 0; i < MPS_PER_PAGE; i++) { 165 + mp = src_anchor->mp[i]; 166 + if (mp && metapage_locked(mp)) 167 + return -EAGAIN; 168 + } 169 + 170 + rc = filemap_migrate_folio(mapping, dst, src, mode); 171 + if (rc != MIGRATEPAGE_SUCCESS) 172 + return rc; 173 + 174 + for (i = 0; i < MPS_PER_PAGE; i++) { 175 + mp = src_anchor->mp[i]; 176 + if (!mp) 177 + continue; 178 + if (unlikely(insert_metapage(dst, mp))) { 179 + /* If error, roll-back previosly inserted pages */ 180 + for (int j = 0 ; j < i; j++) { 181 + if (mps[j]) 182 + remove_metapage(dst, mps[j]); 183 + } 184 + return -EAGAIN; 185 + } 186 + mps[i] = mp; 187 + } 188 + 189 + /* Update the metapage and remove it from src */ 190 + for (i = 0; i < MPS_PER_PAGE; i++) { 191 + mp = mps[i]; 192 + if (mp) { 193 + int page_offset = mp->data - folio_address(src); 194 + 195 + mp->data = folio_address(dst) + page_offset; 196 + mp->folio = dst; 197 + remove_metapage(src, mp); 198 + } 199 + } 200 + 201 + return MIGRATEPAGE_SUCCESS; 202 + } 203 + #endif /* CONFIG_MIGRATION */ 204 + 155 205 #else 206 + 156 207 static inline struct metapage *folio_to_mp(struct folio *folio, int offset) 157 208 { 158 209 return folio->private; ··· 227 174 228 175 #define inc_io(folio) do {} while(0) 229 176 #define dec_io(folio, status, handler) handler(folio, status) 177 + 178 + #ifdef CONFIG_MIGRATION 179 + static int __metapage_migrate_folio(struct address_space *mapping, 180 + struct folio *dst, struct folio *src, 181 + enum migrate_mode mode) 182 + { 183 + struct metapage *mp; 184 + int page_offset; 185 + int rc; 186 + 187 + mp = folio_to_mp(src, 0); 188 + if (metapage_locked(mp)) 189 + return -EAGAIN; 190 + 191 + rc = filemap_migrate_folio(mapping, dst, src, mode); 192 + if (rc != MIGRATEPAGE_SUCCESS) 193 + return rc; 194 + 195 + if (unlikely(insert_metapage(dst, mp))) 196 + return -EAGAIN; 197 + 198 + page_offset = mp->data - folio_address(src); 199 + mp->data = folio_address(dst) + page_offset; 200 + mp->folio = dst; 201 + remove_metapage(src, mp); 202 + 203 + return MIGRATEPAGE_SUCCESS; 204 + } 205 + #endif /* CONFIG_MIGRATION */ 230 206 231 207 #endif 232 208 ··· 636 554 return ret; 637 555 } 638 556 557 + #ifdef CONFIG_MIGRATION 558 + /* 559 + * metapage_migrate_folio - Migration function for JFS metapages 560 + */ 561 + static int metapage_migrate_folio(struct address_space *mapping, 562 + struct folio *dst, struct folio *src, 563 + enum migrate_mode mode) 564 + { 565 + int expected_count; 566 + 567 + if (!src->private) 568 + return filemap_migrate_folio(mapping, dst, src, mode); 569 + 570 + /* Check whether page does not have extra refs before we do more work */ 571 + expected_count = folio_expected_ref_count(src) + 1; 572 + if (folio_ref_count(src) != expected_count) 573 + return -EAGAIN; 574 + return __metapage_migrate_folio(mapping, dst, src, mode); 575 + } 576 + #else 577 + #define metapage_migrate_folio NULL 578 + #endif /* CONFIG_MIGRATION */ 579 + 639 580 static void metapage_invalidate_folio(struct folio *folio, size_t offset, 640 581 size_t length) 641 582 { ··· 675 570 .release_folio = metapage_release_folio, 676 571 .invalidate_folio = metapage_invalidate_folio, 677 572 .dirty_folio = filemap_dirty_folio, 573 + .migrate_folio = metapage_migrate_folio, 678 574 }; 679 575 680 576 struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,