diff --git a/src/afs/AIX/osi_vcache.c b/src/afs/AIX/osi_vcache.c index 1c99d73c7f..b61d466c02 100644 --- a/src/afs/AIX/osi_vcache.c +++ b/src/afs/AIX/osi_vcache.c @@ -16,7 +16,7 @@ extern struct vnodeops *afs_ops; int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { int code; if (!VREFCOUNT_GT(avc,0) && avc->opens == 0 && (avc->f.states & CUnlinkedDel) == 0) { diff --git a/src/afs/DARWIN/osi_vcache.c b/src/afs/DARWIN/osi_vcache.c index 4f2e5a87c8..ce3bb5f49d 100644 --- a/src/afs/DARWIN/osi_vcache.c +++ b/src/afs/DARWIN/osi_vcache.c @@ -27,9 +27,10 @@ osi_NewVnode(void) { #if defined(AFS_DARWIN80_ENV) int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { *slept = 0; + /* we ignore defersleep, as we *always* need to sleep */ if (!VREFCOUNT_GT(avc, 0) && avc->opens == 0 && (avc->f.states & CUnlinkedDel) == 0) { @@ -64,7 +65,7 @@ osi_TryEvictVCache(struct vcache *avc, int *slept) { } #else int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { if (!VREFCOUNT_GT(avc,0) || ((VREFCOUNT(avc) == 1) && (UBCINFOEXISTS(AFSTOV(avc)))) && avc->opens == 0 && (avc->f.states & CUnlinkedDel) == 0) diff --git a/src/afs/FBSD/osi_vcache.c b/src/afs/FBSD/osi_vcache.c index 1e48fcccc1..d400492daa 100644 --- a/src/afs/FBSD/osi_vcache.c +++ b/src/afs/FBSD/osi_vcache.c @@ -24,7 +24,7 @@ #endif int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { /* * essentially all we want to do here is check that the diff --git a/src/afs/HPUX/osi_vcache.c b/src/afs/HPUX/osi_vcache.c index e08afda624..cf669a29dc 100644 --- a/src/afs/HPUX/osi_vcache.c +++ b/src/afs/HPUX/osi_vcache.c @@ -14,9 +14,10 @@ #include "afsincludes.h" /*AFS-based standard headers */ int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { int code; + /* we can't control whether we sleep */ if (!VREFCOUNT_GT(avc,0) && avc->opens == 0 && (avc->f.states & CUnlinkedDel) == 0) { code = afs_FlushVCache(avc, slept); diff --git a/src/afs/IRIX/osi_vcache.c b/src/afs/IRIX/osi_vcache.c index a34c9b9cb8..01a8d53585 100644 --- a/src/afs/IRIX/osi_vcache.c +++ b/src/afs/IRIX/osi_vcache.c @@ -14,8 +14,9 @@ #include "afsincludes.h" /*AFS-based standard headers */ int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { int code; + /* we can't control whether we sleep */ if (!VREFCOUNT_GT(avc,0) && avc->opens == 0 && (avc->f.states & CUnlinkedDel) == 0) { code = afs_FlushVCache(avc, slept); diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c index 21ad7c2097..e82d78e5da 100644 --- a/src/afs/LINUX/osi_vcache.c +++ b/src/afs/LINUX/osi_vcache.c @@ -14,7 +14,7 @@ #include "afsincludes.h" /*AFS-based standard headers */ int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { int code; struct dentry *dentry; @@ -22,7 +22,7 @@ osi_TryEvictVCache(struct vcache *avc, int *slept) { struct list_head *cur, *head; /* First, see if we can evict the inode from the dcache */ - if (avc != afs_globalVp && VREFCOUNT(avc) > 1 && avc->opens == 0) { + if (defersleep && avc != afs_globalVp && VREFCOUNT(avc) > 1 && avc->opens == 0) { *slept = 1; ReleaseWriteLock(&afs_xvcache); AFS_GUNLOCK(); diff --git a/src/afs/LINUX24/osi_vcache.c b/src/afs/LINUX24/osi_vcache.c index e3e3003ef1..bbaf5ce2f9 100644 --- a/src/afs/LINUX24/osi_vcache.c +++ b/src/afs/LINUX24/osi_vcache.c @@ -22,13 +22,15 @@ #endif int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { int code; struct dentry *dentry; struct list_head *cur, *head; /* First, see if we can evict the inode from the dcache */ - if (avc != afs_globalVp && VREFCOUNT(avc) > 1 && avc->opens == 0) { + if (defersleep && avc != afs_globalVp && VREFCOUNT(avc) > 1 && avc->opens == 0) { + *slept = 1; + ReleaseWriteLock(&afs_xvcache); AFS_GUNLOCK(); afs_linux_lock_dcache(); head = &(AFSTOV(avc))->i_dentry; @@ -57,13 +59,19 @@ restart: afs_linux_unlock_dcache(); inuse: AFS_GLOCK(); + ObtainWriteLock(&afs_xvcache, 733); } /* See if we can evict it from the VLRUQ */ if (VREFCOUNT_GT(avc,0) && !VREFCOUNT_GT(avc,1) && avc->opens == 0 && (avc->f.states & CUnlinkedDel) == 0) { + int didsleep = *slept; code = afs_FlushVCache(avc, slept); + /* flushvcache wipes slept; restore slept if we did before */ + if (didsleep) + *slept = didsleep; + if (code == 0) return 1; } diff --git a/src/afs/NBSD/osi_vcache.c b/src/afs/NBSD/osi_vcache.c index f7a544e9af..976c8758a4 100644 --- a/src/afs/NBSD/osi_vcache.c +++ b/src/afs/NBSD/osi_vcache.c @@ -14,7 +14,7 @@ #include "afsincludes.h" /*AFS-based standard headers */ int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { *slept = 0; if (!VREFCOUNT_GT(avc,0) diff --git a/src/afs/OBSD/osi_vcache.c b/src/afs/OBSD/osi_vcache.c index cbd37f81c2..6598ceabdb 100644 --- a/src/afs/OBSD/osi_vcache.c +++ b/src/afs/OBSD/osi_vcache.c @@ -14,7 +14,7 @@ #include "afsincludes.h" /*AFS-based standard headers */ int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { *slept = 0; if (!VREFCOUNT_GT(avc,0) diff --git a/src/afs/SOLARIS/osi_vcache.c b/src/afs/SOLARIS/osi_vcache.c index 2bb8f26ec1..6bd542890c 100644 --- a/src/afs/SOLARIS/osi_vcache.c +++ b/src/afs/SOLARIS/osi_vcache.c @@ -14,7 +14,7 @@ #include "afsincludes.h" /*AFS-based standard headers */ int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { int code; if (!VREFCOUNT_GT(avc,0) diff --git a/src/afs/UKERNEL/osi_vcache.c b/src/afs/UKERNEL/osi_vcache.c index 9fe66ec71c..dce051e847 100644 --- a/src/afs/UKERNEL/osi_vcache.c +++ b/src/afs/UKERNEL/osi_vcache.c @@ -14,7 +14,7 @@ #include "afsincludes.h" /*AFS-based standard headers */ int -osi_TryEvictVCache(struct vcache *avc, int *slept) { +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { int code; if (!VREFCOUNT_GT(avc,0) diff --git a/src/afs/afs_osi.h b/src/afs/afs_osi.h index 2bb57f5a2a..548ead53d3 100644 --- a/src/afs/afs_osi.h +++ b/src/afs/afs_osi.h @@ -140,7 +140,7 @@ extern struct vnodeops *afs_ops; #endif struct vcache; -extern int osi_TryEvictVCache(struct vcache *, int *); +extern int osi_TryEvictVCache(struct vcache *, int *, int); extern struct vcache *osi_NewVnode(void); extern void osi_PrePopulateVCache(struct vcache *); extern void osi_PostPopulateVCache(struct vcache *); diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index f357744637..d96bfc0222 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -698,7 +698,7 @@ afs_ShakeLooseVCaches(afs_int32 anumber) afs_int32 i, loop; struct vcache *tvc; struct afs_q *tq, *uq; - int fv_slept; + int fv_slept, defersleep = 0; afs_int32 target = anumber; i = 0; @@ -718,7 +718,7 @@ afs_ShakeLooseVCaches(afs_int32 anumber) } fv_slept = 0; - if (osi_TryEvictVCache(tvc, &fv_slept)) + if (osi_TryEvictVCache(tvc, &fv_slept, defersleep)) anumber--; if (fv_slept) { @@ -728,8 +728,14 @@ afs_ShakeLooseVCaches(afs_int32 anumber) i = 0; continue; /* start over - may have raced. */ } - if (tq == uq) + if (tq == uq) { + if (anumber && !defersleep) { + defersleep = 1; + tq = VLRU.prev; + continue; + } break; + } } if (!afsd_dynamic_vcaches && anumber == target) { afs_warn("afs_ShakeLooseVCaches: warning none freed, using %d of %d\n",