Commit 3072b7ba authored by Tom Lane's avatar Tom Lane

Send only one FORGET_RELATION_FSYNC request when dropping a relation.

We were sending one per fork, but a little bit of refactoring allows us
to send just one request with forknum == InvalidForkNumber.  This not only
reduces pressure on the shared-memory request queue, but saves repeated
traversals of the checkpointer's hash table.
parent a7a4add6
...@@ -166,6 +166,8 @@ typedef enum /* behavior for mdopen & _mdfd_getseg */ ...@@ -166,6 +166,8 @@ typedef enum /* behavior for mdopen & _mdfd_getseg */
} ExtensionBehavior; } ExtensionBehavior;
/* local routines */ /* local routines */
static void mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum,
bool isRedo);
static MdfdVec *mdopen(SMgrRelation reln, ForkNumber forknum, static MdfdVec *mdopen(SMgrRelation reln, ForkNumber forknum,
ExtensionBehavior behavior); ExtensionBehavior behavior);
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum,
...@@ -308,6 +310,9 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo) ...@@ -308,6 +310,9 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
* Note that we're passed a RelFileNodeBackend --- by the time this is called, * Note that we're passed a RelFileNodeBackend --- by the time this is called,
* there won't be an SMgrRelation hashtable entry anymore. * there won't be an SMgrRelation hashtable entry anymore.
* *
* forkNum can be a fork number to delete a specific fork, or InvalidForkNumber
* to delete all forks.
*
* For regular relations, we don't unlink the first segment file of the rel, * For regular relations, we don't unlink the first segment file of the rel,
* but just truncate it to zero length, and record a request to unlink it after * but just truncate it to zero length, and record a request to unlink it after
* the next checkpoint. Additional segments can be unlinked immediately, * the next checkpoint. Additional segments can be unlinked immediately,
...@@ -349,17 +354,32 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo) ...@@ -349,17 +354,32 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
void void
mdunlink(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo) mdunlink(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
{ {
char *path;
int ret;
/* /*
* We have to clean out any pending fsync requests for the doomed * We have to clean out any pending fsync requests for the doomed
* relation, else the next mdsync() will fail. There can't be any such * relation, else the next mdsync() will fail. There can't be any such
* requests for a temp relation, though. * requests for a temp relation, though. We can send just one request
* even when deleting multiple forks, since the fsync queuing code accepts
* the "InvalidForkNumber = all forks" convention.
*/ */
if (!RelFileNodeBackendIsTemp(rnode)) if (!RelFileNodeBackendIsTemp(rnode))
ForgetRelationFsyncRequests(rnode.node, forkNum); ForgetRelationFsyncRequests(rnode.node, forkNum);
/* Now do the per-fork work */
if (forkNum == InvalidForkNumber)
{
for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
mdunlinkfork(rnode, forkNum, isRedo);
}
else
mdunlinkfork(rnode, forkNum, isRedo);
}
static void
mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
{
char *path;
int ret;
path = relpath(rnode, forkNum); path = relpath(rnode, forkNum);
/* /*
...@@ -1340,7 +1360,8 @@ register_unlink(RelFileNodeBackend rnode) ...@@ -1340,7 +1360,8 @@ register_unlink(RelFileNodeBackend rnode)
* The range of possible segment numbers is way less than the range of * The range of possible segment numbers is way less than the range of
* BlockNumber, so we can reserve high values of segno for special purposes. * BlockNumber, so we can reserve high values of segno for special purposes.
* We define three: * We define three:
* - FORGET_RELATION_FSYNC means to cancel pending fsyncs for a relation * - FORGET_RELATION_FSYNC means to cancel pending fsyncs for a relation,
* either for one fork, or all forks if forknum is InvalidForkNumber
* - FORGET_DATABASE_FSYNC means to cancel pending fsyncs for a whole database * - FORGET_DATABASE_FSYNC means to cancel pending fsyncs for a whole database
* - UNLINK_RELATION_REQUEST is a request to delete the file after the next * - UNLINK_RELATION_REQUEST is a request to delete the file after the next
* checkpoint. * checkpoint.
...@@ -1356,7 +1377,7 @@ RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum, BlockNumber segno) ...@@ -1356,7 +1377,7 @@ RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
if (segno == FORGET_RELATION_FSYNC) if (segno == FORGET_RELATION_FSYNC)
{ {
/* Remove any pending requests for the entire relation */ /* Remove any pending requests for the relation (one or all forks) */
HASH_SEQ_STATUS hstat; HASH_SEQ_STATUS hstat;
PendingOperationEntry *entry; PendingOperationEntry *entry;
...@@ -1364,7 +1385,8 @@ RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum, BlockNumber segno) ...@@ -1364,7 +1385,8 @@ RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL) while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
{ {
if (RelFileNodeEquals(entry->tag.rnode, rnode) && if (RelFileNodeEquals(entry->tag.rnode, rnode) &&
entry->tag.forknum == forknum) (entry->tag.forknum == forknum ||
forknum == InvalidForkNumber))
{ {
/* Okay, cancel this entry */ /* Okay, cancel this entry */
entry->canceled = true; entry->canceled = true;
...@@ -1466,6 +1488,9 @@ RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum, BlockNumber segno) ...@@ -1466,6 +1488,9 @@ RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
/* /*
* ForgetRelationFsyncRequests -- forget any fsyncs for a relation fork * ForgetRelationFsyncRequests -- forget any fsyncs for a relation fork
*
* forknum == InvalidForkNumber means all forks, although this code doesn't
* actually know that, since it's just forwarding the request elsewhere.
*/ */
void void
ForgetRelationFsyncRequests(RelFileNode rnode, ForkNumber forknum) ForgetRelationFsyncRequests(RelFileNode rnode, ForkNumber forknum)
......
...@@ -381,8 +381,7 @@ smgrdounlink(SMgrRelation reln, bool isRedo) ...@@ -381,8 +381,7 @@ smgrdounlink(SMgrRelation reln, bool isRedo)
* ERROR, because we've already decided to commit or abort the current * ERROR, because we've already decided to commit or abort the current
* xact. * xact.
*/ */
for (forknum = 0; forknum <= MAX_FORKNUM; forknum++) (*(smgrsw[which].smgr_unlink)) (rnode, InvalidForkNumber, isRedo);
(*(smgrsw[which].smgr_unlink)) (rnode, forknum, isRedo);
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment