Pass struct wb_writeback_work all the way down to writeback_sb_inodes(),and initialize the struct writeback_control there.

struct writeback_control is basically designed to control writeback of asingle file, but we keep abuse it for writing multiple files inwriteback_sb_inodes() and its callers.

It immediately clean things up, e.g. suddenly wbc.nr_to_write vswork->nr_pages starts to make sense, and instead of saving and restoringpages_skipped in writeback_sb_inodes it can always start with a cleanzero value.

It also makes a neat IO pattern change: large dirty files are nowwritten in the full 4MB writeback chunk size, rather than whateverremained quota in wbc->nr_to_write.

/*+ * The maximum number of pages to writeout in a single bdi flush/kupdate+ * operation. We do this so we don't hold I_SYNC against an inode for+ * enormous amounts of time, which would block a userspace task which has+ * been forced to throttle against that inode. Also, the code reevaluates+ * the dirty each time it has written this many pages.+ */+#define MAX_WRITEBACK_PAGES 1024L++/* * Passed into wb_writeback(), essentially a subset of writeback_control */ struct wb_writeback_work { long nr_pages; struct super_block *sb;+ unsigned long *older_than_this; enum writeback_sync_modes sync_mode; unsigned int tagged_writepages:1; unsigned int for_kupdate:1;@@ -472,7 +482,6 @@ writeback_single_inode(struct inode *ino * No need to add it back to the LRU. */ list_del_init(&inode->i_wb_list);- wbc->inodes_written++; } } inode_sync_complete(inode);@@ -506,6 +515,31 @@ static bool pin_sb_for_writeback(struct return false; }

if (inode->i_sb != sb) {- if (only_this_sb) {+ if (work->sb) { /* * We only want to write back data for this * superblock, move all inodes not belonging@@ -539,7 +585,7 @@ static int writeback_sb_inodes(struct su * Bounce back to the caller to unpin this and * pin the next superblock. */- return 0;+ break; }

-/*- * The maximum number of pages to writeout in a single bdi flush/kupdate- * operation. We do this so we don't hold I_SYNC against an inode for- * enormous amounts of time, which would block a userspace task which has- * been forced to throttle against that inode. Also, the code reevaluates- * the dirty each time it has written this many pages.- */-#define MAX_WRITEBACK_PAGES 1024+ return nr_pages - work.nr_pages;+}