because we're only willing to loop 100 times worth of "sleeps",
on a machine with heavy vcache demands we can end up just growing
the list huge. in the first pass, just clean up as many entries which
do not require sleeping as needed. if we need more entries, make
a second pass.
Reviewed-on: http://gerrit.openafs.org/3971
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
(cherry picked from commit
3105c7ff0b4ae9c372dc4c1424f63b7f259dcda1)
Change-Id: Iced11ca56ced5971ab0cb8dbb65d275754ec33d5
Reviewed-on: http://gerrit.openafs.org/4186
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
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) {
#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) {
}
#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)
#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
#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);
#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);
#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;
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();
#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;
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;
}
#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)
#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)
#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)
#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)
#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 *);
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;
}
fv_slept = 0;
- if (osi_TryEvictVCache(tvc, &fv_slept))
+ if (osi_TryEvictVCache(tvc, &fv_slept, defersleep))
anumber--;
if (fv_slept) {
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",