diff options
-rw-r--r-- | fs/ext4/ext4.h | 3 | ||||
-rw-r--r-- | fs/ext4/inode.c | 6 | ||||
-rw-r--r-- | fs/ext4/page-io.c | 8 | ||||
-rw-r--r-- | include/linux/page-flags.h | 12 | ||||
-rw-r--r-- | mm/page-writeback.c | 11 |
5 files changed, 29 insertions, 11 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 1d08a1b51bdd..aeda5061a59a 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2772,7 +2772,8 @@ extern void ext4_io_submit(struct ext4_io_submit *io); | |||
2772 | extern int ext4_bio_write_page(struct ext4_io_submit *io, | 2772 | extern int ext4_bio_write_page(struct ext4_io_submit *io, |
2773 | struct page *page, | 2773 | struct page *page, |
2774 | int len, | 2774 | int len, |
2775 | struct writeback_control *wbc); | 2775 | struct writeback_control *wbc, |
2776 | bool keep_towrite); | ||
2776 | 2777 | ||
2777 | /* mmp.c */ | 2778 | /* mmp.c */ |
2778 | extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t); | 2779 | extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 9b3c52fbe86d..04dd2de10796 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1846,6 +1846,7 @@ static int ext4_writepage(struct page *page, | |||
1846 | struct buffer_head *page_bufs = NULL; | 1846 | struct buffer_head *page_bufs = NULL; |
1847 | struct inode *inode = page->mapping->host; | 1847 | struct inode *inode = page->mapping->host; |
1848 | struct ext4_io_submit io_submit; | 1848 | struct ext4_io_submit io_submit; |
1849 | bool keep_towrite = false; | ||
1849 | 1850 | ||
1850 | trace_ext4_writepage(page); | 1851 | trace_ext4_writepage(page); |
1851 | size = i_size_read(inode); | 1852 | size = i_size_read(inode); |
@@ -1876,6 +1877,7 @@ static int ext4_writepage(struct page *page, | |||
1876 | unlock_page(page); | 1877 | unlock_page(page); |
1877 | return 0; | 1878 | return 0; |
1878 | } | 1879 | } |
1880 | keep_towrite = true; | ||
1879 | } | 1881 | } |
1880 | 1882 | ||
1881 | if (PageChecked(page) && ext4_should_journal_data(inode)) | 1883 | if (PageChecked(page) && ext4_should_journal_data(inode)) |
@@ -1892,7 +1894,7 @@ static int ext4_writepage(struct page *page, | |||
1892 | unlock_page(page); | 1894 | unlock_page(page); |
1893 | return -ENOMEM; | 1895 | return -ENOMEM; |
1894 | } | 1896 | } |
1895 | ret = ext4_bio_write_page(&io_submit, page, len, wbc); | 1897 | ret = ext4_bio_write_page(&io_submit, page, len, wbc, keep_towrite); |
1896 | ext4_io_submit(&io_submit); | 1898 | ext4_io_submit(&io_submit); |
1897 | /* Drop io_end reference we got from init */ | 1899 | /* Drop io_end reference we got from init */ |
1898 | ext4_put_io_end_defer(io_submit.io_end); | 1900 | ext4_put_io_end_defer(io_submit.io_end); |
@@ -1911,7 +1913,7 @@ static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page) | |||
1911 | else | 1913 | else |
1912 | len = PAGE_CACHE_SIZE; | 1914 | len = PAGE_CACHE_SIZE; |
1913 | clear_page_dirty_for_io(page); | 1915 | clear_page_dirty_for_io(page); |
1914 | err = ext4_bio_write_page(&mpd->io_submit, page, len, mpd->wbc); | 1916 | err = ext4_bio_write_page(&mpd->io_submit, page, len, mpd->wbc, false); |
1915 | if (!err) | 1917 | if (!err) |
1916 | mpd->wbc->nr_to_write--; | 1918 | mpd->wbc->nr_to_write--; |
1917 | mpd->first_page++; | 1919 | mpd->first_page++; |
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index c18d95b50540..4cb2743cb2e3 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
@@ -401,7 +401,8 @@ submit_and_retry: | |||
401 | int ext4_bio_write_page(struct ext4_io_submit *io, | 401 | int ext4_bio_write_page(struct ext4_io_submit *io, |
402 | struct page *page, | 402 | struct page *page, |
403 | int len, | 403 | int len, |
404 | struct writeback_control *wbc) | 404 | struct writeback_control *wbc, |
405 | bool keep_towrite) | ||
405 | { | 406 | { |
406 | struct inode *inode = page->mapping->host; | 407 | struct inode *inode = page->mapping->host; |
407 | unsigned block_start, blocksize; | 408 | unsigned block_start, blocksize; |
@@ -414,7 +415,10 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
414 | BUG_ON(!PageLocked(page)); | 415 | BUG_ON(!PageLocked(page)); |
415 | BUG_ON(PageWriteback(page)); | 416 | BUG_ON(PageWriteback(page)); |
416 | 417 | ||
417 | set_page_writeback(page); | 418 | if (keep_towrite) |
419 | set_page_writeback_keepwrite(page); | ||
420 | else | ||
421 | set_page_writeback(page); | ||
418 | ClearPageError(page); | 422 | ClearPageError(page); |
419 | 423 | ||
420 | /* | 424 | /* |
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index d1fe1a761047..ca71a1d347a0 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h | |||
@@ -317,13 +317,23 @@ CLEARPAGEFLAG(Uptodate, uptodate) | |||
317 | extern void cancel_dirty_page(struct page *page, unsigned int account_size); | 317 | extern void cancel_dirty_page(struct page *page, unsigned int account_size); |
318 | 318 | ||
319 | int test_clear_page_writeback(struct page *page); | 319 | int test_clear_page_writeback(struct page *page); |
320 | int test_set_page_writeback(struct page *page); | 320 | int __test_set_page_writeback(struct page *page, bool keep_write); |
321 | |||
322 | #define test_set_page_writeback(page) \ | ||
323 | __test_set_page_writeback(page, false) | ||
324 | #define test_set_page_writeback_keepwrite(page) \ | ||
325 | __test_set_page_writeback(page, true) | ||
321 | 326 | ||
322 | static inline void set_page_writeback(struct page *page) | 327 | static inline void set_page_writeback(struct page *page) |
323 | { | 328 | { |
324 | test_set_page_writeback(page); | 329 | test_set_page_writeback(page); |
325 | } | 330 | } |
326 | 331 | ||
332 | static inline void set_page_writeback_keepwrite(struct page *page) | ||
333 | { | ||
334 | test_set_page_writeback_keepwrite(page); | ||
335 | } | ||
336 | |||
327 | #ifdef CONFIG_PAGEFLAGS_EXTENDED | 337 | #ifdef CONFIG_PAGEFLAGS_EXTENDED |
328 | /* | 338 | /* |
329 | * System with lots of page flags available. This allows separate | 339 | * System with lots of page flags available. This allows separate |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index ef413492a149..d8691d9de3c4 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -2398,7 +2398,7 @@ int test_clear_page_writeback(struct page *page) | |||
2398 | return ret; | 2398 | return ret; |
2399 | } | 2399 | } |
2400 | 2400 | ||
2401 | int test_set_page_writeback(struct page *page) | 2401 | int __test_set_page_writeback(struct page *page, bool keep_write) |
2402 | { | 2402 | { |
2403 | struct address_space *mapping = page_mapping(page); | 2403 | struct address_space *mapping = page_mapping(page); |
2404 | int ret; | 2404 | int ret; |
@@ -2423,9 +2423,10 @@ int test_set_page_writeback(struct page *page) | |||
2423 | radix_tree_tag_clear(&mapping->page_tree, | 2423 | radix_tree_tag_clear(&mapping->page_tree, |
2424 | page_index(page), | 2424 | page_index(page), |
2425 | PAGECACHE_TAG_DIRTY); | 2425 | PAGECACHE_TAG_DIRTY); |
2426 | radix_tree_tag_clear(&mapping->page_tree, | 2426 | if (!keep_write) |
2427 | page_index(page), | 2427 | radix_tree_tag_clear(&mapping->page_tree, |
2428 | PAGECACHE_TAG_TOWRITE); | 2428 | page_index(page), |
2429 | PAGECACHE_TAG_TOWRITE); | ||
2429 | spin_unlock_irqrestore(&mapping->tree_lock, flags); | 2430 | spin_unlock_irqrestore(&mapping->tree_lock, flags); |
2430 | } else { | 2431 | } else { |
2431 | ret = TestSetPageWriteback(page); | 2432 | ret = TestSetPageWriteback(page); |
@@ -2436,7 +2437,7 @@ int test_set_page_writeback(struct page *page) | |||
2436 | return ret; | 2437 | return ret; |
2437 | 2438 | ||
2438 | } | 2439 | } |
2439 | EXPORT_SYMBOL(test_set_page_writeback); | 2440 | EXPORT_SYMBOL(__test_set_page_writeback); |
2440 | 2441 | ||
2441 | /* | 2442 | /* |
2442 | * Return true if any of the pages in the mapping are marked with the | 2443 | * Return true if any of the pages in the mapping are marked with the |