aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4.h3
-rw-r--r--fs/ext4/inode.c6
-rw-r--r--fs/ext4/page-io.c8
-rw-r--r--include/linux/page-flags.h12
-rw-r--r--mm/page-writeback.c11
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);
2772extern int ext4_bio_write_page(struct ext4_io_submit *io, 2772extern 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 */
2778extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t); 2779extern 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:
401int ext4_bio_write_page(struct ext4_io_submit *io, 401int 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)
317extern void cancel_dirty_page(struct page *page, unsigned int account_size); 317extern void cancel_dirty_page(struct page *page, unsigned int account_size);
318 318
319int test_clear_page_writeback(struct page *page); 319int test_clear_page_writeback(struct page *page);
320int test_set_page_writeback(struct page *page); 320int __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
322static inline void set_page_writeback(struct page *page) 327static 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
332static 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
2401int test_set_page_writeback(struct page *page) 2401int __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}
2439EXPORT_SYMBOL(test_set_page_writeback); 2440EXPORT_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