diff options
Diffstat (limited to 'src/backend/storage/freespace/freespace.c')
-rw-r--r-- | src/backend/storage/freespace/freespace.c | 52 |
1 files changed, 31 insertions, 21 deletions
diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c index 8c12dda2380..09d4b16067d 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -265,13 +265,11 @@ FreeSpaceMapPrepareTruncateRel(Relation rel, BlockNumber nblocks) uint16 first_removed_slot; Buffer buf; - RelationOpenSmgr(rel); - /* * If no FSM has been created yet for this relation, there's nothing to * truncate. */ - if (!smgrexists(rel->rd_smgr, FSM_FORKNUM)) + if (!smgrexists(RelationGetSmgr(rel), FSM_FORKNUM)) return InvalidBlockNumber; /* Get the location in the FSM of the first removed heap block */ @@ -317,7 +315,7 @@ FreeSpaceMapPrepareTruncateRel(Relation rel, BlockNumber nblocks) else { new_nfsmblocks = fsm_logical_to_physical(first_removed_address); - if (smgrnblocks(rel->rd_smgr, FSM_FORKNUM) <= new_nfsmblocks) + if (smgrnblocks(RelationGetSmgr(rel), FSM_FORKNUM) <= new_nfsmblocks) return InvalidBlockNumber; /* nothing to do; the FSM was already * smaller */ } @@ -532,8 +530,14 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend) { BlockNumber blkno = fsm_logical_to_physical(addr); Buffer buf; + SMgrRelation reln; - 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); /* * If we haven't cached the size of the FSM yet, check it first. Also @@ -541,19 +545,19 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend) * value might be stale. (We send smgr inval messages on truncation, but * not on extension.) */ - if (rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] == InvalidBlockNumber || - blkno >= rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM]) + if (reln->smgr_cached_nblocks[FSM_FORKNUM] == InvalidBlockNumber || + blkno >= reln->smgr_cached_nblocks[FSM_FORKNUM]) { /* Invalidate the cache so smgrnblocks asks the kernel. */ - rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] = InvalidBlockNumber; - if (smgrexists(rel->rd_smgr, FSM_FORKNUM)) - smgrnblocks(rel->rd_smgr, FSM_FORKNUM); + reln->smgr_cached_nblocks[FSM_FORKNUM] = InvalidBlockNumber; + if (smgrexists(reln, FSM_FORKNUM)) + smgrnblocks(reln, FSM_FORKNUM); else - rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] = 0; + reln->smgr_cached_nblocks[FSM_FORKNUM] = 0; } /* Handle requests beyond EOF */ - if (blkno >= rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM]) + if (blkno >= reln->smgr_cached_nblocks[FSM_FORKNUM]) { if (extend) fsm_extend(rel, blkno + 1); @@ -603,6 +607,7 @@ fsm_extend(Relation rel, BlockNumber fsm_nblocks) { BlockNumber fsm_nblocks_now; PGAlignedBlock pg; + SMgrRelation reln; PageInit((Page) pg.data, BLCKSZ, 0); @@ -618,28 +623,33 @@ fsm_extend(Relation rel, BlockNumber fsm_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 FSM file first if it doesn't exist. If * smgr_cached_nblocks[FSM_FORKNUM] is positive then it must exist, no * need for an smgrexists call. */ - if ((rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] == 0 || - rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] == InvalidBlockNumber) && - !smgrexists(rel->rd_smgr, FSM_FORKNUM)) - smgrcreate(rel->rd_smgr, FSM_FORKNUM, false); + if ((reln->smgr_cached_nblocks[FSM_FORKNUM] == 0 || + reln->smgr_cached_nblocks[FSM_FORKNUM] == InvalidBlockNumber) && + !smgrexists(reln, FSM_FORKNUM)) + smgrcreate(reln, FSM_FORKNUM, false); /* Invalidate cache so that smgrnblocks() asks the kernel. */ - rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] = InvalidBlockNumber; - fsm_nblocks_now = smgrnblocks(rel->rd_smgr, FSM_FORKNUM); + reln->smgr_cached_nblocks[FSM_FORKNUM] = InvalidBlockNumber; + fsm_nblocks_now = smgrnblocks(reln, FSM_FORKNUM); + /* Extend as needed. */ while (fsm_nblocks_now < fsm_nblocks) { PageSetChecksumInplace((Page) pg.data, fsm_nblocks_now); - smgrextend(rel->rd_smgr, FSM_FORKNUM, fsm_nblocks_now, + smgrextend(reln, FSM_FORKNUM, fsm_nblocks_now, pg.data, false); fsm_nblocks_now++; } |