linux-mmap-antirecursion-fix-20090512

LICENSE IPL10
FIXES 124627

fix the mmap anti-recursion protection to set and mask CPageWrite appropriately
and with the correct lock protection. this leaves us with an issue to handle
when the mmap'd file is larger (possibly considerably larger) than the
cache
This commit is contained in:
Felix Frank 2009-05-12 18:56:30 +00:00 committed by Derrick Brashear
parent 3b6bf1a057
commit 5e0e1ea254
2 changed files with 16 additions and 11 deletions

View File

@ -102,9 +102,7 @@ osi_VM_StoreAllSegments(struct vcache *avc)
{
struct inode *ip = AFSTOV(avc);
if (!avc->f.states & CPageWrite)
avc->f.states |= CPageWrite;
else
if (avc->f.states & CPageWrite)
return; /* someone already writing */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5)
@ -120,7 +118,6 @@ osi_VM_StoreAllSegments(struct vcache *avc)
AFS_GLOCK();
ObtainWriteLock(&avc->lock, 121);
#endif
avc->f.states &= ~CPageWrite;
}
/* Purge VM for a file when its callback is revoked.

View File

@ -1188,7 +1188,7 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
if (code == ENOENT)
return ERR_PTR(0);
#endif
else if ((code >= 0) && (code <= MAX_ERRNO))
else if ((code > 0) && (code <= MAX_ERRNO))
return ERR_PTR(-code);
else
return ERR_PTR(-EIO);
@ -1895,9 +1895,9 @@ afs_linux_writepage_sync(struct inode *ip, struct page *pp,
ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
ICL_TYPE_INT32, 99999);
ObtainReadLock(&vcp->lock);
ObtainWriteLock(&vcp->lock, 532);
if (vcp->f.states & CPageWrite) {
ReleaseReadLock(&vcp->lock);
ReleaseWriteLock(&vcp->lock);
AFS_GUNLOCK();
maybe_unlock_kernel();
crfree(credp);
@ -1913,7 +1913,8 @@ afs_linux_writepage_sync(struct inode *ip, struct page *pp,
return(0);
#endif
}
ReleaseReadLock(&vcp->lock);
vcp->states |= CPageWrite;
ReleaseWriteLock(&vcp->lock);
setup_uio(&tuio, &iovec, buffer, base, count, UIO_WRITE, AFS_UIOSYS);
@ -1922,16 +1923,18 @@ afs_linux_writepage_sync(struct inode *ip, struct page *pp,
i_size_write(ip, vcp->f.m.Length);
ip->i_blocks = ((vcp->f.m.Length + 1023) >> 10) << 1;
ObtainWriteLock(&vcp->lock, 533);
if (!code) {
struct vrequest treq;
ObtainWriteLock(&vcp->lock, 533);
if (!afs_InitReq(&treq, credp))
code = afs_DoPartialWrite(vcp, &treq);
ReleaseWriteLock(&vcp->lock);
}
code = code ? -code : count - tuio.uio_resid;
vcp->states &= ~CPageWrite;
ReleaseWriteLock(&vcp->lock);
afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
ICL_TYPE_INT32, code);
@ -1986,6 +1989,11 @@ afs_linux_writepage(struct page *pp)
do_it:
status = afs_linux_writepage_sync(inode, pp, 0, offset);
SetPageUptodate(pp);
#if defined(WRITEPAGE_ACTIVATE)
if ( status != WRITEPAGE_ACTIVATE )
#else
if ( status != AOP_WRITEPAGE_ACTIVATE )
#endif
UnlockPage(pp);
if (status == offset)
return 0;