| From 8227b29722fdbac72357aae155d171a5c777670c Mon Sep 17 00:00:00 2001 |
| From: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> |
| Date: Thu, 18 Jun 2009 23:52:23 +0900 |
| Subject: nilfs2: fix hang problem of log writer which occurs after write failures |
| |
| From: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> |
| |
| commit 8227b29722fdbac72357aae155d171a5c777670c upstream. |
| |
| Leandro Lucarella gave me a report that nilfs gets stuck after its |
| write function fails. |
| |
| The problem turned out to be caused by bugs which leave writeback flag |
| on pages. This fixes the problem by ensuring to clear the writeback |
| flag in error path. |
| |
| Reported-by: Leandro Lucarella <llucax@gmail.com> |
| Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/nilfs2/segment.c | 26 ++++++-------------------- |
| 1 file changed, 6 insertions(+), 20 deletions(-) |
| |
| --- a/fs/nilfs2/segment.c |
| +++ b/fs/nilfs2/segment.c |
| @@ -1853,19 +1853,6 @@ static int nilfs_segctor_write(struct ni |
| return 0; |
| } |
| |
| -static int nilfs_page_has_uncleared_buffer(struct page *page) |
| -{ |
| - struct buffer_head *head, *bh; |
| - |
| - head = bh = page_buffers(page); |
| - do { |
| - if (buffer_dirty(bh) && !list_empty(&bh->b_assoc_buffers)) |
| - return 1; |
| - bh = bh->b_this_page; |
| - } while (bh != head); |
| - return 0; |
| -} |
| - |
| static void __nilfs_end_page_io(struct page *page, int err) |
| { |
| if (!err) { |
| @@ -1889,12 +1876,11 @@ static void nilfs_end_page_io(struct pag |
| if (!page) |
| return; |
| |
| - if (buffer_nilfs_node(page_buffers(page)) && |
| - nilfs_page_has_uncleared_buffer(page)) |
| - /* For b-tree node pages, this function may be called twice |
| - or more because they might be split in a segment. |
| - This check assures that cleanup has been done for all |
| - buffers in a split btnode page. */ |
| + if (buffer_nilfs_node(page_buffers(page)) && !PageWriteback(page)) |
| + /* |
| + * For b-tree node pages, this function may be called twice |
| + * or more because they might be split in a segment. |
| + */ |
| return; |
| |
| __nilfs_end_page_io(page, err); |
| @@ -1957,7 +1943,7 @@ static void nilfs_segctor_abort_write(st |
| } |
| if (bh->b_page != fs_page) { |
| nilfs_end_page_io(fs_page, err); |
| - if (unlikely(fs_page == failed_page)) |
| + if (fs_page && fs_page == failed_page) |
| goto done; |
| fs_page = bh->b_page; |
| } |