From 9776de96e51565286da25c74d6f631abc50c63ef Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Wed, 13 Aug 2014 12:58:16 -0400 Subject: [PATCH] FS-Cache: Timeout for releasepage() This is meant to avoid a recusive hang caused by underlying filesystem trying to grab a free page and causing a write-out. INFO: task kworker/u30:7:28375 blocked for more than 120 seconds. Not tainted 3.15.0-virtual #74 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. kworker/u30:7 D 0000000000000000 0 28375 2 0x00000000 Workqueue: fscache_operation fscache_op_work_func [fscache] ffff88000b147148 0000000000000046 0000000000000000 ffff88000b1471c8 ffff8807aa031820 0000000000014040 ffff88000b147fd8 0000000000014040 ffff880f0c50c860 ffff8807aa031820 ffff88000b147158 ffff88007be59cd0 Call Trace: [] schedule+0x29/0x70 [] __fscache_wait_on_page_write+0x55/0x90 [fscache] [] ? __wake_up_sync+0x20/0x20 [] __fscache_maybe_release_page+0x65/0x1e0 [fscache] [] ceph_releasepage+0x83/0x100 [ceph] [] ? anon_vma_fork+0x130/0x130 [] try_to_release_page+0x32/0x50 [] shrink_page_list+0x7e6/0x9d0 [] ? isolate_lru_pages.isra.73+0x78/0x1e0 [] shrink_inactive_list+0x252/0x4c0 [] shrink_lruvec+0x3e1/0x670 [] shrink_zone+0x3f/0x110 [] do_try_to_free_pages+0x1d6/0x450 [] ? zone_statistics+0x99/0xc0 [] try_to_free_pages+0xc4/0x180 [] __alloc_pages_nodemask+0x6b2/0xa60 [] ? __find_get_block+0xbe/0x250 [] ? wake_up_bit+0x2e/0x40 [] alloc_pages_current+0xb3/0x180 [] __page_cache_alloc+0xb7/0xd0 [] grab_cache_page_write_begin+0x7c/0xe0 [] ? ext4_mark_inode_dirty+0x82/0x220 [] ext4_da_write_begin+0x89/0x2d0 [] generic_perform_write+0xbe/0x1d0 [] ? update_time+0x81/0xc0 [] ? mnt_clone_write+0x12/0x30 [] __generic_file_aio_write+0x1ce/0x3f0 [] generic_file_aio_write+0x5e/0xe0 [] ext4_file_write+0x9f/0x410 [] ? ext4_file_open+0x66/0x180 [] do_sync_write+0x5a/0x90 [] cachefiles_write_page+0x149/0x430 [cachefiles] [] ? radix_tree_gang_lookup_tag+0x89/0xd0 [] fscache_write_op+0x222/0x3b0 [fscache] [] fscache_op_work_func+0x3a/0x100 [fscache] [] process_one_work+0x179/0x4a0 [] worker_thread+0x11b/0x370 [] ? manage_workers.isra.21+0x2e0/0x2e0 [] kthread+0xc9/0xe0 [] ? ftrace_raw_event_xen_mmu_release_ptpage+0x70/0x90 [] ? flush_kthread_worker+0xb0/0xb0 [] ret_from_fork+0x7c/0xb0 [] ? flush_kthread_worker+0xb0/0xb0 Signed-off-by: Milosz Tanski Signed-off-by: David Howells --- fs/fscache/page.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/fs/fscache/page.c b/fs/fscache/page.c index 85332b9d19d1..781ac7b0b53e 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c @@ -43,6 +43,19 @@ void __fscache_wait_on_page_write(struct fscache_cookie *cookie, struct page *pa } EXPORT_SYMBOL(__fscache_wait_on_page_write); +/* + * wait for a page to finish being written to the cache. Put a timeout here + * since we might be called recursively via parent fs. + */ +static +bool release_page_wait_timeout(struct fscache_cookie *cookie, struct page *page) +{ + wait_queue_head_t *wq = bit_waitqueue(&cookie->flags, 0); + + return wait_event_timeout(*wq, !__fscache_check_page_write(cookie, page), + HZ); +} + /* * decide whether a page can be released, possibly by cancelling a store to it * - we're allowed to sleep if __GFP_WAIT is flagged @@ -115,7 +128,10 @@ bool __fscache_maybe_release_page(struct fscache_cookie *cookie, } fscache_stat(&fscache_n_store_vmscan_wait); - __fscache_wait_on_page_write(cookie, page); + if (!release_page_wait_timeout(cookie, page)) + _debug("fscache writeout timeout page: %p{%lx}", + page, page->index); + gfp &= ~__GFP_WAIT; goto try_again; }