aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-04-15 13:22:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-16 10:47:49 -0400
commit35c80d5f400f68f2eccf3069d1c068e154bde9c9 (patch)
tree43dd3ebb3e654b1a1ed4210089b7dc27b1f516e9
parentf69955855eac55a048d26a1618f50dfaa160a006 (diff)
Add block_write_full_page_endio for passing endio handler
block_write_full_page doesn't allow the caller to control what happens when the IO is over. This adds a new call named block_write_full_page_endio so the buffer head end_io handler can be provided by the caller. This will be used by the ext3 data=guarded mode to do i_size updates in a workqueue based end_io handler. end_buffer_async_write is also exported so it can be called to do the dirty work of managing page writeback for the higher level end_io handler. Signed-off-by: Chris Mason <chris.mason@oracle.com> Acked-by: Theodore Tso <tytso@mit.edu> Acked-by: Jan Kara <jack@suse.cz> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/buffer.c45
-rw-r--r--include/linux/buffer_head.h3
2 files changed, 37 insertions, 11 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index ff8bb1f2333a..b3e5be7514f5 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -360,7 +360,7 @@ still_busy:
360 * Completion handler for block_write_full_page() - pages which are unlocked 360 * Completion handler for block_write_full_page() - pages which are unlocked
361 * during I/O, and which have PageWriteback cleared upon I/O completion. 361 * during I/O, and which have PageWriteback cleared upon I/O completion.
362 */ 362 */
363static void end_buffer_async_write(struct buffer_head *bh, int uptodate) 363void end_buffer_async_write(struct buffer_head *bh, int uptodate)
364{ 364{
365 char b[BDEVNAME_SIZE]; 365 char b[BDEVNAME_SIZE];
366 unsigned long flags; 366 unsigned long flags;
@@ -438,11 +438,17 @@ static void mark_buffer_async_read(struct buffer_head *bh)
438 set_buffer_async_read(bh); 438 set_buffer_async_read(bh);
439} 439}
440 440
441void mark_buffer_async_write(struct buffer_head *bh) 441void mark_buffer_async_write_endio(struct buffer_head *bh,
442 bh_end_io_t *handler)
442{ 443{
443 bh->b_end_io = end_buffer_async_write; 444 bh->b_end_io = handler;
444 set_buffer_async_write(bh); 445 set_buffer_async_write(bh);
445} 446}
447
448void mark_buffer_async_write(struct buffer_head *bh)
449{
450 mark_buffer_async_write_endio(bh, end_buffer_async_write);
451}
446EXPORT_SYMBOL(mark_buffer_async_write); 452EXPORT_SYMBOL(mark_buffer_async_write);
447 453
448 454
@@ -1615,7 +1621,8 @@ EXPORT_SYMBOL(unmap_underlying_metadata);
1615 * unplugging the device queue. 1621 * unplugging the device queue.
1616 */ 1622 */
1617static int __block_write_full_page(struct inode *inode, struct page *page, 1623static int __block_write_full_page(struct inode *inode, struct page *page,
1618 get_block_t *get_block, struct writeback_control *wbc) 1624 get_block_t *get_block, struct writeback_control *wbc,
1625 bh_end_io_t *handler)
1619{ 1626{
1620 int err; 1627 int err;
1621 sector_t block; 1628 sector_t block;
@@ -1700,7 +1707,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
1700 continue; 1707 continue;
1701 } 1708 }
1702 if (test_clear_buffer_dirty(bh)) { 1709 if (test_clear_buffer_dirty(bh)) {
1703 mark_buffer_async_write(bh); 1710 mark_buffer_async_write_endio(bh, handler);
1704 } else { 1711 } else {
1705 unlock_buffer(bh); 1712 unlock_buffer(bh);
1706 } 1713 }
@@ -1753,7 +1760,7 @@ recover:
1753 if (buffer_mapped(bh) && buffer_dirty(bh) && 1760 if (buffer_mapped(bh) && buffer_dirty(bh) &&
1754 !buffer_delay(bh)) { 1761 !buffer_delay(bh)) {
1755 lock_buffer(bh); 1762 lock_buffer(bh);
1756 mark_buffer_async_write(bh); 1763 mark_buffer_async_write_endio(bh, handler);
1757 } else { 1764 } else {
1758 /* 1765 /*
1759 * The buffer may have been set dirty during 1766 * The buffer may have been set dirty during
@@ -2679,7 +2686,8 @@ int nobh_writepage(struct page *page, get_block_t *get_block,
2679out: 2686out:
2680 ret = mpage_writepage(page, get_block, wbc); 2687 ret = mpage_writepage(page, get_block, wbc);
2681 if (ret == -EAGAIN) 2688 if (ret == -EAGAIN)
2682 ret = __block_write_full_page(inode, page, get_block, wbc); 2689 ret = __block_write_full_page(inode, page, get_block, wbc,
2690 end_buffer_async_write);
2683 return ret; 2691 return ret;
2684} 2692}
2685EXPORT_SYMBOL(nobh_writepage); 2693EXPORT_SYMBOL(nobh_writepage);
@@ -2837,9 +2845,10 @@ out:
2837 2845
2838/* 2846/*
2839 * The generic ->writepage function for buffer-backed address_spaces 2847 * The generic ->writepage function for buffer-backed address_spaces
2848 * this form passes in the end_io handler used to finish the IO.
2840 */ 2849 */
2841int block_write_full_page(struct page *page, get_block_t *get_block, 2850int block_write_full_page_endio(struct page *page, get_block_t *get_block,
2842 struct writeback_control *wbc) 2851 struct writeback_control *wbc, bh_end_io_t *handler)
2843{ 2852{
2844 struct inode * const inode = page->mapping->host; 2853 struct inode * const inode = page->mapping->host;
2845 loff_t i_size = i_size_read(inode); 2854 loff_t i_size = i_size_read(inode);
@@ -2848,7 +2857,8 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
2848 2857
2849 /* Is the page fully inside i_size? */ 2858 /* Is the page fully inside i_size? */
2850 if (page->index < end_index) 2859 if (page->index < end_index)
2851 return __block_write_full_page(inode, page, get_block, wbc); 2860 return __block_write_full_page(inode, page, get_block, wbc,
2861 handler);
2852 2862
2853 /* Is the page fully outside i_size? (truncate in progress) */ 2863 /* Is the page fully outside i_size? (truncate in progress) */
2854 offset = i_size & (PAGE_CACHE_SIZE-1); 2864 offset = i_size & (PAGE_CACHE_SIZE-1);
@@ -2871,9 +2881,20 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
2871 * writes to that region are not written out to the file." 2881 * writes to that region are not written out to the file."
2872 */ 2882 */
2873 zero_user_segment(page, offset, PAGE_CACHE_SIZE); 2883 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
2874 return __block_write_full_page(inode, page, get_block, wbc); 2884 return __block_write_full_page(inode, page, get_block, wbc, handler);
2875} 2885}
2876 2886
2887/*
2888 * The generic ->writepage function for buffer-backed address_spaces
2889 */
2890int block_write_full_page(struct page *page, get_block_t *get_block,
2891 struct writeback_control *wbc)
2892{
2893 return block_write_full_page_endio(page, get_block, wbc,
2894 end_buffer_async_write);
2895}
2896
2897
2877sector_t generic_block_bmap(struct address_space *mapping, sector_t block, 2898sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
2878 get_block_t *get_block) 2899 get_block_t *get_block)
2879{ 2900{
@@ -3342,9 +3363,11 @@ EXPORT_SYMBOL(block_read_full_page);
3342EXPORT_SYMBOL(block_sync_page); 3363EXPORT_SYMBOL(block_sync_page);
3343EXPORT_SYMBOL(block_truncate_page); 3364EXPORT_SYMBOL(block_truncate_page);
3344EXPORT_SYMBOL(block_write_full_page); 3365EXPORT_SYMBOL(block_write_full_page);
3366EXPORT_SYMBOL(block_write_full_page_endio);
3345EXPORT_SYMBOL(cont_write_begin); 3367EXPORT_SYMBOL(cont_write_begin);
3346EXPORT_SYMBOL(end_buffer_read_sync); 3368EXPORT_SYMBOL(end_buffer_read_sync);
3347EXPORT_SYMBOL(end_buffer_write_sync); 3369EXPORT_SYMBOL(end_buffer_write_sync);
3370EXPORT_SYMBOL(end_buffer_async_write);
3348EXPORT_SYMBOL(file_fsync); 3371EXPORT_SYMBOL(file_fsync);
3349EXPORT_SYMBOL(generic_block_bmap); 3372EXPORT_SYMBOL(generic_block_bmap);
3350EXPORT_SYMBOL(generic_cont_expand_simple); 3373EXPORT_SYMBOL(generic_cont_expand_simple);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 7b73bb8f1970..16ed0284d780 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -155,6 +155,7 @@ void create_empty_buffers(struct page *, unsigned long,
155 unsigned long b_state); 155 unsigned long b_state);
156void end_buffer_read_sync(struct buffer_head *bh, int uptodate); 156void end_buffer_read_sync(struct buffer_head *bh, int uptodate);
157void end_buffer_write_sync(struct buffer_head *bh, int uptodate); 157void end_buffer_write_sync(struct buffer_head *bh, int uptodate);
158void end_buffer_async_write(struct buffer_head *bh, int uptodate);
158 159
159/* Things to do with buffers at mapping->private_list */ 160/* Things to do with buffers at mapping->private_list */
160void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode); 161void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode);
@@ -197,6 +198,8 @@ extern int buffer_heads_over_limit;
197void block_invalidatepage(struct page *page, unsigned long offset); 198void block_invalidatepage(struct page *page, unsigned long offset);
198int block_write_full_page(struct page *page, get_block_t *get_block, 199int block_write_full_page(struct page *page, get_block_t *get_block,
199 struct writeback_control *wbc); 200 struct writeback_control *wbc);
201int block_write_full_page_endio(struct page *page, get_block_t *get_block,
202 struct writeback_control *wbc, bh_end_io_t *handler);
200int block_read_full_page(struct page*, get_block_t*); 203int block_read_full_page(struct page*, get_block_t*);
201int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, 204int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
202 unsigned long from); 205 unsigned long from);