From 6eac4e69cf348fcce13e8d8d63196876bf80d730 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Tue, 2 Aug 2005 20:52:08 +0000
Subject: [PATCH] Tweak BgBufferSync() so that a persistent write error on a
 dirty buffer doesn't block the bgwriter from making progress writing out
 other buffers. This was a hard problem in the context of the ARC/2Q design,
 but it's trivial in the context of clock sweep ... just advance the sweep
 counter before we try to write not after.

---
 src/backend/postmaster/bgwriter.c   |  5 ++---
 src/backend/storage/buffer/bufmgr.c | 23 +++++++++++++++--------
 2 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index d826a6190de..f4158fc89a5 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.17 2005/06/30 00:00:51 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.18 2005/08/02 20:52:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -256,8 +256,7 @@ BackgroundWriterMain(void)
 		/*
 		 * Sleep at least 1 second after any error.  A write error is
 		 * likely to be repeated, and we don't want to be filling the
-		 * error logs as fast as we can.  (XXX think about ways to make
-		 * progress when the LRU dirty buffer cannot be written...)
+		 * error logs as fast as we can.
 		 */
 		pg_usleep(1000000L);
 	}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 1fe681e1aba..4fb16eb6145 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.189 2005/05/19 21:35:46 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.190 2005/08/02 20:52:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -903,6 +903,11 @@ BgBufferSync(void)
 	/*
 	 * This loop runs over all buffers, including pinned ones.  The
 	 * starting point advances through the buffer pool on successive calls.
+	 *
+	 * Note that we advance the static counter *before* trying to write.
+	 * This ensures that, if we have a persistent write failure on a dirty
+	 * buffer, we'll still be able to make progress writing other buffers.
+	 * (The bgwriter will catch the error and just call us again later.)
 	 */
 	if (bgwriter_all_percent > 0.0 && bgwriter_all_maxpages > 0)
 	{
@@ -911,12 +916,13 @@ BgBufferSync(void)
 
 		while (num_to_scan-- > 0)
 		{
-			if (SyncOneBuffer(buf_id1, false))
-				num_written++;
 			if (++buf_id1 >= NBuffers)
 				buf_id1 = 0;
-			if (num_written >= bgwriter_all_maxpages)
-				break;
+			if (SyncOneBuffer(buf_id1, false))
+			{
+				if (++num_written >= bgwriter_all_maxpages)
+					break;
+			}
 		}
 	}
 
@@ -934,11 +940,12 @@ BgBufferSync(void)
 		while (num_to_scan-- > 0)
 		{
 			if (SyncOneBuffer(buf_id2, true))
-				num_written++;
+			{
+				if (++num_written >= bgwriter_lru_maxpages)
+					break;
+			}
 			if (++buf_id2 >= NBuffers)
 				buf_id2 = 0;
-			if (num_written >= bgwriter_lru_maxpages)
-				break;
 		}
 	}
 }
-- 
GitLab