Messages in this thread Patch in this message | | | Date | Tue, 17 Oct 2006 00:32:44 +1000 | From | Nick Piggin <> | Subject | Re: INFO: possible circular locking dependency detected |
| |
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) { | |