diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c new file mode 100644 index e5dec9d..d3028da *** a/src/backend/storage/smgr/md.c --- b/src/backend/storage/smgr/md.c *************** *** 59,64 **** --- 59,66 ---- #define FILE_POSSIBLY_DELETED(err) ((err) == ENOENT || (err) == EACCES) #endif + static bool mdsync_scan_in_progress = false; + /* * The magnetic disk storage manager keeps track of open file * descriptors in its own descriptor pool. This is done to make it *************** static MdfdVec *_mdfd_getseg(SMgrRelatio *** 176,181 **** --- 178,184 ---- BlockNumber blkno, bool skipFsync, ExtensionBehavior behavior); static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg); + static void _cancel_fsync(PendingOperationEntry *entry); /* *************** mdsync(void) *** 1010,1015 **** --- 1013,1021 ---- /* Set flag to detect failure if we don't reach the end of the loop */ mdsync_in_progress = true; + /* advice FORGET_*_FSYNC operations that they can't delete from the pendingOpsTable */ + mdsync_scan_in_progress = true; + /* Now scan the hashtable for fsync requests to process */ absorb_counter = FSYNCS_PER_ABSORB; hash_seq_init(&hstat, pendingOpsTable); *************** mdsync(void) *** 1125,1133 **** --- 1131,1142 ---- entry->tag.segno); if (!FILE_POSSIBLY_DELETED(errno) || failures > 0) + { + mdsync_scan_in_progress = false; ereport(ERROR, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", path))); + } else ereport(DEBUG1, (errcode_for_file_access(), *************** mdsync(void) *** 1163,1168 **** --- 1172,1178 ---- /* Flag successful completion of mdsync */ mdsync_in_progress = false; + mdsync_scan_in_progress = false; } /* *************** register_unlink(RelFileNodeBackend rnode *** 1328,1336 **** * - UNLINK_RELATION_REQUEST is a request to delete the file after the next * checkpoint. * ! * (Handling the FORGET_* requests is a tad slow because the hash table has * to be searched linearly, but it doesn't seem worth rethinking the table ! * structure for them.) */ void RememberFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum, --- 1338,1349 ---- * - UNLINK_RELATION_REQUEST is a request to delete the file after the next * checkpoint. * ! * Handling the FORGET_* requests is a tad slow because the hash table has * to be searched linearly, but it doesn't seem worth rethinking the table ! * structure for them. However, when it is safe to delete the entry ! * rather than mark it canceled, do so. This prevents excessive bloat ! * when relations are being created and dropped (or truncated) at a ! * prodigous rate. */ void RememberFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum, *************** RememberFsyncRequest(RelFileNodeBackend *** 1349,1358 **** { if (RelFileNodeBackendEquals(entry->tag.rnode, rnode) && entry->tag.forknum == forknum) ! { ! /* Okay, cancel this entry */ ! entry->canceled = true; ! } } } else if (segno == FORGET_DATABASE_FSYNC) --- 1362,1368 ---- { if (RelFileNodeBackendEquals(entry->tag.rnode, rnode) && entry->tag.forknum == forknum) ! _cancel_fsync(entry); } } else if (segno == FORGET_DATABASE_FSYNC) *************** RememberFsyncRequest(RelFileNodeBackend *** 1369,1378 **** while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL) { if (entry->tag.rnode.node.dbNode == rnode.node.dbNode) ! { ! /* Okay, cancel this entry */ ! entry->canceled = true; ! } } /* Remove unlink requests */ --- 1379,1385 ---- while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL) { if (entry->tag.rnode.node.dbNode == rnode.node.dbNode) ! _cancel_fsync(entry); } /* Remove unlink requests */ *************** _mdnblocks(SMgrRelation reln, ForkNumber *** 1670,1672 **** --- 1677,1694 ---- /* note that this calculation will ignore any partial block at EOF */ return (BlockNumber) (len / BLCKSZ); } + + static void + _cancel_fsync(PendingOperationEntry *entry) + { + /* When we are sure there is no other seq_scan going on, just delete the entry + * rather than marking it canceled + */ + if (mdsync_scan_in_progress) { + entry->canceled = true; + } else { + if (hash_search(pendingOpsTable, &entry->tag, + HASH_REMOVE, NULL) == NULL) + elog(ERROR, "pendingOpsTable corrupted"); + }; + };