#include "afs/sysincludes.h" /*Standard vendor system headers */
#include "afsincludes.h" /*AFS-based standard headers */
-int
-osi_TryEvictVCache(struct vcache *avc, int *slept) {
- int code;
+#include "osi_compat.h"
+void
+osi_TryEvictDentries(struct vcache *avc)
+{
struct dentry *dentry;
- struct list_head *cur, *head;
+ 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 (avc != afs_globalVp && VREFCOUNT(avc) > 1 && avc->opens == 0) {
- *slept = 1;
- ReleaseWriteLock(&afs_xvcache);
- AFS_GUNLOCK();
- spin_lock(&dcache_lock);
- head = &(AFSTOV(avc))->i_dentry;
+#if defined(HAVE_DCACHE_LOCK)
+ spin_lock(&dcache_lock);
restart:
- cur = head;
- while ((cur = cur->next) != head) {
- dentry = list_entry(cur, struct dentry, d_alias);
+ list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+ if (d_unhashed(dentry))
+ continue;
+ dget_locked(dentry);
- if (d_unhashed(dentry))
- continue;
+ spin_unlock(&dcache_lock);
+ if (d_invalidate(dentry) == -EBUSY) {
+ dput(dentry);
+ /* perhaps lock and try to continue? (use cur as head?) */
+ goto inuse;
+ }
+ dput(dentry);
+ spin_lock(&dcache_lock);
+ goto restart;
+ }
+ spin_unlock(&dcache_lock);
+#else /* HAVE_DCACHE_LOCK */
+ spin_lock(&inode->i_lock);
- dget_locked(dentry);
+restart:
+#if defined(D_ALIAS_IS_HLIST)
+# if defined(HLIST_ITERATOR_NO_NODE)
+ hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+# else
+ hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
+# endif
+#else
+ 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_unlock(&dentry->d_lock);
+ dget(dentry);
- spin_unlock(&dcache_lock);
- if (d_invalidate(dentry) == -EBUSY) {
- dput(dentry);
- /* perhaps lock and try to continue? (use cur as head?) */
- goto inuse;
- }
+ spin_unlock(&inode->i_lock);
+ if (afs_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(&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);
}
/* See if we can evict it from the VLRUQ */
tvc->v = ip;
#endif
+ INIT_LIST_HEAD(&tvc->pagewriters);
+ spin_lock_init(&tvc->pagewriter_lock);
+
return tvc;
}
vSetType(avc, VREG);
}
+/**
+ * osi_ResetRootVCache - Reset the root vcache
+ * Reset the dentry associated with the afs root.
+ * Called from afs_CheckRootVolume when we notice that
+ * the root volume ID has changed.
+ *
+ * @volid: volume ID for the afs root
+ */
+void
+osi_ResetRootVCache(afs_uint32 volid)
+{
+ struct vrequest *treq = NULL;
+ struct vattr vattr;
+ cred_t *credp;
+ struct dentry *dp;
+ struct vcache *vcp;
+ struct inode *root = AFSTOV(afs_globalVp);
+
+ afs_rootFid.Fid.Volume = volid;
+ afs_rootFid.Fid.Vnode = 1;
+ afs_rootFid.Fid.Unique = 1;
+
+ credp = crref();
+ if (afs_CreateReq(&treq, credp))
+ goto out;
+ vcp = afs_GetVCache(&afs_rootFid, treq, NULL, NULL);
+ if (!vcp)
+ goto out;
+ afs_getattr(vcp, &vattr, credp);
+ afs_fill_inode(AFSTOV(vcp), &vattr);
+
+ dp = d_find_alias(root);
+
+#if defined(HAVE_DCACHE_LOCK)
+ spin_lock(&dcache_lock);
+#else
+ spin_lock(&AFSTOV(vcp)->i_lock);
+#endif
+ spin_lock(&dp->d_lock);
+#if defined(D_ALIAS_IS_HLIST)
+ hlist_del_init(&dp->d_alias);
+ hlist_add_head(&dp->d_alias, &(AFSTOV(vcp)->i_dentry));
+#else
+ list_del_init(&dp->d_alias);
+ list_add(&dp->d_alias, &(AFSTOV(vcp)->i_dentry));
+#endif
+ dp->d_inode = AFSTOV(vcp);
+ spin_unlock(&dp->d_lock);
+#if defined(HAVE_DCACHE_LOCK)
+ spin_unlock(&dcache_lock);
+#else
+ spin_unlock(&AFSTOV(vcp)->i_lock);
+#endif
+ dput(dp);
+
+ AFS_RELE(root);
+ afs_globalVp = vcp;
+out:
+ crfree(credp);
+ afs_DestroyReq(treq);
+}