* Generate an index into the hash table for a given Fid.
*/
static int
-afs_HashCBRFid(struct AFSFid *fid) {
+afs_HashCBRFid(struct AFSFid *fid)
+{
return (fid->Volume + fid->Vnode + fid->Unique) % CBRSIZE;
}
* Must be called with afs_xvcb held.
*/
static void
-afs_InsertHashCBR(struct afs_cbr *cbr) {
+afs_InsertHashCBR(struct afs_cbr *cbr)
+{
int slot = afs_HashCBRFid(&cbr->fid);
cbr->hash_next = afs_cbrHashT[slot];
struct vrequest treq;
struct conn *tc;
int safety1, safety2, safety3;
- XSTATS_DECLS if ((code = afs_InitReq(&treq, afs_osi_credp)))
+ XSTATS_DECLS;
+ if ((code = afs_InitReq(&treq, afs_osi_credp)))
return code;
treq.flags |= O_NONBLOCK;
tfids = afs_osi_Alloc(sizeof(struct AFSFid) * AFS_MAXCBRSCALL);
ncbr = cbr->hash_next;
if (afid->Fid.Volume == cbr->fid.Volume &&
- afid->Fid.Vnode == cbr->fid.Vnode &&
+ afid->Fid.Vnode == cbr->fid.Vnode &&
afid->Fid.Unique == cbr->fid.Unique) {
afs_FreeCBR(cbr);
}
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 (!list_empty(&dentry->d_hash) && !list_empty(&dentry->d_subdirs))
__shrink_dcache_parent(dentry);
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);
refpanic("VLRU inconsistent");
}
#ifdef AFS_DARWIN_ENV
+ if ((VREFCOUNT(tvc) < DARWIN_REFBASE) ||
+ (VREFCOUNT(tvc) < 1 + DARWIN_REFBASE &&
+ UBCINFOEXISTS(&tvc->v))) {
+ VREFCOUNT_SET(tvc,
+ DARWIN_REFBASE +
+ (UBCINFOEXISTS(&tvc->v) ? 1 : 0));
+ }
if (tvc->opens == 0 && ((tvc->states & CUnlinkedDel) == 0)
- && VREFCOUNT(tvc) == 1 && UBCINFOEXISTS(&tvc->v)) {
+ && VREFCOUNT(tvc) == DARWIN_REFBASE + 1
+ && UBCINFOEXISTS(&tvc->v)) {
osi_VM_TryReclaim(tvc, &fv_slept);
if (fv_slept) {
uq = VLRU.prev;
#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();
+ struct dentry *dentry;
+ struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
+ AFS_FAST_HOLD(tvc);
+ AFS_GUNLOCK();
+
+restart:
+ spin_lock(&dcache_lock);
+ cur = head;
+ while ((cur = cur->next) != head) {
+ dentry = list_entry(cur, struct dentry, d_alias);
+
+ if (d_unhashed(dentry))
+ continue;
+
+ dget_locked(dentry);
+
+ if (!list_empty(&dentry->d_subdirs)) {
+ DUNLOCK();
+ shrink_dcache_parent(dentry);
+ DLOCK();
+ }
+
+ spin_lock(&dentry->d_lock);
+ if (atomic_read(&dentry->d_count) > 1) {
+ if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
+ spin_unlock(&dentry->d_lock);
+ spin_unlock(&dcache_lock);
+ dput(dentry);
+ goto inuse;
+ }
+ }
+
+ __d_drop(dentry);
+ spin_unlock(&dentry->d_lock);
+ spin_unlock(&dcache_lock);
+ dput(dentry);
+ goto restart;
+
+ }
+ DUNLOCK();
+inuse:
+
+ AFS_GLOCK();
+ AFS_FAST_RELE(tvc);
#else
afs_TryFlushDcacheChildren(tvc);
#endif
}
#endif
- if (VREFCOUNT(tvc) == 0 && tvc->opens == 0
- && (tvc->states & CUnlinkedDel) == 0) {
+ if (VREFCOUNT(tvc) ==
+#ifdef AFS_DARWIN_ENV
+ DARWIN_REFBASE
+#else
+ 0
+#endif
+ && tvc->opens == 0 && (tvc->states & CUnlinkedDel) == 0) {
#if defined(AFS_XBSD_ENV)
/*
* vgone() reclaims the vnode, which calls afs_FlushVCache(),
AFS_GLOCK();
if (tvc->v != NULL) {
/* I'd like to know if this ever happens...
- We don't drop global for the rest of this function,
- so if we do lose the race, the other thread should
- have found the same vnode and finished initializing
- the vcache entry. Is it conceivable that this vcache
- entry could be recycled during this interval? If so,
- then there probably needs to be some sort of additional
- mutual exclusion (an Embryonic flag would suffice).
- -GAW */
+ * We don't drop global for the rest of this function,
+ * so if we do lose the race, the other thread should
+ * have found the same vnode and finished initializing
+ * the vcache entry. Is it conceivable that this vcache
+ * entry could be recycled during this interval? If so,
+ * then there probably needs to be some sort of additional
+ * mutual exclusion (an Embryonic flag would suffice).
+ * -GAW */
printf("afs_NewVCache: lost the race\n");
return (tvc);
}
tvc->truncPos = AFS_NOTRUNC; /* don't truncate until we need to */
hzero(tvc->m.DataVersion); /* in case we copy it into flushDV */
#if defined(AFS_LINUX22_ENV)
-{
- struct inode *ip = AFSTOI(tvc);
- struct address_space *mapping = &ip->i_data;
+ {
+ struct inode *ip = AFSTOI(tvc);
+ struct address_space *mapping = &ip->i_data;
#if defined(AFS_LINUX26_ENV)
- inode_init_once(ip);
+ inode_init_once(ip);
#else
- sema_init(&ip->i_sem, 1);
- INIT_LIST_HEAD(&ip->i_hash);
- INIT_LIST_HEAD(&ip->i_dentry);
+ sema_init(&ip->i_sem, 1);
+ INIT_LIST_HEAD(&ip->i_hash);
+ INIT_LIST_HEAD(&ip->i_dentry);
#if defined(AFS_LINUX24_ENV)
- sema_init(&ip->i_zombie, 1);
- init_waitqueue_head(&ip->i_wait);
- spin_lock_init(&ip->i_data.i_shared_lock);
+ sema_init(&ip->i_zombie, 1);
+ init_waitqueue_head(&ip->i_wait);
+ spin_lock_init(&ip->i_data.i_shared_lock);
#ifdef STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK
- spin_lock_init(&ip->i_data.page_lock);
+ spin_lock_init(&ip->i_data.page_lock);
#endif
- INIT_LIST_HEAD(&ip->i_data.clean_pages);
- INIT_LIST_HEAD(&ip->i_data.dirty_pages);
- INIT_LIST_HEAD(&ip->i_data.locked_pages);
- INIT_LIST_HEAD(&ip->i_dirty_buffers);
+ INIT_LIST_HEAD(&ip->i_data.clean_pages);
+ INIT_LIST_HEAD(&ip->i_data.dirty_pages);
+ INIT_LIST_HEAD(&ip->i_data.locked_pages);
+ INIT_LIST_HEAD(&ip->i_dirty_buffers);
#ifdef STRUCT_INODE_HAS_I_DIRTY_DATA_BUFFERS
- INIT_LIST_HEAD(&ip->i_dirty_data_buffers);
+ INIT_LIST_HEAD(&ip->i_dirty_data_buffers);
#endif
#ifdef STRUCT_INODE_HAS_I_DEVICES
- INIT_LIST_HEAD(&ip->i_devices);
+ INIT_LIST_HEAD(&ip->i_devices);
#endif
#ifdef STRUCT_INODE_HAS_I_TRUNCATE_SEM
- init_rwsem(&ip->i_truncate_sem);
+ init_rwsem(&ip->i_truncate_sem);
#endif
#ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
- init_rwsem(&ip->i_alloc_sem);
-#endif
+ init_rwsem(&ip->i_alloc_sem);
+#endif
#else /* AFS_LINUX22_ENV */
- sema_init(&ip->i_atomic_write, 1);
- init_waitqueue(&ip->i_wait);
+ sema_init(&ip->i_atomic_write, 1);
+ init_waitqueue(&ip->i_wait);
#endif
#endif
#if defined(AFS_LINUX24_ENV)
- mapping->host = ip;
- ip->i_mapping = mapping;
+ mapping->host = ip;
+ ip->i_mapping = mapping;
#ifdef STRUCT_ADDRESS_SPACE_HAS_GFP_MASK
- ip->i_data.gfp_mask = GFP_HIGHUSER;
+ ip->i_data.gfp_mask = GFP_HIGHUSER;
#endif
#if defined(AFS_LINUX26_ENV)
- mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
-{
- extern struct backing_dev_info afs_backing_dev_info;
+ mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
+ {
+ extern struct backing_dev_info afs_backing_dev_info;
- mapping->backing_dev_info = &afs_backing_dev_info;
-}
+ mapping->backing_dev_info = &afs_backing_dev_info;
+ }
#endif
#endif
#if !defined(AFS_LINUX26_ENV)
- if (afs_globalVFS)
- ip->i_dev = afs_globalVFS->s_dev;
+ if (afs_globalVFS)
+ ip->i_dev = afs_globalVFS->s_dev;
+#else
+#ifdef STRUCT_INODE_HAS_I_SECURITY
+ ip->i_security = NULL;
+ if (security_inode_alloc(ip))
+ panic("Cannot allocate inode security");
#endif
- ip->i_sb = afs_globalVFS;
- put_inode_on_dummy_list(ip);
-}
+#endif
+ ip->i_sb = afs_globalVFS;
+ put_inode_on_dummy_list(ip);
+ }
#endif
#ifdef AFS_OSF_ENV
/* VLISTNONE(&tvc->v); */
tvc->v.v_freelist.tqe_next = 0;
tvc->v.v_freelist.tqe_prev = (struct vnode **)0xdeadb;
- /*tvc->vrefCount++; */
+ tvc->vrefCount += DARWIN_REFBASE;
#endif
/*
* The proper value for mvstat (for root fids) is setup by the caller.
struct vrequest treq, ureq;
struct AFSVolSync tsync;
int didCore;
- XSTATS_DECLS AFS_STATCNT(afs_FlushActiveVcaches);
+ XSTATS_DECLS;
+ AFS_STATCNT(afs_FlushActiveVcaches);
ObtainReadLock(&afs_xvcache);
for (i = 0; i < VCSIZE; i++) {
for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
}
}
#ifdef AFS_DARWIN_ENV
- if (VREFCOUNT(tvc) == 1 && UBCINFOEXISTS(&tvc->v)) {
+ if (VREFCOUNT(tvc) == 1 + DARWIN_REFBASE
+ && UBCINFOEXISTS(&tvc->v)) {
if (tvc->opens)
panic("flushactive open, hasubc, but refcnt 1");
osi_VM_TryReclaim(tvc, 0);
struct conn *tc;
struct AFSFetchStatus OutStatus;
struct AFSVolSync tsync;
- XSTATS_DECLS AFS_STATCNT(afs_WriteVCache);
+ XSTATS_DECLS;
+ AFS_STATCNT(afs_WriteVCache);
afs_Trace2(afs_iclSetp, CM_TRACE_WVCACHE, ICL_TYPE_POINTER, avc,
ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
afs_uint32 start;
register struct conn *tc;
struct AFSFetchStatus OutDirStatus;
- XSTATS_DECLS if (!name)
- name = ""; /* XXX */
+ XSTATS_DECLS;
+ if (!name)
+ name = ""; /* XXX */
do {
tc = afs_Conn(afid, areq, SHARED_LOCK);
if (tc) {
if (vg)
continue;
#endif /* AFS_OSF_ENV */
+#ifdef AFS_DARWIN14_ENV
+ /* It'd really suck if we allowed duplicate vcaches for the
+ * same fid to happen. Wonder if this will work? */
+ struct vnode *vp = AFSTOV(tvc);
+ if (vp->v_flag & (VXLOCK | VORECLAIM | VTERMINATE)) {
+ printf("precluded FindVCache on %x (%d:%d:%d)\n",
+ vp, tvc->fid.Fid.Volume, tvc->fid.Fid.Vnode,
+ tvc->fid.Fid.Unique);
+ simple_lock(&vp->v_interlock);
+ SET(vp->v_flag, VTERMWANT);
+ simple_unlock(&vp->v_interlock);
+ (void)tsleep((caddr_t) & vp->v_ubcinfo, PINOD, "vget1", 0);
+ printf("VTERMWANT ended on %x\n", vp);
+ continue;
+ }
+#endif
break;
}
}
struct AFSCallBack CallBack;
struct AFSVolSync tsync;
struct volume *volp;
- XSTATS_DECLS
+ XSTATS_DECLS;
do {
tc = afs_Conn(afid, areq, SHARED_LOCK);
avc->quick.stamp = 0;
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