diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/buffer.c | 45 |
1 files changed, 34 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 | */ |
| 363 | static void end_buffer_async_write(struct buffer_head *bh, int uptodate) | 363 | void 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 | ||
| 441 | void mark_buffer_async_write(struct buffer_head *bh) | 441 | void 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 | |||
| 448 | void mark_buffer_async_write(struct buffer_head *bh) | ||
| 449 | { | ||
| 450 | mark_buffer_async_write_endio(bh, end_buffer_async_write); | ||
| 451 | } | ||
| 446 | EXPORT_SYMBOL(mark_buffer_async_write); | 452 | EXPORT_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 | */ |
| 1617 | static int __block_write_full_page(struct inode *inode, struct page *page, | 1623 | static 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, | |||
| 2679 | out: | 2686 | out: |
| 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 | } |
| 2685 | EXPORT_SYMBOL(nobh_writepage); | 2693 | EXPORT_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 | */ |
| 2841 | int block_write_full_page(struct page *page, get_block_t *get_block, | 2850 | int 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 | */ | ||
| 2890 | int 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 | |||
| 2877 | sector_t generic_block_bmap(struct address_space *mapping, sector_t block, | 2898 | sector_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); | |||
| 3342 | EXPORT_SYMBOL(block_sync_page); | 3363 | EXPORT_SYMBOL(block_sync_page); |
| 3343 | EXPORT_SYMBOL(block_truncate_page); | 3364 | EXPORT_SYMBOL(block_truncate_page); |
| 3344 | EXPORT_SYMBOL(block_write_full_page); | 3365 | EXPORT_SYMBOL(block_write_full_page); |
| 3366 | EXPORT_SYMBOL(block_write_full_page_endio); | ||
| 3345 | EXPORT_SYMBOL(cont_write_begin); | 3367 | EXPORT_SYMBOL(cont_write_begin); |
| 3346 | EXPORT_SYMBOL(end_buffer_read_sync); | 3368 | EXPORT_SYMBOL(end_buffer_read_sync); |
| 3347 | EXPORT_SYMBOL(end_buffer_write_sync); | 3369 | EXPORT_SYMBOL(end_buffer_write_sync); |
| 3370 | EXPORT_SYMBOL(end_buffer_async_write); | ||
| 3348 | EXPORT_SYMBOL(file_fsync); | 3371 | EXPORT_SYMBOL(file_fsync); |
| 3349 | EXPORT_SYMBOL(generic_block_bmap); | 3372 | EXPORT_SYMBOL(generic_block_bmap); |
| 3350 | EXPORT_SYMBOL(generic_cont_expand_simple); | 3373 | EXPORT_SYMBOL(generic_cont_expand_simple); |
