Commit 8227b297 authored by Ryusuke Konishi's avatar Ryusuke Konishi

nilfs2: fix hang problem of log writer which occurs after write failures

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: default avatarLeandro Lucarella <llucax@gmail.com>
Signed-off-by: default avatarRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Cc: stable@kernel.org
parent 0cfae3d8
...@@ -1836,19 +1836,6 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci, ...@@ -1836,19 +1836,6 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci,
return 0; 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) static void __nilfs_end_page_io(struct page *page, int err)
{ {
if (!err) { if (!err) {
...@@ -1872,12 +1859,11 @@ static void nilfs_end_page_io(struct page *page, int err) ...@@ -1872,12 +1859,11 @@ static void nilfs_end_page_io(struct page *page, int err)
if (!page) if (!page)
return; return;
if (buffer_nilfs_node(page_buffers(page)) && if (buffer_nilfs_node(page_buffers(page)) && !PageWriteback(page))
nilfs_page_has_uncleared_buffer(page)) /*
/* For b-tree node pages, this function may be called twice * For b-tree node pages, this function may be called twice
or more because they might be split in a segment. * 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. */
return; return;
__nilfs_end_page_io(page, err); __nilfs_end_page_io(page, err);
...@@ -1940,7 +1926,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, ...@@ -1940,7 +1926,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci,
} }
if (bh->b_page != fs_page) { if (bh->b_page != fs_page) {
nilfs_end_page_io(fs_page, err); nilfs_end_page_io(fs_page, err);
if (unlikely(fs_page == failed_page)) if (fs_page && fs_page == failed_page)
goto done; goto done;
fs_page = bh->b_page; fs_page = bh->b_page;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment