netfs: Provide invalidate_folio and release_folio calls
authorDavid Howells <dhowells@redhat.com>
Fri, 20 Aug 2021 16:08:30 +0000 (17:08 +0100)
committerDavid Howells <dhowells@redhat.com>
Sun, 24 Dec 2023 15:08:51 +0000 (15:08 +0000)
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 <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
cc: linux-fsdevel@vger.kernel.org
cc: linux-mm@kvack.org

fs/9p/vfs_addr.c
fs/afs/file.c
fs/ceph/addr.c
fs/ceph/cache.h
fs/netfs/misc.c
include/linux/netfs.h

index 131b83c31f85daa413ebd0bff010e5bd7b0ca958..055b672a247d7eacc0bc437bd89172cca2b6e5e8 100644 (file)
@@ -88,35 +88,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)
@@ -324,8 +295,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,
 };
index 0d783e5b2147b48b6ef2cd9346005612eda7e350..d152ba451f0ecefb8272da6de03b06b8bd3c8e9a 100644 (file)
@@ -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    = netfs_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,
 };
 
@@ -386,48 +383,6 @@ const struct netfs_request_ops afs_req_ops = {
        .issue_read             = afs_issue_read,
 };
 
-/*
- * 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) {
index 3b8641febeac0f31fec612c5206ecc6aab0212df..8eedc62e7ac4e79a429b3e132f79c1c7e7da9101 100644 (file)
@@ -159,27 +159,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;
-       struct ceph_client *cl = ceph_inode_to_client(inode);
-
-       doutc(cl, "%llx.%llx 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)
@@ -1585,7 +1565,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,
 };
 
index 8fc7d828d99033acade4f8317b4067411e832fe5..20efac020394eeb3608d6a2200e8a08591f6e7ba 100644 (file)
@@ -56,12 +56,6 @@ static inline bool ceph_is_cache_enabled(struct inode *inode)
        return fscache_cookie_enabled(ceph_fscache_cookie(ceph_inode(inode)));
 }
 
-static inline void ceph_fscache_note_page_release(struct inode *inode)
-{
-       struct ceph_inode_info *ci = ceph_inode(inode);
-
-       fscache_note_page_release(ceph_fscache_cookie(ci));
-}
 #else /* CONFIG_CEPH_FSCACHE */
 static inline int ceph_fscache_register_fs(struct ceph_fs_client* fsc,
                                           struct fs_context *fc)
@@ -118,10 +112,6 @@ static inline bool ceph_is_cache_enabled(struct inode *inode)
 {
        return false;
 }
-
-static inline void ceph_fscache_note_page_release(struct inode *inode)
-{
-}
 #endif /* CONFIG_CEPH_FSCACHE */
 
 #endif
index 68baf55c47a43a181afa83db6087afe99c5a97b2..45bb19ec9a638d740c426cefb7079502c2c79a3d 100644 (file)
@@ -84,3 +84,45 @@ void netfs_clear_inode_writeback(struct inode *inode, const void *aux)
        }
 }
 EXPORT_SYMBOL(netfs_clear_inode_writeback);
+
+/**
+ * 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);
index 06f57d9d09f6c32d61cda97eac1d3afe64bcd697..8efbfd3b282020e5a416dd9c50134351c8a30c2c 100644 (file)
@@ -293,11 +293,13 @@ 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);
 bool netfs_dirty_folio(struct address_space *mapping, struct folio *folio);
 int netfs_unpin_writeback(struct inode *inode, struct writeback_control *wbc);
 void netfs_clear_inode_writeback(struct inode *inode, const void *aux);
+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,