|
@@ -39,13 +39,18 @@
|
|
|
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 */
|
|
@@ -246,10 +251,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++;
|
|
@@ -733,6 +738,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);
|
|
@@ -791,12 +798,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 (;;) {
|
|
@@ -830,10 +838,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))
|
|
@@ -1345,18 +1353,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,
|