linux-mmap-antirecursion-20081020
authorDerrick Brashear <shadow@dementia.org>
Mon, 20 Oct 2008 13:38:07 +0000 (13:38 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 20 Oct 2008 13:38:07 +0000 (13:38 +0000)
LICENSE IPL10
FIXES 120491

avoid deadlocking ourselves due to recursion when flushing pages on an
mmap()ed file larger than the cache

src/afs/LINUX/osi_vm.c
src/afs/LINUX/osi_vnodeops.c
src/afs/afs.h

index 2776aff..c7e39e2 100644 (file)
@@ -102,6 +102,11 @@ osi_VM_StoreAllSegments(struct vcache *avc)
 {
     struct inode *ip = AFSTOV(avc);
 
+    if (!avc->states & CPageWrite)
+       avc->states |= CPageWrite;
+    else 
+       return; /* someone already writing */
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5)
     /* filemap_fdatasync() only exported in 2.4.5 and above */
     ReleaseWriteLock(&avc->lock);
@@ -115,6 +120,7 @@ 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.
index 7e7edab..7638a5c 100644 (file)
@@ -1894,6 +1894,21 @@ 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);
+    if (vcp->states & CPageWrite) {
+       ReleaseReadLock(&vcp->lock);
+       AFS_GUNLOCK();
+       maybe_unlock_kernel();
+       crfree(credp);
+       kunmap(pp);
+#if defined(WRITEPAGE_ACTIVATE)
+       return WRITEPAGE_ACTIVATE;
+#else
+       return AOP_WRITEPAGE_ACTIVATE;
+#endif
+    }
+    ReleaseReadLock(&vcp->lock);
+
     setup_uio(&tuio, &iovec, buffer, base, count, UIO_WRITE, AFS_UIOSYS);
 
     code = afs_write(vcp, &tuio, f_flags, credp, 0);
index df6da6f..0aedd46 100644 (file)
@@ -562,7 +562,11 @@ struct SimpleLocks {
 #define CUnlinkedDel   0x00040000
 #define CVFlushed      0x00080000
 #define CCore1         0x00100000      /* osf1 core file; not same as CCore above */
+#ifdef AFS_LINUX22_ENV
+#define CPageWrite      0x00200000      /* to detect vm deadlock - linux */
+#else
 #define CWritingUFS    0x00200000      /* to detect vm deadlock - used by sgi */
+#endif
 #define CCreating      0x00400000      /* avoid needless store after open truncate */
 #define CPageHog       0x00800000      /* AIX - dumping large cores is a page hog. */
 #define CDCLock                0x02000000      /* Vnode lock held over call to GetDownD */