PostgreSQL Source Code git master
buf_internals.h File Reference
#include "pgstat.h"
#include "port/atomics.h"
#include "storage/aio_types.h"
#include "storage/buf.h"
#include "storage/bufmgr.h"
#include "storage/condition_variable.h"
#include "storage/lwlock.h"
#include "storage/procnumber.h"
#include "storage/shmem.h"
#include "storage/smgr.h"
#include "storage/spin.h"
#include "utils/relcache.h"
#include "utils/resowner.h"
Include dependency graph for buf_internals.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  buftag
 
struct  BufferDesc
 
union  BufferDescPadded
 
struct  PendingWriteback
 
struct  WritebackContext
 
struct  CkptSortItem
 

Macros

#define BUF_REFCOUNT_BITS   18
 
#define BUF_USAGECOUNT_BITS   4
 
#define BUF_FLAG_BITS   10
 
#define BUF_REFCOUNT_ONE   1
 
#define BUF_REFCOUNT_MASK   ((1U << BUF_REFCOUNT_BITS) - 1)
 
#define BUF_USAGECOUNT_MASK   (((1U << BUF_USAGECOUNT_BITS) - 1) << (BUF_REFCOUNT_BITS))
 
#define BUF_USAGECOUNT_ONE   (1U << BUF_REFCOUNT_BITS)
 
#define BUF_USAGECOUNT_SHIFT   BUF_REFCOUNT_BITS
 
#define BUF_FLAG_MASK   (((1U << BUF_FLAG_BITS) - 1) << (BUF_REFCOUNT_BITS + BUF_USAGECOUNT_BITS))
 
#define BUF_STATE_GET_REFCOUNT(state)   ((state) & BUF_REFCOUNT_MASK)
 
#define BUF_STATE_GET_USAGECOUNT(state)   (((state) & BUF_USAGECOUNT_MASK) >> BUF_USAGECOUNT_SHIFT)
 
#define BM_LOCKED   (1U << 22) /* buffer header is locked */
 
#define BM_DIRTY   (1U << 23) /* data needs writing */
 
#define BM_VALID   (1U << 24) /* data is valid */
 
#define BM_TAG_VALID   (1U << 25) /* tag is assigned */
 
#define BM_IO_IN_PROGRESS   (1U << 26) /* read or write in progress */
 
#define BM_IO_ERROR   (1U << 27) /* previous I/O failed */
 
#define BM_JUST_DIRTIED   (1U << 28) /* dirtied since write started */
 
#define BM_PIN_COUNT_WAITER   (1U << 29) /* have waiter for sole pin */
 
#define BM_CHECKPOINT_NEEDED   (1U << 30) /* must write for checkpoint */
 
#define BM_PERMANENT
 
#define BM_MAX_USAGE_COUNT   5
 
#define BUFFERDESC_PAD_TO_SIZE   (SIZEOF_VOID_P == 8 ? 64 : 1)
 

Typedefs

typedef struct buftag BufferTag
 
typedef struct BufferDesc BufferDesc
 
typedef union BufferDescPadded BufferDescPadded
 
typedef struct PendingWriteback PendingWriteback
 
typedef struct WritebackContext WritebackContext
 
typedef struct CkptSortItem CkptSortItem
 

Functions

 StaticAssertDecl (BUF_REFCOUNT_BITS+BUF_USAGECOUNT_BITS+BUF_FLAG_BITS==32, "parts of buffer state space need to equal 32")
 
 StaticAssertDecl (BM_MAX_USAGE_COUNT<(1<< BUF_USAGECOUNT_BITS), "BM_MAX_USAGE_COUNT doesn't fit in BUF_USAGECOUNT_BITS bits")
 
 StaticAssertDecl (MAX_BACKENDS_BITS<=BUF_REFCOUNT_BITS, "MAX_BACKENDS_BITS needs to be <= BUF_REFCOUNT_BITS")
 
static RelFileNumber BufTagGetRelNumber (const BufferTag *tag)
 
static ForkNumber BufTagGetForkNum (const BufferTag *tag)
 
static void BufTagSetRelForkDetails (BufferTag *tag, RelFileNumber relnumber, ForkNumber forknum)
 
static RelFileLocator BufTagGetRelFileLocator (const BufferTag *tag)
 
static void ClearBufferTag (BufferTag *tag)
 
static void InitBufferTag (BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
 
static bool BufferTagsEqual (const BufferTag *tag1, const BufferTag *tag2)
 
static bool BufTagMatchesRelFileLocator (const BufferTag *tag, const RelFileLocator *rlocator)
 
static uint32 BufTableHashPartition (uint32 hashcode)
 
static LWLockBufMappingPartitionLock (uint32 hashcode)
 
static LWLockBufMappingPartitionLockByIndex (uint32 index)
 
static BufferDescGetBufferDescriptor (uint32 id)
 
static BufferDescGetLocalBufferDescriptor (uint32 id)
 
static Buffer BufferDescriptorGetBuffer (const BufferDesc *bdesc)
 
static ConditionVariableBufferDescriptorGetIOCV (const BufferDesc *bdesc)
 
static LWLockBufferDescriptorGetContentLock (const BufferDesc *bdesc)
 
uint32 LockBufHdr (BufferDesc *desc)
 
static void UnlockBufHdr (BufferDesc *desc)
 
static uint32 UnlockBufHdrExt (BufferDesc *desc, uint32 old_buf_state, uint32 set_bits, uint32 unset_bits, int refcount_change)
 
uint32 WaitBufHdrUnlocked (BufferDesc *buf)
 
static void ResourceOwnerRememberBuffer (ResourceOwner owner, Buffer buffer)
 
static void ResourceOwnerForgetBuffer (ResourceOwner owner, Buffer buffer)
 
static void ResourceOwnerRememberBufferIO (ResourceOwner owner, Buffer buffer)
 
static void ResourceOwnerForgetBufferIO (ResourceOwner owner, Buffer buffer)
 
void WritebackContextInit (WritebackContext *context, int *max_pending)
 
void IssuePendingWritebacks (WritebackContext *wb_context, IOContext io_context)
 
void ScheduleBufferTagForWriteback (WritebackContext *wb_context, IOContext io_context, BufferTag *tag)
 
void TrackNewBufferPin (Buffer buf)
 
bool StartBufferIO (BufferDesc *buf, bool forInput, bool nowait)
 
void TerminateBufferIO (BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits, bool forget_owner, bool release_aio)
 
IOContext IOContextForStrategy (BufferAccessStrategy strategy)
 
BufferDescStrategyGetBuffer (BufferAccessStrategy strategy, uint32 *buf_state, bool *from_ring)
 
bool StrategyRejectBuffer (BufferAccessStrategy strategy, BufferDesc *buf, bool from_ring)
 
int StrategySyncStart (uint32 *complete_passes, uint32 *num_buf_alloc)
 
void StrategyNotifyBgWriter (int bgwprocno)
 
Size StrategyShmemSize (void)
 
void StrategyInitialize (bool init)
 
Size BufTableShmemSize (int size)
 
void InitBufTable (int size)
 
uint32 BufTableHashCode (BufferTag *tagPtr)
 
int BufTableLookup (BufferTag *tagPtr, uint32 hashcode)
 
int BufTableInsert (BufferTag *tagPtr, uint32 hashcode, int buf_id)
 
void BufTableDelete (BufferTag *tagPtr, uint32 hashcode)
 
bool PinLocalBuffer (BufferDesc *buf_hdr, bool adjust_usagecount)
 
void UnpinLocalBuffer (Buffer buffer)
 
void UnpinLocalBufferNoOwner (Buffer buffer)
 
PrefetchBufferResult PrefetchLocalBuffer (SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
 
BufferDescLocalBufferAlloc (SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, bool *foundPtr)
 
BlockNumber ExtendBufferedRelLocal (BufferManagerRelation bmr, ForkNumber fork, uint32 flags, uint32 extend_by, BlockNumber extend_upto, Buffer *buffers, uint32 *extended_by)
 
void MarkLocalBufferDirty (Buffer buffer)
 
void TerminateLocalBufferIO (BufferDesc *bufHdr, bool clear_dirty, uint32 set_flag_bits, bool release_aio)
 
bool StartLocalBufferIO (BufferDesc *bufHdr, bool forInput, bool nowait)
 
void FlushLocalBuffer (BufferDesc *bufHdr, SMgrRelation reln)
 
void InvalidateLocalBuffer (BufferDesc *bufHdr, bool check_unreferenced)
 
void DropRelationLocalBuffers (RelFileLocator rlocator, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
 
void DropRelationAllLocalBuffers (RelFileLocator rlocator)
 
void AtEOXact_LocalBuffers (bool isCommit)
 

Variables

PGDLLIMPORT BufferDescPaddedBufferDescriptors
 
PGDLLIMPORT ConditionVariableMinimallyPaddedBufferIOCVArray
 
PGDLLIMPORT WritebackContext BackendWritebackContext
 
PGDLLIMPORT BufferDescLocalBufferDescriptors
 
PGDLLIMPORT CkptSortItemCkptBufferIds
 
PGDLLIMPORT const ResourceOwnerDesc buffer_io_resowner_desc
 
PGDLLIMPORT const ResourceOwnerDesc buffer_pin_resowner_desc
 

Macro Definition Documentation

◆ BM_CHECKPOINT_NEEDED

#define BM_CHECKPOINT_NEEDED   (1U << 30) /* must write for checkpoint */

Definition at line 76 of file buf_internals.h.

◆ BM_DIRTY

#define BM_DIRTY   (1U << 23) /* data needs writing */

Definition at line 69 of file buf_internals.h.

◆ BM_IO_ERROR

#define BM_IO_ERROR   (1U << 27) /* previous I/O failed */

Definition at line 73 of file buf_internals.h.

◆ BM_IO_IN_PROGRESS

#define BM_IO_IN_PROGRESS   (1U << 26) /* read or write in progress */

Definition at line 72 of file buf_internals.h.

◆ BM_JUST_DIRTIED

#define BM_JUST_DIRTIED   (1U << 28) /* dirtied since write started */

Definition at line 74 of file buf_internals.h.

◆ BM_LOCKED

#define BM_LOCKED   (1U << 22) /* buffer header is locked */

Definition at line 68 of file buf_internals.h.

◆ BM_MAX_USAGE_COUNT

#define BM_MAX_USAGE_COUNT   5

Definition at line 86 of file buf_internals.h.

◆ BM_PERMANENT

#define BM_PERMANENT
Value:
(1U << 31) /* permanent buffer (not unlogged,
* or init fork) */

Definition at line 77 of file buf_internals.h.

◆ BM_PIN_COUNT_WAITER

#define BM_PIN_COUNT_WAITER   (1U << 29) /* have waiter for sole pin */

Definition at line 75 of file buf_internals.h.

◆ BM_TAG_VALID

#define BM_TAG_VALID   (1U << 25) /* tag is assigned */

Definition at line 71 of file buf_internals.h.

◆ BM_VALID

#define BM_VALID   (1U << 24) /* data is valid */

Definition at line 70 of file buf_internals.h.

◆ BUF_FLAG_BITS

#define BUF_FLAG_BITS   10

Definition at line 46 of file buf_internals.h.

◆ BUF_FLAG_MASK

#define BUF_FLAG_MASK   (((1U << BUF_FLAG_BITS) - 1) << (BUF_REFCOUNT_BITS + BUF_USAGECOUNT_BITS))

Definition at line 56 of file buf_internals.h.

◆ BUF_REFCOUNT_BITS

#define BUF_REFCOUNT_BITS   18

Definition at line 44 of file buf_internals.h.

◆ BUF_REFCOUNT_MASK

#define BUF_REFCOUNT_MASK   ((1U << BUF_REFCOUNT_BITS) - 1)

Definition at line 52 of file buf_internals.h.

◆ BUF_REFCOUNT_ONE

#define BUF_REFCOUNT_ONE   1

Definition at line 51 of file buf_internals.h.

◆ BUF_STATE_GET_REFCOUNT

#define BUF_STATE_GET_REFCOUNT (   state)    ((state) & BUF_REFCOUNT_MASK)

Definition at line 59 of file buf_internals.h.

◆ BUF_STATE_GET_USAGECOUNT

#define BUF_STATE_GET_USAGECOUNT (   state)    (((state) & BUF_USAGECOUNT_MASK) >> BUF_USAGECOUNT_SHIFT)

Definition at line 60 of file buf_internals.h.

◆ BUF_USAGECOUNT_BITS

#define BUF_USAGECOUNT_BITS   4

Definition at line 45 of file buf_internals.h.

◆ BUF_USAGECOUNT_MASK

#define BUF_USAGECOUNT_MASK   (((1U << BUF_USAGECOUNT_BITS) - 1) << (BUF_REFCOUNT_BITS))

Definition at line 53 of file buf_internals.h.

◆ BUF_USAGECOUNT_ONE

#define BUF_USAGECOUNT_ONE   (1U << BUF_REFCOUNT_BITS)

Definition at line 54 of file buf_internals.h.

◆ BUF_USAGECOUNT_SHIFT

#define BUF_USAGECOUNT_SHIFT   BUF_REFCOUNT_BITS

Definition at line 55 of file buf_internals.h.

◆ BUFFERDESC_PAD_TO_SIZE

#define BUFFERDESC_PAD_TO_SIZE   (SIZEOF_VOID_P == 8 ? 64 : 1)

Definition at line 314 of file buf_internals.h.

Typedef Documentation

◆ BufferDesc

typedef struct BufferDesc BufferDesc

◆ BufferDescPadded

◆ BufferTag

typedef struct buftag BufferTag

◆ CkptSortItem

typedef struct CkptSortItem CkptSortItem

◆ PendingWriteback

◆ WritebackContext

Function Documentation

◆ AtEOXact_LocalBuffers()

void AtEOXact_LocalBuffers ( bool  isCommit)

Definition at line 1003 of file localbuf.c.

1004{
1006}
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:970

References CheckForLocalBufferLeaks().

Referenced by AtEOXact_Buffers().

◆ BufferDescriptorGetBuffer()

◆ BufferDescriptorGetContentLock()

◆ BufferDescriptorGetIOCV()

static ConditionVariable * BufferDescriptorGetIOCV ( const BufferDesc bdesc)
inlinestatic

Definition at line 373 of file buf_internals.h.

375{
376 return &(BufferIOCVArray[bdesc->buf_id]).cv;
PGDLLIMPORT ConditionVariableMinimallyPadded * BufferIOCVArray
Definition: buf_init.c:23

References BufferDesc::buf_id, and BufferIOCVArray.

Referenced by BufferManagerShmemInit(), TerminateBufferIO(), and WaitIO().

◆ BufferTagsEqual()

static bool BufferTagsEqual ( const BufferTag tag1,
const BufferTag tag2 
)
inlinestatic

Definition at line 166 of file buf_internals.h.

168{
169 return (tag1->spcOid == tag2->spcOid) &&
170 (tag1->dbOid == tag2->dbOid) &&
171 (tag1->relNumber == tag2->relNumber) &&
172 (tag1->blockNum == tag2->blockNum) &&
173 (tag1->forkNum == tag2->forkNum);
BlockNumber blockNum
RelFileNumber relNumber
ForkNumber forkNum
Oid spcOid

References buftag::blockNum, buftag::dbOid, buftag::forkNum, buftag::relNumber, and buftag::spcOid.

Referenced by InvalidateBuffer(), InvalidateVictimBuffer(), LocalBufferAlloc(), and ReadRecentBuffer().

◆ BufMappingPartitionLock()

static LWLock * BufMappingPartitionLock ( uint32  hashcode)
inlinestatic

Definition at line 198 of file buf_internals.h.

200{
202 BufTableHashPartition(hashcode)].lock;
static uint32 BufTableHashPartition(uint32 hashcode)
LWLockPadded * MainLWLockArray
Definition: lwlock.c:161
#define BUFFER_MAPPING_LWLOCK_OFFSET
Definition: lwlock.h:102
LWLock lock
Definition: lwlock.h:70

References BUFFER_MAPPING_LWLOCK_OFFSET, BufTableHashPartition(), LWLockPadded::lock, and MainLWLockArray.

Referenced by BufferAlloc(), ExtendBufferedRelShared(), FindAndDropRelationBuffers(), InvalidateBuffer(), InvalidateVictimBuffer(), and PrefetchSharedBuffer().

◆ BufMappingPartitionLockByIndex()

static LWLock * BufMappingPartitionLockByIndex ( uint32  index)
inlinestatic

◆ BufTableDelete()

void BufTableDelete ( BufferTag tagPtr,
uint32  hashcode 
)

Definition at line 148 of file buf_table.c.

149{
150 BufferLookupEnt *result;
151
152 result = (BufferLookupEnt *)
154 tagPtr,
155 hashcode,
157 NULL);
158
159 if (!result) /* shouldn't happen */
160 elog(ERROR, "shared buffer hash table corrupted");
161}
static HTAB * SharedBufHash
Definition: buf_table.c:33
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:965
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
@ HASH_REMOVE
Definition: hsearch.h:115

References elog, ERROR, HASH_REMOVE, hash_search_with_hash_value(), and SharedBufHash.

Referenced by InvalidateBuffer(), and InvalidateVictimBuffer().

◆ BufTableHashCode()

uint32 BufTableHashCode ( BufferTag tagPtr)

Definition at line 78 of file buf_table.c.

79{
80 return get_hash_value(SharedBufHash, tagPtr);
81}
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition: dynahash.c:908

References get_hash_value(), and SharedBufHash.

Referenced by BufferAlloc(), ExtendBufferedRelShared(), FindAndDropRelationBuffers(), InvalidateBuffer(), InvalidateVictimBuffer(), and PrefetchSharedBuffer().

◆ BufTableHashPartition()

static uint32 BufTableHashPartition ( uint32  hashcode)
inlinestatic

Definition at line 192 of file buf_internals.h.

194{
195 return hashcode % NUM_BUFFER_PARTITIONS;
#define NUM_BUFFER_PARTITIONS
Definition: lwlock.h:91

References NUM_BUFFER_PARTITIONS.

Referenced by BufMappingPartitionLock().

◆ BufTableInsert()

int BufTableInsert ( BufferTag tagPtr,
uint32  hashcode,
int  buf_id 
)

Definition at line 118 of file buf_table.c.

119{
120 BufferLookupEnt *result;
121 bool found;
122
123 Assert(buf_id >= 0); /* -1 is reserved for not-in-table */
124 Assert(tagPtr->blockNum != P_NEW); /* invalid tag */
125
126 result = (BufferLookupEnt *)
128 tagPtr,
129 hashcode,
131 &found);
132
133 if (found) /* found something already in the table */
134 return result->id;
135
136 result->id = buf_id;
137
138 return -1;
139}
#define P_NEW
Definition: bufmgr.h:198
Assert(PointerIsAligned(start, uint64))
@ HASH_ENTER
Definition: hsearch.h:114

References Assert(), buftag::blockNum, HASH_ENTER, hash_search_with_hash_value(), BufferLookupEnt::id, P_NEW, and SharedBufHash.

Referenced by BufferAlloc(), and ExtendBufferedRelShared().

◆ BufTableLookup()

int BufTableLookup ( BufferTag tagPtr,
uint32  hashcode 
)

Definition at line 90 of file buf_table.c.

91{
92 BufferLookupEnt *result;
93
94 result = (BufferLookupEnt *)
96 tagPtr,
97 hashcode,
99 NULL);
100
101 if (!result)
102 return -1;
103
104 return result->id;
105}
@ HASH_FIND
Definition: hsearch.h:113

References HASH_FIND, hash_search_with_hash_value(), BufferLookupEnt::id, and SharedBufHash.

Referenced by BufferAlloc(), FindAndDropRelationBuffers(), and PrefetchSharedBuffer().

◆ BufTableShmemSize()

Size BufTableShmemSize ( int  size)

Definition at line 41 of file buf_table.c.

42{
43 return hash_estimate_size(size, sizeof(BufferLookupEnt));
44}
Size hash_estimate_size(int64 num_entries, Size entrysize)
Definition: dynahash.c:783

References hash_estimate_size().

Referenced by StrategyShmemSize().

◆ BufTagGetForkNum()

◆ BufTagGetRelFileLocator()

◆ BufTagGetRelNumber()

static RelFileNumber BufTagGetRelNumber ( const BufferTag tag)
inlinestatic

◆ BufTagMatchesRelFileLocator()

◆ BufTagSetRelForkDetails()

static void BufTagSetRelForkDetails ( BufferTag tag,
RelFileNumber  relnumber,
ForkNumber  forknum 
)
inlinestatic

Definition at line 127 of file buf_internals.h.

130{
131 tag->relNumber = relnumber;
132 tag->forkNum = forknum;

References buftag::forkNum, and buftag::relNumber.

Referenced by ClearBufferTag(), and InitBufferTag().

◆ ClearBufferTag()

static void ClearBufferTag ( BufferTag tag)
inlinestatic

Definition at line 147 of file buf_internals.h.

149{
150 tag->spcOid = InvalidOid;
151 tag->dbOid = InvalidOid;
#define InvalidBlockNumber
Definition: block.h:33
static void BufTagSetRelForkDetails(BufferTag *tag, RelFileNumber relnumber, ForkNumber forknum)
#define InvalidOid
Definition: postgres_ext.h:37
@ InvalidForkNumber
Definition: relpath.h:57
#define InvalidRelFileNumber
Definition: relpath.h:26

References buftag::blockNum, BufTagSetRelForkDetails(), buftag::dbOid, InvalidBlockNumber, InvalidForkNumber, InvalidOid, InvalidRelFileNumber, and buftag::spcOid.

Referenced by BufferManagerShmemInit(), InvalidateBuffer(), InvalidateLocalBuffer(), and InvalidateVictimBuffer().

◆ DropRelationAllLocalBuffers()

void DropRelationAllLocalBuffers ( RelFileLocator  rlocator)

Definition at line 702 of file localbuf.c.

703{
704 int i;
705
706 for (i = 0; i < NLocBuffer; i++)
707 {
709 uint32 buf_state;
710
711 buf_state = pg_atomic_read_u32(&bufHdr->state);
712
713 if ((buf_state & BM_TAG_VALID) &&
714 BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator))
715 {
716 InvalidateLocalBuffer(bufHdr, true);
717 }
718 }
719}
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:237
#define BM_TAG_VALID
Definition: buf_internals.h:71
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
uint32_t uint32
Definition: c.h:552
int i
Definition: isn.c:77
void InvalidateLocalBuffer(BufferDesc *bufHdr, bool check_unreferenced)
Definition: localbuf.c:605
int NLocBuffer
Definition: localbuf.c:45
BufferTag tag
pg_atomic_uint32 state

References BM_TAG_VALID, BufTagMatchesRelFileLocator(), GetLocalBufferDescriptor(), i, InvalidateLocalBuffer(), NLocBuffer, pg_atomic_read_u32(), BufferDesc::state, and BufferDesc::tag.

Referenced by DropRelationsAllBuffers().

◆ DropRelationLocalBuffers()

void DropRelationLocalBuffers ( RelFileLocator  rlocator,
ForkNumber forkNum,
int  nforks,
BlockNumber firstDelBlock 
)

Definition at line 665 of file localbuf.c.

667{
668 int i;
669 int j;
670
671 for (i = 0; i < NLocBuffer; i++)
672 {
674 uint32 buf_state;
675
676 buf_state = pg_atomic_read_u32(&bufHdr->state);
677
678 if (!(buf_state & BM_TAG_VALID) ||
679 !BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator))
680 continue;
681
682 for (j = 0; j < nforks; j++)
683 {
684 if (BufTagGetForkNum(&bufHdr->tag) == forkNum[j] &&
685 bufHdr->tag.blockNum >= firstDelBlock[j])
686 {
687 InvalidateLocalBuffer(bufHdr, true);
688 break;
689 }
690 }
691 }
692}
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
int j
Definition: isn.c:78

References buftag::blockNum, BM_TAG_VALID, BufTagGetForkNum(), BufTagMatchesRelFileLocator(), GetLocalBufferDescriptor(), i, InvalidateLocalBuffer(), j, NLocBuffer, pg_atomic_read_u32(), BufferDesc::state, and BufferDesc::tag.

Referenced by DropRelationBuffers().

◆ ExtendBufferedRelLocal()

BlockNumber ExtendBufferedRelLocal ( BufferManagerRelation  bmr,
ForkNumber  fork,
uint32  flags,
uint32  extend_by,
BlockNumber  extend_upto,
Buffer buffers,
uint32 extended_by 
)

Definition at line 346 of file localbuf.c.

353{
354 BlockNumber first_block;
355 instr_time io_start;
356
357 /* Initialize local buffers if first request in this session */
358 if (LocalBufHash == NULL)
360
361 LimitAdditionalLocalPins(&extend_by);
362
363 for (uint32 i = 0; i < extend_by; i++)
364 {
365 BufferDesc *buf_hdr;
366 Block buf_block;
367
368 buffers[i] = GetLocalVictimBuffer();
369 buf_hdr = GetLocalBufferDescriptor(-buffers[i] - 1);
370 buf_block = LocalBufHdrGetBlock(buf_hdr);
371
372 /* new buffers are zero-filled */
373 MemSet(buf_block, 0, BLCKSZ);
374 }
375
376 first_block = smgrnblocks(BMR_GET_SMGR(bmr), fork);
377
378 if (extend_upto != InvalidBlockNumber)
379 {
380 /*
381 * In contrast to shared relations, nothing could change the relation
382 * size concurrently. Thus we shouldn't end up finding that we don't
383 * need to do anything.
384 */
385 Assert(first_block <= extend_upto);
386
387 Assert((uint64) first_block + extend_by <= extend_upto);
388 }
389
390 /* Fail if relation is already at maximum possible length */
391 if ((uint64) first_block + extend_by >= MaxBlockNumber)
393 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
394 errmsg("cannot extend relation %s beyond %u blocks",
395 relpath(BMR_GET_SMGR(bmr)->smgr_rlocator, fork).str,
397
398 for (uint32 i = 0; i < extend_by; i++)
399 {
400 int victim_buf_id;
401 BufferDesc *victim_buf_hdr;
402 BufferTag tag;
403 LocalBufferLookupEnt *hresult;
404 bool found;
405
406 victim_buf_id = -buffers[i] - 1;
407 victim_buf_hdr = GetLocalBufferDescriptor(victim_buf_id);
408
409 /* in case we need to pin an existing buffer below */
411
412 InitBufferTag(&tag, &BMR_GET_SMGR(bmr)->smgr_rlocator.locator, fork,
413 first_block + i);
414
415 hresult = (LocalBufferLookupEnt *)
416 hash_search(LocalBufHash, &tag, HASH_ENTER, &found);
417 if (found)
418 {
419 BufferDesc *existing_hdr;
420 uint32 buf_state;
421
423
424 existing_hdr = GetLocalBufferDescriptor(hresult->id);
425 PinLocalBuffer(existing_hdr, false);
426 buffers[i] = BufferDescriptorGetBuffer(existing_hdr);
427
428 /*
429 * Clear the BM_VALID bit, do StartLocalBufferIO() and proceed.
430 */
431 buf_state = pg_atomic_read_u32(&existing_hdr->state);
432 Assert(buf_state & BM_TAG_VALID);
433 Assert(!(buf_state & BM_DIRTY));
434 buf_state &= ~BM_VALID;
435 pg_atomic_unlocked_write_u32(&existing_hdr->state, buf_state);
436
437 /* no need to loop for local buffers */
438 StartLocalBufferIO(existing_hdr, true, false);
439 }
440 else
441 {
442 uint32 buf_state = pg_atomic_read_u32(&victim_buf_hdr->state);
443
444 Assert(!(buf_state & (BM_VALID | BM_TAG_VALID | BM_DIRTY | BM_JUST_DIRTIED)));
445
446 victim_buf_hdr->tag = tag;
447
448 buf_state |= BM_TAG_VALID | BUF_USAGECOUNT_ONE;
449
450 pg_atomic_unlocked_write_u32(&victim_buf_hdr->state, buf_state);
451
452 hresult->id = victim_buf_id;
453
454 StartLocalBufferIO(victim_buf_hdr, true, false);
455 }
456 }
457
459
460 /* actually extend relation */
461 smgrzeroextend(BMR_GET_SMGR(bmr), fork, first_block, extend_by, false);
462
464 io_start, 1, extend_by * BLCKSZ);
465
466 for (uint32 i = 0; i < extend_by; i++)
467 {
468 Buffer buf = buffers[i];
469 BufferDesc *buf_hdr;
470 uint32 buf_state;
471
472 buf_hdr = GetLocalBufferDescriptor(-buf - 1);
473
474 buf_state = pg_atomic_read_u32(&buf_hdr->state);
475 buf_state |= BM_VALID;
476 pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state);
477 }
478
479 *extended_by = extend_by;
480
482
483 return first_block;
484}
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:295
uint32 BlockNumber
Definition: block.h:31
#define MaxBlockNumber
Definition: block.h:35
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
#define BM_DIRTY
Definition: buf_internals.h:69
#define BM_JUST_DIRTIED
Definition: buf_internals.h:74
#define BUF_USAGECOUNT_ONE
Definition: buf_internals.h:54
#define BM_VALID
Definition: buf_internals.h:70
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
bool track_io_timing
Definition: bufmgr.c:169
void * Block
Definition: bufmgr.h:26
#define BMR_GET_SMGR(bmr)
Definition: bufmgr.h:118
uint64_t uint64
Definition: c.h:553
#define MemSet(start, val, len)
Definition: c.h:1011
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:952
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ereport(elevel,...)
Definition: elog.h:150
const char * str
BufferUsage pgBufferUsage
Definition: instrument.c:20
void UnpinLocalBuffer(Buffer buffer)
Definition: localbuf.c:841
bool StartLocalBufferIO(BufferDesc *bufHdr, bool forInput, bool nowait)
Definition: localbuf.c:523
static HTAB * LocalBufHash
Definition: localbuf.c:53
#define LocalBufHdrGetBlock(bufHdr)
Definition: localbuf.c:42
bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
Definition: localbuf.c:805
static void InitLocalBuffers(void)
Definition: localbuf.c:728
void LimitAdditionalLocalPins(uint32 *additional_pins)
Definition: localbuf.c:323
static Buffer GetLocalVictimBuffer(void)
Definition: localbuf.c:224
static char buf[DEFAULT_XLOG_SEG_SIZE]
Definition: pg_test_fsync.c:71
@ IOOBJECT_TEMP_RELATION
Definition: pgstat.h:278
@ IOCONTEXT_NORMAL
Definition: pgstat.h:289
@ IOOP_EXTEND
Definition: pgstat.h:314
instr_time pgstat_prepare_io_time(bool track_io_guc)
Definition: pgstat_io.c:91
void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt, uint64 bytes)
Definition: pgstat_io.c:122
#define relpath(rlocator, forknum)
Definition: relpath.h:150
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:449
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:819
void smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks, bool skipFsync)
Definition: smgr.c:649
int64 local_blks_written
Definition: instrument.h:33

References Assert(), BM_DIRTY, BM_JUST_DIRTIED, BM_TAG_VALID, BM_VALID, BMR_GET_SMGR, buf, BUF_USAGECOUNT_ONE, BufferDescriptorGetBuffer(), CurrentResourceOwner, ereport, errcode(), errmsg(), ERROR, GetLocalBufferDescriptor(), GetLocalVictimBuffer(), HASH_ENTER, hash_search(), i, LocalBufferLookupEnt::id, InitBufferTag(), InitLocalBuffers(), InvalidBlockNumber, IOCONTEXT_NORMAL, IOOBJECT_TEMP_RELATION, IOOP_EXTEND, LimitAdditionalLocalPins(), BufferUsage::local_blks_written, LocalBufHash, LocalBufHdrGetBlock, MaxBlockNumber, MemSet, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgBufferUsage, pgstat_count_io_op_time(), pgstat_prepare_io_time(), PinLocalBuffer(), relpath, ResourceOwnerEnlarge(), smgrnblocks(), smgrzeroextend(), StartLocalBufferIO(), BufferDesc::state, str, BufferDesc::tag, track_io_timing, and UnpinLocalBuffer().

Referenced by ExtendBufferedRelCommon().

◆ FlushLocalBuffer()

void FlushLocalBuffer ( BufferDesc bufHdr,
SMgrRelation  reln 
)

Definition at line 183 of file localbuf.c.

184{
185 instr_time io_start;
186 Page localpage = (char *) LocalBufHdrGetBlock(bufHdr);
187
189
190 /*
191 * Try to start an I/O operation. There currently are no reasons for
192 * StartLocalBufferIO to return false, so we raise an error in that case.
193 */
194 if (!StartLocalBufferIO(bufHdr, false, false))
195 elog(ERROR, "failed to start write IO on local buffer");
196
197 /* Find smgr relation for buffer */
198 if (reln == NULL)
199 reln = smgropen(BufTagGetRelFileLocator(&bufHdr->tag),
201
202 PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
203
205
206 /* And write... */
207 smgrwrite(reln,
208 BufTagGetForkNum(&bufHdr->tag),
209 bufHdr->tag.blockNum,
210 localpage,
211 false);
212
213 /* Temporary table I/O does not use Buffer Access Strategies */
215 IOOP_WRITE, io_start, 1, BLCKSZ);
216
217 /* Mark not-dirty */
218 TerminateLocalBufferIO(bufHdr, true, 0, false);
219
221}
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1541
PageData * Page
Definition: bufpage.h:81
ProcNumber MyProcNumber
Definition: globals.c:90
int32 * LocalRefCount
Definition: localbuf.c:49
void TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty, uint32 set_flag_bits, bool release_aio)
Definition: localbuf.c:562
@ IOOP_WRITE
Definition: pgstat.h:316
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
Definition: smgr.c:240
static void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition: smgr.h:131

References Assert(), buftag::blockNum, BufferDescriptorGetBuffer(), BufTagGetForkNum(), BufTagGetRelFileLocator(), elog, ERROR, IOCONTEXT_NORMAL, IOOBJECT_TEMP_RELATION, IOOP_WRITE, BufferUsage::local_blks_written, LocalBufHdrGetBlock, LocalRefCount, MyProcNumber, PageSetChecksumInplace(), pgBufferUsage, pgstat_count_io_op_time(), pgstat_prepare_io_time(), smgropen(), smgrwrite(), StartLocalBufferIO(), BufferDesc::tag, TerminateLocalBufferIO(), and track_io_timing.

Referenced by FlushRelationBuffers(), GetLocalVictimBuffer(), and invalidate_rel_block().

◆ GetBufferDescriptor()

static BufferDesc * GetBufferDescriptor ( uint32  id)
inlinestatic

Definition at line 355 of file buf_internals.h.

357{
358 return &(BufferDescriptors[id]).bufferdesc;
PGDLLIMPORT BufferDescPadded * BufferDescriptors
Definition: buf_init.c:21

References BufferDescriptors.

Referenced by AbortBufferIO(), apw_dump_now(), buffer_call_start_io(), buffer_call_terminate_io(), buffer_readv_complete_one(), buffer_stage_common(), BufferAlloc(), BufferGetBlockNumber(), BufferGetLSNAtomic(), BufferGetTag(), BufferIsDirty(), BufferIsLockedByMe(), BufferIsLockedByMeInMode(), BufferIsPermanent(), BufferManagerShmemInit(), BufferSync(), CheckReadBuffersOperation(), ConditionalLockBuffer(), ConditionalLockBufferForCleanup(), create_toy_buffer(), DebugPrintBufferRefcount(), DropDatabaseBuffers(), DropRelationBuffers(), DropRelationsAllBuffers(), EvictAllUnpinnedBuffers(), EvictRelUnpinnedBuffers(), EvictUnpinnedBuffer(), ExtendBufferedRelShared(), FindAndDropRelationBuffers(), FlushDatabaseBuffers(), FlushOneBuffer(), FlushRelationBuffers(), FlushRelationsAllBuffers(), GetBufferFromRing(), invalidate_rel_block(), IsBufferCleanupOK(), LockBuffer(), LockBufferForCleanup(), MarkBufferDirty(), MarkBufferDirtyHint(), MarkDirtyAllUnpinnedBuffers(), MarkDirtyRelUnpinnedBuffers(), MarkDirtyUnpinnedBuffer(), pg_buffercache_os_pages_internal(), pg_buffercache_pages(), pg_buffercache_summary(), read_rel_block_ll(), ReadBuffersCanStartIOOnce(), ReadRecentBuffer(), ReleaseAndReadBuffer(), ReleaseBuffer(), ResOwnerReleaseBufferPin(), StartReadBuffersImpl(), StrategyGetBuffer(), SyncOneBuffer(), TrackNewBufferPin(), and ZeroAndLockBuffer().

◆ GetLocalBufferDescriptor()

◆ InitBufferTag()

static void InitBufferTag ( BufferTag tag,
const RelFileLocator rlocator,
ForkNumber  forkNum,
BlockNumber  blockNum 
)
inlinestatic

◆ InitBufTable()

void InitBufTable ( int  size)

Definition at line 51 of file buf_table.c.

52{
53 HASHCTL info;
54
55 /* assume no locking is needed yet */
56
57 /* BufferTag maps to Buffer */
58 info.keysize = sizeof(BufferTag);
59 info.entrysize = sizeof(BufferLookupEnt);
61
62 SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
63 size, size,
64 &info,
66}
struct buftag BufferTag
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define HASH_FIXED_SIZE
Definition: hsearch.h:105
#define HASH_PARTITION
Definition: hsearch.h:92
HTAB * ShmemInitHash(const char *name, int64 init_size, int64 max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:334
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
int64 num_partitions
Definition: hsearch.h:68

References HASHCTL::entrysize, HASH_BLOBS, HASH_ELEM, HASH_FIXED_SIZE, HASH_PARTITION, HASHCTL::keysize, NUM_BUFFER_PARTITIONS, HASHCTL::num_partitions, SharedBufHash, and ShmemInitHash().

Referenced by StrategyInitialize().

◆ InvalidateLocalBuffer()

void InvalidateLocalBuffer ( BufferDesc bufHdr,
bool  check_unreferenced 
)

Definition at line 605 of file localbuf.c.

606{
607 Buffer buffer = BufferDescriptorGetBuffer(bufHdr);
608 int bufid = -buffer - 1;
609 uint32 buf_state;
610 LocalBufferLookupEnt *hresult;
611
612 /*
613 * It's possible that we started IO on this buffer before e.g. aborting
614 * the transaction that created a table. We need to wait for that IO to
615 * complete before removing / reusing the buffer.
616 */
617 if (pgaio_wref_valid(&bufHdr->io_wref))
618 {
619 PgAioWaitRef iow = bufHdr->io_wref;
620
621 pgaio_wref_wait(&iow);
622 Assert(!pgaio_wref_valid(&bufHdr->io_wref));
623 }
624
625 buf_state = pg_atomic_read_u32(&bufHdr->state);
626
627 /*
628 * We need to test not just LocalRefCount[bufid] but also the BufferDesc
629 * itself, as the latter is used to represent a pin by the AIO subsystem.
630 * This can happen if AIO is initiated and then the query errors out.
631 */
632 if (check_unreferenced &&
633 (LocalRefCount[bufid] != 0 || BUF_STATE_GET_REFCOUNT(buf_state) != 0))
634 elog(ERROR, "block %u of %s is still referenced (local %d)",
635 bufHdr->tag.blockNum,
638 BufTagGetForkNum(&bufHdr->tag)).str,
639 LocalRefCount[bufid]);
640
641 /* Remove entry from hashtable */
642 hresult = (LocalBufferLookupEnt *)
643 hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
644 if (!hresult) /* shouldn't happen */
645 elog(ERROR, "local buffer hash table corrupted");
646 /* Mark buffer invalid */
647 ClearBufferTag(&bufHdr->tag);
648 buf_state &= ~BUF_FLAG_MASK;
649 buf_state &= ~BUF_USAGECOUNT_MASK;
650 pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
651}
bool pgaio_wref_valid(PgAioWaitRef *iow)
Definition: aio.c:971
void pgaio_wref_wait(PgAioWaitRef *iow)
Definition: aio.c:991
static void ClearBufferTag(BufferTag *tag)
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:59
#define relpathbackend(rlocator, backend, forknum)
Definition: relpath.h:141
PgAioWaitRef io_wref

References Assert(), buftag::blockNum, BUF_STATE_GET_REFCOUNT, BufferDescriptorGetBuffer(), BufTagGetForkNum(), BufTagGetRelFileLocator(), ClearBufferTag(), elog, ERROR, HASH_REMOVE, hash_search(), BufferDesc::io_wref, LocalBufHash, LocalRefCount, MyProcNumber, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgaio_wref_valid(), pgaio_wref_wait(), relpathbackend, BufferDesc::state, and BufferDesc::tag.

Referenced by DropRelationAllLocalBuffers(), DropRelationLocalBuffers(), GetLocalVictimBuffer(), invalidate_rel_block(), and modify_rel_block().

◆ IOContextForStrategy()

IOContext IOContextForStrategy ( BufferAccessStrategy  strategy)

Definition at line 747 of file freelist.c.

748{
749 if (!strategy)
750 return IOCONTEXT_NORMAL;
751
752 switch (strategy->btype)
753 {
754 case BAS_NORMAL:
755
756 /*
757 * Currently, GetAccessStrategy() returns NULL for
758 * BufferAccessStrategyType BAS_NORMAL, so this case is
759 * unreachable.
760 */
762 return IOCONTEXT_NORMAL;
763 case BAS_BULKREAD:
764 return IOCONTEXT_BULKREAD;
765 case BAS_BULKWRITE:
766 return IOCONTEXT_BULKWRITE;
767 case BAS_VACUUM:
768 return IOCONTEXT_VACUUM;
769 }
770
771 elog(ERROR, "unrecognized BufferAccessStrategyType: %d", strategy->btype);
773}
@ BAS_BULKREAD
Definition: bufmgr.h:37
@ BAS_NORMAL
Definition: bufmgr.h:36
@ BAS_VACUUM
Definition: bufmgr.h:40
@ BAS_BULKWRITE
Definition: bufmgr.h:39
#define pg_unreachable()
Definition: c.h:347
@ IOCONTEXT_VACUUM
Definition: pgstat.h:290
@ IOCONTEXT_BULKREAD
Definition: pgstat.h:286
@ IOCONTEXT_BULKWRITE
Definition: pgstat.h:287
BufferAccessStrategyType btype
Definition: freelist.c:67

References BAS_BULKREAD, BAS_BULKWRITE, BAS_NORMAL, BAS_VACUUM, BufferAccessStrategyData::btype, elog, ERROR, IOCONTEXT_BULKREAD, IOCONTEXT_BULKWRITE, IOCONTEXT_NORMAL, IOCONTEXT_VACUUM, and pg_unreachable.

Referenced by AsyncReadBuffers(), ExtendBufferedRelShared(), PinBufferForBlock(), and WaitReadBuffers().

◆ IssuePendingWritebacks()

void IssuePendingWritebacks ( WritebackContext wb_context,
IOContext  io_context 
)

Definition at line 6563 of file bufmgr.c.

6564{
6565 instr_time io_start;
6566 int i;
6567
6568 if (wb_context->nr_pending == 0)
6569 return;
6570
6571 /*
6572 * Executing the writes in-order can make them a lot faster, and allows to
6573 * merge writeback requests to consecutive blocks into larger writebacks.
6574 */
6575 sort_pending_writebacks(wb_context->pending_writebacks,
6576 wb_context->nr_pending);
6577
6579
6580 /*
6581 * Coalesce neighbouring writes, but nothing else. For that we iterate
6582 * through the, now sorted, array of pending flushes, and look forward to
6583 * find all neighbouring (or identical) writes.
6584 */
6585 for (i = 0; i < wb_context->nr_pending; i++)
6586 {
6589 SMgrRelation reln;
6590 int ahead;
6591 BufferTag tag;
6592 RelFileLocator currlocator;
6593 Size nblocks = 1;
6594
6595 cur = &wb_context->pending_writebacks[i];
6596 tag = cur->tag;
6597 currlocator = BufTagGetRelFileLocator(&tag);
6598
6599 /*
6600 * Peek ahead, into following writeback requests, to see if they can
6601 * be combined with the current one.
6602 */
6603 for (ahead = 0; i + ahead + 1 < wb_context->nr_pending; ahead++)
6604 {
6605
6606 next = &wb_context->pending_writebacks[i + ahead + 1];
6607
6608 /* different file, stop */
6609 if (!RelFileLocatorEquals(currlocator,
6610 BufTagGetRelFileLocator(&next->tag)) ||
6611 BufTagGetForkNum(&cur->tag) != BufTagGetForkNum(&next->tag))
6612 break;
6613
6614 /* ok, block queued twice, skip */
6615 if (cur->tag.blockNum == next->tag.blockNum)
6616 continue;
6617
6618 /* only merge consecutive writes */
6619 if (cur->tag.blockNum + 1 != next->tag.blockNum)
6620 break;
6621
6622 nblocks++;
6623 cur = next;
6624 }
6625
6626 i += ahead;
6627
6628 /* and finally tell the kernel to write the data to storage */
6629 reln = smgropen(currlocator, INVALID_PROC_NUMBER);
6630 smgrwriteback(reln, BufTagGetForkNum(&tag), tag.blockNum, nblocks);
6631 }
6632
6633 /*
6634 * Assume that writeback requests are only issued for buffers containing
6635 * blocks of permanent relations.
6636 */
6638 IOOP_WRITEBACK, io_start, wb_context->nr_pending, 0);
6639
6640 wb_context->nr_pending = 0;
6641}
static int32 next
Definition: blutils.c:224
size_t Size
Definition: c.h:624
struct cursor * cur
Definition: ecpg.c:29
@ IOOBJECT_RELATION
Definition: pgstat.h:277
@ IOOP_WRITEBACK
Definition: pgstat.h:311
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
#define RelFileLocatorEquals(locator1, locator2)
void smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
Definition: smgr.c:805
PendingWriteback pending_writebacks[WRITEBACK_MAX_PENDING_FLUSHES]

References buftag::blockNum, BufTagGetForkNum(), BufTagGetRelFileLocator(), cur, i, INVALID_PROC_NUMBER, IOOBJECT_RELATION, IOOP_WRITEBACK, next, WritebackContext::nr_pending, WritebackContext::pending_writebacks, pgstat_count_io_op_time(), pgstat_prepare_io_time(), RelFileLocatorEquals, smgropen(), smgrwriteback(), and track_io_timing.

Referenced by BufferSync(), and ScheduleBufferTagForWriteback().

◆ LocalBufferAlloc()

BufferDesc * LocalBufferAlloc ( SMgrRelation  smgr,
ForkNumber  forkNum,
BlockNumber  blockNum,
bool *  foundPtr 
)

Definition at line 119 of file localbuf.c.

121{
122 BufferTag newTag; /* identity of requested block */
123 LocalBufferLookupEnt *hresult;
124 BufferDesc *bufHdr;
125 Buffer victim_buffer;
126 int bufid;
127 bool found;
128
129 InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
130
131 /* Initialize local buffers if first request in this session */
132 if (LocalBufHash == NULL)
134
136
137 /* See if the desired buffer already exists */
138 hresult = (LocalBufferLookupEnt *)
139 hash_search(LocalBufHash, &newTag, HASH_FIND, NULL);
140
141 if (hresult)
142 {
143 bufid = hresult->id;
144 bufHdr = GetLocalBufferDescriptor(bufid);
145 Assert(BufferTagsEqual(&bufHdr->tag, &newTag));
146
147 *foundPtr = PinLocalBuffer(bufHdr, true);
148 }
149 else
150 {
151 uint32 buf_state;
152
153 victim_buffer = GetLocalVictimBuffer();
154 bufid = -victim_buffer - 1;
155 bufHdr = GetLocalBufferDescriptor(bufid);
156
157 hresult = (LocalBufferLookupEnt *)
158 hash_search(LocalBufHash, &newTag, HASH_ENTER, &found);
159 if (found) /* shouldn't happen */
160 elog(ERROR, "local buffer hash table corrupted");
161 hresult->id = bufid;
162
163 /*
164 * it's all ours now.
165 */
166 bufHdr->tag = newTag;
167
168 buf_state = pg_atomic_read_u32(&bufHdr->state);
169 buf_state &= ~(BUF_FLAG_MASK | BUF_USAGECOUNT_MASK);
170 buf_state |= BM_TAG_VALID | BUF_USAGECOUNT_ONE;
171 pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
172
173 *foundPtr = false;
174 }
175
176 return bufHdr;
177}
#define BUF_USAGECOUNT_MASK
Definition: buf_internals.h:53
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
#define BUF_FLAG_MASK
Definition: buf_internals.h:56
RelFileLocator locator
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:38

References Assert(), BM_TAG_VALID, BUF_FLAG_MASK, BUF_USAGECOUNT_MASK, BUF_USAGECOUNT_ONE, BufferTagsEqual(), CurrentResourceOwner, elog, ERROR, GetLocalBufferDescriptor(), GetLocalVictimBuffer(), HASH_ENTER, HASH_FIND, hash_search(), LocalBufferLookupEnt::id, InitBufferTag(), InitLocalBuffers(), LocalBufHash, RelFileLocatorBackend::locator, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), PinLocalBuffer(), ResourceOwnerEnlarge(), SMgrRelationData::smgr_rlocator, BufferDesc::state, and BufferDesc::tag.

Referenced by PinBufferForBlock().

◆ LockBufHdr()

uint32 LockBufHdr ( BufferDesc desc)

Definition at line 6359 of file bufmgr.c.

6360{
6361 SpinDelayStatus delayStatus;
6362 uint32 old_buf_state;
6363
6365
6366 init_local_spin_delay(&delayStatus);
6367
6368 while (true)
6369 {
6370 /* set BM_LOCKED flag */
6371 old_buf_state = pg_atomic_fetch_or_u32(&desc->state, BM_LOCKED);
6372 /* if it wasn't set before we're OK */
6373 if (!(old_buf_state & BM_LOCKED))
6374 break;
6375 perform_spin_delay(&delayStatus);
6376 }
6377 finish_spin_delay(&delayStatus);
6378 return old_buf_state | BM_LOCKED;
6379}
static uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
Definition: atomics.h:410
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BM_LOCKED
Definition: buf_internals.h:68
void perform_spin_delay(SpinDelayStatus *status)
Definition: s_lock.c:126
void finish_spin_delay(SpinDelayStatus *status)
Definition: s_lock.c:186
#define init_local_spin_delay(status)
Definition: s_lock.h:733

References Assert(), BM_LOCKED, BufferDescriptorGetBuffer(), BufferIsLocal, finish_spin_delay(), init_local_spin_delay, perform_spin_delay(), pg_atomic_fetch_or_u32(), and BufferDesc::state.

Referenced by AbortBufferIO(), apw_dump_now(), buffer_stage_common(), BufferAlloc(), BufferGetLSNAtomic(), BufferSync(), ConditionalLockBufferForCleanup(), create_toy_buffer(), DropDatabaseBuffers(), DropRelationBuffers(), DropRelationsAllBuffers(), EvictAllUnpinnedBuffers(), EvictRelUnpinnedBuffers(), EvictUnpinnedBuffer(), ExtendBufferedRelShared(), FindAndDropRelationBuffers(), FlushBuffer(), FlushDatabaseBuffers(), FlushRelationBuffers(), FlushRelationsAllBuffers(), GetVictimBuffer(), InvalidateBuffer(), InvalidateVictimBuffer(), IsBufferCleanupOK(), LockBufferForCleanup(), MarkBufferDirtyHint(), MarkDirtyAllUnpinnedBuffers(), MarkDirtyRelUnpinnedBuffers(), MarkDirtyUnpinnedBuffer(), pg_buffercache_os_pages_internal(), pg_buffercache_pages(), StartBufferIO(), SyncOneBuffer(), TerminateBufferIO(), UnlockBuffers(), WaitIO(), and WakePinCountWaiter().

◆ MarkLocalBufferDirty()

void MarkLocalBufferDirty ( Buffer  buffer)

Definition at line 491 of file localbuf.c.

492{
493 int bufid;
494 BufferDesc *bufHdr;
495 uint32 buf_state;
496
497 Assert(BufferIsLocal(buffer));
498
499#ifdef LBDEBUG
500 fprintf(stderr, "LB DIRTY %d\n", buffer);
501#endif
502
503 bufid = -buffer - 1;
504
505 Assert(LocalRefCount[bufid] > 0);
506
507 bufHdr = GetLocalBufferDescriptor(bufid);
508
509 buf_state = pg_atomic_read_u32(&bufHdr->state);
510
511 if (!(buf_state & BM_DIRTY))
513
514 buf_state |= BM_DIRTY;
515
516 pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
517}
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
int64 local_blks_dirtied
Definition: instrument.h:32

References Assert(), BM_DIRTY, BufferIsLocal, fprintf, GetLocalBufferDescriptor(), BufferUsage::local_blks_dirtied, LocalRefCount, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgBufferUsage, and BufferDesc::state.

Referenced by MarkBufferDirty(), and MarkBufferDirtyHint().

◆ PinLocalBuffer()

bool PinLocalBuffer ( BufferDesc buf_hdr,
bool  adjust_usagecount 
)

Definition at line 805 of file localbuf.c.

806{
807 uint32 buf_state;
808 Buffer buffer = BufferDescriptorGetBuffer(buf_hdr);
809 int bufid = -buffer - 1;
810
811 buf_state = pg_atomic_read_u32(&buf_hdr->state);
812
813 if (LocalRefCount[bufid] == 0)
814 {
816 buf_state += BUF_REFCOUNT_ONE;
817 if (adjust_usagecount &&
819 {
820 buf_state += BUF_USAGECOUNT_ONE;
821 }
822 pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state);
823
824 /*
825 * See comment in PinBuffer().
826 *
827 * If the buffer isn't allocated yet, it'll be marked as defined in
828 * GetLocalBufferStorage().
829 */
830 if (LocalBufHdrGetBlock(buf_hdr) != NULL)
832 }
833 LocalRefCount[bufid]++;
836
837 return buf_state & BM_VALID;
838}
#define BM_MAX_USAGE_COUNT
Definition: buf_internals.h:86
#define BUF_REFCOUNT_ONE
Definition: buf_internals.h:51
#define BUF_STATE_GET_USAGECOUNT(state)
Definition: buf_internals.h:60
static void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
static int NLocalPinnedBuffers
Definition: localbuf.c:56
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26

References BM_MAX_USAGE_COUNT, BM_VALID, BUF_REFCOUNT_ONE, BUF_STATE_GET_USAGECOUNT, BUF_USAGECOUNT_ONE, BufferDescriptorGetBuffer(), CurrentResourceOwner, LocalBufHdrGetBlock, LocalRefCount, NLocalPinnedBuffers, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), ResourceOwnerRememberBuffer(), BufferDesc::state, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by ExtendBufferedRelLocal(), FlushRelationBuffers(), GetLocalVictimBuffer(), LocalBufferAlloc(), and ReadRecentBuffer().

◆ PrefetchLocalBuffer()

PrefetchBufferResult PrefetchLocalBuffer ( SMgrRelation  smgr,
ForkNumber  forkNum,
BlockNumber  blockNum 
)

Definition at line 72 of file localbuf.c.

74{
75 PrefetchBufferResult result = {InvalidBuffer, false};
76 BufferTag newTag; /* identity of requested block */
77 LocalBufferLookupEnt *hresult;
78
79 InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
80
81 /* Initialize local buffers if first request in this session */
82 if (LocalBufHash == NULL)
84
85 /* See if the desired buffer already exists */
86 hresult = (LocalBufferLookupEnt *)
87 hash_search(LocalBufHash, &newTag, HASH_FIND, NULL);
88
89 if (hresult)
90 {
91 /* Yes, so nothing to do */
92 result.recent_buffer = -hresult->id - 1;
93 }
94 else
95 {
96#ifdef USE_PREFETCH
97 /* Not in buffers, so initiate prefetch */
98 if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
99 smgrprefetch(smgr, forkNum, blockNum, 1))
100 {
101 result.initiated_io = true;
102 }
103#endif /* USE_PREFETCH */
104 }
105
106 return result;
107}
#define InvalidBuffer
Definition: buf.h:25
int io_direct_flags
Definition: fd.c:168
#define IO_DIRECT_DATA
Definition: fd.h:54
bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks)
Definition: smgr.c:678
Buffer recent_buffer
Definition: bufmgr.h:61

References HASH_FIND, hash_search(), LocalBufferLookupEnt::id, InitBufferTag(), PrefetchBufferResult::initiated_io, InitLocalBuffers(), InvalidBuffer, IO_DIRECT_DATA, io_direct_flags, LocalBufHash, RelFileLocatorBackend::locator, PrefetchBufferResult::recent_buffer, SMgrRelationData::smgr_rlocator, and smgrprefetch().

Referenced by PrefetchBuffer().

◆ ResourceOwnerForgetBuffer()

static void ResourceOwnerForgetBuffer ( ResourceOwner  owner,
Buffer  buffer 
)
inlinestatic

Definition at line 470 of file buf_internals.h.

472{
PGDLLIMPORT const ResourceOwnerDesc buffer_pin_resowner_desc
Definition: bufmgr.c:269
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:222
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:561

References buffer_pin_resowner_desc, Int32GetDatum(), and ResourceOwnerForget().

Referenced by UnpinBuffer(), and UnpinLocalBuffer().

◆ ResourceOwnerForgetBufferIO()

static void ResourceOwnerForgetBufferIO ( ResourceOwner  owner,
Buffer  buffer 
)
inlinestatic

Definition at line 480 of file buf_internals.h.

482{
PGDLLIMPORT const ResourceOwnerDesc buffer_io_resowner_desc
Definition: bufmgr.c:260

References buffer_io_resowner_desc, Int32GetDatum(), and ResourceOwnerForget().

Referenced by buffer_call_start_io(), buffer_stage_common(), and TerminateBufferIO().

◆ ResourceOwnerRememberBuffer()

static void ResourceOwnerRememberBuffer ( ResourceOwner  owner,
Buffer  buffer 
)
inlinestatic

Definition at line 465 of file buf_internals.h.

467{
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:521

References buffer_pin_resowner_desc, Int32GetDatum(), and ResourceOwnerRemember().

Referenced by IncrBufferRefCount(), PinBuffer(), PinLocalBuffer(), and TrackNewBufferPin().

◆ ResourceOwnerRememberBufferIO()

static void ResourceOwnerRememberBufferIO ( ResourceOwner  owner,
Buffer  buffer 
)
inlinestatic

◆ ScheduleBufferTagForWriteback()

void ScheduleBufferTagForWriteback ( WritebackContext wb_context,
IOContext  io_context,
BufferTag tag 
)

Definition at line 6513 of file bufmgr.c.

6515{
6516 PendingWriteback *pending;
6517
6518 /*
6519 * As pg_flush_data() doesn't do anything with fsync disabled, there's no
6520 * point in tracking in that case.
6521 */
6523 !enableFsync)
6524 return;
6525
6526 /*
6527 * Add buffer to the pending writeback array, unless writeback control is
6528 * disabled.
6529 */
6530 if (*wb_context->max_pending > 0)
6531 {
6533
6534 pending = &wb_context->pending_writebacks[wb_context->nr_pending++];
6535
6536 pending->tag = *tag;
6537 }
6538
6539 /*
6540 * Perform pending flushes if the writeback limit is exceeded. This
6541 * includes the case where previously an item has been added, but control
6542 * is now disabled.
6543 */
6544 if (wb_context->nr_pending >= *wb_context->max_pending)
6545 IssuePendingWritebacks(wb_context, io_context);
6546}
void IssuePendingWritebacks(WritebackContext *wb_context, IOContext io_context)
Definition: bufmgr.c:6563
bool enableFsync
Definition: globals.c:129
#define WRITEBACK_MAX_PENDING_FLUSHES

References Assert(), enableFsync, IO_DIRECT_DATA, io_direct_flags, IssuePendingWritebacks(), WritebackContext::max_pending, WritebackContext::nr_pending, WritebackContext::pending_writebacks, PendingWriteback::tag, and WRITEBACK_MAX_PENDING_FLUSHES.

Referenced by GetVictimBuffer(), and SyncOneBuffer().

◆ StartBufferIO()

bool StartBufferIO ( BufferDesc buf,
bool  forInput,
bool  nowait 
)

Definition at line 6141 of file bufmgr.c.

6142{
6143 uint32 buf_state;
6144
6146
6147 for (;;)
6148 {
6149 buf_state = LockBufHdr(buf);
6150
6151 if (!(buf_state & BM_IO_IN_PROGRESS))
6152 break;
6154 if (nowait)
6155 return false;
6156 WaitIO(buf);
6157 }
6158
6159 /* Once we get here, there is definitely no I/O active on this buffer */
6160
6161 /* Check if someone else already did the I/O */
6162 if (forInput ? (buf_state & BM_VALID) : !(buf_state & BM_DIRTY))
6163 {
6165 return false;
6166 }
6167
6168 UnlockBufHdrExt(buf, buf_state,
6170 0);
6171
6174
6175 return true;
6176}
static void UnlockBufHdr(BufferDesc *desc)
static uint32 UnlockBufHdrExt(BufferDesc *desc, uint32 old_buf_state, uint32 set_bits, uint32 unset_bits, int refcount_change)
static void ResourceOwnerRememberBufferIO(ResourceOwner owner, Buffer buffer)
#define BM_IO_IN_PROGRESS
Definition: buf_internals.h:72
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:6359
static void WaitIO(BufferDesc *buf)
Definition: bufmgr.c:6062

References BM_DIRTY, BM_IO_IN_PROGRESS, BM_VALID, buf, BufferDescriptorGetBuffer(), CurrentResourceOwner, LockBufHdr(), ResourceOwnerEnlarge(), ResourceOwnerRememberBufferIO(), UnlockBufHdr(), UnlockBufHdrExt(), and WaitIO().

Referenced by buffer_call_start_io(), ExtendBufferedRelShared(), FlushBuffer(), read_rel_block_ll(), ReadBuffersCanStartIOOnce(), and ZeroAndLockBuffer().

◆ StartLocalBufferIO()

bool StartLocalBufferIO ( BufferDesc bufHdr,
bool  forInput,
bool  nowait 
)

Definition at line 523 of file localbuf.c.

524{
525 uint32 buf_state;
526
527 /*
528 * With AIO the buffer could have IO in progress, e.g. when there are two
529 * scans of the same relation. Either wait for the other IO or return
530 * false.
531 */
532 if (pgaio_wref_valid(&bufHdr->io_wref))
533 {
534 PgAioWaitRef iow = bufHdr->io_wref;
535
536 if (nowait)
537 return false;
538
539 pgaio_wref_wait(&iow);
540 }
541
542 /* Once we get here, there is definitely no I/O active on this buffer */
543
544 /* Check if someone else already did the I/O */
545 buf_state = pg_atomic_read_u32(&bufHdr->state);
546 if (forInput ? (buf_state & BM_VALID) : !(buf_state & BM_DIRTY))
547 {
548 return false;
549 }
550
551 /* BM_IO_IN_PROGRESS isn't currently used for local buffers */
552
553 /* local buffers don't track IO using resowners */
554
555 return true;
556}

References BM_DIRTY, BM_VALID, BufferDesc::io_wref, pg_atomic_read_u32(), pgaio_wref_valid(), pgaio_wref_wait(), and BufferDesc::state.

Referenced by buffer_call_start_io(), ExtendBufferedRelLocal(), FlushLocalBuffer(), read_rel_block_ll(), ReadBuffersCanStartIOOnce(), and ZeroAndLockBuffer().

◆ StaticAssertDecl() [1/3]

StaticAssertDecl ( )

◆ StaticAssertDecl() [2/3]

StaticAssertDecl ( BUF_REFCOUNT_BITS+BUF_USAGECOUNT_BITS BUF_FLAG_BITS = =32,
"parts of buffer state space need to equal 32"   
)

◆ StaticAssertDecl() [3/3]

StaticAssertDecl ( MAX_BACKENDS_BITS<=  BUF_REFCOUNT_BITS,
"MAX_BACKENDS_BITS needs to be <= BUF_REFCOUNT_BITS  
)

◆ StrategyGetBuffer()

BufferDesc * StrategyGetBuffer ( BufferAccessStrategy  strategy,
uint32 buf_state,
bool *  from_ring 
)

Definition at line 174 of file freelist.c.

175{
177 int bgwprocno;
178 int trycounter;
179
180 *from_ring = false;
181
182 /*
183 * If given a strategy object, see whether it can select a buffer. We
184 * assume strategy objects don't need buffer_strategy_lock.
185 */
186 if (strategy != NULL)
187 {
188 buf = GetBufferFromRing(strategy, buf_state);
189 if (buf != NULL)
190 {
191 *from_ring = true;
192 return buf;
193 }
194 }
195
196 /*
197 * If asked, we need to waken the bgwriter. Since we don't want to rely on
198 * a spinlock for this we force a read from shared memory once, and then
199 * set the latch based on that value. We need to go through that length
200 * because otherwise bgwprocno might be reset while/after we check because
201 * the compiler might just reread from memory.
202 *
203 * This can possibly set the latch of the wrong process if the bgwriter
204 * dies in the wrong moment. But since PGPROC->procLatch is never
205 * deallocated the worst consequence of that is that we set the latch of
206 * some arbitrary process.
207 */
209 if (bgwprocno != -1)
210 {
211 /* reset bgwprocno first, before setting the latch */
213
214 /*
215 * Not acquiring ProcArrayLock here which is slightly icky. It's
216 * actually fine because procLatch isn't ever freed, so we just can
217 * potentially set the wrong process' (or no process') latch.
218 */
220 }
221
222 /*
223 * We count buffer allocation requests so that the bgwriter can estimate
224 * the rate of buffer consumption. Note that buffers recycled by a
225 * strategy object are intentionally not counted here.
226 */
228
229 /* Use the "clock sweep" algorithm to find a free buffer */
230 trycounter = NBuffers;
231 for (;;)
232 {
233 uint32 old_buf_state;
234 uint32 local_buf_state;
235
237
238 /*
239 * Check whether the buffer can be used and pin it if so. Do this
240 * using a CAS loop, to avoid having to lock the buffer header.
241 */
242 old_buf_state = pg_atomic_read_u32(&buf->state);
243 for (;;)
244 {
245 local_buf_state = old_buf_state;
246
247 /*
248 * If the buffer is pinned or has a nonzero usage_count, we cannot
249 * use it; decrement the usage_count (unless pinned) and keep
250 * scanning.
251 */
252
253 if (BUF_STATE_GET_REFCOUNT(local_buf_state) != 0)
254 {
255 if (--trycounter == 0)
256 {
257 /*
258 * We've scanned all the buffers without making any state
259 * changes, so all the buffers are pinned (or were when we
260 * looked at them). We could hope that someone will free
261 * one eventually, but it's probably better to fail than
262 * to risk getting stuck in an infinite loop.
263 */
264 elog(ERROR, "no unpinned buffers available");
265 }
266 break;
267 }
268
269 /* See equivalent code in PinBuffer() */
270 if (unlikely(local_buf_state & BM_LOCKED))
271 {
272 old_buf_state = WaitBufHdrUnlocked(buf);
273 continue;
274 }
275
276 if (BUF_STATE_GET_USAGECOUNT(local_buf_state) != 0)
277 {
278 local_buf_state -= BUF_USAGECOUNT_ONE;
279
280 if (pg_atomic_compare_exchange_u32(&buf->state, &old_buf_state,
281 local_buf_state))
282 {
283 trycounter = NBuffers;
284 break;
285 }
286 }
287 else
288 {
289 /* pin the buffer if the CAS succeeds */
290 local_buf_state += BUF_REFCOUNT_ONE;
291
292 if (pg_atomic_compare_exchange_u32(&buf->state, &old_buf_state,
293 local_buf_state))
294 {
295 /* Found a usable buffer */
296 if (strategy != NULL)
297 AddBufferToRing(strategy, buf);
298 *buf_state = local_buf_state;
299
301
302 return buf;
303 }
304 }
305 }
306 }
307}
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:349
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:366
static BufferDesc * GetBufferDescriptor(uint32 id)
pg_noinline uint32 WaitBufHdrUnlocked(BufferDesc *buf)
Definition: bufmgr.c:6389
void TrackNewBufferPin(Buffer buf)
Definition: bufmgr.c:3397
#define unlikely(x)
Definition: c.h:418
static BufferStrategyControl * StrategyControl
Definition: freelist.c:57
static uint32 ClockSweepTick(void)
Definition: freelist.c:100
static void AddBufferToRing(BufferAccessStrategy strategy, BufferDesc *buf)
Definition: freelist.c:737
#define INT_ACCESS_ONCE(var)
Definition: freelist.c:24
static BufferDesc * GetBufferFromRing(BufferAccessStrategy strategy, uint32 *buf_state)
Definition: freelist.c:658
int NBuffers
Definition: globals.c:142
void SetLatch(Latch *latch)
Definition: latch.c:290
PROC_HDR * ProcGlobal
Definition: proc.c:79
pg_atomic_uint32 numBufferAllocs
Definition: freelist.c:47
Latch procLatch
Definition: proc.h:186
PGPROC * allProcs
Definition: proc.h:388

References AddBufferToRing(), PROC_HDR::allProcs, BufferStrategyControl::bgwprocno, BM_LOCKED, buf, BUF_REFCOUNT_ONE, BUF_STATE_GET_REFCOUNT, BUF_STATE_GET_USAGECOUNT, BUF_USAGECOUNT_ONE, BufferDescriptorGetBuffer(), ClockSweepTick(), elog, ERROR, GetBufferDescriptor(), GetBufferFromRing(), INT_ACCESS_ONCE, NBuffers, BufferStrategyControl::numBufferAllocs, pg_atomic_compare_exchange_u32(), pg_atomic_fetch_add_u32(), pg_atomic_read_u32(), ProcGlobal, PGPROC::procLatch, SetLatch(), StrategyControl, TrackNewBufferPin(), unlikely, and WaitBufHdrUnlocked().

Referenced by GetVictimBuffer().

◆ StrategyInitialize()

void StrategyInitialize ( bool  init)

Definition at line 401 of file freelist.c.

402{
403 bool found;
404
405 /*
406 * Initialize the shared buffer lookup hashtable.
407 *
408 * Since we can't tolerate running out of lookup table entries, we must be
409 * sure to specify an adequate table size here. The maximum steady-state
410 * usage is of course NBuffers entries, but BufferAlloc() tries to insert
411 * a new entry before deleting the old. In principle this could be
412 * happening in each partition concurrently, so we could need as many as
413 * NBuffers + NUM_BUFFER_PARTITIONS entries.
414 */
416
417 /*
418 * Get or create the shared strategy control block
419 */
421 ShmemInitStruct("Buffer Strategy Status",
422 sizeof(BufferStrategyControl),
423 &found);
424
425 if (!found)
426 {
427 /*
428 * Only done once, usually in postmaster
429 */
430 Assert(init);
431
433
434 /* Initialize the clock-sweep pointer */
436
437 /* Clear statistics */
440
441 /* No pending notification */
443 }
444 else
445 Assert(!init);
446}
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:219
void InitBufTable(int size)
Definition: buf_table.c:51
int init
Definition: isn.c:79
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:389
#define SpinLockInit(lock)
Definition: spin.h:57
pg_atomic_uint32 nextVictimBuffer
Definition: freelist.c:40
slock_t buffer_strategy_lock
Definition: freelist.c:33

References Assert(), BufferStrategyControl::bgwprocno, BufferStrategyControl::buffer_strategy_lock, BufferStrategyControl::completePasses, init, InitBufTable(), NBuffers, BufferStrategyControl::nextVictimBuffer, NUM_BUFFER_PARTITIONS, BufferStrategyControl::numBufferAllocs, pg_atomic_init_u32(), ShmemInitStruct(), SpinLockInit, and StrategyControl.

Referenced by BufferManagerShmemInit().

◆ StrategyNotifyBgWriter()

void StrategyNotifyBgWriter ( int  bgwprocno)

Definition at line 358 of file freelist.c.

359{
360 /*
361 * We acquire buffer_strategy_lock just to ensure that the store appears
362 * atomic to StrategyGetBuffer. The bgwriter should call this rather
363 * infrequently, so there's no performance penalty from being safe.
364 */
366 StrategyControl->bgwprocno = bgwprocno;
368}
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59

References BufferStrategyControl::bgwprocno, BufferStrategyControl::buffer_strategy_lock, SpinLockAcquire, SpinLockRelease, and StrategyControl.

Referenced by BackgroundWriterMain().

◆ StrategyRejectBuffer()

bool StrategyRejectBuffer ( BufferAccessStrategy  strategy,
BufferDesc buf,
bool  from_ring 
)

Definition at line 787 of file freelist.c.

788{
789 /* We only do this in bulkread mode */
790 if (strategy->btype != BAS_BULKREAD)
791 return false;
792
793 /* Don't muck with behavior of normal buffer-replacement strategy */
794 if (!from_ring ||
795 strategy->buffers[strategy->current] != BufferDescriptorGetBuffer(buf))
796 return false;
797
798 /*
799 * Remove the dirty buffer from the ring; necessary to prevent infinite
800 * loop if all ring members are dirty.
801 */
802 strategy->buffers[strategy->current] = InvalidBuffer;
803
804 return true;
805}
Buffer buffers[FLEXIBLE_ARRAY_MEMBER]
Definition: freelist.c:83

References BAS_BULKREAD, BufferAccessStrategyData::btype, buf, BufferDescriptorGetBuffer(), BufferAccessStrategyData::buffers, BufferAccessStrategyData::current, and InvalidBuffer.

Referenced by GetVictimBuffer().

◆ StrategyShmemSize()

Size StrategyShmemSize ( void  )

Definition at line 380 of file freelist.c.

381{
382 Size size = 0;
383
384 /* size of lookup hash table ... see comment in StrategyInitialize */
386
387 /* size of the shared replacement strategy control block */
388 size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl)));
389
390 return size;
391}
Size BufTableShmemSize(int size)
Definition: buf_table.c:41
#define MAXALIGN(LEN)
Definition: c.h:824
Size add_size(Size s1, Size s2)
Definition: shmem.c:495

References add_size(), BufTableShmemSize(), MAXALIGN, NBuffers, and NUM_BUFFER_PARTITIONS.

Referenced by BufferManagerShmemSize().

◆ StrategySyncStart()

int StrategySyncStart ( uint32 complete_passes,
uint32 num_buf_alloc 
)

Definition at line 321 of file freelist.c.

322{
323 uint32 nextVictimBuffer;
324 int result;
325
328 result = nextVictimBuffer % NBuffers;
329
330 if (complete_passes)
331 {
332 *complete_passes = StrategyControl->completePasses;
333
334 /*
335 * Additionally add the number of wraparounds that happened before
336 * completePasses could be incremented. C.f. ClockSweepTick().
337 */
338 *complete_passes += nextVictimBuffer / NBuffers;
339 }
340
341 if (num_buf_alloc)
342 {
344 }
346 return result;
347}
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:330

References BufferStrategyControl::buffer_strategy_lock, BufferStrategyControl::completePasses, NBuffers, BufferStrategyControl::nextVictimBuffer, BufferStrategyControl::numBufferAllocs, pg_atomic_exchange_u32(), pg_atomic_read_u32(), SpinLockAcquire, SpinLockRelease, and StrategyControl.

Referenced by BgBufferSync().

◆ TerminateBufferIO()

void TerminateBufferIO ( BufferDesc buf,
bool  clear_dirty,
uint32  set_flag_bits,
bool  forget_owner,
bool  release_aio 
)

Definition at line 6199 of file bufmgr.c.

6201{
6202 uint32 buf_state;
6203 uint32 unset_flag_bits = 0;
6204 int refcount_change = 0;
6205
6206 buf_state = LockBufHdr(buf);
6207
6208 Assert(buf_state & BM_IO_IN_PROGRESS);
6209 unset_flag_bits |= BM_IO_IN_PROGRESS;
6210
6211 /* Clear earlier errors, if this IO failed, it'll be marked again */
6212 unset_flag_bits |= BM_IO_ERROR;
6213
6214 if (clear_dirty && !(buf_state & BM_JUST_DIRTIED))
6215 unset_flag_bits |= BM_DIRTY | BM_CHECKPOINT_NEEDED;
6216
6217 if (release_aio)
6218 {
6219 /* release ownership by the AIO subsystem */
6220 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
6221 refcount_change = -1;
6222 pgaio_wref_clear(&buf->io_wref);
6223 }
6224
6225 buf_state = UnlockBufHdrExt(buf, buf_state,
6226 set_flag_bits, unset_flag_bits,
6227 refcount_change);
6228
6229 if (forget_owner)
6232
6234
6235 /*
6236 * Support LockBufferForCleanup()
6237 *
6238 * We may have just released the last pin other than the waiter's. In most
6239 * cases, this backend holds another pin on the buffer. But, if, for
6240 * example, this backend is completing an IO issued by another backend, it
6241 * may be time to wake the waiter.
6242 */
6243 if (release_aio && (buf_state & BM_PIN_COUNT_WAITER))
6245}
void pgaio_wref_clear(PgAioWaitRef *iow)
Definition: aio.c:964
static ConditionVariable * BufferDescriptorGetIOCV(const BufferDesc *bdesc)
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:75
static void ResourceOwnerForgetBufferIO(ResourceOwner owner, Buffer buffer)
#define BM_IO_ERROR
Definition: buf_internals.h:73
#define BM_CHECKPOINT_NEEDED
Definition: buf_internals.h:76
static void WakePinCountWaiter(BufferDesc *buf)
Definition: bufmgr.c:3305
void ConditionVariableBroadcast(ConditionVariable *cv)

References Assert(), BM_CHECKPOINT_NEEDED, BM_DIRTY, BM_IO_ERROR, BM_IO_IN_PROGRESS, BM_JUST_DIRTIED, BM_PIN_COUNT_WAITER, buf, BUF_STATE_GET_REFCOUNT, BufferDescriptorGetBuffer(), BufferDescriptorGetIOCV(), ConditionVariableBroadcast(), CurrentResourceOwner, LockBufHdr(), pgaio_wref_clear(), ResourceOwnerForgetBufferIO(), UnlockBufHdrExt(), and WakePinCountWaiter().

Referenced by AbortBufferIO(), buffer_call_terminate_io(), buffer_readv_complete_one(), ExtendBufferedRelShared(), FlushBuffer(), and ZeroAndLockBuffer().

◆ TerminateLocalBufferIO()

void TerminateLocalBufferIO ( BufferDesc bufHdr,
bool  clear_dirty,
uint32  set_flag_bits,
bool  release_aio 
)

Definition at line 562 of file localbuf.c.

564{
565 /* Only need to adjust flags */
566 uint32 buf_state = pg_atomic_read_u32(&bufHdr->state);
567
568 /* BM_IO_IN_PROGRESS isn't currently used for local buffers */
569
570 /* Clear earlier errors, if this IO failed, it'll be marked again */
571 buf_state &= ~BM_IO_ERROR;
572
573 if (clear_dirty)
574 buf_state &= ~BM_DIRTY;
575
576 if (release_aio)
577 {
578 /* release pin held by IO subsystem, see also buffer_stage_common() */
579 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
580 buf_state -= BUF_REFCOUNT_ONE;
581 pgaio_wref_clear(&bufHdr->io_wref);
582 }
583
584 buf_state |= set_flag_bits;
585 pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
586
587 /* local buffers don't track IO using resowners */
588
589 /* local buffers don't use the IO CV, as no other process can see buffer */
590
591 /* local buffers don't use BM_PIN_COUNT_WAITER, so no need to wake */
592}

References Assert(), BUF_REFCOUNT_ONE, BUF_STATE_GET_REFCOUNT, BufferDesc::io_wref, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgaio_wref_clear(), and BufferDesc::state.

Referenced by buffer_call_terminate_io(), buffer_readv_complete_one(), FlushLocalBuffer(), and ZeroAndLockBuffer().

◆ TrackNewBufferPin()

void TrackNewBufferPin ( Buffer  buf)
inline

Definition at line 3397 of file bufmgr.c.

3398{
3400
3402 ref->data.refcount++;
3403
3405
3406 /*
3407 * This is the first pin for this page by this backend, mark its page as
3408 * defined to valgrind. While the page contents might not actually be
3409 * valid yet, we don't currently guarantee that such pages are marked
3410 * undefined or non-accessible.
3411 *
3412 * It's not necessarily the prettiest to do this here, but otherwise we'd
3413 * need this block of code in multiple places.
3414 */
3416 BLCKSZ);
3417}
static PrivateRefCountEntry * NewPrivateRefCountEntry(Buffer buffer)
Definition: bufmgr.c:363
#define BufHdrGetBlock(bufHdr)
Definition: bufmgr.c:72
PrivateRefCountData data
Definition: bufmgr.c:118

References buf, BufHdrGetBlock, CurrentResourceOwner, PrivateRefCountEntry::data, GetBufferDescriptor(), NewPrivateRefCountEntry(), PrivateRefCountData::refcount, ResourceOwnerRememberBuffer(), and VALGRIND_MAKE_MEM_DEFINED.

Referenced by GetBufferFromRing(), PinBuffer(), PinBuffer_Locked(), and StrategyGetBuffer().

◆ UnlockBufHdr()

◆ UnlockBufHdrExt()

static uint32 UnlockBufHdrExt ( BufferDesc desc,
uint32  old_buf_state,
uint32  set_bits,
uint32  unset_bits,
int  refcount_change 
)
inlinestatic

Definition at line 413 of file buf_internals.h.

417{
418 for (;;)
419 {
420 uint32 buf_state = old_buf_state;
421
422 Assert(buf_state & BM_LOCKED);
423
424 buf_state |= set_bits;
425 buf_state &= ~unset_bits;
426 buf_state &= ~BM_LOCKED;
427
428 if (refcount_change != 0)
429 buf_state += BUF_REFCOUNT_ONE * refcount_change;
430
431 if (pg_atomic_compare_exchange_u32(&desc->state, &old_buf_state,
432 buf_state))
433 {
434 return old_buf_state;
435 }
436 }

References Assert(), BM_LOCKED, BUF_REFCOUNT_ONE, pg_atomic_compare_exchange_u32(), and BufferDesc::state.

Referenced by buffer_stage_common(), BufferAlloc(), BufferSync(), create_toy_buffer(), ExtendBufferedRelShared(), FlushBuffer(), InvalidateBuffer(), InvalidateVictimBuffer(), LockBufferForCleanup(), MarkBufferDirtyHint(), PinBuffer_Locked(), StartBufferIO(), TerminateBufferIO(), UnlockBuffers(), and WakePinCountWaiter().

◆ UnpinLocalBuffer()

void UnpinLocalBuffer ( Buffer  buffer)

Definition at line 841 of file localbuf.c.

842{
845}
static void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
void UnpinLocalBufferNoOwner(Buffer buffer)
Definition: localbuf.c:848

References CurrentResourceOwner, ResourceOwnerForgetBuffer(), and UnpinLocalBufferNoOwner().

Referenced by ExtendBufferedRelLocal(), FlushRelationBuffers(), ReleaseAndReadBuffer(), and ReleaseBuffer().

◆ UnpinLocalBufferNoOwner()

void UnpinLocalBufferNoOwner ( Buffer  buffer)

Definition at line 848 of file localbuf.c.

849{
850 int buffid = -buffer - 1;
851
852 Assert(BufferIsLocal(buffer));
853 Assert(LocalRefCount[buffid] > 0);
855
856 if (--LocalRefCount[buffid] == 0)
857 {
858 BufferDesc *buf_hdr = GetLocalBufferDescriptor(buffid);
859 uint32 buf_state;
860
862
863 buf_state = pg_atomic_read_u32(&buf_hdr->state);
864 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
865 buf_state -= BUF_REFCOUNT_ONE;
866 pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state);
867
868 /* see comment in UnpinBufferNoOwner */
870 }
871}
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition: memdebug.h:27

References Assert(), BUF_REFCOUNT_ONE, BUF_STATE_GET_REFCOUNT, BufferIsLocal, GetLocalBufferDescriptor(), LocalBufHdrGetBlock, LocalRefCount, NLocalPinnedBuffers, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), BufferDesc::state, and VALGRIND_MAKE_MEM_NOACCESS.

Referenced by ResOwnerReleaseBufferPin(), and UnpinLocalBuffer().

◆ WaitBufHdrUnlocked()

uint32 WaitBufHdrUnlocked ( BufferDesc buf)

Definition at line 6389 of file bufmgr.c.

6390{
6391 SpinDelayStatus delayStatus;
6392 uint32 buf_state;
6393
6394 init_local_spin_delay(&delayStatus);
6395
6396 buf_state = pg_atomic_read_u32(&buf->state);
6397
6398 while (buf_state & BM_LOCKED)
6399 {
6400 perform_spin_delay(&delayStatus);
6401 buf_state = pg_atomic_read_u32(&buf->state);
6402 }
6403
6404 finish_spin_delay(&delayStatus);
6405
6406 return buf_state;
6407}

References BM_LOCKED, buf, finish_spin_delay(), init_local_spin_delay, perform_spin_delay(), and pg_atomic_read_u32().

Referenced by GetBufferFromRing(), MarkBufferDirty(), PinBuffer(), and StrategyGetBuffer().

◆ WritebackContextInit()

void WritebackContextInit ( WritebackContext context,
int *  max_pending 
)

Definition at line 6501 of file bufmgr.c.

6502{
6503 Assert(*max_pending <= WRITEBACK_MAX_PENDING_FLUSHES);
6504
6505 context->max_pending = max_pending;
6506 context->nr_pending = 0;
6507}

References Assert(), WritebackContext::max_pending, WritebackContext::nr_pending, and WRITEBACK_MAX_PENDING_FLUSHES.

Referenced by BackgroundWriterMain(), BufferManagerShmemInit(), and BufferSync().

Variable Documentation

◆ BackendWritebackContext

PGDLLIMPORT WritebackContext BackendWritebackContext
extern

Definition at line 24 of file buf_init.c.

Referenced by BufferManagerShmemInit(), and GetVictimBuffer().

◆ buffer_io_resowner_desc

PGDLLIMPORT const ResourceOwnerDesc buffer_io_resowner_desc
extern

Definition at line 260 of file bufmgr.c.

Referenced by ResourceOwnerForgetBufferIO(), and ResourceOwnerRememberBufferIO().

◆ buffer_pin_resowner_desc

PGDLLIMPORT const ResourceOwnerDesc buffer_pin_resowner_desc
extern

Definition at line 269 of file bufmgr.c.

Referenced by ResourceOwnerForgetBuffer(), and ResourceOwnerRememberBuffer().

◆ BufferDescriptors

PGDLLIMPORT BufferDescPadded* BufferDescriptors
extern

Definition at line 21 of file buf_init.c.

Referenced by BufferManagerShmemInit(), and GetBufferDescriptor().

◆ BufferIOCVArray

Definition at line 23 of file buf_init.c.

Referenced by BufferDescriptorGetIOCV(), and BufferManagerShmemInit().

◆ CkptBufferIds

PGDLLIMPORT CkptSortItem* CkptBufferIds
extern

Definition at line 25 of file buf_init.c.

Referenced by BufferManagerShmemInit(), and BufferSync().

◆ LocalBufferDescriptors

PGDLLIMPORT BufferDesc* LocalBufferDescriptors
extern

Definition at line 47 of file localbuf.c.

Referenced by GetLocalBufferDescriptor(), and InitLocalBuffers().