#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"
-int
-osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) {
- int code;
-
+static void
+TryEvictDentries(struct vcache *avc)
+{
+#ifndef D_INVALIDATE_IS_VOID
struct dentry *dentry;
+#endif
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;
- ReleaseWriteLock(&afs_xvcache);
- AFS_GUNLOCK();
-
+#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);
+ 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:
+#endif /* D_INVALIDATE_IS_VOID */
+ 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();
+
+ TryEvictDentries(avc);
+
AFS_GLOCK();
ObtainWriteLock(&afs_xvcache, 733);
+ AFS_FAST_RELE(avc);
}
/* 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;
}
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);
}