diff -cpr HEAD/src/backend/storage/smgr/md.c fix_mdsync/src/backend/storage/smgr/md.c
*** HEAD/src/backend/storage/smgr/md.c	Mon Jan 22 13:08:11 2007
--- fix_mdsync/src/backend/storage/smgr/md.c	Mon Apr  9 13:27:50 2007
*************** typedef struct
*** 126,135 ****
--- 126,148 ----
  {
  	PendingOperationTag tag;	/* hash table key (must be first!) */
  	int			failures;		/* number of failed attempts to fsync */
+ 								/* or -1 if canceled */
+ 	uint32		counter;		/* counter incremented for each mdsync */
  } PendingOperationEntry;
  
  static HTAB *pendingOpsTable = NULL;
  
+ #define PendingOperationCancel(entry) \
+ 	do { (entry)->failures = -1; } while(0)
+ #define PendingOperationIsCanceled(entry) \
+ 	((entry)->failures < 0)
+ 
+ /*
+  * The mdsync counter will eventually wrap around, so we must use
+  * mdsyncCounterCompare to compare two counters.
+  */
+ static uint32	mdsyncCounter = 0;
+ #define mdsyncCounterCompare(lhs, rhs) ((int32) ((lhs) - (rhs)))
  
  typedef enum					/* behavior for mdopen & _mdfd_getseg */
  {
*************** mdsync(void)
*** 869,874 ****
--- 882,901 ----
  		elog(ERROR, "cannot sync without a pendingOpsTable");
  
  	/*
+ 	 * If we are in the bgwriter, the sync had better include all fsync
+ 	 * requests that were queued by backends before the checkpoint REDO
+ 	 * point was determined. We go that a little better by accepting all
+ 	 * requests queued up to the point where we start fsync'ing.
+ 	 */
+ 	AbsorbFsyncRequests();
+ 
+ 	/*
+ 	 * Increment mdsyncCounter and we only fsync entries that have smaller 
+ 	 * counter values than mdsyncCounter.
+ 	 */
+ 	mdsyncCounter++;
+ 
+ 	/*
  	 * The fsync table could contain requests to fsync relations that have
  	 * been deleted (unlinked) by the time we get to them.  Rather than
  	 * just hoping an ENOENT (or EACCES on Windows) error can be ignored,
*************** mdsync(void)
*** 885,898 ****
  
  		need_retry = false;
  
- 		/*
- 		 * If we are in the bgwriter, the sync had better include all fsync
- 		 * requests that were queued by backends before the checkpoint REDO
- 		 * point was determined. We go that a little better by accepting all
- 		 * requests queued up to the point where we start fsync'ing.
- 		 */
- 		AbsorbFsyncRequests();
- 
  		absorb_counter = FSYNCS_PER_ABSORB;
  		hash_seq_init(&hstat, pendingOpsTable);
  		while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
--- 912,917 ----
*************** mdsync(void)
*** 901,923 ****
  			 * If fsync is off then we don't have to bother opening the file
  			 * at all.  (We delay checking until this point so that changing
  			 * fsync on the fly behaves sensibly.)
  			 */
! 			if (enableFsync)
  			{
  				SMgrRelation reln;
  				MdfdVec    *seg;
  
  				/*
  				 * If in bgwriter, we want to absorb pending requests every so
! 				 * often to prevent overflow of the fsync request queue.  This
! 				 * could result in deleting the current entry out from under
! 				 * our hashtable scan, so the procedure is to fall out of the
! 				 * scan and start over from the top of the function.
  				 */
  				if (--absorb_counter <= 0)
  				{
! 					need_retry = true;
! 					break;
  				}
  
  				/*
--- 920,944 ----
  			 * If fsync is off then we don't have to bother opening the file
  			 * at all.  (We delay checking until this point so that changing
  			 * fsync on the fly behaves sensibly.)
+ 			 * We also merely remove the canceled pending operations.
  			 */
! 			if (enableFsync && !PendingOperationIsCanceled(entry))
  			{
  				SMgrRelation reln;
  				MdfdVec    *seg;
  
+ 				/* Skip entries added after we started this mdsync. */
+ 				if (mdsyncCounterCompare(entry->counter, mdsyncCounter) >= 0)
+ 					continue;
+ 
  				/*
  				 * If in bgwriter, we want to absorb pending requests every so
! 				 * often to prevent overflow of the fsync request queue.
  				 */
  				if (--absorb_counter <= 0)
  				{
! 					AbsorbFsyncRequests();
! 					absorb_counter = FSYNCS_PER_ABSORB;
  				}
  
  				/*
*************** mdsync(void)
*** 983,988 ****
--- 1004,1015 ----
  							HASH_REMOVE, NULL) == NULL)
  				elog(ERROR, "pendingOpsTable corrupted");
  		}
+ 
+ 		/*
+ 		 * Absorb pending requests for the next retry, especially we need to
+ 		 * see requests against recently droped relations.
+ 		 */
+ 		AbsorbFsyncRequests();
  	} while (need_retry);
  }
  
*************** register_dirty_segment(SMgrRelation reln
*** 1032,1037 ****
--- 1059,1066 ----
   * a whole database.  (These are a tad slow because the hash table has to be
   * searched linearly, but it doesn't seem worth rethinking the table structure
   * for them.)
+  * Notice that we don't actually delete FORGET entries here to avoid dangling
+  * references in linear search at mdsync.
   */
  void
  RememberFsyncRequest(RelFileNode rnode, BlockNumber segno)
*************** RememberFsyncRequest(RelFileNode rnode, 
*** 1048,1059 ****
  		while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
  		{
  			if (RelFileNodeEquals(entry->tag.rnode, rnode))
! 			{
! 				/* Okay, delete this entry */
! 				if (hash_search(pendingOpsTable, &entry->tag,
! 								HASH_REMOVE, NULL) == NULL)
! 					elog(ERROR, "pendingOpsTable corrupted");
! 			}
  		}
  	}
  	else if (segno == FORGET_DATABASE_FSYNC)
--- 1077,1083 ----
  		while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
  		{
  			if (RelFileNodeEquals(entry->tag.rnode, rnode))
! 				PendingOperationCancel(entry);
  		}
  	}
  	else if (segno == FORGET_DATABASE_FSYNC)
*************** RememberFsyncRequest(RelFileNode rnode, 
*** 1066,1077 ****
  		while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
  		{
  			if (entry->tag.rnode.dbNode == rnode.dbNode)
! 			{
! 				/* Okay, delete this entry */
! 				if (hash_search(pendingOpsTable, &entry->tag,
! 								HASH_REMOVE, NULL) == NULL)
! 					elog(ERROR, "pendingOpsTable corrupted");
! 			}
  		}
  	}
  	else
--- 1090,1096 ----
  		while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
  		{
  			if (entry->tag.rnode.dbNode == rnode.dbNode)
! 				PendingOperationCancel(entry);
  		}
  	}
  	else
*************** RememberFsyncRequest(RelFileNode rnode, 
*** 1090,1097 ****
  													  &key,
  													  HASH_ENTER,
  													  &found);
! 		if (!found)				/* new entry, so initialize it */
  			entry->failures = 0;
  	}
  }
  
--- 1109,1120 ----
  													  &key,
  													  HASH_ENTER,
  													  &found);
! 		if (!found || PendingOperationIsCanceled(entry))
! 		{
! 			/* new or recycled entry, so initialize it */
  			entry->failures = 0;
+ 			entry->counter = mdsyncCounter;
+ 		}
  	}
  }
  
