]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Add shake-harder patches
authorAnders Kaseorg <andersk@mit.edu>
Wed, 30 Nov 2016 09:51:33 +0000 (04:51 -0500)
committerAnders Kaseorg <andersk@mit.edu>
Thu, 1 Dec 2016 05:13:27 +0000 (00:13 -0500)
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
debian/changelog
debian/patches/LINUX-do-not-use-d_invalidate-to-evict-dentries.patch [new file with mode: 0644]
debian/patches/LINUX-split-dentry-eviction-from-osi_TryEvictVCache.patch [new file with mode: 0644]
debian/patches/Reformat-src-afs-LINUX-osi_vcache.c.patch [new file with mode: 0644]
debian/patches/afs-shake-harder-in-shake-loose-vcaches.patch [new file with mode: 0644]
debian/patches/series

index 5b402a4521de021f82f095b2ce0e52667ee1f20d..5ada667943a3a0394b5eb04d17615aaf509b3675 100644 (file)
@@ -2,6 +2,12 @@ openafs (1.6.20-2) UNRELEASED; urgency=medium
 
   * Build-Depend debhelper (>= 9.20160114) for dh_strip
     --dbgsym-migration.
+  * debian/patches:
+    - LINUX-split-dentry-eviction-from-osi_TryEvictVCache.patch,
+      Reformat-src-afs-LINUX-osi_vcache.c.patch,
+      LINUX-do-not-use-d_invalidate-to-evict-dentries.patch,
+      afs-shake-harder-in-shake-loose-vcaches.patch: Avoid system hangs on
+      busy machines due to vcache deallocation failures.
 
  -- Anders Kaseorg <andersk@mit.edu>  Thu, 01 Dec 2016 00:13:01 -0500
 
diff --git a/debian/patches/LINUX-do-not-use-d_invalidate-to-evict-dentries.patch b/debian/patches/LINUX-do-not-use-d_invalidate-to-evict-dentries.patch
new file mode 100644 (file)
index 0000000..3b754ce
--- /dev/null
@@ -0,0 +1,63 @@
+From 83a174de588c56cedbf13e6abab786fb56e8082f Mon Sep 17 00:00:00 2001
+From: Mark Vitale <mvitale@sinenomine.net>
+Date: Thu, 4 Aug 2016 18:42:27 -0400
+Subject: LINUX: do not use d_invalidate to evict dentries
+
+When working within the AFS filespace, commands which access large
+numbers of OpenAFS files (e.g., git operations and builds) may result in
+active files (e.g., the current working directory) being evicted from the
+dentry cache.  One symptom of this is the following message upon return
+to the shell prompt:
+
+"fatal: unable to get current working directory: No such file or
+directory"
+
+Starting with Linux 3.18, d_invalidate returns void because it always
+succeeds.  Commit a42f01d5ebb13da575b3123800ee6990743155ab adapted
+OpenAFS to cope with the new return type, but not with the changed
+semantics of d_invalidate.  Because d_invalidate can no longer fail with
+-EBUSY when invoked on an in-use dentry. OpenAFS must no longer trust it
+to preserve in-use dentries.
+
+Modify the dentry eviction code to use a method (d_prune_aliases) that
+does not evict in-use dentries.
+
+Reviewed-on: https://gerrit.openafs.org/12363
+Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
+Tested-by: Benjamin Kaduk <kaduk@mit.edu>
+(cherry picked from commit c3bbf0b4444db88192eea4580ac9e9ca3de0d286)
+
+Change-Id: Ic72a280f136cc414b54d4b8ec280f225290df122
+---
+ src/afs/LINUX/osi_vcache.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c
+index bc74b6744..23040b12c 100644
+--- a/src/afs/LINUX/osi_vcache.c
++++ b/src/afs/LINUX/osi_vcache.c
+@@ -24,6 +24,13 @@ TryEvictDentries(struct vcache *avc)
+     struct hlist_node *p;
+ #endif
++#if defined(D_INVALIDATE_IS_VOID)
++    /* At this kernel level, d_invalidate always succeeds;
++     * that is, it will now invalidate even an active directory,
++     * Therefore we must use a different method to evict dentries.
++     */
++    d_prune_aliases(inode);
++#else
+ #if defined(HAVE_DCACHE_LOCK)
+     spin_lock(&dcache_lock);
+@@ -78,6 +85,7 @@ restart:
+     spin_unlock(&inode->i_lock);
+ #endif /* HAVE_DCACHE_LOCK */
+ inuse:
++#endif /* D_INVALIDATE_IS_VOID */
+     return;
+ }
+-- 
+2.11.0
+
diff --git a/debian/patches/LINUX-split-dentry-eviction-from-osi_TryEvictVCache.patch b/debian/patches/LINUX-split-dentry-eviction-from-osi_TryEvictVCache.patch
new file mode 100644 (file)
index 0000000..9de17f1
--- /dev/null
@@ -0,0 +1,164 @@
+From cb2e2c26dc841bb4cab2d3b2ff376936f6c39e68 Mon Sep 17 00:00:00 2001
+From: Mark Vitale <mvitale@sinenomine.net>
+Date: Thu, 4 Aug 2016 18:18:15 -0400
+Subject: LINUX: split dentry eviction from osi_TryEvictVCache
+
+To make osi_TryEvictVCache clearer, and to prepare for a future change
+in dentry eviction, split the dentry eviction logic into its own routine
+osi_TryEvictDentries.
+
+No functional difference should be incurred by this commit.
+
+Reviewed-on: https://gerrit.openafs.org/12362
+Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
+Tested-by: BuildBot <buildbot@rampaginggeek.com>
+Reviewed-by: Joe Gorse <jhgorse@gmail.com>
+(cherry picked from commit 742643e306929ac979ab69515a33ee2a3f2fa3fa)
+
+Change-Id: I750fc7606ca56e784a60bdbc13a32d21fe307429
+---
+ src/afs/LINUX/osi_vcache.c | 103 +++++++++++++++++++++++++--------------------
+ 1 file changed, 57 insertions(+), 46 deletions(-)
+
+diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c
+index 8a0c57899..3682bdc29 100644
+--- a/src/afs/LINUX/osi_vcache.c
++++ b/src/afs/LINUX/osi_vcache.c
+@@ -15,77 +15,88 @@
+ #include "osi_compat.h"
+-int
+-osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) {
+-    int code;
+-
++void
++osi_TryEvictDentries(struct vcache *avc)
++{
+     struct dentry *dentry;
+     struct inode *inode = AFSTOV(avc);
+ #if defined(D_ALIAS_IS_HLIST) && !defined(HLIST_ITERATOR_NO_NODE)
+     struct hlist_node *p;
+ #endif
+-    /* First, see if we can evict the inode from the dcache */
+-    if (defersleep && avc != afs_globalVp && VREFCOUNT(avc) > 1 && avc->opens == 0) {
+-      *slept = 1;
+-      AFS_FAST_HOLD(avc);
+-      ReleaseWriteLock(&afs_xvcache);
+-        AFS_GUNLOCK();
+-
+ #if defined(HAVE_DCACHE_LOCK)
+-        spin_lock(&dcache_lock);
++    spin_lock(&dcache_lock);
+ restart:
+-      list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+-          if (d_unhashed(dentry))
+-              continue;
+-          dget_locked(dentry);
+-
+-          spin_unlock(&dcache_lock);
+-          if (d_invalidate(dentry) == -EBUSY) {
+-              dput(dentry);
+-              /* perhaps lock and try to continue? (use cur as head?) */
+-              goto inuse;
+-          }
++    list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
++      if (d_unhashed(dentry))
++          continue;
++      dget_locked(dentry);
++
++      spin_unlock(&dcache_lock);
++      if (d_invalidate(dentry) == -EBUSY) {
+           dput(dentry);
+-          spin_lock(&dcache_lock);
+-          goto restart;
++          /* perhaps lock and try to continue? (use cur as head?) */
++          goto inuse;
+       }
+-      spin_unlock(&dcache_lock);
++      dput(dentry);
++      spin_lock(&dcache_lock);
++      goto restart;
++    }
++    spin_unlock(&dcache_lock);
+ #else /* HAVE_DCACHE_LOCK */
+-      spin_lock(&inode->i_lock);
++    spin_lock(&inode->i_lock);
+ restart:
+ #if defined(D_ALIAS_IS_HLIST)
+ # if defined(HLIST_ITERATOR_NO_NODE)
+-      hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
++    hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+ # else
+-      hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
++    hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
+ # endif
+ #else
+-      list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
++    list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+ #endif
+-          spin_lock(&dentry->d_lock);
+-          if (d_unhashed(dentry)) {
+-              spin_unlock(&dentry->d_lock);
+-              continue;
+-          }
++      spin_lock(&dentry->d_lock);
++      if (d_unhashed(dentry)) {
+           spin_unlock(&dentry->d_lock);
+-          dget(dentry);
+-
+-          spin_unlock(&inode->i_lock);
+-          if (afs_d_invalidate(dentry) == -EBUSY) {
+-              dput(dentry);
+-              /* perhaps lock and try to continue? (use cur as head?) */
+-              goto inuse;
+-          }
+-          dput(dentry);
+-          spin_lock(&inode->i_lock);
+-          goto restart;
++          continue;
+       }
++      spin_unlock(&dentry->d_lock);
++      dget(dentry);
++
+       spin_unlock(&inode->i_lock);
++      if (afs_d_invalidate(dentry) == -EBUSY) {
++          dput(dentry);
++          /* perhaps lock and try to continue? (use cur as head?) */
++          goto inuse;
++      }
++      dput(dentry);
++      spin_lock(&inode->i_lock);
++      goto restart;
++    }
++    spin_unlock(&inode->i_lock);
+ #endif /* HAVE_DCACHE_LOCK */
+ inuse:
++    return;
++}
++
++
++int
++osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep)
++{
++    int code;
++
++    /* First, see if we can evict the inode from the dcache */
++    if (defersleep && avc != afs_globalVp && VREFCOUNT(avc) > 1
++      && avc->opens == 0) {
++      *slept = 1;
++      AFS_FAST_HOLD(avc);
++      ReleaseWriteLock(&afs_xvcache);
++      AFS_GUNLOCK();
++
++      osi_TryEvictDentries(avc);
++
+       AFS_GLOCK();
+       ObtainWriteLock(&afs_xvcache, 733);
+       AFS_FAST_RELE(avc);
+-- 
+2.11.0
+
diff --git a/debian/patches/Reformat-src-afs-LINUX-osi_vcache.c.patch b/debian/patches/Reformat-src-afs-LINUX-osi_vcache.c.patch
new file mode 100644 (file)
index 0000000..ee03ba9
--- /dev/null
@@ -0,0 +1,89 @@
+From f31b673509664714b146f23be069b69be7e1ac89 Mon Sep 17 00:00:00 2001
+From: Benjamin Kaduk <kaduk@mit.edu>
+Date: Thu, 27 Oct 2016 17:27:26 -0500
+Subject: Reformat src/afs/LINUX/osi_vcache.c
+
+Apply the GNU indent options from CODING, with manual adjustments
+to leave jump labels in column zero.
+
+Also rename and mark static a function-local helper function.
+
+Reviewed-on: https://gerrit.openafs.org/12422
+Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
+Tested-by: BuildBot <buildbot@rampaginggeek.com>
+(cherry picked from commit 22933e02e2510f25b79230964f135571c7bfe710)
+
+Change-Id: I9fb2886ae2213218ae80ea9d5b80540b9c79077b
+---
+ src/afs/LINUX/osi_vcache.c | 23 ++++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c
+index 3682bdc29..bc74b6744 100644
+--- a/src/afs/LINUX/osi_vcache.c
++++ b/src/afs/LINUX/osi_vcache.c
+@@ -10,13 +10,13 @@
+ #include <afsconfig.h>
+ #include "afs/param.h"
+-#include "afs/sysincludes.h"    /*Standard vendor system headers */
+-#include "afsincludes.h"        /*AFS-based standard headers */
++#include "afs/sysincludes.h"  /*Standard vendor system headers */
++#include "afsincludes.h"      /*AFS-based standard headers */
+ #include "osi_compat.h"
+-void
+-osi_TryEvictDentries(struct vcache *avc)
++static void
++TryEvictDentries(struct vcache *avc)
+ {
+     struct dentry *dentry;
+     struct inode *inode = AFSTOV(avc);
+@@ -95,7 +95,7 @@ osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep)
+       ReleaseWriteLock(&afs_xvcache);
+       AFS_GUNLOCK();
+-      osi_TryEvictDentries(avc);
++      TryEvictDentries(avc);
+       AFS_GLOCK();
+       ObtainWriteLock(&afs_xvcache, 733);
+@@ -103,7 +103,7 @@ osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep)
+     }
+     /* See if we can evict it from the VLRUQ */
+-    if (VREFCOUNT_GT(avc,0) && !VREFCOUNT_GT(avc,1) && avc->opens == 0
++    if (VREFCOUNT_GT(avc, 0) && !VREFCOUNT_GT(avc, 1) && avc->opens == 0
+       && (avc->f.states & CUnlinkedDel) == 0) {
+       int didsleep = *slept;
+@@ -145,17 +145,22 @@ osi_NewVnode(void)
+ }
+ void
+-osi_PrePopulateVCache(struct vcache *avc) {
++osi_PrePopulateVCache(struct vcache *avc)
++{
+     avc->uncred = 0;
+     memset(&(avc->f), 0, sizeof(struct fvcache));
+     avc->cred = NULL;
+ }
+ void
+-osi_AttachVnode(struct vcache *avc, int seq) { /* Nada */ }
++osi_AttachVnode(struct vcache *avc, int seq)
++{
++    /* Nada */
++}
+ void
+-osi_PostPopulateVCache(struct vcache *avc) {
++osi_PostPopulateVCache(struct vcache *avc)
++{
+     vSetType(avc, VREG);
+ }
+-- 
+2.11.0
+
diff --git a/debian/patches/afs-shake-harder-in-shake-loose-vcaches.patch b/debian/patches/afs-shake-harder-in-shake-loose-vcaches.patch
new file mode 100644 (file)
index 0000000..5ca1f28
--- /dev/null
@@ -0,0 +1,109 @@
+From 163fcc59b919877ee01d4fd47be46009e97a5e60 Mon Sep 17 00:00:00 2001
+From: Michael Meffie <mmeffie@sinenomine.net>
+Date: Thu, 27 Aug 2015 13:06:05 -0400
+Subject: afs: shake harder in shake-loose-vcaches
+
+Linux based cache managers will allocate vcaches on demand and
+deallocate batches of vcaches in the background. This feature is called
+dynamic vcaches.
+
+Vcaches to be deallocated are found by traversing the vcache LRU list
+(VLRU) from the oldest vcache to the newest. Up to a target number of
+vcaches are attempted to be evicted.  The afs_xvcache lock protecting
+the VLRU may be dropped and re-acquired while attempting to evict a
+vcache. When this happens, it is possible the VLRU may have changed, so
+the traversal of the VLRU is restarted.  This restarting of the VLRU
+transversal is limited to 100 iterations to avoid looping indefinitely.
+
+Vcaches which are busy cannot be evicted and remain in the VLRU. When a
+busy cache was not evicted and the afs_xvache lock was dropped, the VLRU
+traversal is restarted from the end of the VLRU. When the busy vcache is
+encountered on the retry, it will trigger additional retries until the
+loop limit is reached, at which point the target number of vcaches will
+not be deallocated.
+
+This can leave a very large number of unbusy vcaches which are never
+deallocated.  On a busy machine, tens of millions of unused vcaches can
+remain in memory. When the busy vcache at the end of the VLRU is finally
+evicted, the log jam is broken, and the background deamon will hold the
+afs_xvcache lock for an excessively long time, hanging the system.
+
+Fix this by moving busy vcaches to the head of the VLRU before
+restarting the VLRU traversal. These busy vcaches will be skipped when
+retrying the VLRU traversal, allowing the cache manager to make progress
+deallocating vcaches down to the target level.
+
+This was already done on the mac osx platform while attempting to evict
+vcaches. Move the code to move busy vcaches to the head of the VLRU up
+the the platform agnostic caller.
+
+Thanks to Andrew Deason for the initial version of this patch.
+
+Reviewed-on: https://gerrit.openafs.org/11654
+Tested-by: BuildBot <buildbot@rampaginggeek.com>
+Reviewed-by: Andrew Deason <adeason@dson.org>
+Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
+(cherry picked from commit 5c136c7d93ed97166f39bf716cc7f5d579b70677)
+
+Change-Id: If60b1889d012a739aa5b43e842abb80a6ebfdb6a
+---
+ src/afs/DARWIN/osi_vcache.c |  5 +----
+ src/afs/afs_vcache.c        | 14 +++++++++++++-
+ 2 files changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/src/afs/DARWIN/osi_vcache.c b/src/afs/DARWIN/osi_vcache.c
+index 18d8d9a08..1a1199c4c 100644
+--- a/src/afs/DARWIN/osi_vcache.c
++++ b/src/afs/DARWIN/osi_vcache.c
+@@ -53,10 +53,7 @@ osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) {
+        * this out, since the iocount we have to hold makes it
+        * always "fail" */
+       if (AFSTOV(avc) == tvp) {
+-          if (*slept) {
+-              QRemove(&avc->vlruq);
+-              QAdd(&VLRU, &avc->vlruq);
+-            }
++          /* Caller will move this vcache to the head of the VLRU. */
+           return 0;
+       } else
+           return 1;
+diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c
+index d751a564c..ca5a956ea 100644
+--- a/src/afs/afs_vcache.c
++++ b/src/afs/afs_vcache.c
+@@ -725,6 +725,7 @@ int
+ afs_ShakeLooseVCaches(afs_int32 anumber)
+ {
+     afs_int32 i, loop;
++    int evicted;
+     struct vcache *tvc;
+     struct afs_q *tq, *uq;
+     int fv_slept, defersleep = 0;
+@@ -752,12 +753,23 @@ afs_ShakeLooseVCaches(afs_int32 anumber)
+       }
+       fv_slept = 0;
+-      if (osi_TryEvictVCache(tvc, &fv_slept, defersleep))
++      evicted = osi_TryEvictVCache(tvc, &fv_slept, defersleep);
++      if (evicted) {
+           anumber--;
++      }
+       if (fv_slept) {
+           if (loop++ > 100)
+               break;
++          if (!evicted) {
++              /*
++               * This vcache was busy and we slept while trying to evict it.
++               * Move this busy vcache to the head of the VLRU so vcaches
++               * following this busy vcache can be evicted during the retry.
++               */
++              QRemove(&tvc->vlruq);
++              QAdd(&VLRU, &tvc->vlruq);
++          }
+           goto retry; /* start over - may have raced. */
+       }
+       if (uq == &VLRU) {
+-- 
+2.11.0
+
index 58bc02e5f914486cdee155a66d25e99baf15a6ef..722ab5864f5bb83e2bf0a7b1661bba20be573642 100644 (file)
@@ -1 +1,5 @@
 0003-Add-dummy-exit-command-for-afsd-to-do-nothing.patch
+LINUX-split-dentry-eviction-from-osi_TryEvictVCache.patch
+Reformat-src-afs-LINUX-osi_vcache.c.patch
+LINUX-do-not-use-d_invalidate-to-evict-dentries.patch
+afs-shake-harder-in-shake-loose-vcaches.patch