diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index f93131a645ea..48f65188dc0a 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -899,11 +899,8 @@ ExtendBufferedRelBy(BufferManagerRelation bmr, Assert(bmr.smgr == NULL || bmr.relpersistence != 0); Assert(extend_by > 0); - if (bmr.smgr == NULL) - { - bmr.smgr = RelationGetSmgr(bmr.rel); + if (bmr.relpersistence == 0) bmr.relpersistence = bmr.rel->rd_rel->relpersistence; - } return ExtendBufferedRelCommon(bmr, fork, strategy, flags, extend_by, InvalidBlockNumber, @@ -935,11 +932,8 @@ ExtendBufferedRelTo(BufferManagerRelation bmr, Assert(bmr.smgr == NULL || bmr.relpersistence != 0); Assert(extend_to != InvalidBlockNumber && extend_to > 0); - if (bmr.smgr == NULL) - { - bmr.smgr = RelationGetSmgr(bmr.rel); + if (bmr.relpersistence == 0) bmr.relpersistence = bmr.rel->rd_rel->relpersistence; - } /* * If desired, create the file if it doesn't exist. If @@ -947,15 +941,15 @@ ExtendBufferedRelTo(BufferManagerRelation bmr, * an smgrexists call. */ if ((flags & EB_CREATE_FORK_IF_NEEDED) && - (bmr.smgr->smgr_cached_nblocks[fork] == 0 || - bmr.smgr->smgr_cached_nblocks[fork] == InvalidBlockNumber) && - !smgrexists(bmr.smgr, fork)) + (BMR_GET_SMGR(bmr)->smgr_cached_nblocks[fork] == 0 || + BMR_GET_SMGR(bmr)->smgr_cached_nblocks[fork] == InvalidBlockNumber) && + !smgrexists(BMR_GET_SMGR(bmr), fork)) { LockRelationForExtension(bmr.rel, ExclusiveLock); /* recheck, fork might have been created concurrently */ - if (!smgrexists(bmr.smgr, fork)) - smgrcreate(bmr.smgr, fork, flags & EB_PERFORMING_RECOVERY); + if (!smgrexists(BMR_GET_SMGR(bmr), fork)) + smgrcreate(BMR_GET_SMGR(bmr), fork, flags & EB_PERFORMING_RECOVERY); UnlockRelationForExtension(bmr.rel, ExclusiveLock); } @@ -965,13 +959,13 @@ ExtendBufferedRelTo(BufferManagerRelation bmr, * kernel. */ if (flags & EB_CLEAR_SIZE_CACHE) - bmr.smgr->smgr_cached_nblocks[fork] = InvalidBlockNumber; + BMR_GET_SMGR(bmr)->smgr_cached_nblocks[fork] = InvalidBlockNumber; /* * Estimate how many pages we'll need to extend by. This avoids acquiring * unnecessarily many victim buffers. */ - current_size = smgrnblocks(bmr.smgr, fork); + current_size = smgrnblocks(BMR_GET_SMGR(bmr), fork); /* * Since no-one else can be looking at the page contents yet, there is no @@ -1015,7 +1009,7 @@ ExtendBufferedRelTo(BufferManagerRelation bmr, if (buffer == InvalidBuffer) { Assert(extended_by == 0); - buffer = ReadBuffer_common(bmr.rel, bmr.smgr, bmr.relpersistence, + buffer = ReadBuffer_common(bmr.rel, BMR_GET_SMGR(bmr), bmr.relpersistence, fork, extend_to - 1, mode, strategy); } @@ -2575,10 +2569,10 @@ ExtendBufferedRelCommon(BufferManagerRelation bmr, BlockNumber first_block; TRACE_POSTGRESQL_BUFFER_EXTEND_START(fork, - bmr.smgr->smgr_rlocator.locator.spcOid, - bmr.smgr->smgr_rlocator.locator.dbOid, - bmr.smgr->smgr_rlocator.locator.relNumber, - bmr.smgr->smgr_rlocator.backend, + BMR_GET_SMGR(bmr)->smgr_rlocator.locator.spcOid, + BMR_GET_SMGR(bmr)->smgr_rlocator.locator.dbOid, + BMR_GET_SMGR(bmr)->smgr_rlocator.locator.relNumber, + BMR_GET_SMGR(bmr)->smgr_rlocator.backend, extend_by); if (bmr.relpersistence == RELPERSISTENCE_TEMP) @@ -2592,10 +2586,10 @@ ExtendBufferedRelCommon(BufferManagerRelation bmr, *extended_by = extend_by; TRACE_POSTGRESQL_BUFFER_EXTEND_DONE(fork, - bmr.smgr->smgr_rlocator.locator.spcOid, - bmr.smgr->smgr_rlocator.locator.dbOid, - bmr.smgr->smgr_rlocator.locator.relNumber, - bmr.smgr->smgr_rlocator.backend, + BMR_GET_SMGR(bmr)->smgr_rlocator.locator.spcOid, + BMR_GET_SMGR(bmr)->smgr_rlocator.locator.dbOid, + BMR_GET_SMGR(bmr)->smgr_rlocator.locator.relNumber, + BMR_GET_SMGR(bmr)->smgr_rlocator.backend, *extended_by, first_block); @@ -2661,9 +2655,9 @@ ExtendBufferedRelShared(BufferManagerRelation bmr, * kernel. */ if (flags & EB_CLEAR_SIZE_CACHE) - bmr.smgr->smgr_cached_nblocks[fork] = InvalidBlockNumber; + BMR_GET_SMGR(bmr)->smgr_cached_nblocks[fork] = InvalidBlockNumber; - first_block = smgrnblocks(bmr.smgr, fork); + first_block = smgrnblocks(BMR_GET_SMGR(bmr), fork); /* * Now that we have the accurate relation size, check if the caller wants @@ -2706,7 +2700,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr, ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("cannot extend relation %s beyond %u blocks", - relpath(bmr.smgr->smgr_rlocator, fork).str, + relpath(BMR_GET_SMGR(bmr)->smgr_rlocator, fork).str, MaxBlockNumber))); /* @@ -2728,7 +2722,8 @@ ExtendBufferedRelShared(BufferManagerRelation bmr, ResourceOwnerEnlarge(CurrentResourceOwner); ReservePrivateRefCountEntry(); - InitBufferTag(&tag, &bmr.smgr->smgr_rlocator.locator, fork, first_block + i); + InitBufferTag(&tag, &BMR_GET_SMGR(bmr)->smgr_rlocator.locator, fork, + first_block + i); hash = BufTableHashCode(&tag); partition_lock = BufMappingPartitionLock(hash); @@ -2778,7 +2773,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr, ereport(ERROR, (errmsg("unexpected data beyond EOF in block %u of relation %s", existing_hdr->tag.blockNum, - relpath(bmr.smgr->smgr_rlocator, fork).str), + relpath(BMR_GET_SMGR(bmr)->smgr_rlocator, fork).str), errhint("This has been seen to occur with buggy kernels; consider updating your system."))); /* @@ -2836,7 +2831,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr, * * We don't need to set checksum for all-zero pages. */ - smgrzeroextend(bmr.smgr, fork, first_block, extend_by, false); + smgrzeroextend(BMR_GET_SMGR(bmr), fork, first_block, extend_by, false); /* * Release the file-extension lock; it's now OK for someone else to extend diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index 63101d56a074..a3bcc4e22b31 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -372,7 +372,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr, MemSet(buf_block, 0, BLCKSZ); } - first_block = smgrnblocks(bmr.smgr, fork); + first_block = smgrnblocks(BMR_GET_SMGR(bmr), fork); if (extend_upto != InvalidBlockNumber) { @@ -391,7 +391,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr, ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("cannot extend relation %s beyond %u blocks", - relpath(bmr.smgr->smgr_rlocator, fork).str, + relpath(BMR_GET_SMGR(bmr)->smgr_rlocator, fork).str, MaxBlockNumber))); for (uint32 i = 0; i < extend_by; i++) @@ -408,7 +408,8 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr, /* in case we need to pin an existing buffer below */ ResourceOwnerEnlarge(CurrentResourceOwner); - InitBufferTag(&tag, &bmr.smgr->smgr_rlocator.locator, fork, first_block + i); + InitBufferTag(&tag, &BMR_GET_SMGR(bmr)->smgr_rlocator.locator, fork, + first_block + i); hresult = (LocalBufferLookupEnt *) hash_search(LocalBufHash, &tag, HASH_ENTER, &found); @@ -456,7 +457,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr, io_start = pgstat_prepare_io_time(track_io_timing); /* actually extend relation */ - smgrzeroextend(bmr.smgr, fork, first_block, extend_by, false); + smgrzeroextend(BMR_GET_SMGR(bmr), fork, first_block, extend_by, false); pgstat_count_io_op_time(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL, IOOP_EXTEND, io_start, 1, extend_by * BLCKSZ); diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index 41fdc1e76938..80f81e04c9bb 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -101,13 +101,26 @@ typedef enum ExtendBufferedFlags typedef struct BufferManagerRelation { Relation rel; + + /* + * Must be accessed via BMR_GET_SMGR if we want to access some fields + * of structure + */ struct SMgrRelationData *smgr; + char relpersistence; } BufferManagerRelation; #define BMR_REL(p_rel) ((BufferManagerRelation){.rel = p_rel}) #define BMR_SMGR(p_smgr, p_relpersistence) ((BufferManagerRelation){.smgr = p_smgr, .relpersistence = p_relpersistence}) +/* + * In case of cache invalidation, we need to be sure that we access a valid + * smgr reference + */ +#define BMR_GET_SMGR(bmr) \ + (RelationIsValid((bmr).rel) ? RelationGetSmgr((bmr).rel) : (bmr).smgr) + /* Zero out page if reading fails. */ #define READ_BUFFERS_ZERO_ON_ERROR (1 << 0) /* Call smgrprefetch() if I/O necessary. */