PostgreSQL Source Code  git master
buf_internals.h File Reference
#include "pgstat.h"
#include "port/atomics.h"
#include "storage/buf.h"
#include "storage/bufmgr.h"
#include "storage/condition_variable.h"
#include "storage/latch.h"
#include "storage/lwlock.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_ONE   1
 
#define BUF_REFCOUNT_MASK   ((1U << 18) - 1)
 
#define BUF_USAGECOUNT_MASK   0x003C0000U
 
#define BUF_USAGECOUNT_ONE   (1U << 18)
 
#define BUF_USAGECOUNT_SHIFT   18
 
#define BUF_FLAG_MASK   0xFFC00000U
 
#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)
 
#define FREENEXT_END_OF_LIST   (-1)
 
#define FREENEXT_NOT_IN_LIST   (-2)
 

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

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, uint32 buf_state)
 
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)
 
IOContext IOContextForStrategy (BufferAccessStrategy strategy)
 
BufferDescStrategyGetBuffer (BufferAccessStrategy strategy, uint32 *buf_state, bool *from_ring)
 
void StrategyFreeBuffer (BufferDesc *buf)
 
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)
 
bool have_free_buffer (void)
 
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 DropRelationLocalBuffers (RelFileLocator rlocator, ForkNumber forkNum, 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 68 of file buf_internals.h.

◆ BM_DIRTY

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

Definition at line 61 of file buf_internals.h.

◆ BM_IO_ERROR

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

Definition at line 65 of file buf_internals.h.

◆ BM_IO_IN_PROGRESS

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

Definition at line 64 of file buf_internals.h.

◆ BM_JUST_DIRTIED

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

Definition at line 66 of file buf_internals.h.

◆ BM_LOCKED

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

Definition at line 60 of file buf_internals.h.

◆ BM_MAX_USAGE_COUNT

#define BM_MAX_USAGE_COUNT   5

Definition at line 78 of file buf_internals.h.

◆ BM_PERMANENT

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

Definition at line 69 of file buf_internals.h.

◆ BM_PIN_COUNT_WAITER

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

Definition at line 67 of file buf_internals.h.

◆ BM_TAG_VALID

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

Definition at line 63 of file buf_internals.h.

◆ BM_VALID

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

Definition at line 62 of file buf_internals.h.

◆ BUF_FLAG_MASK

#define BUF_FLAG_MASK   0xFFC00000U

Definition at line 48 of file buf_internals.h.

◆ BUF_REFCOUNT_MASK

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

Definition at line 44 of file buf_internals.h.

◆ BUF_REFCOUNT_ONE

#define BUF_REFCOUNT_ONE   1

Definition at line 43 of file buf_internals.h.

◆ BUF_STATE_GET_REFCOUNT

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

Definition at line 51 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 52 of file buf_internals.h.

◆ BUF_USAGECOUNT_MASK

#define BUF_USAGECOUNT_MASK   0x003C0000U

Definition at line 45 of file buf_internals.h.

◆ BUF_USAGECOUNT_ONE

#define BUF_USAGECOUNT_ONE   (1U << 18)

Definition at line 46 of file buf_internals.h.

◆ BUF_USAGECOUNT_SHIFT

#define BUF_USAGECOUNT_SHIFT   18

Definition at line 47 of file buf_internals.h.

◆ BUFFERDESC_PAD_TO_SIZE

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

Definition at line 277 of file buf_internals.h.

◆ FREENEXT_END_OF_LIST

#define FREENEXT_END_OF_LIST   (-1)

Definition at line 351 of file buf_internals.h.

◆ FREENEXT_NOT_IN_LIST

#define FREENEXT_NOT_IN_LIST   (-2)

Definition at line 352 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 819 of file localbuf.c.

820 {
822 }
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:786

References CheckForLocalBufferLeaks().

Referenced by AtEOXact_Buffers().

◆ BufferDescriptorGetBuffer()

◆ BufferDescriptorGetContentLock()

◆ BufferDescriptorGetIOCV()

static ConditionVariable* BufferDescriptorGetIOCV ( const BufferDesc bdesc)
inlinestatic

Definition at line 336 of file buf_internals.h.

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

References BufferDesc::buf_id, and BufferIOCVArray.

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

◆ BufferTagsEqual()

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

Definition at line 153 of file buf_internals.h.

155 {
156  return (tag1->spcOid == tag2->spcOid) &&
157  (tag1->dbOid == tag2->dbOid) &&
158  (tag1->relNumber == tag2->relNumber) &&
159  (tag1->blockNum == tag2->blockNum) &&
160  (tag1->forkNum == tag2->forkNum);
BlockNumber blockNum
Definition: buf_internals.h:98
RelFileNumber relNumber
Definition: buf_internals.h:96
ForkNumber forkNum
Definition: buf_internals.h:97
Oid spcOid
Definition: buf_internals.h:94
Oid dbOid
Definition: buf_internals.h:95

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 185 of file buf_internals.h.

187 {
189  BufTableHashPartition(hashcode)].lock;
static uint32 BufTableHashPartition(uint32 hashcode)
LWLockPadded * MainLWLockArray
Definition: lwlock.c:191
#define BUFFER_MAPPING_LWLOCK_OFFSET
Definition: lwlock.h:104
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,
156  HASH_REMOVE,
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:968
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
@ 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, (void *) tagPtr);
81 }
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition: dynahash.c:911

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 179 of file buf_internals.h.

181 {
182  return hashcode % NUM_BUFFER_PARTITIONS;
#define NUM_BUFFER_PARTITIONS
Definition: lwlock.h:93

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,
130  HASH_ENTER,
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:192
#define Assert(condition)
Definition: c.h:858
@ 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,
98  HASH_FIND,
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(long num_entries, Size entrysize)
Definition: dynahash.c:783
static pg_noinline void Size size
Definition: slab.c:607

References hash_estimate_size(), and size.

Referenced by StrategyShmemSize().

◆ BufTagGetForkNum()

◆ BufTagGetRelFileLocator()

◆ BufTagGetRelNumber()

static RelFileNumber BufTagGetRelNumber ( const BufferTag tag)
inlinestatic

Definition at line 102 of file buf_internals.h.

104 {
105  return tag->relNumber;

References buftag::relNumber.

Referenced by apw_dump_now(), BufferSync(), BufTagGetRelFileLocator(), BufTagMatchesRelFileLocator(), and pg_buffercache_pages().

◆ BufTagMatchesRelFileLocator()

static bool BufTagMatchesRelFileLocator ( const BufferTag tag,
const RelFileLocator rlocator 
)
inlinestatic

◆ BufTagSetRelForkDetails()

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

Definition at line 114 of file buf_internals.h.

117 {
118  tag->relNumber = relnumber;
119  tag->forkNum = forknum;

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

Referenced by ClearBufferTag(), and InitBufferTag().

◆ ClearBufferTag()

static void ClearBufferTag ( BufferTag tag)
inlinestatic

Definition at line 134 of file buf_internals.h.

136 {
137  tag->spcOid = InvalidOid;
138  tag->dbOid = InvalidOid;
#define InvalidBlockNumber
Definition: block.h:33
static void BufTagSetRelForkDetails(BufferTag *tag, RelFileNumber relnumber, ForkNumber forknum)
#define InvalidOid
Definition: postgres_ext.h:36
@ InvalidForkNumber
Definition: relpath.h:49
#define InvalidRelFileNumber
Definition: relpath.h:26

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

Referenced by DropRelationAllLocalBuffers(), DropRelationLocalBuffers(), GetLocalVictimBuffer(), InitBufferPool(), InvalidateBuffer(), and InvalidateVictimBuffer().

◆ DropRelationAllLocalBuffers()

void DropRelationAllLocalBuffers ( RelFileLocator  rlocator)

Definition at line 537 of file localbuf.c.

538 {
539  int i;
540 
541  for (i = 0; i < NLocBuffer; i++)
542  {
544  LocalBufferLookupEnt *hresult;
545  uint32 buf_state;
546 
547  buf_state = pg_atomic_read_u32(&bufHdr->state);
548 
549  if ((buf_state & BM_TAG_VALID) &&
550  BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator))
551  {
552  if (LocalRefCount[i] != 0)
553  elog(ERROR, "block %u of %s is still referenced (local %u)",
554  bufHdr->tag.blockNum,
556  MyProcNumber,
557  BufTagGetForkNum(&bufHdr->tag)),
558  LocalRefCount[i]);
559  /* Remove entry from hashtable */
560  hresult = (LocalBufferLookupEnt *)
561  hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
562  if (!hresult) /* shouldn't happen */
563  elog(ERROR, "local buffer hash table corrupted");
564  /* Mark buffer invalid */
565  ClearBufferTag(&bufHdr->tag);
566  buf_state &= ~BUF_FLAG_MASK;
567  buf_state &= ~BUF_USAGECOUNT_MASK;
568  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
569  }
570  }
571 }
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:290
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:234
#define BM_TAG_VALID
Definition: buf_internals.h:63
#define BUF_USAGECOUNT_MASK
Definition: buf_internals.h:45
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
#define BUF_FLAG_MASK
Definition: buf_internals.h:48
static void ClearBufferTag(BufferTag *tag)
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)
unsigned int uint32
Definition: c.h:506
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
ProcNumber MyProcNumber
Definition: globals.c:87
int i
Definition: isn.c:73
int32 * LocalRefCount
Definition: localbuf.c:46
static HTAB * LocalBufHash
Definition: localbuf.c:50
int NLocBuffer
Definition: localbuf.c:42
#define relpathbackend(rlocator, backend, forknum)
Definition: relpath.h:85
BufferTag tag
pg_atomic_uint32 state

References buftag::blockNum, BM_TAG_VALID, BUF_FLAG_MASK, BUF_USAGECOUNT_MASK, BufTagGetForkNum(), BufTagGetRelFileLocator(), BufTagMatchesRelFileLocator(), ClearBufferTag(), elog, ERROR, GetLocalBufferDescriptor(), HASH_REMOVE, hash_search(), i, LocalBufHash, LocalRefCount, MyProcNumber, NLocBuffer, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), relpathbackend, BufferDesc::state, and BufferDesc::tag.

Referenced by DropRelationsAllBuffers().

◆ DropRelationLocalBuffers()

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

Definition at line 489 of file localbuf.c.

491 {
492  int i;
493 
494  for (i = 0; i < NLocBuffer; i++)
495  {
497  LocalBufferLookupEnt *hresult;
498  uint32 buf_state;
499 
500  buf_state = pg_atomic_read_u32(&bufHdr->state);
501 
502  if ((buf_state & BM_TAG_VALID) &&
503  BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator) &&
504  BufTagGetForkNum(&bufHdr->tag) == forkNum &&
505  bufHdr->tag.blockNum >= firstDelBlock)
506  {
507  if (LocalRefCount[i] != 0)
508  elog(ERROR, "block %u of %s is still referenced (local %u)",
509  bufHdr->tag.blockNum,
511  MyProcNumber,
512  BufTagGetForkNum(&bufHdr->tag)),
513  LocalRefCount[i]);
514 
515  /* Remove entry from hashtable */
516  hresult = (LocalBufferLookupEnt *)
517  hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
518  if (!hresult) /* shouldn't happen */
519  elog(ERROR, "local buffer hash table corrupted");
520  /* Mark buffer invalid */
521  ClearBufferTag(&bufHdr->tag);
522  buf_state &= ~BUF_FLAG_MASK;
523  buf_state &= ~BUF_USAGECOUNT_MASK;
524  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
525  }
526  }
527 }

References buftag::blockNum, BM_TAG_VALID, BUF_FLAG_MASK, BUF_USAGECOUNT_MASK, BufTagGetForkNum(), BufTagGetRelFileLocator(), BufTagMatchesRelFileLocator(), ClearBufferTag(), elog, ERROR, GetLocalBufferDescriptor(), HASH_REMOVE, hash_search(), i, LocalBufHash, LocalRefCount, MyProcNumber, NLocBuffer, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), relpathbackend, 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 313 of file localbuf.c.

320 {
321  BlockNumber first_block;
322  instr_time io_start;
323 
324  /* Initialize local buffers if first request in this session */
325  if (LocalBufHash == NULL)
327 
328  LimitAdditionalLocalPins(&extend_by);
329 
330  for (uint32 i = 0; i < extend_by; i++)
331  {
332  BufferDesc *buf_hdr;
333  Block buf_block;
334 
335  buffers[i] = GetLocalVictimBuffer();
336  buf_hdr = GetLocalBufferDescriptor(-buffers[i] - 1);
337  buf_block = LocalBufHdrGetBlock(buf_hdr);
338 
339  /* new buffers are zero-filled */
340  MemSet((char *) buf_block, 0, BLCKSZ);
341  }
342 
343  first_block = smgrnblocks(bmr.smgr, fork);
344 
345  if (extend_upto != InvalidBlockNumber)
346  {
347  /*
348  * In contrast to shared relations, nothing could change the relation
349  * size concurrently. Thus we shouldn't end up finding that we don't
350  * need to do anything.
351  */
352  Assert(first_block <= extend_upto);
353 
354  Assert((uint64) first_block + extend_by <= extend_upto);
355  }
356 
357  /* Fail if relation is already at maximum possible length */
358  if ((uint64) first_block + extend_by >= MaxBlockNumber)
359  ereport(ERROR,
360  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
361  errmsg("cannot extend relation %s beyond %u blocks",
362  relpath(bmr.smgr->smgr_rlocator, fork),
363  MaxBlockNumber)));
364 
365  for (uint32 i = 0; i < extend_by; i++)
366  {
367  int victim_buf_id;
368  BufferDesc *victim_buf_hdr;
369  BufferTag tag;
370  LocalBufferLookupEnt *hresult;
371  bool found;
372 
373  victim_buf_id = -buffers[i] - 1;
374  victim_buf_hdr = GetLocalBufferDescriptor(victim_buf_id);
375 
376  /* in case we need to pin an existing buffer below */
378 
379  InitBufferTag(&tag, &bmr.smgr->smgr_rlocator.locator, fork, first_block + i);
380 
381  hresult = (LocalBufferLookupEnt *)
382  hash_search(LocalBufHash, (void *) &tag, HASH_ENTER, &found);
383  if (found)
384  {
385  BufferDesc *existing_hdr;
386  uint32 buf_state;
387 
389 
390  existing_hdr = GetLocalBufferDescriptor(hresult->id);
391  PinLocalBuffer(existing_hdr, false);
392  buffers[i] = BufferDescriptorGetBuffer(existing_hdr);
393 
394  buf_state = pg_atomic_read_u32(&existing_hdr->state);
395  Assert(buf_state & BM_TAG_VALID);
396  Assert(!(buf_state & BM_DIRTY));
397  buf_state &= ~BM_VALID;
398  pg_atomic_unlocked_write_u32(&existing_hdr->state, buf_state);
399  }
400  else
401  {
402  uint32 buf_state = pg_atomic_read_u32(&victim_buf_hdr->state);
403 
404  Assert(!(buf_state & (BM_VALID | BM_TAG_VALID | BM_DIRTY | BM_JUST_DIRTIED)));
405 
406  victim_buf_hdr->tag = tag;
407 
408  buf_state |= BM_TAG_VALID | BUF_USAGECOUNT_ONE;
409 
410  pg_atomic_unlocked_write_u32(&victim_buf_hdr->state, buf_state);
411 
412  hresult->id = victim_buf_id;
413  }
414  }
415 
417 
418  /* actually extend relation */
419  smgrzeroextend(bmr.smgr, fork, first_block, extend_by, false);
420 
422  io_start, extend_by);
423 
424  for (uint32 i = 0; i < extend_by; i++)
425  {
426  Buffer buf = buffers[i];
427  BufferDesc *buf_hdr;
428  uint32 buf_state;
429 
430  buf_hdr = GetLocalBufferDescriptor(-buf - 1);
431 
432  buf_state = pg_atomic_read_u32(&buf_hdr->state);
433  buf_state |= BM_VALID;
434  pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state);
435  }
436 
437  *extended_by = extend_by;
438 
439  pgBufferUsage.local_blks_written += extend_by;
440 
441  return first_block;
442 }
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:61
#define BM_JUST_DIRTIED
Definition: buf_internals.h:66
#define BUF_USAGECOUNT_ONE
Definition: buf_internals.h:46
#define BM_VALID
Definition: buf_internals.h:62
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
bool track_io_timing
Definition: bufmgr.c:142
void * Block
Definition: bufmgr.h:25
#define MemSet(start, val, len)
Definition: c.h:1020
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ereport(elevel,...)
Definition: elog.h:149
BufferUsage pgBufferUsage
Definition: instrument.c:20
void UnpinLocalBuffer(Buffer buffer)
Definition: localbuf.c:681
#define LocalBufHdrGetBlock(bufHdr)
Definition: localbuf.c:39
bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
Definition: localbuf.c:655
static void InitLocalBuffers(void)
Definition: localbuf.c:580
void LimitAdditionalLocalPins(uint32 *additional_pins)
Definition: localbuf.c:290
static Buffer GetLocalVictimBuffer(void)
Definition: localbuf.c:177
static char * buf
Definition: pg_test_fsync.c:73
@ IOOBJECT_TEMP_RELATION
Definition: pgstat.h:281
@ IOCONTEXT_NORMAL
Definition: pgstat.h:290
@ IOOP_EXTEND
Definition: pgstat.h:299
instr_time pgstat_prepare_io_time(bool track_io_guc)
Definition: pgstat_io.c:100
void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt)
Definition: pgstat_io.c:122
#define relpath(rlocator, forknum)
Definition: relpath.h:94
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:442
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:655
void smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks, bool skipFsync)
Definition: smgr.c:560
struct SMgrRelationData * smgr
Definition: bufmgr.h:103
int64 local_blks_written
Definition: instrument.h:33
RelFileLocator locator
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:37

References Assert, BM_DIRTY, BM_JUST_DIRTIED, BM_TAG_VALID, BM_VALID, 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, RelFileLocatorBackend::locator, MaxBlockNumber, MemSet, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgBufferUsage, pgstat_count_io_op_time(), pgstat_prepare_io_time(), PinLocalBuffer(), relpath, ResourceOwnerEnlarge(), BufferManagerRelation::smgr, SMgrRelationData::smgr_rlocator, smgrnblocks(), smgrzeroextend(), BufferDesc::state, BufferDesc::tag, track_io_timing, and UnpinLocalBuffer().

Referenced by ExtendBufferedRelCommon().

◆ GetBufferDescriptor()

◆ GetLocalBufferDescriptor()

◆ have_free_buffer()

bool have_free_buffer ( void  )

Definition at line 175 of file freelist.c.

176 {
178  return true;
179  else
180  return false;
181 }
static BufferStrategyControl * StrategyControl
Definition: freelist.c:65

References BufferStrategyControl::firstFreeBuffer, and StrategyControl.

Referenced by apw_load_buffers(), and autoprewarm_database_main().

◆ 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_PARTITION
Definition: hsearch.h:92
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:332
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
long num_partitions
Definition: hsearch.h:68

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

Referenced by StrategyInitialize().

◆ IOContextForStrategy()

IOContext IOContextForStrategy ( BufferAccessStrategy  strategy)

Definition at line 758 of file freelist.c.

759 {
760  if (!strategy)
761  return IOCONTEXT_NORMAL;
762 
763  switch (strategy->btype)
764  {
765  case BAS_NORMAL:
766 
767  /*
768  * Currently, GetAccessStrategy() returns NULL for
769  * BufferAccessStrategyType BAS_NORMAL, so this case is
770  * unreachable.
771  */
772  pg_unreachable();
773  return IOCONTEXT_NORMAL;
774  case BAS_BULKREAD:
775  return IOCONTEXT_BULKREAD;
776  case BAS_BULKWRITE:
777  return IOCONTEXT_BULKWRITE;
778  case BAS_VACUUM:
779  return IOCONTEXT_VACUUM;
780  }
781 
782  elog(ERROR, "unrecognized BufferAccessStrategyType: %d", strategy->btype);
783  pg_unreachable();
784 }
@ BAS_BULKREAD
Definition: bufmgr.h:36
@ BAS_NORMAL
Definition: bufmgr.h:35
@ BAS_VACUUM
Definition: bufmgr.h:39
@ BAS_BULKWRITE
Definition: bufmgr.h:38
#define pg_unreachable()
Definition: c.h:296
@ IOCONTEXT_VACUUM
Definition: pgstat.h:291
@ IOCONTEXT_BULKREAD
Definition: pgstat.h:288
@ IOCONTEXT_BULKWRITE
Definition: pgstat.h:289
BufferAccessStrategyType btype
Definition: freelist.c:75

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 ExtendBufferedRelShared(), PinBufferForBlock(), and WaitReadBuffers().

◆ IssuePendingWritebacks()

void IssuePendingWritebacks ( WritebackContext wb_context,
IOContext  io_context 
)

Definition at line 5887 of file bufmgr.c.

5888 {
5889  instr_time io_start;
5890  int i;
5891 
5892  if (wb_context->nr_pending == 0)
5893  return;
5894 
5895  /*
5896  * Executing the writes in-order can make them a lot faster, and allows to
5897  * merge writeback requests to consecutive blocks into larger writebacks.
5898  */
5899  sort_pending_writebacks(wb_context->pending_writebacks,
5900  wb_context->nr_pending);
5901 
5903 
5904  /*
5905  * Coalesce neighbouring writes, but nothing else. For that we iterate
5906  * through the, now sorted, array of pending flushes, and look forward to
5907  * find all neighbouring (or identical) writes.
5908  */
5909  for (i = 0; i < wb_context->nr_pending; i++)
5910  {
5913  SMgrRelation reln;
5914  int ahead;
5915  BufferTag tag;
5916  RelFileLocator currlocator;
5917  Size nblocks = 1;
5918 
5919  cur = &wb_context->pending_writebacks[i];
5920  tag = cur->tag;
5921  currlocator = BufTagGetRelFileLocator(&tag);
5922 
5923  /*
5924  * Peek ahead, into following writeback requests, to see if they can
5925  * be combined with the current one.
5926  */
5927  for (ahead = 0; i + ahead + 1 < wb_context->nr_pending; ahead++)
5928  {
5929 
5930  next = &wb_context->pending_writebacks[i + ahead + 1];
5931 
5932  /* different file, stop */
5933  if (!RelFileLocatorEquals(currlocator,
5934  BufTagGetRelFileLocator(&next->tag)) ||
5935  BufTagGetForkNum(&cur->tag) != BufTagGetForkNum(&next->tag))
5936  break;
5937 
5938  /* ok, block queued twice, skip */
5939  if (cur->tag.blockNum == next->tag.blockNum)
5940  continue;
5941 
5942  /* only merge consecutive writes */
5943  if (cur->tag.blockNum + 1 != next->tag.blockNum)
5944  break;
5945 
5946  nblocks++;
5947  cur = next;
5948  }
5949 
5950  i += ahead;
5951 
5952  /* and finally tell the kernel to write the data to storage */
5953  reln = smgropen(currlocator, INVALID_PROC_NUMBER);
5954  smgrwriteback(reln, BufTagGetForkNum(&tag), tag.blockNum, nblocks);
5955  }
5956 
5957  /*
5958  * Assume that writeback requests are only issued for buffers containing
5959  * blocks of permanent relations.
5960  */
5962  IOOP_WRITEBACK, io_start, wb_context->nr_pending);
5963 
5964  wb_context->nr_pending = 0;
5965 }
static int32 next
Definition: blutils.c:221
size_t Size
Definition: c.h:605
struct cursor * cur
Definition: ecpg.c:28
@ IOOBJECT_RELATION
Definition: pgstat.h:280
@ IOOP_WRITEBACK
Definition: pgstat.h:305
#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:643
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
Definition: smgr.c:198
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 116 of file localbuf.c.

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

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 5688 of file bufmgr.c.

5689 {
5690  SpinDelayStatus delayStatus;
5691  uint32 old_buf_state;
5692 
5694 
5695  init_local_spin_delay(&delayStatus);
5696 
5697  while (true)
5698  {
5699  /* set BM_LOCKED flag */
5700  old_buf_state = pg_atomic_fetch_or_u32(&desc->state, BM_LOCKED);
5701  /* if it wasn't set before we're OK */
5702  if (!(old_buf_state & BM_LOCKED))
5703  break;
5704  perform_spin_delay(&delayStatus);
5705  }
5706  finish_spin_delay(&delayStatus);
5707  return old_buf_state | BM_LOCKED;
5708 }
static uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
Definition: atomics.h:405
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BM_LOCKED
Definition: buf_internals.h:60
void perform_spin_delay(SpinDelayStatus *status)
Definition: s_lock.c:132
void finish_spin_delay(SpinDelayStatus *status)
Definition: s_lock.c:192
#define init_local_spin_delay(status)
Definition: s_lock.h:843

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(), BufferAlloc(), BufferGetLSNAtomic(), BufferSync(), ConditionalLockBufferForCleanup(), DropDatabaseBuffers(), DropRelationBuffers(), DropRelationsAllBuffers(), EvictUnpinnedBuffer(), ExtendBufferedRelShared(), FindAndDropRelationBuffers(), FlushBuffer(), FlushDatabaseBuffers(), FlushRelationBuffers(), FlushRelationsAllBuffers(), GetBufferFromRing(), GetVictimBuffer(), InvalidateBuffer(), InvalidateVictimBuffer(), IsBufferCleanupOK(), LockBufferForCleanup(), MarkBufferDirtyHint(), pg_buffercache_pages(), ReadRecentBuffer(), StartBufferIO(), StrategyGetBuffer(), SyncOneBuffer(), TerminateBufferIO(), UnlockBuffers(), UnpinBufferNoOwner(), WaitIO(), and ZeroBuffer().

◆ MarkLocalBufferDirty()

void MarkLocalBufferDirty ( Buffer  buffer)

Definition at line 449 of file localbuf.c.

450 {
451  int bufid;
452  BufferDesc *bufHdr;
453  uint32 buf_state;
454 
455  Assert(BufferIsLocal(buffer));
456 
457 #ifdef LBDEBUG
458  fprintf(stderr, "LB DIRTY %d\n", buffer);
459 #endif
460 
461  bufid = -buffer - 1;
462 
463  Assert(LocalRefCount[bufid] > 0);
464 
465  bufHdr = GetLocalBufferDescriptor(bufid);
466 
467  buf_state = pg_atomic_read_u32(&bufHdr->state);
468 
469  if (!(buf_state & BM_DIRTY))
471 
472  buf_state |= BM_DIRTY;
473 
474  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
475 }
#define fprintf
Definition: port.h:242
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 655 of file localbuf.c.

656 {
657  uint32 buf_state;
658  Buffer buffer = BufferDescriptorGetBuffer(buf_hdr);
659  int bufid = -buffer - 1;
660 
661  buf_state = pg_atomic_read_u32(&buf_hdr->state);
662 
663  if (LocalRefCount[bufid] == 0)
664  {
666  if (adjust_usagecount &&
668  {
669  buf_state += BUF_USAGECOUNT_ONE;
670  pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state);
671  }
672  }
673  LocalRefCount[bufid]++;
675  BufferDescriptorGetBuffer(buf_hdr));
676 
677  return buf_state & BM_VALID;
678 }
#define BM_MAX_USAGE_COUNT
Definition: buf_internals.h:78
#define BUF_STATE_GET_USAGECOUNT(state)
Definition: buf_internals.h:52
static int NLocalPinnedBuffers
Definition: localbuf.c:53
void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)

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

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

◆ PrefetchLocalBuffer()

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

Definition at line 69 of file localbuf.c.

71 {
72  PrefetchBufferResult result = {InvalidBuffer, false};
73  BufferTag newTag; /* identity of requested block */
74  LocalBufferLookupEnt *hresult;
75 
76  InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
77 
78  /* Initialize local buffers if first request in this session */
79  if (LocalBufHash == NULL)
81 
82  /* See if the desired buffer already exists */
83  hresult = (LocalBufferLookupEnt *)
84  hash_search(LocalBufHash, &newTag, HASH_FIND, NULL);
85 
86  if (hresult)
87  {
88  /* Yes, so nothing to do */
89  result.recent_buffer = -hresult->id - 1;
90  }
91  else
92  {
93 #ifdef USE_PREFETCH
94  /* Not in buffers, so initiate prefetch */
95  if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
96  smgrprefetch(smgr, forkNum, blockNum, 1))
97  {
98  result.initiated_io = true;
99  }
100 #endif /* USE_PREFETCH */
101  }
102 
103  return result;
104 }
#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:585
Buffer recent_buffer
Definition: bufmgr.h:60

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 397 of file buf_internals.h.

399 {
PGDLLIMPORT const ResourceOwnerDesc buffer_pin_resowner_desc
Definition: bufmgr.c:234
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:554

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

◆ ResourceOwnerForgetBufferIO()

static void ResourceOwnerForgetBufferIO ( ResourceOwner  owner,
Buffer  buffer 
)
inlinestatic

Definition at line 407 of file buf_internals.h.

409 {
PGDLLIMPORT const ResourceOwnerDesc buffer_io_resowner_desc
Definition: bufmgr.c:225

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

◆ ResourceOwnerRememberBuffer()

static void ResourceOwnerRememberBuffer ( ResourceOwner  owner,
Buffer  buffer 
)
inlinestatic

Definition at line 392 of file buf_internals.h.

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

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

◆ ResourceOwnerRememberBufferIO()

static void ResourceOwnerRememberBufferIO ( ResourceOwner  owner,
Buffer  buffer 
)
inlinestatic

◆ ScheduleBufferTagForWriteback()

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

Definition at line 5842 of file bufmgr.c.

5844 {
5845  PendingWriteback *pending;
5846 
5848  return;
5849 
5850  /*
5851  * Add buffer to the pending writeback array, unless writeback control is
5852  * disabled.
5853  */
5854  if (*wb_context->max_pending > 0)
5855  {
5857 
5858  pending = &wb_context->pending_writebacks[wb_context->nr_pending++];
5859 
5860  pending->tag = *tag;
5861  }
5862 
5863  /*
5864  * Perform pending flushes if the writeback limit is exceeded. This
5865  * includes the case where previously an item has been added, but control
5866  * is now disabled.
5867  */
5868  if (wb_context->nr_pending >= *wb_context->max_pending)
5869  IssuePendingWritebacks(wb_context, io_context);
5870 }
void IssuePendingWritebacks(WritebackContext *wb_context, IOContext io_context)
Definition: bufmgr.c:5887
#define WRITEBACK_MAX_PENDING_FLUSHES

References Assert, 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().

◆ StrategyFreeBuffer()

void StrategyFreeBuffer ( BufferDesc buf)

Definition at line 363 of file freelist.c.

364 {
366 
367  /*
368  * It is possible that we are told to put something in the freelist that
369  * is already in it; don't screw up the list if so.
370  */
371  if (buf->freeNext == FREENEXT_NOT_IN_LIST)
372  {
373  buf->freeNext = StrategyControl->firstFreeBuffer;
374  if (buf->freeNext < 0)
377  }
378 
380 }
#define FREENEXT_NOT_IN_LIST
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
slock_t buffer_strategy_lock
Definition: freelist.c:33

References buf, BufferStrategyControl::buffer_strategy_lock, BufferStrategyControl::firstFreeBuffer, FREENEXT_NOT_IN_LIST, BufferStrategyControl::lastFreeBuffer, SpinLockAcquire, SpinLockRelease, and StrategyControl.

Referenced by BufferAlloc(), ExtendBufferedRelShared(), and InvalidateBuffer().

◆ StrategyGetBuffer()

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

Definition at line 196 of file freelist.c.

197 {
198  BufferDesc *buf;
199  int bgwprocno;
200  int trycounter;
201  uint32 local_buf_state; /* to avoid repeated (de-)referencing */
202 
203  *from_ring = false;
204 
205  /*
206  * If given a strategy object, see whether it can select a buffer. We
207  * assume strategy objects don't need buffer_strategy_lock.
208  */
209  if (strategy != NULL)
210  {
211  buf = GetBufferFromRing(strategy, buf_state);
212  if (buf != NULL)
213  {
214  *from_ring = true;
215  return buf;
216  }
217  }
218 
219  /*
220  * If asked, we need to waken the bgwriter. Since we don't want to rely on
221  * a spinlock for this we force a read from shared memory once, and then
222  * set the latch based on that value. We need to go through that length
223  * because otherwise bgwprocno might be reset while/after we check because
224  * the compiler might just reread from memory.
225  *
226  * This can possibly set the latch of the wrong process if the bgwriter
227  * dies in the wrong moment. But since PGPROC->procLatch is never
228  * deallocated the worst consequence of that is that we set the latch of
229  * some arbitrary process.
230  */
232  if (bgwprocno != -1)
233  {
234  /* reset bgwprocno first, before setting the latch */
236 
237  /*
238  * Not acquiring ProcArrayLock here which is slightly icky. It's
239  * actually fine because procLatch isn't ever freed, so we just can
240  * potentially set the wrong process' (or no process') latch.
241  */
242  SetLatch(&ProcGlobal->allProcs[bgwprocno].procLatch);
243  }
244 
245  /*
246  * We count buffer allocation requests so that the bgwriter can estimate
247  * the rate of buffer consumption. Note that buffers recycled by a
248  * strategy object are intentionally not counted here.
249  */
251 
252  /*
253  * First check, without acquiring the lock, whether there's buffers in the
254  * freelist. Since we otherwise don't require the spinlock in every
255  * StrategyGetBuffer() invocation, it'd be sad to acquire it here -
256  * uselessly in most cases. That obviously leaves a race where a buffer is
257  * put on the freelist but we don't see the store yet - but that's pretty
258  * harmless, it'll just get used during the next buffer acquisition.
259  *
260  * If there's buffers on the freelist, acquire the spinlock to pop one
261  * buffer of the freelist. Then check whether that buffer is usable and
262  * repeat if not.
263  *
264  * Note that the freeNext fields are considered to be protected by the
265  * buffer_strategy_lock not the individual buffer spinlocks, so it's OK to
266  * manipulate them without holding the spinlock.
267  */
269  {
270  while (true)
271  {
272  /* Acquire the spinlock to remove element from the freelist */
274 
276  {
278  break;
279  }
280 
282  Assert(buf->freeNext != FREENEXT_NOT_IN_LIST);
283 
284  /* Unconditionally remove buffer from freelist */
285  StrategyControl->firstFreeBuffer = buf->freeNext;
286  buf->freeNext = FREENEXT_NOT_IN_LIST;
287 
288  /*
289  * Release the lock so someone else can access the freelist while
290  * we check out this buffer.
291  */
293 
294  /*
295  * If the buffer is pinned or has a nonzero usage_count, we cannot
296  * use it; discard it and retry. (This can only happen if VACUUM
297  * put a valid buffer in the freelist and then someone else used
298  * it before we got to it. It's probably impossible altogether as
299  * of 8.3, but we'd better check anyway.)
300  */
301  local_buf_state = LockBufHdr(buf);
302  if (BUF_STATE_GET_REFCOUNT(local_buf_state) == 0
303  && BUF_STATE_GET_USAGECOUNT(local_buf_state) == 0)
304  {
305  if (strategy != NULL)
306  AddBufferToRing(strategy, buf);
307  *buf_state = local_buf_state;
308  return buf;
309  }
310  UnlockBufHdr(buf, local_buf_state);
311  }
312  }
313 
314  /* Nothing on the freelist, so run the "clock sweep" algorithm */
315  trycounter = NBuffers;
316  for (;;)
317  {
319 
320  /*
321  * If the buffer is pinned or has a nonzero usage_count, we cannot use
322  * it; decrement the usage_count (unless pinned) and keep scanning.
323  */
324  local_buf_state = LockBufHdr(buf);
325 
326  if (BUF_STATE_GET_REFCOUNT(local_buf_state) == 0)
327  {
328  if (BUF_STATE_GET_USAGECOUNT(local_buf_state) != 0)
329  {
330  local_buf_state -= BUF_USAGECOUNT_ONE;
331 
332  trycounter = NBuffers;
333  }
334  else
335  {
336  /* Found a usable buffer */
337  if (strategy != NULL)
338  AddBufferToRing(strategy, buf);
339  *buf_state = local_buf_state;
340  return buf;
341  }
342  }
343  else if (--trycounter == 0)
344  {
345  /*
346  * We've scanned all the buffers without making any state changes,
347  * so all the buffers are pinned (or were when we looked at them).
348  * We could hope that someone will free one eventually, but it's
349  * probably better to fail than to risk getting stuck in an
350  * infinite loop.
351  */
352  UnlockBufHdr(buf, local_buf_state);
353  elog(ERROR, "no unpinned buffers available");
354  }
355  UnlockBufHdr(buf, local_buf_state);
356  }
357 }
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:361
static BufferDesc * GetBufferDescriptor(uint32 id)
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:51
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:5688
static uint32 ClockSweepTick(void)
Definition: freelist.c:108
static void AddBufferToRing(BufferAccessStrategy strategy, BufferDesc *buf)
Definition: freelist.c:748
#define INT_ACCESS_ONCE(var)
Definition: freelist.c:24
static BufferDesc * GetBufferFromRing(BufferAccessStrategy strategy, uint32 *buf_state)
Definition: freelist.c:695
int NBuffers
Definition: globals.c:139
void SetLatch(Latch *latch)
Definition: latch.c:632
PROC_HDR * ProcGlobal
Definition: proc.c:78
pg_atomic_uint32 numBufferAllocs
Definition: freelist.c:55
Latch procLatch
Definition: proc.h:165
PGPROC * allProcs
Definition: proc.h:380

References AddBufferToRing(), PROC_HDR::allProcs, Assert, BufferStrategyControl::bgwprocno, buf, BUF_STATE_GET_REFCOUNT, BUF_STATE_GET_USAGECOUNT, BUF_USAGECOUNT_ONE, BufferStrategyControl::buffer_strategy_lock, ClockSweepTick(), elog, ERROR, BufferStrategyControl::firstFreeBuffer, FREENEXT_NOT_IN_LIST, GetBufferDescriptor(), GetBufferFromRing(), INT_ACCESS_ONCE, LockBufHdr(), NBuffers, BufferStrategyControl::numBufferAllocs, pg_atomic_fetch_add_u32(), ProcGlobal, PGPROC::procLatch, SetLatch(), SpinLockAcquire, SpinLockRelease, StrategyControl, and UnlockBufHdr().

Referenced by GetVictimBuffer().

◆ StrategyInitialize()

void StrategyInitialize ( bool  init)

Definition at line 474 of file freelist.c.

475 {
476  bool found;
477 
478  /*
479  * Initialize the shared buffer lookup hashtable.
480  *
481  * Since we can't tolerate running out of lookup table entries, we must be
482  * sure to specify an adequate table size here. The maximum steady-state
483  * usage is of course NBuffers entries, but BufferAlloc() tries to insert
484  * a new entry before deleting the old. In principle this could be
485  * happening in each partition concurrently, so we could need as many as
486  * NBuffers + NUM_BUFFER_PARTITIONS entries.
487  */
489 
490  /*
491  * Get or create the shared strategy control block
492  */
494  ShmemInitStruct("Buffer Strategy Status",
495  sizeof(BufferStrategyControl),
496  &found);
497 
498  if (!found)
499  {
500  /*
501  * Only done once, usually in postmaster
502  */
503  Assert(init);
504 
506 
507  /*
508  * Grab the whole linked list of free buffers for our strategy. We
509  * assume it was previously set up by InitBufferPool().
510  */
513 
514  /* Initialize the clock sweep pointer */
516 
517  /* Clear statistics */
520 
521  /* No pending notification */
523  }
524  else
525  Assert(!init);
526 }
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:216
void InitBufTable(int size)
Definition: buf_table.c:51
int init
Definition: isn.c:75
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
#define SpinLockInit(lock)
Definition: spin.h:60
pg_atomic_uint32 nextVictimBuffer
Definition: freelist.c:40

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

Referenced by InitBufferPool().

◆ StrategyNotifyBgWriter()

void StrategyNotifyBgWriter ( int  bgwprocno)

Definition at line 431 of file freelist.c.

432 {
433  /*
434  * We acquire buffer_strategy_lock just to ensure that the store appears
435  * atomic to StrategyGetBuffer. The bgwriter should call this rather
436  * infrequently, so there's no performance penalty from being safe.
437  */
439  StrategyControl->bgwprocno = bgwprocno;
441 }

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 798 of file freelist.c.

799 {
800  /* We only do this in bulkread mode */
801  if (strategy->btype != BAS_BULKREAD)
802  return false;
803 
804  /* Don't muck with behavior of normal buffer-replacement strategy */
805  if (!from_ring ||
806  strategy->buffers[strategy->current] != BufferDescriptorGetBuffer(buf))
807  return false;
808 
809  /*
810  * Remove the dirty buffer from the ring; necessary to prevent infinite
811  * loop if all ring members are dirty.
812  */
813  strategy->buffers[strategy->current] = InvalidBuffer;
814 
815  return true;
816 }
Buffer buffers[FLEXIBLE_ARRAY_MEMBER]
Definition: freelist.c:91

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

Referenced by GetVictimBuffer().

◆ StrategyShmemSize()

Size StrategyShmemSize ( void  )

Definition at line 453 of file freelist.c.

454 {
455  Size size = 0;
456 
457  /* size of lookup hash table ... see comment in StrategyInitialize */
459 
460  /* size of the shared replacement strategy control block */
462 
463  return size;
464 }
Size BufTableShmemSize(int size)
Definition: buf_table.c:41
#define MAXALIGN(LEN)
Definition: c.h:811
Size add_size(Size s1, Size s2)
Definition: shmem.c:493

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

Referenced by BufferShmemSize().

◆ StrategySyncStart()

int StrategySyncStart ( uint32 complete_passes,
uint32 num_buf_alloc 
)

Definition at line 394 of file freelist.c.

395 {
396  uint32 nextVictimBuffer;
397  int result;
398 
401  result = nextVictimBuffer % NBuffers;
402 
403  if (complete_passes)
404  {
405  *complete_passes = StrategyControl->completePasses;
406 
407  /*
408  * Additionally add the number of wraparounds that happened before
409  * completePasses could be incremented. C.f. ClockSweepTick().
410  */
411  *complete_passes += nextVictimBuffer / NBuffers;
412  }
413 
414  if (num_buf_alloc)
415  {
417  }
419  return result;
420 }
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:325

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().

◆ UnlockBufHdr()

◆ UnpinLocalBuffer()

void UnpinLocalBuffer ( Buffer  buffer)

Definition at line 681 of file localbuf.c.

682 {
683  UnpinLocalBufferNoOwner(buffer);
685 }
void UnpinLocalBufferNoOwner(Buffer buffer)
Definition: localbuf.c:688
void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)

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

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

◆ UnpinLocalBufferNoOwner()

void UnpinLocalBufferNoOwner ( Buffer  buffer)

Definition at line 688 of file localbuf.c.

689 {
690  int buffid = -buffer - 1;
691 
692  Assert(BufferIsLocal(buffer));
693  Assert(LocalRefCount[buffid] > 0);
695 
696  if (--LocalRefCount[buffid] == 0)
698 }

References Assert, BufferIsLocal, LocalRefCount, and NLocalPinnedBuffers.

Referenced by ResOwnerReleaseBufferPin(), and UnpinLocalBuffer().

◆ WritebackContextInit()

void WritebackContextInit ( WritebackContext context,
int *  max_pending 
)

Definition at line 5830 of file bufmgr.c.

5831 {
5832  Assert(*max_pending <= WRITEBACK_MAX_PENDING_FLUSHES);
5833 
5834  context->max_pending = max_pending;
5835  context->nr_pending = 0;
5836 }
tree context
Definition: radixtree.h:1829

References Assert, context, and WRITEBACK_MAX_PENDING_FLUSHES.

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

Variable Documentation

◆ BackendWritebackContext

PGDLLIMPORT WritebackContext BackendWritebackContext
extern

Definition at line 24 of file buf_init.c.

Referenced by GetVictimBuffer(), and InitBufferPool().

◆ buffer_io_resowner_desc

PGDLLIMPORT const ResourceOwnerDesc buffer_io_resowner_desc
extern

Definition at line 225 of file bufmgr.c.

Referenced by ResourceOwnerForgetBufferIO(), and ResourceOwnerRememberBufferIO().

◆ buffer_pin_resowner_desc

PGDLLIMPORT const ResourceOwnerDesc buffer_pin_resowner_desc
extern

Definition at line 234 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 GetBufferDescriptor(), and InitBufferPool().

◆ BufferIOCVArray

Definition at line 23 of file buf_init.c.

Referenced by BufferDescriptorGetIOCV(), and InitBufferPool().

◆ CkptBufferIds

PGDLLIMPORT CkptSortItem* CkptBufferIds
extern

Definition at line 25 of file buf_init.c.

Referenced by BufferSync(), and InitBufferPool().

◆ LocalBufferDescriptors

PGDLLIMPORT BufferDesc* LocalBufferDescriptors
extern

Definition at line 44 of file localbuf.c.

Referenced by GetLocalBufferDescriptor(), and InitLocalBuffers().