<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">

Juggle dirty pages and dirty inodes and dirty superblocks and various
different writeback modes and livelock avoidance and fairness to recover from
the loss of mapping-&gt;io_pages.


---

 25-akpm/fs/fs-writeback.c |   50 +++++++++++++++++++++++++++++++++-------------
 1 files changed, 36 insertions(+), 14 deletions(-)

diff -puN fs/fs-writeback.c~kupdate-function-fix fs/fs-writeback.c
--- 25/fs/fs-writeback.c~kupdate-function-fix	2004-04-03 03:00:12.654307808 -0800
+++ 25-akpm/fs/fs-writeback.c	2004-04-03 03:00:12.657307352 -0800
@@ -147,12 +147,6 @@ __sync_single_inode(struct inode *inode,
 	inode-&gt;i_state |= I_LOCK;
 	inode-&gt;i_state &amp;= ~I_DIRTY;
 
-	/*
-	 * smp_rmb(); note: if you remove write_lock below, you must add this.
-	 * mark_inode_dirty doesn't take spinlock, make sure that inode is not
-	 * read speculatively by this cpu before &amp;= ~I_DIRTY  -- mikulas
-	 */
-
 	spin_unlock(&amp;inode_lock);
 
 	ret = do_writepages(mapping, wbc);
@@ -170,18 +164,46 @@ __sync_single_inode(struct inode *inode,
 	spin_lock(&amp;inode_lock);
 	inode-&gt;i_state &amp;= ~I_LOCK;
 	if (!(inode-&gt;i_state &amp; I_FREEING)) {
-		if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
-			/* Redirtied */
-			inode-&gt;i_state |= I_DIRTY_PAGES;
-			inode-&gt;dirtied_when = jiffies;
-			list_move(&amp;inode-&gt;i_list, &amp;sb-&gt;s_dirty);
+		if (!(inode-&gt;i_state &amp; I_DIRTY) &amp;&amp;
+		    mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+			/*
+			 * We didn't write back all the pages.  Redirty the
+			 * inode.  It is still on sb-&gt;s_dirty.
+			 */
+			if (wbc-&gt;for_kupdate) {
+				/*
+				 * For the kupdate function we leave the inode
+				 * where it is on sb_dirty so it will get more
+				 * writeout as soon as the queue becomes
+				 * uncongested.
+				 */
+				inode-&gt;i_state |= I_DIRTY_PAGES;
+			} else {
+				/*
+				 * Otherwise fully redirty the inode so that
+				 * other inodes on this superblock will get some
+				 * writeout.  Otherwise heavy writing to one
+				 * file would indefinitely suspend writeout of
+				 * all the other files.
+				 */
+				inode-&gt;i_state |= I_DIRTY_PAGES;
+				inode-&gt;dirtied_when = jiffies;
+				list_move(&amp;inode-&gt;i_list, &amp;sb-&gt;s_dirty);
+			}
 		} else if (inode-&gt;i_state &amp; I_DIRTY) {
-			/* Redirtied */
-			inode-&gt;dirtied_when = jiffies;
-			list_move(&amp;inode-&gt;i_list, &amp;sb-&gt;s_dirty);
+			/*
+			 * Someone redirtied the inode while were writing back
+			 * the pages: nothing to do.
+			 */
 		} else if (atomic_read(&amp;inode-&gt;i_count)) {
+			/*
+			 * The inode is clean, inuse
+			 */
 			list_move(&amp;inode-&gt;i_list, &amp;inode_in_use);
 		} else {
+			/*
+			 * The inode is clean, unused
+			 */
 			list_move(&amp;inode-&gt;i_list, &amp;inode_unused);
 		}
 	}

_
</pre></body></html>