diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 43a149e..0ce8e2b 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -143,8 +143,8 @@ typedef struct
 
 static BgWriterShmemStruct *BgWriterShmem;
 
-/* interval for calling AbsorbFsyncRequests in CheckpointWriteDelay */
-#define WRITES_PER_ABSORB		1000
+/* Fraction of fsync absorb queue that needs to be filled before acting */
+#define ABSORB_ACTION_DIVISOR	10
 
 /*
  * GUC parameters
@@ -382,7 +382,7 @@ BackgroundWriterMain(void)
 		/*
 		 * Process any requests or signals received recently.
 		 */
-		AbsorbFsyncRequests();
+		AbsorbFsyncRequests(false);
 
 		if (got_SIGHUP)
 		{
@@ -636,7 +636,7 @@ BgWriterNap(void)
 		(ckpt_active ? ImmediateCheckpointRequested() : checkpoint_requested))
 			break;
 		pg_usleep(1000000L);
-		AbsorbFsyncRequests();
+		AbsorbFsyncRequests(true);
 		udelay -= 1000000L;
 	}
 
@@ -684,8 +684,6 @@ ImmediateCheckpointRequested(void)
 void
 CheckpointWriteDelay(int flags, double progress)
 {
-	static int	absorb_counter = WRITES_PER_ABSORB;
-
 	/* Do nothing if checkpoint is being executed by non-bgwriter process */
 	if (!am_bg_writer)
 		return;
@@ -705,22 +703,65 @@ CheckpointWriteDelay(int flags, double progress)
 			ProcessConfigFile(PGC_SIGHUP);
 		}
 
-		AbsorbFsyncRequests();
-		absorb_counter = WRITES_PER_ABSORB;
+		AbsorbFsyncRequests(false);
 
 		BgBufferSync();
 		CheckArchiveTimeout();
 		BgWriterNap();
 	}
-	else if (--absorb_counter <= 0)
+	else
 	{
 		/*
-		 * Absorb pending fsync requests after each WRITES_PER_ABSORB write
-		 * operations even when we don't sleep, to prevent overflow of the
-		 * fsync request queue.
+		 * Check for overflow of the fsync request queue.
 		 */
-		AbsorbFsyncRequests();
-		absorb_counter = WRITES_PER_ABSORB;
+		AbsorbFsyncRequests(false);
+	}
+}
+
+/*
+ * CheckpointSyncDelay -- yield control to bgwriter during a checkpoint
+ *
+ * This function is called after each file sync performed by mdsync().
+ * It is responsible for keeping the bgwriter's normal activities in
+ * progress during a long checkpoint.
+ */
+void
+CheckpointSyncDelay(void)
+{
+	pg_time_t	now;
+ 	pg_time_t	sync_start_time;
+ 	int			sync_delay_secs;
+ 
+ 	/*
+ 	 * Delay after each sync, in seconds.  This could be a parameter.  But
+ 	 * since ideally this will be auto-tuning in the near future, not
+	 * assigning it a GUC setting yet.
+ 	 */
+#define EXTRA_SYNC_DELAY	3
+
+	/* Do nothing if checkpoint is being executed by non-bgwriter process */
+	if (!am_bg_writer)
+		return;
+
+ 	sync_start_time = (pg_time_t) time(NULL);
+
+	/*
+	 * Perform the usual bgwriter duties.
+	 */
+ 	for (;;)
+ 	{
+		AbsorbFsyncRequests(false);
+ 		BgBufferSync();
+ 		CheckArchiveTimeout();
+ 		BgWriterNap();
+ 
+ 		/*
+ 		 * Are we there yet?
+ 		 */
+ 		now = (pg_time_t) time(NULL);
+ 		sync_delay_secs = now - sync_start_time;
+ 		if (sync_delay_secs >= EXTRA_SYNC_DELAY)
+			break;
 	}
 }
 
@@ -1116,16 +1157,41 @@ ForwardFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
  * non-bgwriter processes, do nothing if not bgwriter.
  */
 void
-AbsorbFsyncRequests(void)
+AbsorbFsyncRequests(bool force)
 {
 	BgWriterRequest *requests = NULL;
 	BgWriterRequest *request;
 	int			n;
 
+	/* 
+	 * Divide the size of the request queue by this to determine when
+	 * absorption action needs to be taken.  Default here aims to empty the
+	 * queue whenever 1 / 10 = 10% of it is full.  If this isn't good enough,
+	 * you probably need to lower bgwriter_delay, rather than presume
+	 * this needs to be a tunable you can decrease.
+	 */
+	int			absorb_action_divisor = 10;
+
 	if (!am_bg_writer)
 		return;
 
 	/*
+	 * If the queue isn't very large, don't worry about absorbing yet.
+	 * Access integer counter without lock, to avoid queuing.
+	 */
+	if (!force && BgWriterShmem->num_requests < 
+			(BgWriterShmem->max_requests / ABSORB_ACTION_DIVISOR))
+	{	
+		if (BgWriterShmem->num_requests > 0)
+			elog(DEBUG1,"Absorb queue: %d fsync requests, not processing",
+				BgWriterShmem->num_requests);
+		return;
+	}
+
+	elog(DEBUG1,"Absorb queue: %d fsync requests, processing",
+		BgWriterShmem->num_requests);
+
+	/*
 	 * We have to PANIC if we fail to absorb all the pending requests (eg,
 	 * because our hashtable runs out of memory).  This is because the system
 	 * cannot run safely if we are unable to fsync what we have been told to
@@ -1167,4 +1233,9 @@ AbsorbFsyncRequests(void)
 		pfree(requests);
 
 	END_CRIT_SECTION();
+
+	/*
+	 * Send off activity statistics to the stats collector
+	 */
+	pgstat_send_bgwriter();
 }
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 7140b94..57066c4 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -36,9 +36,6 @@
  */
 #define DEBUG_FSYNC	1
 
-/* interval for calling AbsorbFsyncRequests in mdsync */
-#define FSYNCS_PER_ABSORB		10
-
 /* special values for the segno arg to RememberFsyncRequest */
 #define FORGET_RELATION_FSYNC	(InvalidBlockNumber)
 #define FORGET_DATABASE_FSYNC	(InvalidBlockNumber-1)
@@ -931,7 +928,6 @@ mdsync(void)
 
 	HASH_SEQ_STATUS hstat;
 	PendingOperationEntry *entry;
-	int			absorb_counter;
 
 #ifdef DEBUG_FSYNC
 	/* Statistics on sync times */
@@ -958,7 +954,7 @@ mdsync(void)
 	 * queued an fsync request before clearing the buffer's dirtybit, so we
 	 * are safe as long as we do an Absorb after completing BufferSync().
 	 */
-	AbsorbFsyncRequests();
+	AbsorbFsyncRequests(true);
 
 	/*
 	 * To avoid excess fsync'ing (in the worst case, maybe a never-terminating
@@ -1001,7 +997,6 @@ mdsync(void)
 	mdsync_in_progress = true;
 
 	/* Now scan the hashtable for fsync requests to process */
-	absorb_counter = FSYNCS_PER_ABSORB;
 	hash_seq_init(&hstat, pendingOpsTable);
 	while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
 	{
@@ -1026,17 +1021,9 @@ mdsync(void)
 			int			failures;
 
 			/*
-			 * If in bgwriter, we want to absorb pending requests every so
-			 * often to prevent overflow of the fsync request queue.  It is
-			 * unspecified whether newly-added entries will be visited by
-			 * hash_seq_search, but we don't care since we don't need to
-			 * process them anyway.
+			 * If in bgwriter, perform normal duties.
 			 */
-			if (--absorb_counter <= 0)
-			{
-				AbsorbFsyncRequests();
-				absorb_counter = FSYNCS_PER_ABSORB;
-			}
+			CheckpointSyncDelay();
 
 			/*
 			 * The fsync table could contain requests to fsync segments that
@@ -1131,10 +1118,9 @@ mdsync(void)
 				pfree(path);
 
 				/*
-				 * Absorb incoming requests and check to see if canceled.
+				 * If in bgwriter, perform normal duties.
 				 */
-				AbsorbFsyncRequests();
-				absorb_counter = FSYNCS_PER_ABSORB;		/* might as well... */
+				CheckpointSyncDelay();
 
 				if (entry->canceled)
 					break;
diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h
index e251da6..4939604 100644
--- a/src/include/postmaster/bgwriter.h
+++ b/src/include/postmaster/bgwriter.h
@@ -26,10 +26,11 @@ extern void BackgroundWriterMain(void);
 
 extern void RequestCheckpoint(int flags);
 extern void CheckpointWriteDelay(int flags, double progress);
+extern void CheckpointSyncDelay(void);
 
 extern bool ForwardFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
 					BlockNumber segno);
-extern void AbsorbFsyncRequests(void);
+extern void AbsorbFsyncRequests(bool force);
 
 extern Size BgWriterShmemSize(void);
 extern void BgWriterShmemInit(void);
