Skip to content

Commit

Permalink
nilfs2: fix hang problem of log writer which occurs after write failures
Browse files Browse the repository at this point in the history
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>
Cc: stable@kernel.org
  • Loading branch information
Ryusuke Konishi committed Jul 5, 2009
1 parent 0cfae3d commit 8227b29
Showing 1 changed file with 6 additions and 20 deletions.
26 changes: 6 additions & 20 deletions fs/nilfs2/segment.c
Original file line number Diff line number Diff line change
Expand Up @@ -1836,19 +1836,6 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci,
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) {
Expand All @@ -1872,12 +1859,11 @@ static void nilfs_end_page_io(struct page *page, int err)
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);
Expand Down Expand Up @@ -1940,7 +1926,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci,
}
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;
}
Expand Down

0 comments on commit 8227b29

Please sign in to comment.