Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1b94f8f

Browse files
committed
Avoid using a fake relcache entry to own an SmgrRelation.
If an error occurs before we close the fake relcache entry, the the fake relcache entry will be destroyed by the SmgrRelation will survive until end of transaction. Its smgr_owner pointer ends up pointing to already-freed memory. The original reason for using a fake relcache entry here was to try to avoid reusing an SMgrRelation across a relevant invalidation. To avoid that problem, just call smgropen() again each time we need a reference to it. Hopefully someday we will come up with a more elegant approach, but accessing uninitialized memory is bad so let's do this for now. Dilip Kumar, reviewed by Andres Freund and Tom Lane. Report by Justin Pryzby. Discussion: http://postgr.es/m/20220802175043.GA13682@telsasoft.com Discussion: http://postgr.es/m/CAFiTN-vSFeE6_W9z698XNtFROOA_nSqUXWqLcG0emob_kJ+dEQ@mail.gmail.com
1 parent d6d1fbf commit 1b94f8f

File tree

2 files changed

+28
-38
lines changed

2 files changed

+28
-38
lines changed

src/backend/commands/dbcommands.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ ScanSourceDatabasePgClass(Oid tbid, Oid dbid, char *srcpath)
257257
Page page;
258258
List *rnodelist = NIL;
259259
LockRelId relid;
260-
Relation rel;
261260
Snapshot snapshot;
261+
SMgrRelation smgr;
262262
BufferAccessStrategy bstrategy;
263263

264264
/* Get pg_class relfilenode. */
@@ -275,16 +275,9 @@ ScanSourceDatabasePgClass(Oid tbid, Oid dbid, char *srcpath)
275275
rnode.dbNode = dbid;
276276
rnode.relNode = relfilenode;
277277

278-
/*
279-
* We can't use a real relcache entry for a relation in some other
280-
* database, but since we're only going to access the fields related to
281-
* physical storage, a fake one is good enough. If we didn't do this and
282-
* used the smgr layer directly, we would have to worry about
283-
* invalidations.
284-
*/
285-
rel = CreateFakeRelcacheEntry(rnode);
286-
nblocks = smgrnblocks(RelationGetSmgr(rel), MAIN_FORKNUM);
287-
FreeFakeRelcacheEntry(rel);
278+
smgr = smgropen(rnode, InvalidBackendId);
279+
nblocks = smgrnblocks(smgr, MAIN_FORKNUM);
280+
smgrclose(smgr);
288281

289282
/* Use a buffer access strategy since this is a bulk read operation. */
290283
bstrategy = GetAccessStrategy(BAS_BULKREAD);

src/backend/storage/buffer/bufmgr.c

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,9 @@ static void FindAndDropRelFileNodeBuffers(RelFileNode rnode,
487487
ForkNumber forkNum,
488488
BlockNumber nForkBlock,
489489
BlockNumber firstDelBlock);
490-
static void RelationCopyStorageUsingBuffer(Relation src, Relation dst,
491-
ForkNumber forkNum,
492-
bool isunlogged);
490+
static void RelationCopyStorageUsingBuffer(RelFileNode srcnode,
491+
RelFileNode dstnode,
492+
ForkNumber forkNum, bool permanent);
493493
static void AtProcExit_Buffers(int code, Datum arg);
494494
static void CheckForBufferLeaks(void);
495495
static int rnode_comparator(const void *p1, const void *p2);
@@ -3702,8 +3702,9 @@ FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels)
37023702
* --------------------------------------------------------------------
37033703
*/
37043704
static void
3705-
RelationCopyStorageUsingBuffer(Relation src, Relation dst, ForkNumber forkNum,
3706-
bool permanent)
3705+
RelationCopyStorageUsingBuffer(RelFileNode srcnode,
3706+
RelFileNode dstnode,
3707+
ForkNumber forkNum, bool permanent)
37073708
{
37083709
Buffer srcBuf;
37093710
Buffer dstBuf;
@@ -3723,7 +3724,8 @@ RelationCopyStorageUsingBuffer(Relation src, Relation dst, ForkNumber forkNum,
37233724
use_wal = XLogIsNeeded() && (permanent || forkNum == INIT_FORKNUM);
37243725

37253726
/* Get number of blocks in the source relation. */
3726-
nblocks = smgrnblocks(RelationGetSmgr(src), forkNum);
3727+
nblocks = smgrnblocks(smgropen(srcnode, InvalidBackendId),
3728+
forkNum);
37273729

37283730
/* Nothing to copy; just return. */
37293731
if (nblocks == 0)
@@ -3739,14 +3741,14 @@ RelationCopyStorageUsingBuffer(Relation src, Relation dst, ForkNumber forkNum,
37393741
CHECK_FOR_INTERRUPTS();
37403742

37413743
/* Read block from source relation. */
3742-
srcBuf = ReadBufferWithoutRelcache(src->rd_node, forkNum, blkno,
3744+
srcBuf = ReadBufferWithoutRelcache(srcnode, forkNum, blkno,
37433745
RBM_NORMAL, bstrategy_src,
37443746
permanent);
37453747
LockBuffer(srcBuf, BUFFER_LOCK_SHARE);
37463748
srcPage = BufferGetPage(srcBuf);
37473749

37483750
/* Use P_NEW to extend the destination relation. */
3749-
dstBuf = ReadBufferWithoutRelcache(dst->rd_node, forkNum, P_NEW,
3751+
dstBuf = ReadBufferWithoutRelcache(dstnode, forkNum, P_NEW,
37503752
RBM_NORMAL, bstrategy_dst,
37513753
permanent);
37523754
LockBuffer(dstBuf, BUFFER_LOCK_EXCLUSIVE);
@@ -3784,24 +3786,13 @@ void
37843786
CreateAndCopyRelationData(RelFileNode src_rnode, RelFileNode dst_rnode,
37853787
bool permanent)
37863788
{
3787-
Relation src_rel;
3788-
Relation dst_rel;
3789+
RelFileNodeBackend rnode;
37893790
char relpersistence;
37903791

37913792
/* Set the relpersistence. */
37923793
relpersistence = permanent ?
37933794
RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
37943795

3795-
/*
3796-
* We can't use a real relcache entry for a relation in some other
3797-
* database, but since we're only going to access the fields related to
3798-
* physical storage, a fake one is good enough. If we didn't do this and
3799-
* used the smgr layer directly, we would have to worry about
3800-
* invalidations.
3801-
*/
3802-
src_rel = CreateFakeRelcacheEntry(src_rnode);
3803-
dst_rel = CreateFakeRelcacheEntry(dst_rnode);
3804-
38053796
/*
38063797
* Create and copy all forks of the relation. During create database we
38073798
* have a separate cleanup mechanism which deletes complete database
@@ -3811,15 +3802,16 @@ CreateAndCopyRelationData(RelFileNode src_rnode, RelFileNode dst_rnode,
38113802
RelationCreateStorage(dst_rnode, relpersistence, false);
38123803

38133804
/* copy main fork. */
3814-
RelationCopyStorageUsingBuffer(src_rel, dst_rel, MAIN_FORKNUM, permanent);
3805+
RelationCopyStorageUsingBuffer(src_rnode, dst_rnode, MAIN_FORKNUM,
3806+
permanent);
38153807

38163808
/* copy those extra forks that exist */
38173809
for (ForkNumber forkNum = MAIN_FORKNUM + 1;
38183810
forkNum <= MAX_FORKNUM; forkNum++)
38193811
{
3820-
if (smgrexists(RelationGetSmgr(src_rel), forkNum))
3812+
if (smgrexists(smgropen(src_rnode, InvalidBackendId), forkNum))
38213813
{
3822-
smgrcreate(RelationGetSmgr(dst_rel), forkNum, false);
3814+
smgrcreate(smgropen(dst_rnode, InvalidBackendId), forkNum, false);
38233815

38243816
/*
38253817
* WAL log creation if the relation is persistent, or this is the
@@ -3829,14 +3821,19 @@ CreateAndCopyRelationData(RelFileNode src_rnode, RelFileNode dst_rnode,
38293821
log_smgrcreate(&dst_rnode, forkNum);
38303822

38313823
/* Copy a fork's data, block by block. */
3832-
RelationCopyStorageUsingBuffer(src_rel, dst_rel, forkNum,
3824+
RelationCopyStorageUsingBuffer(src_rnode, dst_rnode, forkNum,
38333825
permanent);
38343826
}
38353827
}
38363828

3837-
/* Release fake relcache entries. */
3838-
FreeFakeRelcacheEntry(src_rel);
3839-
FreeFakeRelcacheEntry(dst_rel);
3829+
/* close source and destination smgr if exists. */
3830+
rnode.backend = InvalidBackendId;
3831+
3832+
rnode.node = src_rnode;
3833+
smgrclosenode(rnode);
3834+
3835+
rnode.node = dst_rnode;
3836+
smgrclosenode(rnode);
38403837
}
38413838

38423839
/* ---------------------------------------------------------------------

0 commit comments

Comments
 (0)