mirror of
https://github.com/postgres/postgres.git
synced 2025-07-09 22:41:56 +03:00
Replace RelationOpenSmgr() with RelationGetSmgr().
The idea behind this patch is to design out bugs like the one fixed
by commit 9d523119f
. Previously, once one did RelationOpenSmgr(rel),
it was considered okay to access rel->rd_smgr directly for some
not-very-clear interval. But since that pointer will be cleared by
relcache flushes, we had bugs arising from overreliance on a previous
RelationOpenSmgr call still being effective.
Now, very little code except that in rel.h and relcache.c should ever
touch the rd_smgr field directly. The normal coding rule is to use
RelationGetSmgr(rel) and not expect the result to be valid for longer
than one smgr function call. There are a couple of places where using
the function every single time seemed like overkill, but they are now
annotated with large warning comments.
Amul Sul, after an idea of mine.
Discussion: https://postgr.es/m/CANiYTQsU7yMFpQYnv=BrcRVqK_3U3mtAzAsJCaqtzsDHfsUbdQ@mail.gmail.com
This commit is contained in:
@ -625,7 +625,6 @@ heapam_relation_copy_data(Relation rel, const RelFileNode *newrnode)
|
||||
SMgrRelation dstrel;
|
||||
|
||||
dstrel = smgropen(*newrnode, rel->rd_backend);
|
||||
RelationOpenSmgr(rel);
|
||||
|
||||
/*
|
||||
* Since we copy the file directly without looking at the shared buffers,
|
||||
@ -645,14 +644,14 @@ heapam_relation_copy_data(Relation rel, const RelFileNode *newrnode)
|
||||
RelationCreateStorage(*newrnode, rel->rd_rel->relpersistence);
|
||||
|
||||
/* copy main fork */
|
||||
RelationCopyStorage(rel->rd_smgr, dstrel, MAIN_FORKNUM,
|
||||
RelationCopyStorage(RelationGetSmgr(rel), dstrel, MAIN_FORKNUM,
|
||||
rel->rd_rel->relpersistence);
|
||||
|
||||
/* copy those extra forks that exist */
|
||||
for (ForkNumber forkNum = MAIN_FORKNUM + 1;
|
||||
forkNum <= MAX_FORKNUM; forkNum++)
|
||||
{
|
||||
if (smgrexists(rel->rd_smgr, forkNum))
|
||||
if (smgrexists(RelationGetSmgr(rel), forkNum))
|
||||
{
|
||||
smgrcreate(dstrel, forkNum, false);
|
||||
|
||||
@ -664,7 +663,7 @@ heapam_relation_copy_data(Relation rel, const RelFileNode *newrnode)
|
||||
(rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
|
||||
forkNum == INIT_FORKNUM))
|
||||
log_smgrcreate(newrnode, forkNum);
|
||||
RelationCopyStorage(rel->rd_smgr, dstrel, forkNum,
|
||||
RelationCopyStorage(RelationGetSmgr(rel), dstrel, forkNum,
|
||||
rel->rd_rel->relpersistence);
|
||||
}
|
||||
}
|
||||
|
@ -326,9 +326,8 @@ end_heap_rewrite(RewriteState state)
|
||||
|
||||
PageSetChecksumInplace(state->rs_buffer, state->rs_blockno);
|
||||
|
||||
RelationOpenSmgr(state->rs_new_rel);
|
||||
smgrextend(state->rs_new_rel->rd_smgr, MAIN_FORKNUM, state->rs_blockno,
|
||||
(char *) state->rs_buffer, true);
|
||||
smgrextend(RelationGetSmgr(state->rs_new_rel), MAIN_FORKNUM,
|
||||
state->rs_blockno, (char *) state->rs_buffer, true);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -339,11 +338,7 @@ end_heap_rewrite(RewriteState state)
|
||||
* wrote before the checkpoint.
|
||||
*/
|
||||
if (RelationNeedsWAL(state->rs_new_rel))
|
||||
{
|
||||
/* for an empty table, this could be first smgr access */
|
||||
RelationOpenSmgr(state->rs_new_rel);
|
||||
smgrimmedsync(state->rs_new_rel->rd_smgr, MAIN_FORKNUM);
|
||||
}
|
||||
smgrimmedsync(RelationGetSmgr(state->rs_new_rel), MAIN_FORKNUM);
|
||||
|
||||
logical_end_heap_rewrite(state);
|
||||
|
||||
@ -695,11 +690,9 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
|
||||
* need for smgr to schedule an fsync for this write; we'll do it
|
||||
* ourselves in end_heap_rewrite.
|
||||
*/
|
||||
RelationOpenSmgr(state->rs_new_rel);
|
||||
|
||||
PageSetChecksumInplace(page, state->rs_blockno);
|
||||
|
||||
smgrextend(state->rs_new_rel->rd_smgr, MAIN_FORKNUM,
|
||||
smgrextend(RelationGetSmgr(state->rs_new_rel), MAIN_FORKNUM,
|
||||
state->rs_blockno, (char *) page, true);
|
||||
|
||||
state->rs_blockno++;
|
||||
|
@ -455,13 +455,11 @@ visibilitymap_prepare_truncate(Relation rel, BlockNumber nheapblocks)
|
||||
elog(DEBUG1, "vm_truncate %s %d", RelationGetRelationName(rel), nheapblocks);
|
||||
#endif
|
||||
|
||||
RelationOpenSmgr(rel);
|
||||
|
||||
/*
|
||||
* If no visibility map has been created yet for this relation, there's
|
||||
* nothing to truncate.
|
||||
*/
|
||||
if (!smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
|
||||
if (!smgrexists(RelationGetSmgr(rel), VISIBILITYMAP_FORKNUM))
|
||||
return InvalidBlockNumber;
|
||||
|
||||
/*
|
||||
@ -528,7 +526,7 @@ visibilitymap_prepare_truncate(Relation rel, BlockNumber nheapblocks)
|
||||
else
|
||||
newnblocks = truncBlock;
|
||||
|
||||
if (smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM) <= newnblocks)
|
||||
if (smgrnblocks(RelationGetSmgr(rel), VISIBILITYMAP_FORKNUM) <= newnblocks)
|
||||
{
|
||||
/* nothing to do, the file was already smaller than requested size */
|
||||
return InvalidBlockNumber;
|
||||
@ -547,30 +545,29 @@ static Buffer
|
||||
vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
|
||||
{
|
||||
Buffer buf;
|
||||
SMgrRelation reln;
|
||||
|
||||
/*
|
||||
* We might not have opened the relation at the smgr level yet, or we
|
||||
* might have been forced to close it by a sinval message. The code below
|
||||
* won't necessarily notice relation extension immediately when extend =
|
||||
* false, so we rely on sinval messages to ensure that our ideas about the
|
||||
* size of the map aren't too far out of date.
|
||||
* Caution: re-using this smgr pointer could fail if the relcache entry
|
||||
* gets closed. It's safe as long as we only do smgr-level operations
|
||||
* between here and the last use of the pointer.
|
||||
*/
|
||||
RelationOpenSmgr(rel);
|
||||
reln = RelationGetSmgr(rel);
|
||||
|
||||
/*
|
||||
* If we haven't cached the size of the visibility map fork yet, check it
|
||||
* first.
|
||||
*/
|
||||
if (rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] == InvalidBlockNumber)
|
||||
if (reln->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] == InvalidBlockNumber)
|
||||
{
|
||||
if (smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
|
||||
smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
|
||||
if (smgrexists(reln, VISIBILITYMAP_FORKNUM))
|
||||
smgrnblocks(reln, VISIBILITYMAP_FORKNUM);
|
||||
else
|
||||
rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = 0;
|
||||
reln->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = 0;
|
||||
}
|
||||
|
||||
/* Handle requests beyond EOF */
|
||||
if (blkno >= rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM])
|
||||
if (blkno >= reln->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM])
|
||||
{
|
||||
if (extend)
|
||||
vm_extend(rel, blkno + 1);
|
||||
@ -618,6 +615,7 @@ vm_extend(Relation rel, BlockNumber vm_nblocks)
|
||||
{
|
||||
BlockNumber vm_nblocks_now;
|
||||
PGAlignedBlock pg;
|
||||
SMgrRelation reln;
|
||||
|
||||
PageInit((Page) pg.data, BLCKSZ, 0);
|
||||
|
||||
@ -633,29 +631,32 @@ vm_extend(Relation rel, BlockNumber vm_nblocks)
|
||||
*/
|
||||
LockRelationForExtension(rel, ExclusiveLock);
|
||||
|
||||
/* Might have to re-open if a cache flush happened */
|
||||
RelationOpenSmgr(rel);
|
||||
/*
|
||||
* Caution: re-using this smgr pointer could fail if the relcache entry
|
||||
* gets closed. It's safe as long as we only do smgr-level operations
|
||||
* between here and the last use of the pointer.
|
||||
*/
|
||||
reln = RelationGetSmgr(rel);
|
||||
|
||||
/*
|
||||
* Create the file first if it doesn't exist. If smgr_vm_nblocks is
|
||||
* positive then it must exist, no need for an smgrexists call.
|
||||
*/
|
||||
if ((rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] == 0 ||
|
||||
rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] == InvalidBlockNumber) &&
|
||||
!smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
|
||||
smgrcreate(rel->rd_smgr, VISIBILITYMAP_FORKNUM, false);
|
||||
if ((reln->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] == 0 ||
|
||||
reln->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] == InvalidBlockNumber) &&
|
||||
!smgrexists(reln, VISIBILITYMAP_FORKNUM))
|
||||
smgrcreate(reln, VISIBILITYMAP_FORKNUM, false);
|
||||
|
||||
/* Invalidate cache so that smgrnblocks() asks the kernel. */
|
||||
rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = InvalidBlockNumber;
|
||||
vm_nblocks_now = smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
|
||||
reln->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = InvalidBlockNumber;
|
||||
vm_nblocks_now = smgrnblocks(reln, VISIBILITYMAP_FORKNUM);
|
||||
|
||||
/* Now extend the file */
|
||||
while (vm_nblocks_now < vm_nblocks)
|
||||
{
|
||||
PageSetChecksumInplace((Page) pg.data, vm_nblocks_now);
|
||||
|
||||
smgrextend(rel->rd_smgr, VISIBILITYMAP_FORKNUM, vm_nblocks_now,
|
||||
pg.data, false);
|
||||
smgrextend(reln, VISIBILITYMAP_FORKNUM, vm_nblocks_now, pg.data, false);
|
||||
vm_nblocks_now++;
|
||||
}
|
||||
|
||||
@ -666,7 +667,7 @@ vm_extend(Relation rel, BlockNumber vm_nblocks)
|
||||
* to keep checking for creation or extension of the file, which happens
|
||||
* infrequently.
|
||||
*/
|
||||
CacheInvalidateSmgr(rel->rd_smgr->smgr_rnode);
|
||||
CacheInvalidateSmgr(reln->smgr_rnode);
|
||||
|
||||
UnlockRelationForExtension(rel, ExclusiveLock);
|
||||
}
|
||||
|
Reference in New Issue
Block a user