From 4a587356a31ac5afdf17d329a8598f70cf8bc3af Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Mon, 20 Oct 2008 13:38:07 +0000 Subject: [PATCH] linux-mmap-antirecursion-20081020 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 | 6 ++++++ src/afs/LINUX/osi_vnodeops.c | 15 +++++++++++++++ src/afs/afs.h | 4 ++++ 3 files changed, 25 insertions(+) diff --git a/src/afs/LINUX/osi_vm.c b/src/afs/LINUX/osi_vm.c index 2776aff89b..c7e39e29a4 100644 --- a/src/afs/LINUX/osi_vm.c +++ b/src/afs/LINUX/osi_vm.c @@ -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. diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 7e7edab943..7638a5c0ed 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -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); diff --git a/src/afs/afs.h b/src/afs/afs.h index df6da6f740..0aedd4692e 100644 --- a/src/afs/afs.h +++ b/src/afs/afs.h @@ -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 */