libafs: Abstract the Linux lru cache interface 67/14167/5
authorCheyenne Wills <cwills@sinenomine.net>
Wed, 29 Apr 2020 22:26:02 +0000 (16:26 -0600)
committerBenjamin Kaduk <kaduk@mit.edu>
Fri, 15 May 2020 15:33:05 +0000 (11:33 -0400)
Define static functions afs_lru_cache_init, afs_lru_cache_add and
afs_lru_cache_finalize to handle interfacing with Linux's lru
facilities.

This change's primary purpose is to isolate the preprocessor
conditionals associated with the details of the system lru interfaces to
just these functions and to simplify the areas that utilize lru caching
by removing the preprocessor conditionals.

As Linux's lru facilities change, additional conditional code will be
needed.

Change-Id: I74c94bb712359975e3fd1df85f1b338b215f61b0
Reviewed-on: https://gerrit.openafs.org/14167
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>

src/afs/LINUX/osi_vnodeops.c

index 4617a34..df50a90 100644 (file)
 #include "osi_compat.h"
 #include "osi_pagecopy.h"
 
-#ifndef HAVE_LINUX_PAGEVEC_LRU_ADD_FILE
-#define __pagevec_lru_add_file __pagevec_lru_add
-#endif
-
 #ifndef MAX_ERRNO
 #define MAX_ERRNO 1000L
 #endif
@@ -69,6 +65,41 @@ extern struct backing_dev_info *afs_backing_dev_info;
 
 extern struct vcache *afs_globalVp;
 
+/* Handle interfacing with Linux's pagevec/lru facilities */
+
+struct afs_lru_pages {
+    struct pagevec lrupv;
+};
+
+static inline void
+afs_lru_cache_init(struct afs_lru_pages *alrupages)
+{
+#if defined(PAGEVEC_INIT_COLD_ARG)
+    pagevec_init(&alrupages->lrupv, 0);
+#else
+    pagevec_init(&alrupages->lrupv);
+#endif
+}
+
+#ifndef HAVE_LINUX_PAGEVEC_LRU_ADD_FILE
+# define __pagevec_lru_add_file __pagevec_lru_add
+#endif
+
+static inline void
+afs_lru_cache_add(struct afs_lru_pages *alrupages, struct page *page)
+{
+    get_page(page);
+    if (!pagevec_add(&alrupages->lrupv, page))
+       __pagevec_lru_add_file(&alrupages->lrupv);
+}
+
+static inline void
+afs_lru_cache_finalize(struct afs_lru_pages *alrupages)
+{
+    if (pagevec_count(&alrupages->lrupv))
+       __pagevec_lru_add_file(&alrupages->lrupv);
+}
+
 /* This function converts a positive error code from AFS into a negative
  * code suitable for passing into the Linux VFS layer. It checks that the
  * error code is within the permissable bounds for the ERR_PTR mechanism.
@@ -2079,7 +2110,7 @@ afs_linux_put_link(struct dentry *dentry, struct nameidata *nd)
  */
 static int
 afs_linux_read_cache(struct file *cachefp, struct page *page,
-                    int chunk, struct pagevec *lrupv,
+                    int chunk, struct afs_lru_pages *alrupages,
                     struct afs_pagecopy_task *task) {
     loff_t offset = page_offset(page);
     struct inode *cacheinode = cachefp->f_dentry->d_inode;
@@ -2121,11 +2152,7 @@ afs_linux_read_cache(struct file *cachefp, struct page *page,
            if (code == 0) {
                cachepage = newpage;
                newpage = NULL;
-
-               get_page(cachepage);
-                if (!pagevec_add(lrupv, cachepage))
-                    __pagevec_lru_add_file(lrupv);
-
+               afs_lru_cache_add(alrupages, cachepage);
            } else {
                put_page(newpage);
                newpage = NULL;
@@ -2185,7 +2212,7 @@ afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep)
     struct file *cacheFp = NULL;
     int code;
     int dcLocked = 0;
-    struct pagevec lrupv;
+    struct afs_lru_pages lrupages;
 
     /* Not a UFS cache, don't do anything */
     if (cacheDiskType != AFS_FCACHE_TYPE_UFS)
@@ -2271,16 +2298,12 @@ afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep)
        AFS_GLOCK();
        goto out;
     }
-#if defined(PAGEVEC_INIT_COLD_ARG)
-    pagevec_init(&lrupv, 0);
-#else
-    pagevec_init(&lrupv);
-#endif
 
-    code = afs_linux_read_cache(cacheFp, pp, tdc->f.chunk, &lrupv, NULL);
+    afs_lru_cache_init(&lrupages);
 
-    if (pagevec_count(&lrupv))
-       __pagevec_lru_add_file(&lrupv);
+    code = afs_linux_read_cache(cacheFp, pp, tdc->f.chunk, &lrupages, NULL);
+
+    afs_lru_cache_finalize(&lrupages);
 
     filp_close(cacheFp, NULL);
     AFS_GLOCK();
@@ -2410,7 +2433,7 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping,
     struct iovec* iovecp;
     struct nocache_read_request *ancr;
     struct page *pp;
-    struct pagevec lrupv;
+    struct afs_lru_pages lrupages;
     afs_int32 code = 0;
 
     cred_t *credp;
@@ -2435,11 +2458,7 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping,
     ancr->offset = auio->uio_offset;
     ancr->length = auio->uio_resid;
 
-#if defined(PAGEVEC_INIT_COLD_ARG)
-    pagevec_init(&lrupv, 0);
-#else
-    pagevec_init(&lrupv);
-#endif
+    afs_lru_cache_init(&lrupages);
 
     for(page_ix = 0; page_ix < num_pages; ++page_ix) {
 
@@ -2485,27 +2504,18 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping,
                lock_page(pp);
            }
 
-            /* increment page refcount--our original design assumed
-             * that locking it would effectively pin it;  protect
-             * ourselves from the possiblity that this assumption is
-             * is faulty, at low cost (provided we do not fail to
-             * do the corresponding decref on the other side) */
-            get_page(pp);
-
            /* save the page for background map */
             iovecp[page_ix].iov_base = (void*) pp;
 
            /* and put it on the LRU cache */
-           if (!pagevec_add(&lrupv, pp))
-               __pagevec_lru_add_file(&lrupv);
+           afs_lru_cache_add(&lrupages, pp);
         }
     }
 
     /* If there were useful pages in the page list, make sure all pages
      * are in the LRU cache, then schedule the read */
     if(page_count) {
-       if (pagevec_count(&lrupv))
-           __pagevec_lru_add_file(&lrupv);
+       afs_lru_cache_finalize(&lrupages);
        credp = crref();
         code = afs_ReadNoCache(avc, ancr, credp);
        crfree(credp);
@@ -2636,7 +2646,7 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
     int code;
     unsigned int page_idx;
     loff_t offset;
-    struct pagevec lrupv;
+    struct afs_lru_pages lrupages;
     struct afs_pagecopy_task *task;
 
     if (afs_linux_bypass_check(inode))
@@ -2661,11 +2671,9 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
     task = afs_pagecopy_init_task();
 
     tdc = NULL;
-#if defined(PAGEVEC_INIT_COLD_ARG)
-    pagevec_init(&lrupv, 0);
-#else
-    pagevec_init(&lrupv);
-#endif
+
+    afs_lru_cache_init(&lrupages);
+
     for (page_idx = 0; page_idx < num_pages; page_idx++) {
        struct page *page = list_entry(page_list->prev, struct page, lru);
        list_del(&page->lru);
@@ -2705,18 +2713,15 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
 
        if (tdc && !add_to_page_cache(page, mapping, page->index,
                                      GFP_KERNEL)) {
-           get_page(page);
-           if (!pagevec_add(&lrupv, page))
-               __pagevec_lru_add_file(&lrupv);
+           afs_lru_cache_add(&lrupages, page);
 
            /* Note that add_to_page_cache() locked 'page'.
             * afs_linux_read_cache() is guaranteed to handle unlocking it. */
-           afs_linux_read_cache(cacheFp, page, tdc->f.chunk, &lrupv, task);
+           afs_linux_read_cache(cacheFp, page, tdc->f.chunk, &lrupages, task);
        }
        put_page(page);
     }
-    if (pagevec_count(&lrupv))
-       __pagevec_lru_add_file(&lrupv);
+    afs_lru_cache_finalize(&lrupages);
 
 out:
     if (tdc)