Merge branch 'akpm' (patches from Andrew Morton)
[cascardo/linux.git] / fs / fs-writeback.c
index 09c1132..1f4a10e 100644 (file)
 struct wb_writeback_work {
        long nr_pages;
        struct super_block *sb;
-       unsigned long *older_than_this;
+       /*
+        * Write only inodes dirtied before this time. Don't forget to set
+        * older_than_this_is_set when you set this.
+        */
+       unsigned long older_than_this;
        enum writeback_sync_modes sync_mode;
        unsigned int tagged_writepages:1;
        unsigned int for_kupdate:1;
        unsigned int range_cyclic:1;
        unsigned int for_background:1;
        unsigned int for_sync:1;        /* sync(2) WB_SYNC_ALL writeback */
+       unsigned int older_than_this_is_set:1;
        enum wb_reason reason;          /* why was writeback initiated? */
 
        struct list_head list;          /* pending work list */
@@ -247,10 +252,10 @@ static int move_expired_inodes(struct list_head *delaying_queue,
        int do_sb_sort = 0;
        int moved = 0;
 
+       WARN_ON_ONCE(!work->older_than_this_is_set);
        while (!list_empty(delaying_queue)) {
                inode = wb_inode(delaying_queue->prev);
-               if (work->older_than_this &&
-                   inode_dirtied_after(inode, *work->older_than_this))
+               if (inode_dirtied_after(inode, work->older_than_this))
                        break;
                list_move(&inode->i_wb_list, &tmp);
                moved++;
@@ -734,6 +739,8 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages,
                .sync_mode      = WB_SYNC_NONE,
                .range_cyclic   = 1,
                .reason         = reason,
+               .older_than_this = jiffies,
+               .older_than_this_is_set = 1,
        };
 
        spin_lock(&wb->list_lock);
@@ -792,12 +799,13 @@ static long wb_writeback(struct bdi_writeback *wb,
 {
        unsigned long wb_start = jiffies;
        long nr_pages = work->nr_pages;
-       unsigned long oldest_jif;
        struct inode *inode;
        long progress;
 
-       oldest_jif = jiffies;
-       work->older_than_this = &oldest_jif;
+       if (!work->older_than_this_is_set) {
+               work->older_than_this = jiffies;
+               work->older_than_this_is_set = 1;
+       }
 
        spin_lock(&wb->list_lock);
        for (;;) {
@@ -831,10 +839,10 @@ static long wb_writeback(struct bdi_writeback *wb,
                 * safe.
                 */
                if (work->for_kupdate) {
-                       oldest_jif = jiffies -
+                       work->older_than_this = jiffies -
                                msecs_to_jiffies(dirty_expire_interval * 10);
                } else if (work->for_background)
-                       oldest_jif = jiffies;
+                       work->older_than_this = jiffies;
 
                trace_writeback_start(wb->bdi, work);
                if (list_empty(&wb->b_io))
@@ -1346,18 +1354,21 @@ EXPORT_SYMBOL(try_to_writeback_inodes_sb);
 
 /**
  * sync_inodes_sb      -       sync sb inode pages
- * @sb: the superblock
+ * @sb:                        the superblock
+ * @older_than_this:   timestamp
  *
  * This function writes and waits on any dirty inode belonging to this
- * super_block.
+ * superblock that has been dirtied before given timestamp.
  */
-void sync_inodes_sb(struct super_block *sb)
+void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this)
 {
        DECLARE_COMPLETION_ONSTACK(done);
        struct wb_writeback_work work = {
                .sb             = sb,
                .sync_mode      = WB_SYNC_ALL,
                .nr_pages       = LONG_MAX,
+               .older_than_this = older_than_this,
+               .older_than_this_is_set = 1,
                .range_cyclic   = 0,
                .done           = &done,
                .reason         = WB_REASON_SYNC,