From 3ef285cb114ec2a52bcf13daeddf068886e6a923 Mon Sep 17 00:00:00 2001 From: Felix Frank Date: Tue, 12 May 2009 18:57:49 +0000 Subject: [PATCH] STABLE14101-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 (cherry picked from commit 5e0e1ea2540d0cb7d7274350eb1fadfd41733ea4) --- src/afs/LINUX/osi_vm.c | 5 +---- src/afs/LINUX/osi_vnodeops.c | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/afs/LINUX/osi_vm.c b/src/afs/LINUX/osi_vm.c index a08da8fafb..4745b38193 100644 --- a/src/afs/LINUX/osi_vm.c +++ b/src/afs/LINUX/osi_vm.c @@ -102,9 +102,7 @@ osi_VM_StoreAllSegments(struct vcache *avc) { struct inode *ip = AFSTOV(avc); - if (!avc->states & CPageWrite) - avc->states |= CPageWrite; - else + if (avc->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->states &= ~CPageWrite; } /* Purge VM for a file when its callback is revoked. diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 9d2a6052a4..3962fea9b2 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -1567,9 +1567,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->states & CPageWrite) { - ReleaseReadLock(&vcp->lock); + ReleaseWriteLock(&vcp->lock); AFS_GUNLOCK(); unlock_kernel(); crfree(credp); @@ -1585,7 +1585,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); @@ -1594,16 +1595,18 @@ afs_linux_writepage_sync(struct inode *ip, struct page *pp, i_size_write(ip, vcp->m.Length); ip->i_blocks = ((vcp->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); @@ -1658,7 +1661,12 @@ afs_linux_writepage(struct page *pp) do_it: status = afs_linux_writepage_sync(inode, pp, 0, offset); SetPageUptodate(pp); - UnlockPage(pp); +#if defined(WRITEPAGE_ACTIVATE) + if ( status != WRITEPAGE_ACTIVATE ) +#else + if ( status != AOP_WRITEPAGE_ACTIVATE ) +#endif + UnlockPage(pp); if (status == offset) return 0; else