Ejemplo n.º 1
0
/* this call, unlike osi_FlushText, is supposed to discard caches that may
   contain invalid information if a file is written remotely, but that may
   contain valid information that needs to be written back if the file is
   being written locally.  It doesn't subsume osi_FlushText, since the latter
   function may be needed to flush caches that are invalidated by local writes.

   avc->pvnLock is already held, avc->lock is guaranteed not to be held (by
   us, of course).
*/
void
osi_FlushPages(struct vcache *avc, afs_ucred_t *credp)
{
    afs_hyper_t origDV;
#if defined(AFS_CACHE_BYPASS)
    /* The optimization to check DV under read lock below is identical a
     * change in CITI cache bypass work.  The problem CITI found in 1999
     * was that this code and background daemon doing prefetching competed
     * for the vcache entry shared lock.  It's not clear to me from the
     * tech report, but it looks like CITI fixed the general prefetch code
     * path as a bonus when experimenting on prefetch for cache bypass, see
     * citi-tr-01-3.
     */
#endif
    if (vType(avc) == VDIR) {
	/* not applicable to directories; they're never mapped or stored in
	 * pages */
	return;
    }
    ObtainReadLock(&avc->lock);
    /* If we've already purged this version, or if we're the ones
     * writing this version, don't flush it (could lose the
     * data we're writing). */
    if ((hcmp((avc->f.m.DataVersion), (avc->mapDV)) <= 0)
	|| ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
	ReleaseReadLock(&avc->lock);
	return;
    }
    ReleaseReadLock(&avc->lock);
    ObtainWriteLock(&avc->lock, 10);
    /* Check again */
    if ((hcmp((avc->f.m.DataVersion), (avc->mapDV)) <= 0)
	|| ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
	ReleaseWriteLock(&avc->lock);
	return;
    }

    /* At this point, you might think that we can skip trying to flush pages
     * if mapDV is zero, since a file with a zero DV will not have any data in
     * it. However, some platforms (notably Linux 2.6.22+) will keep a page
     * full of zeroes around for an empty file. So play it safe and always
     * flush pages. */

    AFS_STATCNT(osi_FlushPages);
    hset(origDV, avc->f.m.DataVersion);
    afs_Trace3(afs_iclSetp, CM_TRACE_FLUSHPAGES, ICL_TYPE_POINTER, avc,
	       ICL_TYPE_INT32, origDV.low, ICL_TYPE_INT32, avc->f.m.Length);

    ReleaseWriteLock(&avc->lock);
#ifndef AFS_FBSD70_ENV
    AFS_GUNLOCK();
#endif
    osi_VM_FlushPages(avc, credp);
#ifndef AFS_FBSD70_ENV
    AFS_GLOCK();
#endif
    ObtainWriteLock(&avc->lock, 88);

    /* do this last, and to original version, since stores may occur
     * while executing above PUTPAGE call */
    hset(avc->mapDV, origDV);
    ReleaseWriteLock(&avc->lock);
}
Ejemplo n.º 2
0
/* this call, unlike osi_FlushText, is supposed to discard caches that may
   contain invalid information if a file is written remotely, but that may
   contain valid information that needs to be written back if the file is
   being written locally.  It doesn't subsume osi_FlushText, since the latter
   function may be needed to flush caches that are invalidated by local writes.

   avc->pvnLock is already held, avc->lock is guaranteed not to be held (by
   us, of course).
*/
void
osi_FlushPages(struct vcache *avc, afs_ucred_t *credp)
{
#ifdef AFS_FBSD70_ENV
    int vfslocked;
#endif
    afs_hyper_t origDV;
#if defined(AFS_CACHE_BYPASS)
    /* The optimization to check DV under read lock below is identical a
     * change in CITI cache bypass work.  The problem CITI found in 1999
     * was that this code and background daemon doing prefetching competed
     * for the vcache entry shared lock.  It's not clear to me from the
     * tech report, but it looks like CITI fixed the general prefetch code
     * path as a bonus when experimenting on prefetch for cache bypass, see
     * citi-tr-01-3.
     */
#endif
    ObtainReadLock(&avc->lock);
    /* If we've already purged this version, or if we're the ones
     * writing this version, don't flush it (could lose the
     * data we're writing). */
    if ((hcmp((avc->f.m.DataVersion), (avc->mapDV)) <= 0)
	|| ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
	ReleaseReadLock(&avc->lock);
	return;
    }
    ReleaseReadLock(&avc->lock);
    ObtainWriteLock(&avc->lock, 10);
    /* Check again */
    if ((hcmp((avc->f.m.DataVersion), (avc->mapDV)) <= 0)
	|| ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
	ReleaseWriteLock(&avc->lock);
	return;
    }
    if (hiszero(avc->mapDV)) {
	hset(avc->mapDV, avc->f.m.DataVersion);
	ReleaseWriteLock(&avc->lock);
	return;
    }

    AFS_STATCNT(osi_FlushPages);
    hset(origDV, avc->f.m.DataVersion);
    afs_Trace3(afs_iclSetp, CM_TRACE_FLUSHPAGES, ICL_TYPE_POINTER, avc,
	       ICL_TYPE_INT32, origDV.low, ICL_TYPE_INT32, avc->f.m.Length);

    ReleaseWriteLock(&avc->lock);
#ifdef AFS_FBSD70_ENV
    vfslocked = VFS_LOCK_GIANT(AFSTOV(avc)->v_mount);
#endif
#ifndef AFS_FBSD70_ENV
    AFS_GUNLOCK();
#endif
    osi_VM_FlushPages(avc, credp);
#ifndef AFS_FBSD70_ENV
    AFS_GLOCK();
#endif
#ifdef AFS_FBSD70_ENV
    VFS_UNLOCK_GIANT(vfslocked);
#endif
    ObtainWriteLock(&avc->lock, 88);

    /* do this last, and to original version, since stores may occur
     * while executing above PUTPAGE call */
    hset(avc->mapDV, origDV);
    ReleaseWriteLock(&avc->lock);
}