From 9adb2ba31349ca5ff3899a8b7c9e4144acfa9bac Mon Sep 17 00:00:00 2001 From: Chaskiel M Grundman Date: Wed, 18 Apr 2007 19:02:47 +0000 Subject: [PATCH] DEVEL15-vmalloc-no-glock-20070418 Based on Chris Wing's analysis which stated in part: GFP_NOFS tells the allocator not to recurse back into the filesystem if it's necessary to free up memory. However, vmalloc() does not have such an option. Therefore, calling osi_Alloc() to request more than a page of memory may end up recursing back into AFS to try to free unused inodes or dentries. In this case, what happened was that osi_Alloc() is called within an AFS_GLOCK(); osi_Alloc() calls vmalloc() which tries to free dentry objects, which then calls back into the AFS module. Unfortunately, AFS_GLOCK() is already held and we deadlock. (cherry picked from commit 9943fe1fd71fc29331dcac7cd6a51bd37f307876) --- src/afs/LINUX/osi_alloc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/afs/LINUX/osi_alloc.c b/src/afs/LINUX/osi_alloc.c index 23994d07b..95ed5e53c 100644 --- a/src/afs/LINUX/osi_alloc.c +++ b/src/afs/LINUX/osi_alloc.c @@ -98,7 +98,12 @@ linux_alloc(unsigned int asize, int drop_glock) if (new) /* piggy back alloc type */ new = (void *)(KM_TYPE | (unsigned long)new); } else { + osi_Assert(drop_glock || !haveGlock); + if (drop_glock && haveGlock) + AFS_GUNLOCK(); new = (void *)vmalloc(asize); + if (drop_glock && haveGlock) + AFS_GLOCK(); if (new) /* piggy back alloc type */ new = (void *)(VM_TYPE | (unsigned long)new); } -- 2.39.5