aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fs-writeback.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fs-writeback.c')
-rw-r--r--fs/fs-writeback.c48
1 files changed, 20 insertions, 28 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 1f4a10ece2f1..d754e3cf99a8 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -40,18 +40,13 @@
40struct wb_writeback_work { 40struct wb_writeback_work {
41 long nr_pages; 41 long nr_pages;
42 struct super_block *sb; 42 struct super_block *sb;
43 /* 43 unsigned long *older_than_this;
44 * Write only inodes dirtied before this time. Don't forget to set
45 * older_than_this_is_set when you set this.
46 */
47 unsigned long older_than_this;
48 enum writeback_sync_modes sync_mode; 44 enum writeback_sync_modes sync_mode;
49 unsigned int tagged_writepages:1; 45 unsigned int tagged_writepages:1;
50 unsigned int for_kupdate:1; 46 unsigned int for_kupdate:1;
51 unsigned int range_cyclic:1; 47 unsigned int range_cyclic:1;
52 unsigned int for_background:1; 48 unsigned int for_background:1;
53 unsigned int for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ 49 unsigned int for_sync:1; /* sync(2) WB_SYNC_ALL writeback */
54 unsigned int older_than_this_is_set:1;
55 enum wb_reason reason; /* why was writeback initiated? */ 50 enum wb_reason reason; /* why was writeback initiated? */
56 51
57 struct list_head list; /* pending work list */ 52 struct list_head list; /* pending work list */
@@ -252,10 +247,10 @@ static int move_expired_inodes(struct list_head *delaying_queue,
252 int do_sb_sort = 0; 247 int do_sb_sort = 0;
253 int moved = 0; 248 int moved = 0;
254 249
255 WARN_ON_ONCE(!work->older_than_this_is_set);
256 while (!list_empty(delaying_queue)) { 250 while (!list_empty(delaying_queue)) {
257 inode = wb_inode(delaying_queue->prev); 251 inode = wb_inode(delaying_queue->prev);
258 if (inode_dirtied_after(inode, work->older_than_this)) 252 if (work->older_than_this &&
253 inode_dirtied_after(inode, *work->older_than_this))
259 break; 254 break;
260 list_move(&inode->i_wb_list, &tmp); 255 list_move(&inode->i_wb_list, &tmp);
261 moved++; 256 moved++;
@@ -516,13 +511,16 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
516 } 511 }
517 WARN_ON(inode->i_state & I_SYNC); 512 WARN_ON(inode->i_state & I_SYNC);
518 /* 513 /*
519 * Skip inode if it is clean. We don't want to mess with writeback 514 * Skip inode if it is clean and we have no outstanding writeback in
520 * lists in this function since flusher thread may be doing for example 515 * WB_SYNC_ALL mode. We don't want to mess with writeback lists in this
521 * sync in parallel and if we move the inode, it could get skipped. So 516 * function since flusher thread may be doing for example sync in
522 * here we make sure inode is on some writeback list and leave it there 517 * parallel and if we move the inode, it could get skipped. So here we
523 * unless we have completely cleaned the inode. 518 * make sure inode is on some writeback list and leave it there unless
519 * we have completely cleaned the inode.
524 */ 520 */
525 if (!(inode->i_state & I_DIRTY)) 521 if (!(inode->i_state & I_DIRTY) &&
522 (wbc->sync_mode != WB_SYNC_ALL ||
523 !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
526 goto out; 524 goto out;
527 inode->i_state |= I_SYNC; 525 inode->i_state |= I_SYNC;
528 spin_unlock(&inode->i_lock); 526 spin_unlock(&inode->i_lock);
@@ -739,8 +737,6 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages,
739 .sync_mode = WB_SYNC_NONE, 737 .sync_mode = WB_SYNC_NONE,
740 .range_cyclic = 1, 738 .range_cyclic = 1,
741 .reason = reason, 739 .reason = reason,
742 .older_than_this = jiffies,
743 .older_than_this_is_set = 1,
744 }; 740 };
745 741
746 spin_lock(&wb->list_lock); 742 spin_lock(&wb->list_lock);
@@ -799,13 +795,12 @@ static long wb_writeback(struct bdi_writeback *wb,
799{ 795{
800 unsigned long wb_start = jiffies; 796 unsigned long wb_start = jiffies;
801 long nr_pages = work->nr_pages; 797 long nr_pages = work->nr_pages;
798 unsigned long oldest_jif;
802 struct inode *inode; 799 struct inode *inode;
803 long progress; 800 long progress;
804 801
805 if (!work->older_than_this_is_set) { 802 oldest_jif = jiffies;
806 work->older_than_this = jiffies; 803 work->older_than_this = &oldest_jif;
807 work->older_than_this_is_set = 1;
808 }
809 804
810 spin_lock(&wb->list_lock); 805 spin_lock(&wb->list_lock);
811 for (;;) { 806 for (;;) {
@@ -839,10 +834,10 @@ static long wb_writeback(struct bdi_writeback *wb,
839 * safe. 834 * safe.
840 */ 835 */
841 if (work->for_kupdate) { 836 if (work->for_kupdate) {
842 work->older_than_this = jiffies - 837 oldest_jif = jiffies -
843 msecs_to_jiffies(dirty_expire_interval * 10); 838 msecs_to_jiffies(dirty_expire_interval * 10);
844 } else if (work->for_background) 839 } else if (work->for_background)
845 work->older_than_this = jiffies; 840 oldest_jif = jiffies;
846 841
847 trace_writeback_start(wb->bdi, work); 842 trace_writeback_start(wb->bdi, work);
848 if (list_empty(&wb->b_io)) 843 if (list_empty(&wb->b_io))
@@ -1354,21 +1349,18 @@ EXPORT_SYMBOL(try_to_writeback_inodes_sb);
1354 1349
1355/** 1350/**
1356 * sync_inodes_sb - sync sb inode pages 1351 * sync_inodes_sb - sync sb inode pages
1357 * @sb: the superblock 1352 * @sb: the superblock
1358 * @older_than_this: timestamp
1359 * 1353 *
1360 * This function writes and waits on any dirty inode belonging to this 1354 * This function writes and waits on any dirty inode belonging to this
1361 * superblock that has been dirtied before given timestamp. 1355 * super_block.
1362 */ 1356 */
1363void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this) 1357void sync_inodes_sb(struct super_block *sb)
1364{ 1358{
1365 DECLARE_COMPLETION_ONSTACK(done); 1359 DECLARE_COMPLETION_ONSTACK(done);
1366 struct wb_writeback_work work = { 1360 struct wb_writeback_work work = {
1367 .sb = sb, 1361 .sb = sb,
1368 .sync_mode = WB_SYNC_ALL, 1362 .sync_mode = WB_SYNC_ALL,
1369 .nr_pages = LONG_MAX, 1363 .nr_pages = LONG_MAX,
1370 .older_than_this = older_than_this,
1371 .older_than_this_is_set = 1,
1372 .range_cyclic = 0, 1364 .range_cyclic = 0,
1373 .done = &done, 1365 .done = &done,
1374 .reason = WB_REASON_SYNC, 1366 .reason = WB_REASON_SYNC,