X-Git-Url: http://git.openafs.org/?p=openafs.git;a=blobdiff_plain;f=src%2Fafs%2FLINUX%2Fosi_vcache.c;h=1a5012c95d086b8b71d7b7fe49f0e67a4e293857;hp=1d0db82cc0ceda0ad79fb1abb493fcb004934f5a;hb=5076dfc14b980aed310f3862875d5e9919fa199d;hpb=a42f01d5ebb13da575b3123800ee6990743155ab diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c index 1d0db82..1a5012c 100644 --- a/src/afs/LINUX/osi_vcache.c +++ b/src/afs/LINUX/osi_vcache.c @@ -10,87 +10,79 @@ #include #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) +{ 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; - ReleaseWriteLock(&afs_xvcache); - AFS_GUNLOCK(); - -#if defined(HAVE_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; - } - dput(dentry); - spin_lock(&dcache_lock); - goto restart; - } - spin_unlock(&dcache_lock); -#else /* HAVE_DCACHE_LOCK */ - spin_lock(&inode->i_lock); + afs_d_alias_lock(inode); 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; - } + continue; + } + spin_unlock(&dentry->d_lock); + afs_linux_dget(dentry); + + afs_d_alias_unlock(inode); + if (afs_d_invalidate(dentry) == -EBUSY) { dput(dentry); - spin_lock(&inode->i_lock); - goto restart; + /* perhaps lock and try to continue? (use cur as head?) */ + goto inuse; } - spin_unlock(&inode->i_lock); -#endif /* HAVE_DCACHE_LOCK */ + dput(dentry); + afs_d_alias_lock(inode); + goto restart; + } + afs_d_alias_unlock(inode); + 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(); + + 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; @@ -125,21 +117,85 @@ osi_NewVnode(void) tvc->v = ip; #endif + INIT_LIST_HEAD(&tvc->pagewriters); + spin_lock_init(&tvc->pagewriter_lock); + return tvc; } 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); } +/** + * 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); + + afs_d_alias_lock(AFSTOV(vcp)); + + 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); + + afs_d_alias_unlock(AFSTOV(vcp)); + + dput(dp); + + AFS_RELE(root); + afs_globalVp = vcp; +out: + crfree(credp); + afs_DestroyReq(treq); +}