On Fri, 2023-10-13 at 17:03 +0100, David Howells wrote:
> Provide default invalidate_folio and release_folio calls.  These will need
> to interact with invalidation correctly at some point.  They will be needed
> if netfslib is to make use of folio->private for its own purposes.
> 
> Signed-off-by: David Howells <dhowe...@redhat.com>
> cc: Jeff Layton <jlay...@kernel.org>
> cc: linux-cachefs@redhat.com
> cc: linux-fsde...@vger.kernel.org
> cc: linux...@kvack.org
> ---
>  fs/9p/vfs_addr.c      | 33 ++-------------------------
>  fs/afs/file.c         | 53 ++++---------------------------------------
>  fs/ceph/addr.c        | 24 ++------------------
>  fs/netfs/Makefile     |  1 +
>  fs/netfs/misc.c       | 51 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/netfs.h |  6 +++--
>  6 files changed, 64 insertions(+), 104 deletions(-)
>  create mode 100644 fs/netfs/misc.c
> 
> diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
> index 8a635999a7d6..18a666c43e4a 100644
> --- a/fs/9p/vfs_addr.c
> +++ b/fs/9p/vfs_addr.c
> @@ -104,35 +104,6 @@ const struct netfs_request_ops v9fs_req_ops = {
>       .issue_read             = v9fs_issue_read,
>  };
>  
> -/**
> - * v9fs_release_folio - release the private state associated with a folio
> - * @folio: The folio to be released
> - * @gfp: The caller's allocation restrictions
> - *
> - * Returns true if the page can be released, false otherwise.
> - */
> -
> -static bool v9fs_release_folio(struct folio *folio, gfp_t gfp)
> -{
> -     if (folio_test_private(folio))
> -             return false;
> -#ifdef CONFIG_9P_FSCACHE
> -     if (folio_test_fscache(folio)) {
> -             if (current_is_kswapd() || !(gfp & __GFP_FS))
> -                     return false;
> -             folio_wait_fscache(folio);
> -     }
> -     
> fscache_note_page_release(v9fs_inode_cookie(V9FS_I(folio_inode(folio))));
> -#endif
> -     return true;
> -}
> -
> -static void v9fs_invalidate_folio(struct folio *folio, size_t offset,
> -                              size_t length)
> -{
> -     folio_wait_fscache(folio);
> -}
> -
>  #ifdef CONFIG_9P_FSCACHE
>  static void v9fs_write_to_cache_done(void *priv, ssize_t 
> transferred_or_error,
>                                    bool was_async)
> @@ -355,8 +326,8 @@ const struct address_space_operations 
> v9fs_addr_operations = {
>       .writepage = v9fs_vfs_writepage,
>       .write_begin = v9fs_write_begin,
>       .write_end = v9fs_write_end,
> -     .release_folio = v9fs_release_folio,
> -     .invalidate_folio = v9fs_invalidate_folio,
> +     .release_folio = netfs_release_folio,
> +     .invalidate_folio = netfs_invalidate_folio,
>       .launder_folio = v9fs_launder_folio,
>       .direct_IO = v9fs_direct_IO,
>  };
> diff --git a/fs/afs/file.c b/fs/afs/file.c
> index 0c49b3b6f214..3fea5cd8ef13 100644
> --- a/fs/afs/file.c
> +++ b/fs/afs/file.c
> @@ -20,9 +20,6 @@
>  
>  static int afs_file_mmap(struct file *file, struct vm_area_struct *vma);
>  static int afs_symlink_read_folio(struct file *file, struct folio *folio);
> -static void afs_invalidate_folio(struct folio *folio, size_t offset,
> -                            size_t length);
> -static bool afs_release_folio(struct folio *folio, gfp_t gfp_flags);
>  
>  static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter);
>  static ssize_t afs_file_splice_read(struct file *in, loff_t *ppos,
> @@ -57,8 +54,8 @@ const struct address_space_operations afs_file_aops = {
>       .readahead      = netfs_readahead,
>       .dirty_folio    = afs_dirty_folio,
>       .launder_folio  = afs_launder_folio,
> -     .release_folio  = afs_release_folio,
> -     .invalidate_folio = afs_invalidate_folio,
> +     .release_folio  = netfs_release_folio,
> +     .invalidate_folio = netfs_invalidate_folio,
>       .write_begin    = afs_write_begin,
>       .write_end      = afs_write_end,
>       .writepages     = afs_writepages,
> @@ -67,8 +64,8 @@ const struct address_space_operations afs_file_aops = {
>  
>  const struct address_space_operations afs_symlink_aops = {
>       .read_folio     = afs_symlink_read_folio,
> -     .release_folio  = afs_release_folio,
> -     .invalidate_folio = afs_invalidate_folio,
> +     .release_folio  = netfs_release_folio,
> +     .invalidate_folio = netfs_invalidate_folio,
>       .migrate_folio  = filemap_migrate_folio,
>  };
>  
> @@ -405,48 +402,6 @@ int afs_write_inode(struct inode *inode, struct 
> writeback_control *wbc)
>       return 0;
>  }
>  
> -/*
> - * invalidate part or all of a page
> - * - release a page and clean up its private data if offset is 0 (indicating
> - *   the entire page)
> - */
> -static void afs_invalidate_folio(struct folio *folio, size_t offset,
> -                            size_t length)
> -{
> -     _enter("{%lu},%zu,%zu", folio->index, offset, length);
> -
> -     folio_wait_fscache(folio);
> -     _leave("");
> -}
> -
> -/*
> - * release a page and clean up its private state if it's not busy
> - * - return true if the page can now be released, false if not
> - */
> -static bool afs_release_folio(struct folio *folio, gfp_t gfp)
> -{
> -     struct afs_vnode *vnode = AFS_FS_I(folio_inode(folio));
> -
> -     _enter("{{%llx:%llu}[%lu],%lx},%x",
> -            vnode->fid.vid, vnode->fid.vnode, folio_index(folio), 
> folio->flags,
> -            gfp);
> -
> -     /* deny if folio is being written to the cache and the caller hasn't
> -      * elected to wait */
> -#ifdef CONFIG_AFS_FSCACHE
> -     if (folio_test_fscache(folio)) {
> -             if (current_is_kswapd() || !(gfp & __GFP_FS))
> -                     return false;
> -             folio_wait_fscache(folio);
> -     }
> -     fscache_note_page_release(afs_vnode_cache(vnode));
> -#endif
> -
> -     /* Indicate that the folio can be released */
> -     _leave(" = T");
> -     return true;
> -}
> -
>  static void afs_add_open_mmap(struct afs_vnode *vnode)
>  {
>       if (atomic_inc_return(&vnode->cb_nr_mmap) == 1) {
> diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
> index f4863078f7fe..ced19ff08988 100644
> --- a/fs/ceph/addr.c
> +++ b/fs/ceph/addr.c
> @@ -160,27 +160,7 @@ static void ceph_invalidate_folio(struct folio *folio, 
> size_t offset,
>               ceph_put_snap_context(snapc);
>       }
>  
> -     folio_wait_fscache(folio);
> -}
> -
> -static bool ceph_release_folio(struct folio *folio, gfp_t gfp)
> -{
> -     struct inode *inode = folio->mapping->host;
> -
> -     dout("%llx:%llx release_folio idx %lu (%sdirty)\n",
> -          ceph_vinop(inode),
> -          folio->index, folio_test_dirty(folio) ? "" : "not ");
> -
> -     if (folio_test_private(folio))
> -             return false;
> -
> -     if (folio_test_fscache(folio)) {
> -             if (current_is_kswapd() || !(gfp & __GFP_FS))
> -                     return false;
> -             folio_wait_fscache(folio);
> -     }
> -     ceph_fscache_note_page_release(inode);
> -     return true;
> +     netfs_invalidate_folio(folio, offset, length);
>  }
>  
>  static void ceph_netfs_expand_readahead(struct netfs_io_request *rreq)
> @@ -1563,7 +1543,7 @@ const struct address_space_operations ceph_aops = {
>       .write_end = ceph_write_end,
>       .dirty_folio = ceph_dirty_folio,
>       .invalidate_folio = ceph_invalidate_folio,
> -     .release_folio = ceph_release_folio,
> +     .release_folio = netfs_release_folio,
>       .direct_IO = noop_direct_IO,
>  };
>  
> diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile
> index 386d6fb92793..cd22554d9048 100644
> --- a/fs/netfs/Makefile
> +++ b/fs/netfs/Makefile
> @@ -5,6 +5,7 @@ netfs-y := \
>       io.o \
>       iterator.o \
>       main.o \
> +     misc.o \
>       objects.o
>  
>  netfs-$(CONFIG_NETFS_STATS) += stats.o
> diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c
> new file mode 100644
> index 000000000000..c3baf2b247d9
> --- /dev/null
> +++ b/fs/netfs/misc.c
> @@ -0,0 +1,51 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Miscellaneous routines.
> + *
> + * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved.
> + * Written by David Howells (dhowe...@redhat.com)
> + */
> +
> +#include <linux/swap.h>
> +#include "internal.h"
> +
> +/**
> + * netfs_invalidate_folio - Invalidate or partially invalidate a folio
> + * @folio: Folio proposed for release
> + * @offset: Offset of the invalidated region
> + * @length: Length of the invalidated region
> + *
> + * Invalidate part or all of a folio for a network filesystem.  The folio 
> will
> + * be removed afterwards if the invalidated region covers the entire folio.
> + */
> +void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t 
> length)
> +{
> +     _enter("{%lx},%zx,%zx", folio_index(folio), offset, length);
> +
> +     folio_wait_fscache(folio);
> +}
> +EXPORT_SYMBOL(netfs_invalidate_folio);
> +
> +/**
> + * netfs_release_folio - Try to release a folio
> + * @folio: Folio proposed for release
> + * @gfp: Flags qualifying the release
> + *
> + * Request release of a folio and clean up its private state if it's not 
> busy.
> + * Returns true if the folio can now be released, false if not
> + */
> +bool netfs_release_folio(struct folio *folio, gfp_t gfp)
> +{
> +     struct netfs_inode *ctx = netfs_inode(folio_inode(folio));
> +
> +     if (folio_test_private(folio))
> +             return false;
> +     if (folio_test_fscache(folio)) {
> +             if (current_is_kswapd() || !(gfp & __GFP_FS))
> +                     return false;
> +             folio_wait_fscache(folio);
> +     }
> +
> +     fscache_note_page_release(netfs_i_cookie(ctx));
> +     return true;
> +}
> +EXPORT_SYMBOL(netfs_release_folio);
> diff --git a/include/linux/netfs.h b/include/linux/netfs.h
> index ed64d1034afa..daa431c4148d 100644
> --- a/include/linux/netfs.h
> +++ b/include/linux/netfs.h
> @@ -299,8 +299,10 @@ struct readahead_control;
>  void netfs_readahead(struct readahead_control *);
>  int netfs_read_folio(struct file *, struct folio *);
>  int netfs_write_begin(struct netfs_inode *, struct file *,
> -             struct address_space *, loff_t pos, unsigned int len,
> -             struct folio **, void **fsdata);
> +                   struct address_space *, loff_t pos, unsigned int len,
> +                   struct folio **, void **fsdata);
> +void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t 
> length);
> +bool netfs_release_folio(struct folio *folio, gfp_t gfp);
>  
>  void netfs_subreq_terminated(struct netfs_io_subrequest *, ssize_t, bool);
>  void netfs_get_subrequest(struct netfs_io_subrequest *subreq,
> 

Nice cleanup. Might can merge this in advance of the rest of the series.

Reviewed-by: Jeff Layton <jlay...@kernel.org>

--
Linux-cachefs mailing list
Linux-cachefs@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-cachefs

Reply via email to