aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorCurt Wohlgemuth <curtw@google.com>2012-03-05 10:40:15 -0500
committerTheodore Ts'o <tytso@mit.edu>2012-03-05 10:40:15 -0500
commitb43d17f319f2c502b17139d1cf70731b2b62c644 (patch)
tree05215b2155e4dbc66f6b1035b8afba7c805284db /fs/ext4
parent491caa43639abcffaa645fbab372a7ef4ce2975c (diff)
ext4: don't release page refs in ext4_end_bio()
We can clear PageWriteback on each page when the IO completes, but we can't release the references on the page until we convert any uninitialized extents. Without this patch, the use of the dioread_nolock mount option can break buffered writes, because extents may not be converted by the time a subsequent buffered read comes in; if the page is not in the page cache, a read will return zeros if the extent is still uninitialized. I tested this with a (temporary) patch that adds a call to msleep(1000) at the start of ext4_end_io_work(), to delay processing of each DIO-unwritten work queue item. With this msleep(), a simple workload of fallocate write fadvise read will fail without this patch, succeeds with it. Signed-off-by: Curt Wohlgemuth <curtw@google.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/page-io.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index dcdeef169a69..74cd1f7f1f88 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -60,7 +60,6 @@ void ext4_ioend_wait(struct inode *inode)
60static void put_io_page(struct ext4_io_page *io_page) 60static void put_io_page(struct ext4_io_page *io_page)
61{ 61{
62 if (atomic_dec_and_test(&io_page->p_count)) { 62 if (atomic_dec_and_test(&io_page->p_count)) {
63 end_page_writeback(io_page->p_page);
64 put_page(io_page->p_page); 63 put_page(io_page->p_page);
65 kmem_cache_free(io_page_cachep, io_page); 64 kmem_cache_free(io_page_cachep, io_page);
66 } 65 }
@@ -234,9 +233,9 @@ static void ext4_end_bio(struct bio *bio, int error)
234 } while (bh != head); 233 } while (bh != head);
235 } 234 }
236 235
237 put_io_page(io_end->pages[i]); 236 if (atomic_read(&io_end->pages[i]->p_count) == 1)
237 end_page_writeback(io_end->pages[i]->p_page);
238 } 238 }
239 io_end->num_io_pages = 0;
240 inode = io_end->inode; 239 inode = io_end->inode;
241 240
242 if (error) { 241 if (error) {
@@ -428,6 +427,8 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
428 * PageWriteback bit from the page to prevent the system from 427 * PageWriteback bit from the page to prevent the system from
429 * wedging later on. 428 * wedging later on.
430 */ 429 */
430 if (atomic_read(&io_page->p_count) == 1)
431 end_page_writeback(page);
431 put_io_page(io_page); 432 put_io_page(io_page);
432 return ret; 433 return ret;
433} 434}