From a089ac1d4cc696e7cba0ed441ba2560e0641589c Mon Sep 17 00:00:00 2001 From: dilip kumar Date: Wed, 29 Jun 2022 13:24:32 +0530 Subject: [PATCH v3 4/4] Don't delay removing Tombstone file until next checkpoint Currently, we can not remove the unused relfilenode until the next checkpoint because if we remove them immediately then there is a risk of reusing the same relfilenode for two different relations during single checkpoint due to Oid wraparound. Now as part of the previous patch set we have made relfilenode 56 bit wider and removed the risk of wraparound so now we don't need to wait till the next checkpoint for removing the unused relation file and we can clean them up on commit. --- src/backend/access/transam/xlog.c | 5 -- src/backend/storage/smgr/md.c | 58 ++++++---------------- src/backend/storage/sync/sync.c | 101 -------------------------------------- src/include/storage/sync.h | 2 - 4 files changed, 14 insertions(+), 152 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 302da4a..50ac3ea 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6644,11 +6644,6 @@ CreateCheckPoint(int flags) END_CRIT_SECTION(); /* - * Let smgr do post-checkpoint cleanup (eg, deleting old files). - */ - SyncPostCheckpoint(); - - /* * Update the average distance between checkpoints if the prior checkpoint * exists. */ diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 3998296..e8c1cfa 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -126,8 +126,6 @@ static void mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forkNum, static MdfdVec *mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior); static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg); -static void register_unlink_segment(RelFileLocatorBackend rlocator, ForkNumber forknum, - BlockNumber segno); static void register_forget_request(RelFileLocatorBackend rlocator, ForkNumber forknum, BlockNumber segno); static void _fdvec_resize(SMgrRelation reln, @@ -325,36 +323,25 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forkNum, bool isRedo) /* * Delete or truncate the first segment. */ - if (isRedo || forkNum != MAIN_FORKNUM || RelFileLocatorBackendIsTemp(rlocator)) + if (!RelFileLocatorBackendIsTemp(rlocator)) { - if (!RelFileLocatorBackendIsTemp(rlocator)) - { - /* Prevent other backends' fds from holding on to the disk space */ - ret = do_truncate(path); - - /* Forget any pending sync requests for the first segment */ - register_forget_request(rlocator, forkNum, 0 /* first seg */ ); - } - else - ret = 0; + /* Prevent other backends' fds from holding on to the disk space */ + ret = do_truncate(path); - /* Next unlink the file, unless it was already found to be missing */ - if (ret == 0 || errno != ENOENT) - { - ret = unlink(path); - if (ret < 0 && errno != ENOENT) - ereport(WARNING, - (errcode_for_file_access(), - errmsg("could not remove file \"%s\": %m", path))); - } + /* Forget any pending sync requests for the first segment */ + register_forget_request(rlocator, forkNum, 0 /* first seg */ ); } else - { - /* Prevent other backends' fds from holding on to the disk space */ - ret = do_truncate(path); + ret = 0; - /* Register request to unlink first segment later */ - register_unlink_segment(rlocator, forkNum, 0 /* first seg */ ); + /* Next unlink the file, unless it was already found to be missing */ + if (ret == 0 || errno != ENOENT) + { + ret = unlink(path); + if (ret < 0 && errno != ENOENT) + ereport(WARNING, + (errcode_for_file_access(), + errmsg("could not remove file \"%s\": %m", path))); } /* @@ -1002,23 +989,6 @@ register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg) } /* - * register_unlink_segment() -- Schedule a file to be deleted after next checkpoint - */ -static void -register_unlink_segment(RelFileLocatorBackend rlocator, ForkNumber forknum, - BlockNumber segno) -{ - FileTag tag; - - INIT_MD_FILETAG(tag, rlocator.locator, forknum, segno); - - /* Should never be used with temp relations */ - Assert(!RelFileLocatorBackendIsTemp(rlocator)); - - RegisterSyncRequest(&tag, SYNC_UNLINK_REQUEST, true /* retryOnError */ ); -} - -/* * register_forget_request() -- forget any fsyncs for a relation fork's segment */ static void diff --git a/src/backend/storage/sync/sync.c b/src/backend/storage/sync/sync.c index e1fb631..9a4a31c 100644 --- a/src/backend/storage/sync/sync.c +++ b/src/backend/storage/sync/sync.c @@ -201,92 +201,6 @@ SyncPreCheckpoint(void) } /* - * SyncPostCheckpoint() -- Do post-checkpoint work - * - * Remove any lingering files that can now be safely removed. - */ -void -SyncPostCheckpoint(void) -{ - int absorb_counter; - ListCell *lc; - - absorb_counter = UNLINKS_PER_ABSORB; - foreach(lc, pendingUnlinks) - { - PendingUnlinkEntry *entry = (PendingUnlinkEntry *) lfirst(lc); - char path[MAXPGPATH]; - - /* Skip over any canceled entries */ - if (entry->canceled) - continue; - - /* - * New entries are appended to the end, so if the entry is new we've - * reached the end of old entries. - * - * Note: if just the right number of consecutive checkpoints fail, we - * could be fooled here by cycle_ctr wraparound. However, the only - * consequence is that we'd delay unlinking for one more checkpoint, - * which is perfectly tolerable. - */ - if (entry->cycle_ctr == checkpoint_cycle_ctr) - break; - - /* Unlink the file */ - if (syncsw[entry->tag.handler].sync_unlinkfiletag(&entry->tag, - path) < 0) - { - /* - * There's a race condition, when the database is dropped at the - * same time that we process the pending unlink requests. If the - * DROP DATABASE deletes the file before we do, we will get ENOENT - * here. rmtree() also has to ignore ENOENT errors, to deal with - * the possibility that we delete the file first. - */ - if (errno != ENOENT) - ereport(WARNING, - (errcode_for_file_access(), - errmsg("could not remove file \"%s\": %m", path))); - } - - /* Mark the list entry as canceled, just in case */ - entry->canceled = true; - - /* - * As in ProcessSyncRequests, we don't want to stop absorbing fsync - * requests for a long time when there are many deletions to be done. - * We can safely call AbsorbSyncRequests() at this point in the loop. - */ - if (--absorb_counter <= 0) - { - AbsorbSyncRequests(); - absorb_counter = UNLINKS_PER_ABSORB; - } - } - - /* - * If we reached the end of the list, we can just remove the whole list - * (remembering to pfree all the PendingUnlinkEntry objects). Otherwise, - * we must keep the entries at or after "lc". - */ - if (lc == NULL) - { - list_free_deep(pendingUnlinks); - pendingUnlinks = NIL; - } - else - { - int ntodelete = list_cell_number(pendingUnlinks, lc); - - for (int i = 0; i < ntodelete; i++) - pfree(list_nth(pendingUnlinks, i)); - - pendingUnlinks = list_delete_first_n(pendingUnlinks, ntodelete); - } -} - -/* * ProcessSyncRequests() -- Process queued fsync requests. */ void @@ -532,21 +446,6 @@ RememberSyncRequest(const FileTag *ftag, SyncRequestType type) entry->canceled = true; } } - else if (type == SYNC_UNLINK_REQUEST) - { - /* Unlink request: put it in the linked list */ - MemoryContext oldcxt = MemoryContextSwitchTo(pendingOpsCxt); - PendingUnlinkEntry *entry; - - entry = palloc(sizeof(PendingUnlinkEntry)); - entry->tag = *ftag; - entry->cycle_ctr = checkpoint_cycle_ctr; - entry->canceled = false; - - pendingUnlinks = lappend(pendingUnlinks, entry); - - MemoryContextSwitchTo(oldcxt); - } else { /* Normal case: enter a request to fsync this segment */ diff --git a/src/include/storage/sync.h b/src/include/storage/sync.h index 049af87..2c0b812 100644 --- a/src/include/storage/sync.h +++ b/src/include/storage/sync.h @@ -23,7 +23,6 @@ typedef enum SyncRequestType { SYNC_REQUEST, /* schedule a call of sync function */ - SYNC_UNLINK_REQUEST, /* schedule a call of unlink function */ SYNC_FORGET_REQUEST, /* forget all calls for a tag */ SYNC_FILTER_REQUEST /* forget all calls satisfying match fn */ } SyncRequestType; @@ -57,7 +56,6 @@ typedef struct FileTag extern void InitSync(void); extern void SyncPreCheckpoint(void); -extern void SyncPostCheckpoint(void); extern void ProcessSyncRequests(void); extern void RememberSyncRequest(const FileTag *ftag, SyncRequestType type); extern bool RegisterSyncRequest(const FileTag *ftag, SyncRequestType type, -- 1.8.3.1