MReleaseWriteLock(&afs_xvcb);
}
-#if defined(AFS_LINUX22_ENV) && !defined(AFS_LINUX26_ENV)
-
-static void
-__shrink_dcache_parent(struct dentry *parent)
-{
- struct dentry *this_parent = parent;
- struct list_head *next;
- int found = 0;
- LIST_HEAD(afs_dentry_unused);
-
- repeat:
- next = this_parent->d_subdirs.next;
- resume:
- while (next != &this_parent->d_subdirs) {
- struct list_head *tmp = next;
- struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
- next = tmp->next;
- if (!DCOUNT(dentry)) {
- list_del(&dentry->d_lru);
- list_add(&dentry->d_lru, afs_dentry_unused.prev);
- found++;
- }
- /*
- * Descend a level if the d_subdirs list is non-empty.
- */
- if (!list_empty(&dentry->d_subdirs)) {
- this_parent = dentry;
- goto repeat;
- }
- }
- /*
- * All done at this level ... ascend and resume the search.
- */
- if (this_parent != parent) {
- next = this_parent->d_child.next;
- this_parent = this_parent->d_parent;
- goto resume;
- }
-
- for (;;) {
- struct dentry *dentry;
- struct list_head *tmp;
-
- tmp = afs_dentry_unused.prev;
-
- if (tmp == &afs_dentry_unused)
- break;
-#ifdef AFS_LINUX24_ENV
- list_del_init(tmp);
-#else
- list_del(tmp);
- INIT_LIST_HEAD(tmp);
-#endif /* AFS_LINUX24_ENV */
- dentry = list_entry(tmp, struct dentry, d_lru);
-
-#ifdef AFS_LINUX24_ENV
- /* Unused dentry with a count? */
- if (DCOUNT(dentry))
- BUG();
-#endif
- DGET(dentry);
-#ifdef AFS_LINUX24_ENV
- list_del_init(&dentry->d_hash); /* d_drop */
-#else
- list_del(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_hash);
-#endif /* AFS_LINUX24_ENV */
- DUNLOCK();
- dput(dentry);
- DLOCK();
- if (!--found)
- break;
- }
-}
-
-/* afs_TryFlushDcacheChildren -- Shakes loose vcache references held by
- * children of the dentry
- *
- * LOCKS -- Called with afs_xvcache write locked. Drops and reaquires
- * AFS_GLOCK, so it can call dput, which may call iput, but
- * keeps afs_xvcache exclusively.
- *
- * Tree traversal algorithm from fs/dcache.c: select_parent()
- */
-static void
-afs_TryFlushDcacheChildren(struct vcache *tvc)
-{
- struct inode *ip = AFSTOI(tvc);
- struct dentry *this_parent;
- struct list_head *next;
- struct list_head *cur;
- struct list_head *head = &ip->i_dentry;
- struct dentry *dentry;
-
- AFS_GUNLOCK();
- restart:
-#ifndef old_vcache_scheme
- DLOCK();
- cur = head;
- while ((cur = cur->next) != head) {
- dentry = list_entry(cur, struct dentry, d_alias);
-
- if (!list_empty(&dentry->d_hash) && !list_empty(&dentry->d_subdirs))
- __shrink_dcache_parent(dentry);
-
- if (!DCOUNT(dentry)) {
- DGET(dentry);
-#ifdef AFS_LINUX24_ENV
- list_del_init(&dentry->d_hash); /* d_drop */
-#else
- list_del(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_hash);
-#endif /* AFS_LINUX24_ENV */
- DUNLOCK();
- dput(dentry);
- goto restart;
- }
- }
- DUNLOCK();
- AFS_GLOCK();
-#else
- restart:
- DLOCK();
- cur = head;
- while ((cur = cur->next) != head) {
- dentry = list_entry(cur, struct dentry, d_alias);
-
- afs_Trace3(afs_iclSetp, CM_TRACE_TRYFLUSHDCACHECHILDREN,
- ICL_TYPE_POINTER, ip, ICL_TYPE_STRING,
- dentry->d_parent->d_name.name, ICL_TYPE_STRING,
- dentry->d_name.name);
-
- if (!DCOUNT(dentry)) {
- AFS_GUNLOCK();
- DGET(dentry);
- DUNLOCK();
- d_drop(dentry);
- dput(dentry);
- AFS_GLOCK();
- goto restart;
- }
- }
- DUNLOCK();
-#endif
-}
-#endif /* AFS_LINUX22_ENV && !AFS_LINUX26_ENV */
-
/*
* afs_NewVCache
*
}
#elif defined(AFS_LINUX22_ENV)
if (tvc != afs_globalVp && VREFCOUNT(tvc) && tvc->opens == 0) {
-#if defined(AFS_LINUX26_ENV)
- AFS_GUNLOCK();
- d_prune_aliases(AFSTOI(tvc));
- AFS_GLOCK();
-#else
- afs_TryFlushDcacheChildren(tvc);
+ struct dentry *dentry;
+ struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
+ AFS_FAST_HOLD(tvc);
+ AFS_GUNLOCK();
+
+restart:
+#if defined(AFS_LINUX24_ENV)
+ spin_lock(&dcache_lock);
+#endif
+ cur = head;
+ while ((cur = cur->next) != head) {
+ dentry = list_entry(cur, struct dentry, d_alias);
+
+ if (d_unhashed(dentry))
+ continue;
+
+ dget_locked(dentry);
+
+#if defined(AFS_LINUX24_ENV)
+ spin_unlock(&dcache_lock);
#endif
+ if (d_invalidate(dentry) == -EBUSY) {
+ dput(dentry);
+ /* perhaps lock and try to continue? (use cur as head?) */
+ goto inuse;
+ }
+ dput(dentry);
+ goto restart;
+ }
+#if defined(AFS_LINUX24_ENV)
+ spin_unlock(&dcache_lock);
+#endif
+ inuse:
+ AFS_GLOCK();
+ AFS_FAST_RELE(tvc);
}
#endif
#if defined(AFS_LINUX22_ENV)
{
struct inode *ip = AFSTOI(tvc);
+#if defined(AFS_LINUX24_ENV)
struct address_space *mapping = &ip->i_data;
+#endif
#if defined(AFS_LINUX26_ENV)
inode_init_once(ip);
#endif
ip->i_sb = afs_globalVFS;
put_inode_on_dummy_list(ip);
+#ifdef STRUCT_INODE_HAS_I_SB_LIST
+ list_add(&ip->i_sb_list, &ip->i_sb->s_inodes);
+#endif
}
#endif
LOCK_INIT(&afs_xvcb, "afs_xvcb");
#if !defined(AFS_OSF_ENV)
+#ifdef AFS_LINUX26_ENV
+ printf("old style would have needed %d contiguous bytes\n", astatSize *
+ sizeof(struct vcache));
+ Initial_freeVCList = freeVCList = tvp = (struct vcache *)
+ afs_osi_Alloc(sizeof(struct vcache));
+ for (i = 0; i < astatSize; i++) {
+ tvp->nextfree = (struct vcache *) afs_osi_Alloc(sizeof(struct vcache));
+ tvp = tvp->nextfree;
+ }
+ tvp->nextfree = NULL;
+#else
/* Allocate and thread the struct vcache entries */
tvp = (struct vcache *)afs_osi_Alloc(astatSize * sizeof(struct vcache));
memset((char *)tvp, 0, sizeof(struct vcache) * astatSize);
pin((char *)tvp, astatSize * sizeof(struct vcache)); /* XXX */
#endif
#endif
-
+#endif
#if defined(AFS_SGI_ENV)
for (i = 0; i < astatSize; i++) {
}
afs_cbrSpace = 0;
+#ifdef AFS_LINUX26_ENV
+ {
+ struct vcache *tvp = Initial_freeVCList;
+ while (tvp) {
+ struct vcache *next = tvp->nextfree;
+
+ afs_osi_Free(tvp, sizeof(struct vcache));
+ tvp = next;
+ }
+ }
+#else
+#ifdef KERNEL_HAVE_PIN
+ unpin(Initial_freeVCList, afs_cacheStats * sizeof(struct vcache));
+#endif
#if !defined(AFS_OSF_ENV)
afs_osi_Free(Initial_freeVCList, afs_cacheStats * sizeof(struct vcache));
#endif
-#ifdef KERNEL_HAVE_PIN
- unpin(Initial_freeVCList, afs_cacheStats * sizeof(struct vcache));
#endif
+
#if !defined(AFS_OSF_ENV)
freeVCList = Initial_freeVCList = 0;
#endif