vmalloc-no-glock-20070418
authorChaskiel M Grundman <cg2v@andrew.cmu.edu>
Wed, 18 Apr 2007 19:01:31 +0000 (19:01 +0000)
committerDerrick Brashear <shadow@dementia.org>
Wed, 18 Apr 2007 19:01:31 +0000 (19:01 +0000)
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.

src/afs/LINUX/osi_alloc.c

index 23994d0..95ed5e5 100644 (file)
@@ -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);
        }