Re: INFO: possible circular locking dependency detected

From: Nick Piggin
Date: Mon Oct 16 2006 - 10:33:23 EST


alpha @ steudten Engineering wrote:
=======================================================
[ INFO: possible circular locking dependency detected ]
2.6.18-1.2189self #1
-------------------------------------------------------
kswapd0/186 is trying to acquire lock:
(&inode->i_mutex){--..}, at: [<c0326e32>] mutex_lock+0x21/0x24

but task is already holding lock:
(iprune_mutex){--..}, at: [<c0326e32>] mutex_lock+0x21/0x24

which lock already depends on the new lock.

Thanks. __grab_cache_page wants to clear __GFP_FS, because it is
holding the i_mutex so we don't want to reenter the filesystem in
page reclaim.

This would be an easy two liner, except those funny page_cache_alloc
routines which take a mapping rather than a gfp_t argument :P

Anyway, I'll get around to writing the real patch and queue it up
with my other buffered write deadlock fixes. It should be fairly
unlikely to cause you a deadlock. You could give this quick patch a
try, though. Does it fix your problem?

--
SUSE Labs, Novell Inc.
Index: linux-2.6/include/linux/pagemap.h
===================================================================
--- linux-2.6.orig/include/linux/pagemap.h 2006-10-17 00:29:40.000000000 +1000
+++ linux-2.6/include/linux/pagemap.h 2006-10-17 00:29:50.000000000 +1000
@@ -57,7 +57,7 @@ extern struct page *page_cache_alloc_col
#else
static inline struct page *page_cache_alloc(struct address_space *x)
{
- return alloc_pages(mapping_gfp_mask(x), 0);
+ return alloc_pages(mapping_gfp_mask(x)&~__GFP_FS, 0);
}

static inline struct page *page_cache_alloc_cold(struct address_space *x)
Index: linux-2.6/mm/filemap.c
===================================================================
--- linux-2.6.orig/mm/filemap.c 2006-10-17 00:29:49.000000000 +1000
+++ linux-2.6/mm/filemap.c 2006-10-17 00:29:50.000000000 +1000
@@ -471,9 +471,9 @@ struct page *page_cache_alloc(struct add
{
if (cpuset_do_page_mem_spread()) {
int n = cpuset_mem_spread_node();
- return alloc_pages_node(n, mapping_gfp_mask(x), 0);
+ return alloc_pages_node(n, mapping_gfp_mask(x)&~__GFP_FS, 0);
}
- return alloc_pages(mapping_gfp_mask(x), 0);
+ return alloc_pages(mapping_gfp_mask(x)&~__GFP_FS, 0);
}
EXPORT_SYMBOL(page_cache_alloc);

@@ -1864,7 +1864,7 @@ repeat:
return NULL;
}
err = add_to_page_cache(*cached_page, mapping,
- index, GFP_KERNEL);
+ index, GFP_KERNEL&~__GFP_FS);
if (err == -EEXIST)
goto repeat;
if (err == 0) {