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 7ee3647243 ("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: 35474d52c6 ("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>
This commit is contained in:
Shivank Garg 2025-04-30 10:01:52 +00:00 committed by Andrew Morton
parent 86ebd50224
commit 906d7ce3b5

View File

@ -15,6 +15,7 @@
#include <linux/mempool.h>
#include <linux/seq_file.h>
#include <linux/writeback.h>
#include <linux/migrate.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_filsys.h"
@ -151,7 +152,59 @@ static inline void dec_io(struct folio *folio, blk_status_t status,
handler(folio, anchor->status);
}
#ifdef CONFIG_MIGRATION
static int __metapage_migrate_folio(struct address_space *mapping,
struct folio *dst, struct folio *src,
enum migrate_mode mode)
{
struct meta_anchor *src_anchor = src->private;
struct metapage *mps[MPS_PER_PAGE] = {0};
struct metapage *mp;
int i, rc;
for (i = 0; i < MPS_PER_PAGE; i++) {
mp = src_anchor->mp[i];
if (mp && metapage_locked(mp))
return -EAGAIN;
}
rc = filemap_migrate_folio(mapping, dst, src, mode);
if (rc != MIGRATEPAGE_SUCCESS)
return rc;
for (i = 0; i < MPS_PER_PAGE; i++) {
mp = src_anchor->mp[i];
if (!mp)
continue;
if (unlikely(insert_metapage(dst, mp))) {
/* If error, roll-back previosly inserted pages */
for (int j = 0 ; j < i; j++) {
if (mps[j])
remove_metapage(dst, mps[j]);
}
return -EAGAIN;
}
mps[i] = mp;
}
/* Update the metapage and remove it from src */
for (i = 0; i < MPS_PER_PAGE; i++) {
mp = mps[i];
if (mp) {
int page_offset = mp->data - folio_address(src);
mp->data = folio_address(dst) + page_offset;
mp->folio = dst;
remove_metapage(src, mp);
}
}
return MIGRATEPAGE_SUCCESS;
}
#endif /* CONFIG_MIGRATION */
#else
static inline struct metapage *folio_to_mp(struct folio *folio, int offset)
{
return folio->private;
@ -175,6 +228,35 @@ static inline void remove_metapage(struct folio *folio, struct metapage *mp)
#define inc_io(folio) do {} while(0)
#define dec_io(folio, status, handler) handler(folio, status)
#ifdef CONFIG_MIGRATION
static int __metapage_migrate_folio(struct address_space *mapping,
struct folio *dst, struct folio *src,
enum migrate_mode mode)
{
struct metapage *mp;
int page_offset;
int rc;
mp = folio_to_mp(src, 0);
if (metapage_locked(mp))
return -EAGAIN;
rc = filemap_migrate_folio(mapping, dst, src, mode);
if (rc != MIGRATEPAGE_SUCCESS)
return rc;
if (unlikely(insert_metapage(dst, mp)))
return -EAGAIN;
page_offset = mp->data - folio_address(src);
mp->data = folio_address(dst) + page_offset;
mp->folio = dst;
remove_metapage(src, mp);
return MIGRATEPAGE_SUCCESS;
}
#endif /* CONFIG_MIGRATION */
#endif
static inline struct metapage *alloc_metapage(gfp_t gfp_mask)
@ -554,6 +636,29 @@ static bool metapage_release_folio(struct folio *folio, gfp_t gfp_mask)
return ret;
}
#ifdef CONFIG_MIGRATION
/*
* metapage_migrate_folio - Migration function for JFS metapages
*/
static int metapage_migrate_folio(struct address_space *mapping,
struct folio *dst, struct folio *src,
enum migrate_mode mode)
{
int expected_count;
if (!src->private)
return filemap_migrate_folio(mapping, dst, src, mode);
/* Check whether page does not have extra refs before we do more work */
expected_count = folio_expected_ref_count(src) + 1;
if (folio_ref_count(src) != expected_count)
return -EAGAIN;
return __metapage_migrate_folio(mapping, dst, src, mode);
}
#else
#define metapage_migrate_folio NULL
#endif /* CONFIG_MIGRATION */
static void metapage_invalidate_folio(struct folio *folio, size_t offset,
size_t length)
{
@ -570,6 +675,7 @@ const struct address_space_operations jfs_metapage_aops = {
.release_folio = metapage_release_folio,
.invalidate_folio = metapage_invalidate_folio,
.dirty_folio = filemap_dirty_folio,
.migrate_folio = metapage_migrate_folio,
};
struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,