diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index 8ffe1b0f84b..e8c040c6385 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -414,6 +414,9 @@ CreateFakeRelcacheEntry(RelFileNode rnode) void FreeFakeRelcacheEntry(Relation fakerel) { + /* make sure the fakerel is not referenced by the SmgrRelation anymore */ + if (fakerel->rd_smgr != NULL) + smgrclearowner(&fakerel->rd_smgr, fakerel->rd_smgr); pfree(fakerel); } diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index 7a35b0a8333..886176bc699 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -197,6 +197,24 @@ smgrsetowner(SMgrRelation *owner, SMgrRelation reln) *owner = reln; } +/* + * smgrclearowner() -- Remove long-lived reference to an SMgrRelation object + * if one exists + */ +void +smgrclearowner(SMgrRelation *owner, SMgrRelation reln) +{ + /* Do nothing if the SMgrRelation object is not owned by the owner */ + if (reln->smgr_owner != owner) + return; + + /* unset the owner's reference */ + *owner = NULL; + + /* unset our reference to the owner */ + reln->smgr_owner = NULL; +} + /* * smgrexists() -- Does the underlying file for a fork exist? */ diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h index c037190b4ba..6eee0a44fdf 100644 --- a/src/include/storage/smgr.h +++ b/src/include/storage/smgr.h @@ -73,6 +73,7 @@ extern void smgrinit(void); extern SMgrRelation smgropen(RelFileNode rnode); extern bool smgrexists(SMgrRelation reln, ForkNumber forknum); extern void smgrsetowner(SMgrRelation *owner, SMgrRelation reln); +extern void smgrclearowner(SMgrRelation *owner, SMgrRelation reln); extern void smgrclose(SMgrRelation reln); extern void smgrcloseall(void); extern void smgrclosenode(RelFileNode rnode);