On Fri Mar 7, 2025 at 8:54 AM EST, Matthew Wilcox (Oracle) wrote: > The writepage callback is going away; filesystems must implement > migrate_folio or else dirty folios will not be migratable. What is the impact of this? Are there any filesystem that has a_ops->writepage() without migrate_folio()? I wonder if it could make the un-migratable problem worse[1] when such FS exists. [1] https://lore.kernel.org/linux-mm/882b566c-34d6-4e68-9447-6c74a0693f18@xxxxxxxxxx/ > > Signed-off-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx> > --- > mm/migrate.c | 57 ++++------------------------------------------------ > 1 file changed, 4 insertions(+), 53 deletions(-) > > diff --git a/mm/migrate.c b/mm/migrate.c > index c0adea67cd62..3d1d9d49fb8e 100644 > --- a/mm/migrate.c > +++ b/mm/migrate.c > @@ -944,67 +944,18 @@ int filemap_migrate_folio(struct address_space *mapping, > } > EXPORT_SYMBOL_GPL(filemap_migrate_folio); > > -/* > - * Writeback a folio to clean the dirty state > - */ > -static int writeout(struct address_space *mapping, struct folio *folio) > -{ > - struct writeback_control wbc = { > - .sync_mode = WB_SYNC_NONE, > - .nr_to_write = 1, > - .range_start = 0, > - .range_end = LLONG_MAX, > - .for_reclaim = 1 > - }; > - int rc; > - > - if (!mapping->a_ops->writepage) > - /* No write method for the address space */ > - return -EINVAL; > - > - if (!folio_clear_dirty_for_io(folio)) > - /* Someone else already triggered a write */ > - return -EAGAIN; > - > - /* > - * A dirty folio may imply that the underlying filesystem has > - * the folio on some queue. So the folio must be clean for > - * migration. Writeout may mean we lose the lock and the > - * folio state is no longer what we checked for earlier. > - * At this point we know that the migration attempt cannot > - * be successful. > - */ > - remove_migration_ptes(folio, folio, 0); > - > - rc = mapping->a_ops->writepage(&folio->page, &wbc); > - > - if (rc != AOP_WRITEPAGE_ACTIVATE) > - /* unlocked. Relock */ > - folio_lock(folio); > - > - return (rc < 0) ? -EIO : -EAGAIN; > -} > - > /* > * Default handling if a filesystem does not provide a migration function. > */ > static int fallback_migrate_folio(struct address_space *mapping, > struct folio *dst, struct folio *src, enum migrate_mode mode) > { > - if (folio_test_dirty(src)) { > - /* Only writeback folios in full synchronous migration */ > - switch (mode) { > - case MIGRATE_SYNC: > - break; > - default: > - return -EBUSY; > - } > - return writeout(mapping, src); > - } Now fallback_migrate_folio() no longer writes out page for FS, so it is the responsibilty of migrate_folio()? +Joanne, since she is touching the above code in the FUSE temp page removal patchset. > + if (folio_test_dirty(src)) > + return -EBUSY; > > /* > - * Buffers may be managed in a filesystem specific way. > - * We must have no buffers or drop them. > + * Filesystem may have private data at folio->private that we > + * can't migrate automatically. > */ > if (!filemap_release_folio(src, GFP_KERNEL)) > return mode == MIGRATE_SYNC ? -EAGAIN : -EBUSY; -- Best Regards, Yan, Zi