From: Elliot Berman <quic_eberman@xxxxxxxxxxx> The plan is to be able to support multiple allocators for guest_memfd folios. To allow each allocator to handle release of a folio from a guest_memfd filemap, ->free_folio() needs to retrieve allocator information that is stored on the guest_memfd inode. ->free_folio() shouldn't assume that folio->mapping is set/valid, and the mapping is well-known to callers of .free_folio(). Hence, pass address_space mapping to ->free_folio() for the callback to retrieve any necessary information. Link: https://lore.kernel.org/all/15f665b4-2d33-41ca-ac50-fafe24ade32f@xxxxxxxxxx/ Suggested-by: David Hildenbrand <david@xxxxxxxxxx> Acked-by: David Hildenbrand <david@xxxxxxxxxx> Change-Id: I8bac907832a0b2491fa403a6ab72fcef1b4713ee Signed-off-by: Elliot Berman <quic_eberman@xxxxxxxxxxx> Tested-by: Mike Day <michael.day@xxxxxxx> Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx> --- Documentation/filesystems/locking.rst | 2 +- Documentation/filesystems/vfs.rst | 15 +++++++++------ fs/nfs/dir.c | 9 +++++++-- fs/orangefs/inode.c | 3 ++- include/linux/fs.h | 2 +- mm/filemap.c | 9 +++++---- mm/secretmem.c | 3 ++- mm/vmscan.c | 4 ++-- virt/kvm/guest_memfd.c | 3 ++- 9 files changed, 31 insertions(+), 19 deletions(-) diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst index 0ec0bb6eb0fb..c3d7430481ae 100644 --- a/Documentation/filesystems/locking.rst +++ b/Documentation/filesystems/locking.rst @@ -263,7 +263,7 @@ prototypes:: sector_t (*bmap)(struct address_space *, sector_t); void (*invalidate_folio) (struct folio *, size_t start, size_t len); bool (*release_folio)(struct folio *, gfp_t); - void (*free_folio)(struct folio *); + void (*free_folio)(struct address_space *, struct folio *); int (*direct_IO)(struct kiocb *, struct iov_iter *iter); int (*migrate_folio)(struct address_space *, struct folio *dst, struct folio *src, enum migrate_mode); diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index ae79c30b6c0c..bba1ac848f96 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -833,7 +833,7 @@ cache in your filesystem. The following members are defined: sector_t (*bmap)(struct address_space *, sector_t); void (*invalidate_folio) (struct folio *, size_t start, size_t len); bool (*release_folio)(struct folio *, gfp_t); - void (*free_folio)(struct folio *); + void (*free_folio)(struct address_space *, struct folio *); ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter); int (*migrate_folio)(struct mapping *, struct folio *dst, struct folio *src, enum migrate_mode); @@ -1011,11 +1011,14 @@ cache in your filesystem. The following members are defined: clear the uptodate flag if it cannot free private data yet. ``free_folio`` - free_folio is called once the folio is no longer visible in the - page cache in order to allow the cleanup of any private data. - Since it may be called by the memory reclaimer, it should not - assume that the original address_space mapping still exists, and - it should not block. + free_folio is called once the folio is no longer visible in + the page cache in order to allow the cleanup of any private + data. Since it may be called by the memory reclaimer, it + should not assume that the original address_space mapping + still exists at folio->mapping. The mapping the folio used to + belong to is instead passed for free_folio to read any + information it might need from the mapping. free_folio should + not block. ``direct_IO`` called by the generic read/write routines to perform direct_IO - diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index bd23fc736b39..148433f6d9d4 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -55,7 +55,7 @@ static int nfs_closedir(struct inode *, struct file *); static int nfs_readdir(struct file *, struct dir_context *); static int nfs_fsync_dir(struct file *, loff_t, loff_t, int); static loff_t nfs_llseek_dir(struct file *, loff_t, int); -static void nfs_readdir_clear_array(struct folio *); +static void nfs_free_folio(struct address_space *, struct folio *); static int nfs_do_create(struct inode *dir, struct dentry *dentry, umode_t mode, int open_flags); @@ -69,7 +69,7 @@ const struct file_operations nfs_dir_operations = { }; const struct address_space_operations nfs_dir_aops = { - .free_folio = nfs_readdir_clear_array, + .free_folio = nfs_free_folio, }; #define NFS_INIT_DTSIZE PAGE_SIZE @@ -230,6 +230,11 @@ static void nfs_readdir_clear_array(struct folio *folio) kunmap_local(array); } +static void nfs_free_folio(struct address_space *mapping, struct folio *folio) +{ + nfs_readdir_clear_array(folio); +} + static void nfs_readdir_folio_reinit_array(struct folio *folio, u64 last_cookie, u64 change_attr) { diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c index 5ac743c6bc2e..884cc5295f3e 100644 --- a/fs/orangefs/inode.c +++ b/fs/orangefs/inode.c @@ -449,7 +449,8 @@ static bool orangefs_release_folio(struct folio *folio, gfp_t foo) return !folio_test_private(folio); } -static void orangefs_free_folio(struct folio *folio) +static void orangefs_free_folio(struct address_space *mapping, + struct folio *folio) { kfree(folio_detach_private(folio)); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 0fded2e3c661..9862ea92a2af 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -455,7 +455,7 @@ struct address_space_operations { sector_t (*bmap)(struct address_space *, sector_t); void (*invalidate_folio) (struct folio *, size_t offset, size_t len); bool (*release_folio)(struct folio *, gfp_t); - void (*free_folio)(struct folio *folio); + void (*free_folio)(struct address_space *mapping, struct folio *folio); ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter); /* * migrate the contents of a folio to the specified target. If diff --git a/mm/filemap.c b/mm/filemap.c index bed7160db214..a02c3d8e00e8 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -226,11 +226,11 @@ void __filemap_remove_folio(struct folio *folio, void *shadow) void filemap_free_folio(struct address_space *mapping, struct folio *folio) { - void (*free_folio)(struct folio *); + void (*free_folio)(struct address_space*, struct folio *); free_folio = mapping->a_ops->free_folio; if (free_folio) - free_folio(folio); + free_folio(mapping, folio); folio_put_refs(folio, folio_nr_pages(folio)); } @@ -820,7 +820,8 @@ EXPORT_SYMBOL(file_write_and_wait_range); void replace_page_cache_folio(struct folio *old, struct folio *new) { struct address_space *mapping = old->mapping; - void (*free_folio)(struct folio *) = mapping->a_ops->free_folio; + void (*free_folio)(struct address_space *, struct folio *) = + mapping->a_ops->free_folio; pgoff_t offset = old->index; XA_STATE(xas, &mapping->i_pages, offset); @@ -849,7 +850,7 @@ void replace_page_cache_folio(struct folio *old, struct folio *new) __lruvec_stat_add_folio(new, NR_SHMEM); xas_unlock_irq(&xas); if (free_folio) - free_folio(old); + free_folio(mapping, old); folio_put(old); } EXPORT_SYMBOL_GPL(replace_page_cache_folio); diff --git a/mm/secretmem.c b/mm/secretmem.c index c0e459e58cb6..178507c1b900 100644 --- a/mm/secretmem.c +++ b/mm/secretmem.c @@ -152,7 +152,8 @@ static int secretmem_migrate_folio(struct address_space *mapping, return -EBUSY; } -static void secretmem_free_folio(struct folio *folio) +static void secretmem_free_folio(struct address_space *mapping, + struct folio *folio) { set_direct_map_default_noflush(&folio->page); folio_zero_segment(folio, 0, folio_size(folio)); diff --git a/mm/vmscan.c b/mm/vmscan.c index 3783e45bfc92..b8add4d0cf18 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -788,7 +788,7 @@ static int __remove_mapping(struct address_space *mapping, struct folio *folio, xa_unlock_irq(&mapping->i_pages); put_swap_folio(folio, swap); } else { - void (*free_folio)(struct folio *); + void (*free_folio)(struct address_space *, struct folio *); free_folio = mapping->a_ops->free_folio; /* @@ -817,7 +817,7 @@ static int __remove_mapping(struct address_space *mapping, struct folio *folio, spin_unlock(&mapping->host->i_lock); if (free_folio) - free_folio(folio); + free_folio(mapping, folio); } return 1; diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c index 24d270b9b725..c578d0ebe314 100644 --- a/virt/kvm/guest_memfd.c +++ b/virt/kvm/guest_memfd.c @@ -1319,7 +1319,8 @@ static void kvm_gmem_invalidate(struct folio *folio) static inline void kvm_gmem_invalidate(struct folio *folio) {} #endif -static void kvm_gmem_free_folio(struct folio *folio) +static void kvm_gmem_free_folio(struct address_space *mapping, + struct folio *folio) { folio_clear_unevictable(folio); -- 2.49.0.1045.g170613ef41-goog