]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
afs: Convert afs to use the new fscache API
authorDavid Howells <dhowells@redhat.com>
Thu, 6 Feb 2020 14:22:21 +0000 (14:22 +0000)
committerDavid Howells <dhowells@redhat.com>
Fri, 7 Jan 2022 13:44:47 +0000 (13:44 +0000)
Change the afs filesystem to support the new afs driver.

The following changes have been made:

 (1) The fscache_netfs struct is no more, and there's no need to register
     the filesystem as a whole.  There's also no longer a cell cookie.

 (2) The volume cookie is now an fscache_volume cookie, allocated with
     fscache_acquire_volume().  This function takes three parameters: a
     string representing the "volume" in the index, a string naming the
     cache to use (or NULL) and a u64 that conveys coherency metadata for
     the volume.

     For afs, I've made it render the volume name string as:

        "afs,<cell>,<volume_id>"

     and the coherency data is currently 0.

 (3) The fscache_cookie_def is no more and needed information is passed
     directly to fscache_acquire_cookie().  The cache no longer calls back
     into the filesystem, but rather metadata changes are indicated at
     other times.

     fscache_acquire_cookie() is passed the same keying and coherency
     information as before, except that these are now stored in big endian
     form instead of cpu endian.  This makes the cache more copyable.

 (4) fscache_use_cookie() and fscache_unuse_cookie() are called when a file
     is opened or closed to prevent a cache file from being culled and to
     keep resources to hand that are needed to do I/O.

     fscache_use_cookie() is given an indication if the cache is likely to
     be modified locally (e.g. the file is open for writing).

     fscache_unuse_cookie() is given a coherency update if we had the file
     open for writing and will update that.

 (5) fscache_invalidate() is now given uptodate auxiliary data and a file
     size.  It can also take a flag to indicate if this was due to a DIO
     write.  This is wrapped into afs_fscache_invalidate() now for
     convenience.

 (6) fscache_resize() now gets called from the finalisation of
     afs_setattr(), and afs_setattr() does use/unuse of the cookie around
     the call to support this.

 (7) fscache_note_page_release() is called from afs_release_page().

 (8) Use a killable wait in nfs_vm_page_mkwrite() when waiting for
     PG_fscache to be cleared.

Render the parts of the cookie key for an afs inode cookie as big endian.

Changes
=======
ver #2:
 - Use gfpflags_allow_blocking() rather than using flag directly.
 - fscache_acquire_volume() now returns errors.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Jeff Layton <jlayton@kernel.org>
Tested-by: kafs-testing@auristor.com
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/163819661382.215744.1485608824741611837.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/163906970002.143852.17678518584089878259.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/163967174665.1823006.1301789965454084220.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/164021568841.640689.6684240152253400380.stgit@warthog.procyon.org.uk/
fs/afs/Kconfig
fs/afs/Makefile
fs/afs/cache.c [deleted file]
fs/afs/cell.c
fs/afs/file.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/main.c
fs/afs/volume.c
fs/afs/write.c

index c40cdfcc25d1263fdc18a31b0156c6a0d1990884..fc8ba9142f2f0e92e8fbd3dfcfde2455d5f94eba 100644 (file)
@@ -25,7 +25,7 @@ config AFS_DEBUG
 
 config AFS_FSCACHE
        bool "Provide AFS client caching support"
-       depends on AFS_FS=m && FSCACHE_OLD_API || AFS_FS=y && FSCACHE_OLD_API=y
+       depends on AFS_FS=m && FSCACHE || AFS_FS=y && FSCACHE=y
        help
          Say Y here if you want AFS data to be cached locally on disk through
          the generic filesystem cache manager
index 75c4e4043d1d89e3e6aaca1123cf648260e435fd..e8956b65d7ffe22b35417cfdc77bd4a30235f972 100644 (file)
@@ -3,10 +3,7 @@
 # Makefile for Red Hat Linux AFS client.
 #
 
-afs-cache-$(CONFIG_AFS_FSCACHE) := cache.o
-
 kafs-y := \
-       $(afs-cache-y) \
        addr_list.o \
        callback.o \
        cell.o \
diff --git a/fs/afs/cache.c b/fs/afs/cache.c
deleted file mode 100644 (file)
index 037af93..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/* AFS caching stuff
- *
- * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- */
-
-#include <linux/sched.h>
-#include "internal.h"
-
-static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
-                                                      const void *buffer,
-                                                      uint16_t buflen,
-                                                      loff_t object_size);
-
-struct fscache_netfs afs_cache_netfs = {
-       .name                   = "afs",
-       .version                = 2,
-};
-
-struct fscache_cookie_def afs_cell_cache_index_def = {
-       .name           = "AFS.cell",
-       .type           = FSCACHE_COOKIE_TYPE_INDEX,
-};
-
-struct fscache_cookie_def afs_volume_cache_index_def = {
-       .name           = "AFS.volume",
-       .type           = FSCACHE_COOKIE_TYPE_INDEX,
-};
-
-struct fscache_cookie_def afs_vnode_cache_index_def = {
-       .name           = "AFS.vnode",
-       .type           = FSCACHE_COOKIE_TYPE_DATAFILE,
-       .check_aux      = afs_vnode_cache_check_aux,
-};
-
-/*
- * check that the auxiliary data indicates that the entry is still valid
- */
-static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
-                                                      const void *buffer,
-                                                      uint16_t buflen,
-                                                      loff_t object_size)
-{
-       struct afs_vnode *vnode = cookie_netfs_data;
-       struct afs_vnode_cache_aux aux;
-
-       _enter("{%llx,%x,%llx},%p,%u",
-              vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
-              buffer, buflen);
-
-       memcpy(&aux, buffer, sizeof(aux));
-
-       /* check the size of the data is what we're expecting */
-       if (buflen != sizeof(aux)) {
-               _leave(" = OBSOLETE [len %hx != %zx]", buflen, sizeof(aux));
-               return FSCACHE_CHECKAUX_OBSOLETE;
-       }
-
-       if (vnode->status.data_version != aux.data_version) {
-               _leave(" = OBSOLETE [vers %llx != %llx]",
-                      aux.data_version, vnode->status.data_version);
-               return FSCACHE_CHECKAUX_OBSOLETE;
-       }
-
-       _leave(" = SUCCESS");
-       return FSCACHE_CHECKAUX_OKAY;
-}
index d88407fb9bc09a8bb0e60ad7c9db320a028cab51..07ad744eef77fd433bc89ec51f52e5518168df0e 100644 (file)
@@ -680,13 +680,6 @@ static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell)
                        return ret;
        }
 
-#ifdef CONFIG_AFS_FSCACHE
-       cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index,
-                                            &afs_cell_cache_index_def,
-                                            cell->name, strlen(cell->name),
-                                            NULL, 0,
-                                            cell, 0, true);
-#endif
        ret = afs_proc_cell_setup(cell);
        if (ret < 0)
                return ret;
@@ -723,11 +716,6 @@ static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell)
        afs_dynroot_rmdir(net, cell);
        mutex_unlock(&net->proc_cells_lock);
 
-#ifdef CONFIG_AFS_FSCACHE
-       fscache_relinquish_cookie(cell->cache, NULL, false);
-       cell->cache = NULL;
-#endif
-
        _leave("");
 }
 
index 97a51e1de55c851a3317bd36f3b5041fd08ff54b..be23635f35b80c09d92b0c1f9597463c15c454aa 100644 (file)
@@ -158,7 +158,9 @@ int afs_open(struct inode *inode, struct file *file)
 
        if (file->f_flags & O_TRUNC)
                set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
-       
+
+       fscache_use_cookie(afs_vnode_cache(vnode), file->f_mode & FMODE_WRITE);
+
        file->private_data = af;
        _leave(" = 0");
        return 0;
@@ -177,8 +179,10 @@ error:
  */
 int afs_release(struct inode *inode, struct file *file)
 {
+       struct afs_vnode_cache_aux aux;
        struct afs_vnode *vnode = AFS_FS_I(inode);
        struct afs_file *af = file->private_data;
+       loff_t i_size;
        int ret = 0;
 
        _enter("{%llx:%llu},", vnode->fid.vid, vnode->fid.vnode);
@@ -189,6 +193,15 @@ int afs_release(struct inode *inode, struct file *file)
        file->private_data = NULL;
        if (af->wb)
                afs_put_wb_key(af->wb);
+
+       if ((file->f_mode & FMODE_WRITE)) {
+               i_size = i_size_read(&vnode->vfs_inode);
+               afs_set_cache_aux(vnode, &aux);
+               fscache_unuse_cookie(afs_vnode_cache(vnode), &aux, &i_size);
+       } else {
+               fscache_unuse_cookie(afs_vnode_cache(vnode), NULL, NULL);
+       }
+
        key_put(af->key);
        kfree(af);
        afs_prune_wb_keys(vnode);
@@ -352,7 +365,9 @@ static void afs_init_rreq(struct netfs_read_request *rreq, struct file *file)
 
 static bool afs_is_cache_enabled(struct inode *inode)
 {
-       return fscache_cookie_enabled(afs_vnode_cache(AFS_FS_I(inode)));
+       struct fscache_cookie *cookie = afs_vnode_cache(AFS_FS_I(inode));
+
+       return fscache_cookie_enabled(cookie) && cookie->cache_priv;
 }
 
 static int afs_begin_cache_operation(struct netfs_read_request *rreq)
@@ -360,7 +375,8 @@ static int afs_begin_cache_operation(struct netfs_read_request *rreq)
 #ifdef CONFIG_AFS_FSCACHE
        struct afs_vnode *vnode = AFS_FS_I(rreq->inode);
 
-       return fscache_begin_read_operation(rreq, afs_vnode_cache(vnode));
+       return fscache_begin_read_operation(&rreq->cache_resources,
+                                           afs_vnode_cache(vnode));
 #else
        return -ENOBUFS;
 #endif
@@ -482,23 +498,24 @@ static void afs_invalidatepage(struct page *page, unsigned int offset,
  * 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 int afs_releasepage(struct page *page, gfp_t gfp_flags)
+static int afs_releasepage(struct page *page, gfp_t gfp)
 {
        struct folio *folio = page_folio(page);
        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_flags);
+              gfp);
 
        /* deny if page is being written to the cache and the caller hasn't
         * elected to wait */
 #ifdef CONFIG_AFS_FSCACHE
        if (folio_test_fscache(folio)) {
-               if (!(gfp_flags & __GFP_DIRECT_RECLAIM) || !(gfp_flags & __GFP_FS))
+               if (!gfpflags_allow_blocking(gfp) || !(gfp & __GFP_FS))
                        return false;
                folio_wait_fscache(folio);
        }
+       fscache_note_page_release(afs_vnode_cache(vnode));
 #endif
 
        if (folio_test_private(folio)) {
index 16906eb592d9e2ee4dd323b648aa099bb8dddddd..509208825907652ca7a6ef9d2892411302713538 100644 (file)
@@ -413,9 +413,9 @@ static void afs_get_inode_cache(struct afs_vnode *vnode)
 {
 #ifdef CONFIG_AFS_FSCACHE
        struct {
-               u32 vnode_id;
-               u32 unique;
-               u32 vnode_id_ext[2];    /* Allow for a 96-bit key */
+               __be32 vnode_id;
+               __be32 unique;
+               __be32 vnode_id_ext[2]; /* Allow for a 96-bit key */
        } __packed key;
        struct afs_vnode_cache_aux aux;
 
@@ -424,17 +424,18 @@ static void afs_get_inode_cache(struct afs_vnode *vnode)
                return;
        }
 
-       key.vnode_id            = vnode->fid.vnode;
-       key.unique              = vnode->fid.unique;
-       key.vnode_id_ext[0]     = vnode->fid.vnode >> 32;
-       key.vnode_id_ext[1]     = vnode->fid.vnode_hi;
-       aux.data_version        = vnode->status.data_version;
-
-       vnode->cache = fscache_acquire_cookie(vnode->volume->cache,
-                                             &afs_vnode_cache_index_def,
-                                             &key, sizeof(key),
-                                             &aux, sizeof(aux),
-                                             vnode, vnode->status.size, true);
+       key.vnode_id            = htonl(vnode->fid.vnode);
+       key.unique              = htonl(vnode->fid.unique);
+       key.vnode_id_ext[0]     = htonl(vnode->fid.vnode >> 32);
+       key.vnode_id_ext[1]     = htonl(vnode->fid.vnode_hi);
+       afs_set_cache_aux(vnode, &aux);
+
+       vnode->cache = fscache_acquire_cookie(
+               vnode->volume->cache,
+               vnode->status.type == AFS_FTYPE_FILE ? 0 : FSCACHE_ADV_SINGLE_CHUNK,
+               &key, sizeof(key),
+               &aux, sizeof(aux),
+               vnode->status.size);
 #endif
 }
 
@@ -563,9 +564,7 @@ static void afs_zap_data(struct afs_vnode *vnode)
 {
        _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
 
-#ifdef CONFIG_AFS_FSCACHE
-       fscache_invalidate(vnode->cache);
-#endif
+       afs_invalidate_cache(vnode, 0);
 
        /* nuke all the non-dirty pages that aren't locked, mapped or being
         * written back in a regular file and completely discard the pages in a
@@ -786,14 +785,9 @@ void afs_evict_inode(struct inode *inode)
        }
 
 #ifdef CONFIG_AFS_FSCACHE
-       {
-               struct afs_vnode_cache_aux aux;
-
-               aux.data_version = vnode->status.data_version;
-               fscache_relinquish_cookie(vnode->cache, &aux,
-                                         test_bit(AFS_VNODE_DELETED, &vnode->flags));
-               vnode->cache = NULL;
-       }
+       fscache_relinquish_cookie(vnode->cache,
+                                 test_bit(AFS_VNODE_DELETED, &vnode->flags));
+       vnode->cache = NULL;
 #endif
 
        afs_prune_wb_keys(vnode);
@@ -833,6 +827,9 @@ static void afs_setattr_edit_file(struct afs_operation *op)
 
                if (size < i_size)
                        truncate_pagecache(inode, size);
+               if (size != i_size)
+                       fscache_resize_cookie(afs_vnode_cache(vp->vnode),
+                                             vp->scb.status.size);
        }
 }
 
@@ -876,6 +873,8 @@ int afs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                        attr->ia_valid &= ~ATTR_SIZE;
        }
 
+       fscache_use_cookie(afs_vnode_cache(vnode), true);
+
        /* flush any dirty data outstanding on a regular file */
        if (S_ISREG(vnode->vfs_inode.i_mode))
                filemap_write_and_wait(vnode->vfs_inode.i_mapping);
@@ -907,6 +906,7 @@ int afs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
 
 out_unlock:
        up_write(&vnode->validate_lock);
+       fscache_unuse_cookie(afs_vnode_cache(vnode), NULL, NULL);
        _leave(" = %d", ret);
        return ret;
 }
index aa4c0d6c9780cf225063b72d9feacec63150602a..1d80649aec722a4d1e150163d4e884f03878d976 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/key.h>
 #include <linux/workqueue.h>
 #include <linux/sched.h>
-#define FSCACHE_USE_NEW_IO_API
 #include <linux/fscache.h>
 #include <linux/backing-dev.h>
 #include <linux/uuid.h>
@@ -364,9 +363,6 @@ struct afs_cell {
        struct key              *anonymous_key; /* anonymous user key for this cell */
        struct work_struct      manager;        /* Manager for init/deinit/dns */
        struct hlist_node       proc_link;      /* /proc cell list link */
-#ifdef CONFIG_AFS_FSCACHE
-       struct fscache_cookie   *cache;         /* caching cookie */
-#endif
        time64_t                dns_expiry;     /* Time AFSDB/SRV record expires */
        time64_t                last_inactive;  /* Time of last drop of usage count */
        atomic_t                ref;            /* Struct refcount */
@@ -590,7 +586,7 @@ struct afs_volume {
 #define AFS_VOLUME_BUSY                5       /* - T if volume busy notice given */
 #define AFS_VOLUME_MAYBE_NO_IBULK 6    /* - T if some servers don't have InlineBulkStatus */
 #ifdef CONFIG_AFS_FSCACHE
-       struct fscache_cookie   *cache;         /* caching cookie */
+       struct fscache_volume   *cache;         /* Caching cookie */
 #endif
        struct afs_server_list __rcu *servers;  /* List of servers on which volume resides */
        rwlock_t                servers_lock;   /* Lock for ->servers */
@@ -872,9 +868,24 @@ struct afs_operation {
  * Cache auxiliary data.
  */
 struct afs_vnode_cache_aux {
-       u64                     data_version;
+       __be64                  data_version;
 } __packed;
 
+static inline void afs_set_cache_aux(struct afs_vnode *vnode,
+                                    struct afs_vnode_cache_aux *aux)
+{
+       aux->data_version = cpu_to_be64(vnode->status.data_version);
+}
+
+static inline void afs_invalidate_cache(struct afs_vnode *vnode, unsigned int flags)
+{
+       struct afs_vnode_cache_aux aux;
+
+       afs_set_cache_aux(vnode, &aux);
+       fscache_invalidate(afs_vnode_cache(vnode), &aux,
+                          i_size_read(&vnode->vfs_inode), flags);
+}
+
 /*
  * We use folio->private to hold the amount of the folio that we've written to,
  * splitting the field into two parts.  However, we need to represent a range
@@ -962,13 +973,6 @@ extern void afs_merge_fs_addr6(struct afs_addr_list *, __be32 *, u16);
  */
 #ifdef CONFIG_AFS_FSCACHE
 extern struct fscache_netfs afs_cache_netfs;
-extern struct fscache_cookie_def afs_cell_cache_index_def;
-extern struct fscache_cookie_def afs_volume_cache_index_def;
-extern struct fscache_cookie_def afs_vnode_cache_index_def;
-#else
-#define afs_cell_cache_index_def       (*(struct fscache_cookie_def *) NULL)
-#define afs_volume_cache_index_def     (*(struct fscache_cookie_def *) NULL)
-#define afs_vnode_cache_index_def      (*(struct fscache_cookie_def *) NULL)
 #endif
 
 /*
@@ -1506,7 +1510,7 @@ extern struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *,
  * volume.c
  */
 extern struct afs_volume *afs_create_volume(struct afs_fs_context *);
-extern void afs_activate_volume(struct afs_volume *);
+extern int afs_activate_volume(struct afs_volume *);
 extern void afs_deactivate_volume(struct afs_volume *);
 extern struct afs_volume *afs_get_volume(struct afs_volume *, enum afs_volume_trace);
 extern void afs_put_volume(struct afs_net *, struct afs_volume *, enum afs_volume_trace);
index 179004b15566d326d507403500486d7f4377234e..eae288c8d40a3b28ac1aed87df61716ed06757c3 100644 (file)
@@ -186,13 +186,6 @@ static int __init afs_init(void)
        if (!afs_lock_manager)
                goto error_lockmgr;
 
-#ifdef CONFIG_AFS_FSCACHE
-       /* we want to be able to cache */
-       ret = fscache_register_netfs(&afs_cache_netfs);
-       if (ret < 0)
-               goto error_cache;
-#endif
-
        ret = register_pernet_device(&afs_net_ops);
        if (ret < 0)
                goto error_net;
@@ -215,10 +208,6 @@ error_proc:
 error_fs:
        unregister_pernet_device(&afs_net_ops);
 error_net:
-#ifdef CONFIG_AFS_FSCACHE
-       fscache_unregister_netfs(&afs_cache_netfs);
-error_cache:
-#endif
        destroy_workqueue(afs_lock_manager);
 error_lockmgr:
        destroy_workqueue(afs_async_calls);
@@ -245,9 +234,6 @@ static void __exit afs_exit(void)
        proc_remove(afs_proc_symlink);
        afs_fs_exit();
        unregister_pernet_device(&afs_net_ops);
-#ifdef CONFIG_AFS_FSCACHE
-       fscache_unregister_netfs(&afs_cache_netfs);
-#endif
        destroy_workqueue(afs_lock_manager);
        destroy_workqueue(afs_async_calls);
        destroy_workqueue(afs_wq);
index f84194b791d3e9f6b93f150003a339694daf742f..94a3d247924bce49a91851f25fae45c9f7c72b84 100644 (file)
@@ -268,15 +268,30 @@ void afs_put_volume(struct afs_net *net, struct afs_volume *volume,
 /*
  * Activate a volume.
  */
-void afs_activate_volume(struct afs_volume *volume)
+int afs_activate_volume(struct afs_volume *volume)
 {
 #ifdef CONFIG_AFS_FSCACHE
-       volume->cache = fscache_acquire_cookie(volume->cell->cache,
-                                              &afs_volume_cache_index_def,
-                                              &volume->vid, sizeof(volume->vid),
-                                              NULL, 0,
-                                              volume, 0, true);
+       struct fscache_volume *vcookie;
+       char *name;
+
+       name = kasprintf(GFP_KERNEL, "afs,%s,%llx",
+                        volume->cell->name, volume->vid);
+       if (!name)
+               return -ENOMEM;
+
+       vcookie = fscache_acquire_volume(name, NULL, NULL, 0);
+       if (IS_ERR(vcookie)) {
+               if (vcookie != ERR_PTR(-EBUSY)) {
+                       kfree(name);
+                       return PTR_ERR(vcookie);
+               }
+               pr_err("AFS: Cache volume key already in use (%s)\n", name);
+               vcookie = NULL;
+       }
+       volume->cache = vcookie;
+       kfree(name);
 #endif
+       return 0;
 }
 
 /*
@@ -287,7 +302,7 @@ void afs_deactivate_volume(struct afs_volume *volume)
        _enter("%s", volume->name);
 
 #ifdef CONFIG_AFS_FSCACHE
-       fscache_relinquish_cookie(volume->cache, NULL,
+       fscache_relinquish_volume(volume->cache, NULL,
                                  test_bit(AFS_VOLUME_DELETED, &volume->flags));
        volume->cache = NULL;
 #endif
index ca4909baf5e6ca36a854013a054f1c1bbce61661..1c8ee6eae90565b94615762b66959971e90a9530 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/writeback.h>
 #include <linux/pagevec.h>
 #include <linux/netfs.h>
-#include <linux/fscache.h>
 #include "internal.h"
 
 /*