diff --git a/src/afs/LINUX/osi_sleep.c b/src/afs/LINUX/osi_sleep.c index 8bfa05087d..36346e3be2 100644 --- a/src/afs/LINUX/osi_sleep.c +++ b/src/afs/LINUX/osi_sleep.c @@ -129,6 +129,9 @@ typedef struct afs_event { int seq; /* Sequence number: this is incremented by wakeup calls; wait will not return until it changes */ + int dontSleep; /* on SMP machines the wakeup call may be + earlier than the sleep call. wakeup sets + dontSleep and sleep resets it at return. */ #if defined(AFS_LINUX24_ENV) wait_queue_head_t cond; #else @@ -174,6 +177,7 @@ static afs_event_t *afs_getevent(char *event) } newp->event = event; newp->refcount = 1; + newp->dontSleep = 0; return newp; } @@ -185,15 +189,42 @@ void afs_osi_Sleep(char *event) { struct afs_event *evp; int seq; + int count = 0; + int timeout = 1; evp = afs_getevent(event); - seq = evp->seq; - while (seq == evp->seq) { - AFS_ASSERT_GLOCK(); - AFS_GUNLOCK(); - interruptible_sleep_on(&evp->cond); - AFS_GLOCK(); + if (evp->dontSleep) { + afs_Trace4(afs_iclSetp, CM_TRACE_SLEEP, + ICL_TYPE_POINTER, evp, + ICL_TYPE_INT32, count, + ICL_TYPE_INT32, seq, + ICL_TYPE_INT32, evp->seq); + } else { + seq = evp->seq; + while (seq == evp->seq && !evp->dontSleep) { + AFS_ASSERT_GLOCK(); + AFS_GUNLOCK(); +#ifdef AFS_SMP + /* + * There seems to be a problem on SMP machines if the wake_up() and + * interruptible_sleep() calls happen at the "same" time. + */ + if (timeout < 1024) + timeout = timeout << 1; + interruptible_sleep_on_timeout(&evp->cond, timeout); +#else + interruptible_sleep_on(&evp->cond); +#endif + AFS_GLOCK(); + count++; + afs_Trace4(afs_iclSetp, CM_TRACE_SLEEP, + ICL_TYPE_POINTER, evp, + ICL_TYPE_INT32, count, + ICL_TYPE_INT32, seq, + ICL_TYPE_INT32, evp->seq); + } } + evp->dontSleep = 0; relevent(evp); } @@ -233,8 +264,12 @@ void afs_osi_Wakeup(char *event) struct afs_event *evp; evp = afs_getevent(event); + evp->dontSleep = 1; if (evp->refcount > 1) { evp->seq++; + afs_Trace2(afs_iclSetp, CM_TRACE_WAKE, + ICL_TYPE_POINTER, evp, + ICL_TYPE_INT32, evp->seq); wake_up(&evp->cond); } relevent(evp); diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c index 94ccaccff4..a4b3d1c059 100644 --- a/src/afs/VNOPS/afs_vnop_lookup.c +++ b/src/afs/VNOPS/afs_vnop_lookup.c @@ -455,6 +455,11 @@ tagain: while ((adp->states & CStatd) && (dcp->flags & DFFetching) && hsame(adp->m.DataVersion, dcp->f.versionNo)) { + afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, + ICL_TYPE_STRING, __FILE__, + ICL_TYPE_INT32, __LINE__, + ICL_TYPE_POINTER, dcp, + ICL_TYPE_INT32, dcp->flags); dcp->flags |= DFWaiting; ReleaseReadLock(&adp->lock); afs_osi_Sleep(&dcp->validPos); diff --git a/src/afs/VNOPS/afs_vnop_read.c b/src/afs/VNOPS/afs_vnop_read.c index 8d337e854a..b63517ee18 100644 --- a/src/afs/VNOPS/afs_vnop_read.c +++ b/src/afs/VNOPS/afs_vnop_read.c @@ -186,6 +186,11 @@ tagain: * data is now streaming in, then wait for some interesting stuff. */ while ((tdc->flags & DFFetching) && tdc->validPos <= filePos) { /* too early: wait for DFFetching flag to vanish, or data to appear */ + afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, + ICL_TYPE_STRING, __FILE__, + ICL_TYPE_INT32, __LINE__, + ICL_TYPE_POINTER, tdc, + ICL_TYPE_INT32, tdc->flags); tdc->flags |= DFWaiting; ReleaseReadLock(&avc->lock); afs_osi_Sleep(&tdc->validPos); @@ -634,6 +639,11 @@ tagain: * data is now streaming in, then wait for some interesting stuff. */ while ((tdc->flags & DFFetching) && tdc->validPos <= filePos) { /* too early: wait for DFFetching flag to vanish, or data to appear */ + afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, + ICL_TYPE_STRING, __FILE__, + ICL_TYPE_INT32, __LINE__, + ICL_TYPE_POINTER, tdc, + ICL_TYPE_INT32, tdc->flags); tdc->flags |= DFWaiting; ReleaseReadLock(&avc->lock); afs_osi_Sleep(&tdc->validPos); @@ -664,7 +674,11 @@ tagain: ObtainReadLock(&avc->lock); } } - + + afs_Trace3(afs_iclSetp, CM_TRACE_VNODEREAD, + ICL_TYPE_POINTER, tdc, + ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(offset), + ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(len)); if (!tdc) { error = EIO; break; diff --git a/src/afs/VNOPS/afs_vnop_readdir.c b/src/afs/VNOPS/afs_vnop_readdir.c index 0305cdf74b..3b09007dd9 100644 --- a/src/afs/VNOPS/afs_vnop_readdir.c +++ b/src/afs/VNOPS/afs_vnop_readdir.c @@ -518,6 +518,11 @@ tagain: while ((avc->states & CStatd) && (tdc->flags & DFFetching) && hsame(avc->m.DataVersion, tdc->f.versionNo)) { + afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, + ICL_TYPE_STRING, __FILE__, + ICL_TYPE_INT32, __LINE__, + ICL_TYPE_POINTER, tdc, + ICL_TYPE_INT32, tdc->flags); tdc->flags |= DFWaiting; ReleaseReadLock(&avc->lock); afs_osi_Sleep(&tdc->validPos); @@ -794,6 +799,11 @@ tagain: while ((avc->states & CStatd) && (tdc->flags & DFFetching) && hsame(avc->m.DataVersion, tdc->f.versionNo)) { + afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, + ICL_TYPE_STRING, __FILE__, + ICL_TYPE_INT32, __LINE__, + ICL_TYPE_POINTER, tdc, + ICL_TYPE_INT32, tdc->flags); tdc->flags |= DFWaiting; ReleaseReadLock(&avc->lock); afs_osi_Sleep(&tdc->validPos); diff --git a/src/afs/afs_dcache.c b/src/afs/afs_dcache.c index dd0f2aa320..535c35001d 100644 --- a/src/afs/afs_dcache.c +++ b/src/afs/afs_dcache.c @@ -1438,6 +1438,11 @@ static int afs_UFSCacheFetchProc(acall, afile, abase, adc, avc, length -= tlen; adc->validPos = abase; if (adc->flags & DFWaiting) { + afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, + ICL_TYPE_STRING, __FILE__, + ICL_TYPE_INT32, __LINE__, + ICL_TYPE_POINTER, adc, + ICL_TYPE_INT32, adc->flags); adc->flags &= ~DFWaiting; afs_osi_Wakeup(&adc->validPos); } @@ -1606,107 +1611,109 @@ struct dcache *afs_GetDCache(avc, abyte, areq, aoffset, alen, aflags) #endif } MReleaseReadLock(&afs_xdcache); + if (!shortcut) + tdc = 0; } - if (!shortcut) - { - - /* - * Hash on the [fid, chunk] and get the corresponding dcache index - * after write-locking the dcache. - */ + if (!tdc) { + /* + * Hash on the [fid, chunk] and get the corresponding dcache index + * after write-locking the dcache. + */ RetryLookup: - i = DCHash(&avc->fid, chunk); - afs_MaybeWakeupTruncateDaemon(); /* check to make sure our space is fine */ - MObtainWriteLock(&afs_xdcache,280); - us = NULLIDX; - for(index = afs_dchashTbl[i]; index != NULLIDX;) { - if (afs_indexUnique[index] == avc->fid.Fid.Unique) { - tdc = afs_GetDSlot(index, (struct dcache *)0); - if (!FidCmp(&tdc->f.fid, &avc->fid) && chunk == tdc->f.chunk) { - /* Move it up in the beginning of the list */ - if (afs_dchashTbl[i] != index) { - afs_dcnextTbl[us] = afs_dcnextTbl[index]; - afs_dcnextTbl[index] = afs_dchashTbl[i]; - afs_dchashTbl[i] = index; + i = DCHash(&avc->fid, chunk); + afs_MaybeWakeupTruncateDaemon(); /* check to make sure our space is fine */ + MObtainWriteLock(&afs_xdcache,280); + us = NULLIDX; + for(index = afs_dchashTbl[i]; index != NULLIDX;) { + if (afs_indexUnique[index] == avc->fid.Fid.Unique) { + tdc = afs_GetDSlot(index, (struct dcache *)0); + if (!FidCmp(&tdc->f.fid, &avc->fid) && chunk == tdc->f.chunk) { + /* Move it up in the beginning of the list */ + if (afs_dchashTbl[i] != index) { + afs_dcnextTbl[us] = afs_dcnextTbl[index]; + afs_dcnextTbl[index] = afs_dchashTbl[i]; + afs_dchashTbl[i] = index; + } + MReleaseWriteLock(&afs_xdcache); + break; /* leaving refCount high for caller */ } + tdc->refCount--; /* was incremented by afs_GetDSlot */ + tdc = 0; + } + us = index; + index = afs_dcnextTbl[index]; + } + /* + * If we didn't find the entry, we'll create one. + */ + if (index == NULLIDX) { + afs_Trace2(afs_iclSetp, CM_TRACE_GETDCACHE1, ICL_TYPE_POINTER, avc, + ICL_TYPE_INT32, chunk); + + if (afs_discardDCList == NULLIDX && afs_freeDCList == NULLIDX) { + while (1) { + if (!setLocks) avc->states |= CDCLock; + afs_GetDownD(5, (int*)0); /* just need slots */ + if (!setLocks) avc->states &= (~CDCLock); + if (afs_discardDCList != NULLIDX || afs_freeDCList != NULLIDX) + break; + /* If we can't get space for 5 mins we give up and panic */ + if (++downDCount > 300) + osi_Panic("getdcache"); + MReleaseWriteLock(&afs_xdcache); + afs_osi_Wait(1000, 0, 0); + goto RetryLookup; + } + } + if (afs_discardDCList == NULLIDX || + ((aflags & 2) && afs_freeDCList != NULLIDX)) { + afs_indexFlags[afs_freeDCList] &= ~IFFree; + tdc = afs_GetDSlot(afs_freeDCList, 0); + afs_freeDCList = afs_dvnextTbl[tdc->index]; + afs_freeDCCount--; + } else { + afs_indexFlags[afs_discardDCList] &= ~IFDiscarded; + tdc = afs_GetDSlot(afs_discardDCList, 0); + afs_discardDCList = afs_dvnextTbl[tdc->index]; + afs_discardDCCount--; + size = ((tdc->f.chunkBytes + afs_fsfragsize)^afs_fsfragsize)>>10; + afs_blocksDiscarded -= size; + afs_stats_cmperf.cacheBlocksDiscarded = afs_blocksDiscarded; + if (aflags & 2) { + /* Truncate the chunk so zeroes get filled properly */ + file = afs_CFileOpen(tdc->f.inode); + afs_CFileTruncate(file, 0); + afs_CFileClose(file); + afs_AdjustSize(tdc, 0); + } + } + + /* + * Fill in the newly-allocated dcache record. + */ + afs_indexFlags[tdc->index] &= ~(IFDirtyPages | IFAnyPages); + tdc->f.fid = avc->fid; + afs_indexUnique[tdc->index] = tdc->f.fid.Fid.Unique; + hones(tdc->f.versionNo); /* invalid value */ + tdc->f.chunk = chunk; + tdc->validPos = AFS_CHUNKTOBASE(chunk); + /* XXX */ + if (tdc->lruq.prev == &tdc->lruq) osi_Panic("lruq 1"); + /* + * Now add to the two hash chains - note that i is still set + * from the above DCHash call. + */ + afs_dcnextTbl[tdc->index] = afs_dchashTbl[i]; + afs_dchashTbl[i] = tdc->index; + i = DVHash(&avc->fid); + afs_dvnextTbl[tdc->index] = afs_dvhashTbl[i]; + afs_dvhashTbl[i] = tdc->index; + tdc->flags = DFEntryMod; + tdc->f.states = 0; + afs_MaybeWakeupTruncateDaemon(); MReleaseWriteLock(&afs_xdcache); - break; /* leaving refCount high for caller */ - } - lockedPutDCache(tdc); - } - us = index; - index = afs_dcnextTbl[index]; - } - /* - * If we didn't find the entry, we'll create one. - */ - if (index == NULLIDX) { - afs_Trace2(afs_iclSetp, CM_TRACE_GETDCACHE1, ICL_TYPE_POINTER, avc, - ICL_TYPE_INT32, chunk); - - if (afs_discardDCList == NULLIDX && afs_freeDCList == NULLIDX) { - while (1) { - if (!setLocks) avc->states |= CDCLock; - afs_GetDownD(5, (int*)0); /* just need slots */ - if (!setLocks) avc->states &= (~CDCLock); - if (afs_discardDCList != NULLIDX || afs_freeDCList != NULLIDX) - break; - /* If we can't get space for 5 mins we give up and panic */ - if (++downDCount > 300) - osi_Panic("getdcache"); - MReleaseWriteLock(&afs_xdcache); - afs_osi_Wait(1000, 0, 0); - goto RetryLookup; - } - } - if (afs_discardDCList == NULLIDX || - ((aflags & 2) && afs_freeDCList != NULLIDX)) { - afs_indexFlags[afs_freeDCList] &= ~IFFree; - tdc = afs_GetDSlot(afs_freeDCList, 0); - afs_freeDCList = afs_dvnextTbl[tdc->index]; - afs_freeDCCount--; - } else { - afs_indexFlags[afs_discardDCList] &= ~IFDiscarded; - tdc = afs_GetDSlot(afs_discardDCList, 0); - afs_discardDCList = afs_dvnextTbl[tdc->index]; - afs_discardDCCount--; - size = ((tdc->f.chunkBytes + afs_fsfragsize)^afs_fsfragsize)>>10; - afs_blocksDiscarded -= size; - afs_stats_cmperf.cacheBlocksDiscarded = afs_blocksDiscarded; - if (aflags & 2) { - /* Truncate the chunk so zeroes get filled properly */ - file = afs_CFileOpen(tdc->f.inode); - afs_CFileTruncate(file, 0); - afs_CFileClose(file); - afs_AdjustSize(tdc, 0); - } - } - - /* - * Fill in the newly-allocated dcache record. - */ - afs_indexFlags[tdc->index] &= ~(IFDirtyPages | IFAnyPages); - tdc->f.fid = avc->fid; - afs_indexUnique[tdc->index] = tdc->f.fid.Fid.Unique; - hones(tdc->f.versionNo); /* invalid value */ - tdc->f.chunk = chunk; - /* XXX */ - if (tdc->lruq.prev == &tdc->lruq) osi_Panic("lruq 1"); - /* - * Now add to the two hash chains - note that i is still set - * from the above DCHash call. - */ - afs_dcnextTbl[tdc->index] = afs_dchashTbl[i]; - afs_dchashTbl[i] = tdc->index; - i = DVHash(&avc->fid); - afs_dvnextTbl[tdc->index] = afs_dvhashTbl[i]; - afs_dvhashTbl[i] = tdc->index; - tdc->flags = DFEntryMod; - tdc->f.states = 0; - afs_MaybeWakeupTruncateDaemon(); - MReleaseWriteLock(&afs_xdcache); - } - } /* else hint failed... */ + } + } /* else hint failed... */ afs_Trace4(afs_iclSetp, CM_TRACE_GETDCACHE2, ICL_TYPE_POINTER, avc, ICL_TYPE_POINTER, tdc, @@ -1727,7 +1734,10 @@ struct dcache *afs_GetDCache(avc, abyte, areq, aoffset, alen, aflags) * that this chunk's data hasn't been filled by another client. */ size = AFS_CHUNKSIZE(abyte); - tlen = *alen; + if (aflags & 4) /* called from write */ + tlen = *alen; + else /* called from read */ + tlen = tdc->validPos - abyte; Position = AFS_CHUNKTOBASE(chunk); afs_Trace4(afs_iclSetp, CM_TRACE_GETDCACHE3, ICL_TYPE_INT32, tlen, @@ -1803,6 +1813,14 @@ struct dcache *afs_GetDCache(avc, abyte, areq, aoffset, alen, aflags) hset(afs_indexTimes[tdc->index], afs_indexCounter); hadd32(afs_indexCounter, 1); updateV2DC(setLocks,avc,tdc,567); + if (vType(avc) == VDIR) + *aoffset = abyte; + else + *aoffset = AFS_CHUNKOFFSET(abyte); + if (tdc->validPos < abyte) + *alen = (afs_size_t) 0; + else + *alen = tdc->validPos - abyte; return tdc; /* check if we're done */ } osi_Assert(setLocks || WriteLocked(&avc->lock)); @@ -1920,7 +1938,7 @@ struct dcache *afs_GetDCache(avc, abyte, areq, aoffset, alen, aflags) afs_RemoveVCB(&avc->fid); tdc->f.states |= DWriting; tdc->flags |= DFFetching; - tdc->validPos = Position; /*Last valid position in this chunk*/ + tdc->validPos = Position; /* which is AFS_CHUNKBASE(abyte) */ if (tdc->flags & DFFetchReq) { tdc->flags &= ~DFFetchReq; afs_osi_Wakeup(&tdc->validPos); @@ -2234,6 +2252,11 @@ struct dcache *afs_GetDCache(avc, abyte, areq, aoffset, alen, aflags) tdc->flags &= ~DFFetching; if (tdc->flags & DFWaiting) { + afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, + ICL_TYPE_STRING, __FILE__, + ICL_TYPE_INT32, __LINE__, + ICL_TYPE_POINTER, tdc, + ICL_TYPE_INT32, tdc->flags); tdc->flags &= ~DFWaiting; afs_osi_Wakeup(&tdc->validPos); } @@ -2309,7 +2332,7 @@ done: *aoffset = abyte; else *aoffset = AFS_CHUNKOFFSET(abyte); - *alen = (tdc->f.chunkBytes - *aoffset); + *alen = *aoffset + tdc->f.chunkBytes - abyte; } return tdc; diff --git a/src/afs/afs_trace.et b/src/afs/afs_trace.et index f892079388..0b6286c257 100644 --- a/src/afs/afs_trace.et +++ b/src/afs/afs_trace.et @@ -1,6 +1,6 @@ # Copyright 2000, International Business Machines Corporation and others. # All Rights Reserved. -# +# # This software has been released under the terms of the IBM Public # License. For details, see the LICENSE file in the top-level source # directory or online at http://www.openafs.org/dl/license10.html @@ -26,6 +26,7 @@ error_table 2 ZCM ec CM_TRACE_STOREALL, "StoreAll vp 0x%lx len (0x%x, 0x%x)" ec CM_TRACE_INVALL, "InvalAll vp 0x%lx len 0x%x" ec CM_TRACE_TRUNCALL, "TruncAll vp 0x%lx old len (0x%x, 0x%x) new len (0x%x, 0x%x)" + ec CM_TRACE_GNLINK, "Gn_link vp 0x%lx name %s (returns 0x%x)" ec CM_TRACE_GMKDIR, "Gn_mkdir vp 0x%lx name %s mode 0x%x (returns 0x%x)" ec CM_TRACE_GMKNOD, "Gn_mknod vp 0x%lx name %s mode 0x%x (returns 0x%x)" @@ -54,7 +55,7 @@ error_table 2 ZCM ec CM_TRACE_STUFFVCACHE, "StuffVcache 0x%lx callback host 0x%lx expires %u (in %u secs)" ec CM_TRACE_GETDCACHE1, "Getdcache vp 0x%lx failed to find chunk 0x%x" ec CM_TRACE_GETDCACHE2, "GetdCache vp 0x%lx dcache 0x%lx dcache low-version 0x%x, vcache low-version 0x%x" - ec CM_TRACE_GETDCACHE3, "GetdCache tlen 0x%x size 0x%x abyte (0x%x, 0x%x) Position (0x%x, 0x%x)" + ec CM_TRACE_GETDCACHE3, "GetdCache tlen 0x%x flags 0x%x abyte (0x%x, 0x%x) Position (0x%x, 0x%x)" ec CM_TRACE_STOREMINI, "storemini vp 0x%lx length 0x%x" ec CM_TRACE_STOREDCACHE, "StoreDCache vp 0x%lx chunk 0x%x length 0x%x at position 0x%x" ec CM_TRACE_STOREDCACHEDONE, "StoreDCache Done for vp 0x%lx (returns 0x%x)" @@ -152,5 +153,9 @@ error_table 2 ZCM ec CM_TRACE_STOREPROC2, "StoreProc got 0x%x" ec CM_TRACE_ADJUSTSIZE, "AdjustSize index %d oldSize %d newSize %d blocksUsed %d" ec CM_TRACE_SETLENGTH, "%s line %d: m.Length was (0x%x, 0x%x), now (0x%x, 0x%x)" + ec CM_TRACE_DCACHEWAIT, "%s line %d: sleeping or waiting for 0x%x flags 0x%x" + ec CM_TRACE_VNODEREAD, "UFSRead: tdc 0x%x, offset (0x%x, 0x%x) len (0x%x 0x%x)" + ec CM_TRACE_SLEEP, "Sleep: evp 0x%x, count %d seq 0x%x evp->seq 0x%x" + ec CM_TRACE_WAKE, "Wapeup: evp 0x%x, evp->seq 0x%x" end