Hisashi Hifumi 6ccfa806a9 VFS: fix dio write returning EIO when try_to_release_page fails
Dio write returns EIO when try_to_release_page fails because bh is
still referenced.

The patch

    commit 3f31fddfa26b7594b44ff2b34f9a04ba409e0f91
    Author: Mingming Cao <cmm@us.ibm.com>
    Date:   Fri Jul 25 01:46:22 2008 -0700

        jbd: fix race between free buffer and commit transaction

was merged into 2.6.27-rc1, but I noticed that this patch is not enough
to fix the race.

I did fsstress test heavily to 2.6.27-rc1, and found that dio write still
sometimes got EIO through this test.

The patch above fixed race between freeing buffer(dio) and committing
transaction(jbd) but I discovered that there is another race, freeing
buffer(dio) and ext3/4_ordered_writepage.

: background_writeout()
     ->write_cache_pages()
       ->ext3_ordered_writepage()
     	   walk_page_buffers() -> take a bh ref
 	   block_write_full_page() -> unlock_page
		: <- end_page_writeback
                : <- race! (dio write->try_to_release_page fails)
      	   walk_page_buffers() ->release a bh ref

ext3_ordered_writepage holds bh ref and does unlock_page remaining
taking a bh ref, so this causes the race and failure of
try_to_release_page.

To fix this race, I used the approach of falling back to buffered
writes if try_to_release_page() fails on a page.

[akpm@linux-foundation.org: cleanups]
Signed-off-by: Hisashi Hifumi <hifumi.hisashi@oss.ntt.co.jp>
Cc: Chris Mason <chris.mason@oracle.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Mingming Cao <cmm@us.ibm.com>
Cc: Zach Brown <zach.brown@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-09-02 19:21:37 -07:00
..
2008-07-28 16:30:21 -07:00
2008-07-19 22:39:46 -07:00
2008-07-24 10:47:17 -07:00
2008-07-28 16:30:21 -07:00
2008-08-04 21:31:34 -07:00
2007-10-20 01:27:18 +02:00
2008-08-04 21:31:34 -07:00
2008-04-28 08:58:18 -07:00
2008-08-04 16:58:45 -07:00
2008-07-28 16:30:21 -07:00
2008-07-28 16:30:21 -07:00
2008-07-28 16:30:21 -07:00
2007-05-21 09:18:19 -07:00
2008-08-04 16:01:47 +09:00
2008-02-05 09:44:19 -08:00
2008-07-26 12:00:06 -07:00
2008-06-12 18:05:41 -07:00
2007-10-20 01:27:18 +02:00
2008-07-26 12:00:06 -07:00
2008-08-20 15:40:32 -07:00
2008-08-04 21:31:34 -07:00
2008-07-29 23:44:26 +03:00
2008-07-29 23:44:26 +03:00
2008-07-04 10:40:04 -07:00
2008-08-20 15:40:30 -07:00
2008-08-04 21:31:34 -07:00
2008-08-04 21:31:34 -07:00
2008-07-26 12:00:07 -07:00
2008-08-04 21:31:34 -07:00