PostgreSQL Source Code  git master
bufmgr.h File Reference
#include "port/pg_iovec.h"
#include "storage/block.h"
#include "storage/buf.h"
#include "storage/bufpage.h"
#include "storage/relfilelocator.h"
#include "utils/relcache.h"
#include "utils/snapmgr.h"
Include dependency graph for bufmgr.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PrefetchBufferResult
 
struct  BufferManagerRelation
 
struct  ReadBuffersOperation
 

Macros

#define BMR_REL(p_rel)   ((BufferManagerRelation){.rel = p_rel})
 
#define BMR_SMGR(p_smgr, p_relpersistence)   ((BufferManagerRelation){.smgr = p_smgr, .relpersistence = p_relpersistence})
 
#define DEFAULT_EFFECTIVE_IO_CONCURRENCY   0
 
#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   0
 
#define MAX_IO_COMBINE_LIMIT   PG_IOV_MAX
 
#define DEFAULT_IO_COMBINE_LIMIT   Min(MAX_IO_COMBINE_LIMIT, (128 * 1024) / BLCKSZ)
 
#define MAX_IO_CONCURRENCY   1000
 
#define P_NEW   InvalidBlockNumber /* grow the file to get a new page */
 
#define BUFFER_LOCK_UNLOCK   0
 
#define BUFFER_LOCK_SHARE   1
 
#define BUFFER_LOCK_EXCLUSIVE   2
 
#define RelationGetNumberOfBlocks(reln)    RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)
 

Typedefs

typedef void * Block
 
typedef enum BufferAccessStrategyType BufferAccessStrategyType
 
typedef struct PrefetchBufferResult PrefetchBufferResult
 
typedef enum ExtendBufferedFlags ExtendBufferedFlags
 
typedef struct BufferManagerRelation BufferManagerRelation
 
typedef enum ReadBuffersFlags ReadBuffersFlags
 
typedef struct ReadBuffersOperation ReadBuffersOperation
 

Enumerations

enum  BufferAccessStrategyType { BAS_NORMAL , BAS_BULKREAD , BAS_BULKWRITE , BAS_VACUUM }
 
enum  ReadBufferMode {
  RBM_NORMAL , RBM_ZERO_AND_LOCK , RBM_ZERO_AND_CLEANUP_LOCK , RBM_ZERO_ON_ERROR ,
  RBM_NORMAL_NO_LOG
}
 
enum  ExtendBufferedFlags {
  EB_SKIP_EXTENSION_LOCK = (1 << 0) , EB_PERFORMING_RECOVERY = (1 << 1) , EB_CREATE_FORK_IF_NEEDED = (1 << 2) , EB_LOCK_FIRST = (1 << 3) ,
  EB_CLEAR_SIZE_CACHE = (1 << 4) , EB_LOCK_TARGET = (1 << 5)
}
 
enum  ReadBuffersFlags { READ_BUFFERS_ZERO_ON_ERROR = (1 << 0) , READ_BUFFERS_ISSUE_ADVICE = (1 << 1) }
 

Functions

PrefetchBufferResult PrefetchSharedBuffer (struct SMgrRelationData *smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
 
PrefetchBufferResult PrefetchBuffer (Relation reln, ForkNumber forkNum, BlockNumber blockNum)
 
bool ReadRecentBuffer (RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, Buffer recent_buffer)
 
Buffer ReadBuffer (Relation reln, BlockNumber blockNum)
 
Buffer ReadBufferExtended (Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
 
Buffer ReadBufferWithoutRelcache (RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool permanent)
 
bool StartReadBuffer (ReadBuffersOperation *operation, Buffer *buffer, BlockNumber blocknum, int flags)
 
bool StartReadBuffers (ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blocknum, int *nblocks, int flags)
 
void WaitReadBuffers (ReadBuffersOperation *operation)
 
void ReleaseBuffer (Buffer buffer)
 
void UnlockReleaseBuffer (Buffer buffer)
 
bool BufferIsExclusiveLocked (Buffer buffer)
 
bool BufferIsDirty (Buffer buffer)
 
void MarkBufferDirty (Buffer buffer)
 
void IncrBufferRefCount (Buffer buffer)
 
void CheckBufferIsPinnedOnce (Buffer buffer)
 
Buffer ReleaseAndReadBuffer (Buffer buffer, Relation relation, BlockNumber blockNum)
 
Buffer ExtendBufferedRel (BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
 
BlockNumber ExtendBufferedRelBy (BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, Buffer *buffers, uint32 *extended_by)
 
Buffer ExtendBufferedRelTo (BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, BlockNumber extend_to, ReadBufferMode mode)
 
void InitBufferPoolAccess (void)
 
void AtEOXact_Buffers (bool isCommit)
 
char * DebugPrintBufferRefcount (Buffer buffer)
 
void CheckPointBuffers (int flags)
 
BlockNumber BufferGetBlockNumber (Buffer buffer)
 
BlockNumber RelationGetNumberOfBlocksInFork (Relation relation, ForkNumber forkNum)
 
void FlushOneBuffer (Buffer buffer)
 
void FlushRelationBuffers (Relation rel)
 
void FlushRelationsAllBuffers (struct SMgrRelationData **smgrs, int nrels)
 
void CreateAndCopyRelationData (RelFileLocator src_rlocator, RelFileLocator dst_rlocator, bool permanent)
 
void FlushDatabaseBuffers (Oid dbid)
 
void DropRelationBuffers (struct SMgrRelationData *smgr_reln, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
 
void DropRelationsAllBuffers (struct SMgrRelationData **smgr_reln, int nlocators)
 
void DropDatabaseBuffers (Oid dbid)
 
bool BufferIsPermanent (Buffer buffer)
 
XLogRecPtr BufferGetLSNAtomic (Buffer buffer)
 
void BufferGetTag (Buffer buffer, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
 
void MarkBufferDirtyHint (Buffer buffer, bool buffer_std)
 
void UnlockBuffers (void)
 
void LockBuffer (Buffer buffer, int mode)
 
bool ConditionalLockBuffer (Buffer buffer)
 
void LockBufferForCleanup (Buffer buffer)
 
bool ConditionalLockBufferForCleanup (Buffer buffer)
 
bool IsBufferCleanupOK (Buffer buffer)
 
bool HoldingBufferPinThatDelaysRecovery (void)
 
bool BgBufferSync (struct WritebackContext *wb_context)
 
void LimitAdditionalPins (uint32 *additional_pins)
 
void LimitAdditionalLocalPins (uint32 *additional_pins)
 
bool EvictUnpinnedBuffer (Buffer buf)
 
void InitBufferPool (void)
 
Size BufferShmemSize (void)
 
void AtProcExit_LocalBuffers (void)
 
BufferAccessStrategy GetAccessStrategy (BufferAccessStrategyType btype)
 
BufferAccessStrategy GetAccessStrategyWithSize (BufferAccessStrategyType btype, int ring_size_kb)
 
int GetAccessStrategyBufferCount (BufferAccessStrategy strategy)
 
int GetAccessStrategyPinLimit (BufferAccessStrategy strategy)
 
void FreeAccessStrategy (BufferAccessStrategy strategy)
 
static bool BufferIsValid (Buffer bufnum)
 
static Block BufferGetBlock (Buffer buffer)
 
static Size BufferGetPageSize (Buffer buffer)
 
static Page BufferGetPage (Buffer buffer)
 

Variables

PGDLLIMPORT int NBuffers
 
PGDLLIMPORT bool zero_damaged_pages
 
PGDLLIMPORT int bgwriter_lru_maxpages
 
PGDLLIMPORT double bgwriter_lru_multiplier
 
PGDLLIMPORT bool track_io_timing
 
PGDLLIMPORT int effective_io_concurrency
 
PGDLLIMPORT int maintenance_io_concurrency
 
PGDLLIMPORT int io_combine_limit
 
PGDLLIMPORT int checkpoint_flush_after
 
PGDLLIMPORT int backend_flush_after
 
PGDLLIMPORT int bgwriter_flush_after
 
PGDLLIMPORT char * BufferBlocks
 
PGDLLIMPORT int NLocBuffer
 
PGDLLIMPORT BlockLocalBufferBlockPointers
 
PGDLLIMPORT int32LocalRefCount
 

Macro Definition Documentation

◆ BMR_REL

#define BMR_REL (   p_rel)    ((BufferManagerRelation){.rel = p_rel})

Definition at line 107 of file bufmgr.h.

◆ BMR_SMGR

#define BMR_SMGR (   p_smgr,
  p_relpersistence 
)    ((BufferManagerRelation){.smgr = p_smgr, .relpersistence = p_relpersistence})

Definition at line 108 of file bufmgr.h.

◆ BUFFER_LOCK_EXCLUSIVE

#define BUFFER_LOCK_EXCLUSIVE   2

Definition at line 199 of file bufmgr.h.

◆ BUFFER_LOCK_SHARE

#define BUFFER_LOCK_SHARE   1

Definition at line 198 of file bufmgr.h.

◆ BUFFER_LOCK_UNLOCK

#define BUFFER_LOCK_UNLOCK   0

Definition at line 197 of file bufmgr.h.

◆ DEFAULT_EFFECTIVE_IO_CONCURRENCY

#define DEFAULT_EFFECTIVE_IO_CONCURRENCY   0

Definition at line 166 of file bufmgr.h.

◆ DEFAULT_IO_COMBINE_LIMIT

#define DEFAULT_IO_COMBINE_LIMIT   Min(MAX_IO_COMBINE_LIMIT, (128 * 1024) / BLCKSZ)

Definition at line 173 of file bufmgr.h.

◆ DEFAULT_MAINTENANCE_IO_CONCURRENCY

#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   0

Definition at line 167 of file bufmgr.h.

◆ MAX_IO_COMBINE_LIMIT

#define MAX_IO_COMBINE_LIMIT   PG_IOV_MAX

Definition at line 172 of file bufmgr.h.

◆ MAX_IO_CONCURRENCY

#define MAX_IO_CONCURRENCY   1000

Definition at line 189 of file bufmgr.h.

◆ P_NEW

#define P_NEW   InvalidBlockNumber /* grow the file to get a new page */

Definition at line 192 of file bufmgr.h.

◆ RelationGetNumberOfBlocks

#define RelationGetNumberOfBlocks (   reln)     RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)

Definition at line 281 of file bufmgr.h.

Typedef Documentation

◆ Block

typedef void* Block

Definition at line 25 of file bufmgr.h.

◆ BufferAccessStrategyType

◆ BufferManagerRelation

◆ ExtendBufferedFlags

◆ PrefetchBufferResult

◆ ReadBuffersFlags

◆ ReadBuffersOperation

Definition at line 25 of file bufmgr.h.

Enumeration Type Documentation

◆ BufferAccessStrategyType

Enumerator
BAS_NORMAL 
BAS_BULKREAD 
BAS_BULKWRITE 
BAS_VACUUM 

Definition at line 33 of file bufmgr.h.

34 {
35  BAS_NORMAL, /* Normal random access */
36  BAS_BULKREAD, /* Large read-only scan (hint bit updates are
37  * ok) */
38  BAS_BULKWRITE, /* Large multi-block write (e.g. COPY IN) */
39  BAS_VACUUM, /* VACUUM */
BufferAccessStrategyType
Definition: bufmgr.h:34
@ BAS_BULKREAD
Definition: bufmgr.h:36
@ BAS_NORMAL
Definition: bufmgr.h:35
@ BAS_VACUUM
Definition: bufmgr.h:39
@ BAS_BULKWRITE
Definition: bufmgr.h:38

◆ ExtendBufferedFlags

Enumerator
EB_SKIP_EXTENSION_LOCK 
EB_PERFORMING_RECOVERY 
EB_CREATE_FORK_IF_NEEDED 
EB_LOCK_FIRST 
EB_CLEAR_SIZE_CACHE 
EB_LOCK_TARGET 

Definition at line 67 of file bufmgr.h.

68 {
69  /*
70  * Don't acquire extension lock. This is safe only if the relation isn't
71  * shared, an access exclusive lock is held or if this is the startup
72  * process.
73  */
74  EB_SKIP_EXTENSION_LOCK = (1 << 0),
75 
76  /* Is this extension part of recovery? */
77  EB_PERFORMING_RECOVERY = (1 << 1),
78 
79  /*
80  * Should the fork be created if it does not currently exist? This likely
81  * only ever makes sense for relation forks.
82  */
83  EB_CREATE_FORK_IF_NEEDED = (1 << 2),
84 
85  /* Should the first (possibly only) return buffer be returned locked? */
86  EB_LOCK_FIRST = (1 << 3),
87 
88  /* Should the smgr size cache be cleared? */
89  EB_CLEAR_SIZE_CACHE = (1 << 4),
90 
91  /* internal flags follow */
92  EB_LOCK_TARGET = (1 << 5),
ExtendBufferedFlags
Definition: bufmgr.h:68
@ EB_LOCK_TARGET
Definition: bufmgr.h:92
@ EB_CLEAR_SIZE_CACHE
Definition: bufmgr.h:89
@ EB_PERFORMING_RECOVERY
Definition: bufmgr.h:77
@ EB_CREATE_FORK_IF_NEEDED
Definition: bufmgr.h:83
@ EB_SKIP_EXTENSION_LOCK
Definition: bufmgr.h:74
@ EB_LOCK_FIRST
Definition: bufmgr.h:86

◆ ReadBufferMode

Enumerator
RBM_NORMAL 
RBM_ZERO_AND_LOCK 
RBM_ZERO_AND_CLEANUP_LOCK 
RBM_ZERO_ON_ERROR 
RBM_NORMAL_NO_LOG 

Definition at line 43 of file bufmgr.h.

44 {
45  RBM_NORMAL, /* Normal read */
46  RBM_ZERO_AND_LOCK, /* Don't read from disk, caller will
47  * initialize. Also locks the page. */
48  RBM_ZERO_AND_CLEANUP_LOCK, /* Like RBM_ZERO_AND_LOCK, but locks the page
49  * in "cleanup" mode */
50  RBM_ZERO_ON_ERROR, /* Read, but return an all-zeros page on error */
51  RBM_NORMAL_NO_LOG, /* Don't log page as invalid during WAL
52  * replay; otherwise same as RBM_NORMAL */
ReadBufferMode
Definition: bufmgr.h:44
@ RBM_ZERO_ON_ERROR
Definition: bufmgr.h:50
@ RBM_ZERO_AND_CLEANUP_LOCK
Definition: bufmgr.h:48
@ RBM_ZERO_AND_LOCK
Definition: bufmgr.h:46
@ RBM_NORMAL
Definition: bufmgr.h:45
@ RBM_NORMAL_NO_LOG
Definition: bufmgr.h:51

◆ ReadBuffersFlags

Enumerator
READ_BUFFERS_ZERO_ON_ERROR 
READ_BUFFERS_ISSUE_ADVICE 

Definition at line 110 of file bufmgr.h.

111 {
112  /* Zero out page if reading fails. */
113  READ_BUFFERS_ZERO_ON_ERROR = (1 << 0),
114 
115  /* Call smgrprefetch() if I/O necessary. */
116  READ_BUFFERS_ISSUE_ADVICE = (1 << 1),
ReadBuffersFlags
Definition: bufmgr.h:111
@ READ_BUFFERS_ZERO_ON_ERROR
Definition: bufmgr.h:113
@ READ_BUFFERS_ISSUE_ADVICE
Definition: bufmgr.h:116

Function Documentation

◆ AtEOXact_Buffers()

void AtEOXact_Buffers ( bool  isCommit)

Definition at line 3502 of file bufmgr.c.

3503 {
3505 
3506  AtEOXact_LocalBuffers(isCommit);
3507 
3509 }
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:3562
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:209
#define Assert(condition)
Definition: c.h:858
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:819

References Assert, AtEOXact_LocalBuffers(), CheckForBufferLeaks(), and PrivateRefCountOverflowed.

Referenced by AbortTransaction(), BackgroundWriterMain(), CheckpointerMain(), CommitTransaction(), PrepareTransaction(), and WalWriterMain().

◆ AtProcExit_LocalBuffers()

void AtProcExit_LocalBuffers ( void  )

Definition at line 830 of file localbuf.c.

831 {
832  /*
833  * We shouldn't be holding any remaining pins; if we are, and assertions
834  * aren't enabled, we'll fail later in DropRelationBuffers while trying to
835  * drop the temp rels.
836  */
838 }
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:786

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

◆ BgBufferSync()

bool BgBufferSync ( struct WritebackContext wb_context)

Definition at line 3131 of file bufmgr.c.

3132 {
3133  /* info obtained from freelist.c */
3134  int strategy_buf_id;
3135  uint32 strategy_passes;
3136  uint32 recent_alloc;
3137 
3138  /*
3139  * Information saved between calls so we can determine the strategy
3140  * point's advance rate and avoid scanning already-cleaned buffers.
3141  */
3142  static bool saved_info_valid = false;
3143  static int prev_strategy_buf_id;
3144  static uint32 prev_strategy_passes;
3145  static int next_to_clean;
3146  static uint32 next_passes;
3147 
3148  /* Moving averages of allocation rate and clean-buffer density */
3149  static float smoothed_alloc = 0;
3150  static float smoothed_density = 10.0;
3151 
3152  /* Potentially these could be tunables, but for now, not */
3153  float smoothing_samples = 16;
3154  float scan_whole_pool_milliseconds = 120000.0;
3155 
3156  /* Used to compute how far we scan ahead */
3157  long strategy_delta;
3158  int bufs_to_lap;
3159  int bufs_ahead;
3160  float scans_per_alloc;
3161  int reusable_buffers_est;
3162  int upcoming_alloc_est;
3163  int min_scan_buffers;
3164 
3165  /* Variables for the scanning loop proper */
3166  int num_to_scan;
3167  int num_written;
3168  int reusable_buffers;
3169 
3170  /* Variables for final smoothed_density update */
3171  long new_strategy_delta;
3172  uint32 new_recent_alloc;
3173 
3174  /*
3175  * Find out where the freelist clock sweep currently is, and how many
3176  * buffer allocations have happened since our last call.
3177  */
3178  strategy_buf_id = StrategySyncStart(&strategy_passes, &recent_alloc);
3179 
3180  /* Report buffer alloc counts to pgstat */
3181  PendingBgWriterStats.buf_alloc += recent_alloc;
3182 
3183  /*
3184  * If we're not running the LRU scan, just stop after doing the stats
3185  * stuff. We mark the saved state invalid so that we can recover sanely
3186  * if LRU scan is turned back on later.
3187  */
3188  if (bgwriter_lru_maxpages <= 0)
3189  {
3190  saved_info_valid = false;
3191  return true;
3192  }
3193 
3194  /*
3195  * Compute strategy_delta = how many buffers have been scanned by the
3196  * clock sweep since last time. If first time through, assume none. Then
3197  * see if we are still ahead of the clock sweep, and if so, how many
3198  * buffers we could scan before we'd catch up with it and "lap" it. Note:
3199  * weird-looking coding of xxx_passes comparisons are to avoid bogus
3200  * behavior when the passes counts wrap around.
3201  */
3202  if (saved_info_valid)
3203  {
3204  int32 passes_delta = strategy_passes - prev_strategy_passes;
3205 
3206  strategy_delta = strategy_buf_id - prev_strategy_buf_id;
3207  strategy_delta += (long) passes_delta * NBuffers;
3208 
3209  Assert(strategy_delta >= 0);
3210 
3211  if ((int32) (next_passes - strategy_passes) > 0)
3212  {
3213  /* we're one pass ahead of the strategy point */
3214  bufs_to_lap = strategy_buf_id - next_to_clean;
3215 #ifdef BGW_DEBUG
3216  elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3217  next_passes, next_to_clean,
3218  strategy_passes, strategy_buf_id,
3219  strategy_delta, bufs_to_lap);
3220 #endif
3221  }
3222  else if (next_passes == strategy_passes &&
3223  next_to_clean >= strategy_buf_id)
3224  {
3225  /* on same pass, but ahead or at least not behind */
3226  bufs_to_lap = NBuffers - (next_to_clean - strategy_buf_id);
3227 #ifdef BGW_DEBUG
3228  elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3229  next_passes, next_to_clean,
3230  strategy_passes, strategy_buf_id,
3231  strategy_delta, bufs_to_lap);
3232 #endif
3233  }
3234  else
3235  {
3236  /*
3237  * We're behind, so skip forward to the strategy point and start
3238  * cleaning from there.
3239  */
3240 #ifdef BGW_DEBUG
3241  elog(DEBUG2, "bgwriter behind: bgw %u-%u strategy %u-%u delta=%ld",
3242  next_passes, next_to_clean,
3243  strategy_passes, strategy_buf_id,
3244  strategy_delta);
3245 #endif
3246  next_to_clean = strategy_buf_id;
3247  next_passes = strategy_passes;
3248  bufs_to_lap = NBuffers;
3249  }
3250  }
3251  else
3252  {
3253  /*
3254  * Initializing at startup or after LRU scanning had been off. Always
3255  * start at the strategy point.
3256  */
3257 #ifdef BGW_DEBUG
3258  elog(DEBUG2, "bgwriter initializing: strategy %u-%u",
3259  strategy_passes, strategy_buf_id);
3260 #endif
3261  strategy_delta = 0;
3262  next_to_clean = strategy_buf_id;
3263  next_passes = strategy_passes;
3264  bufs_to_lap = NBuffers;
3265  }
3266 
3267  /* Update saved info for next time */
3268  prev_strategy_buf_id = strategy_buf_id;
3269  prev_strategy_passes = strategy_passes;
3270  saved_info_valid = true;
3271 
3272  /*
3273  * Compute how many buffers had to be scanned for each new allocation, ie,
3274  * 1/density of reusable buffers, and track a moving average of that.
3275  *
3276  * If the strategy point didn't move, we don't update the density estimate
3277  */
3278  if (strategy_delta > 0 && recent_alloc > 0)
3279  {
3280  scans_per_alloc = (float) strategy_delta / (float) recent_alloc;
3281  smoothed_density += (scans_per_alloc - smoothed_density) /
3282  smoothing_samples;
3283  }
3284 
3285  /*
3286  * Estimate how many reusable buffers there are between the current
3287  * strategy point and where we've scanned ahead to, based on the smoothed
3288  * density estimate.
3289  */
3290  bufs_ahead = NBuffers - bufs_to_lap;
3291  reusable_buffers_est = (float) bufs_ahead / smoothed_density;
3292 
3293  /*
3294  * Track a moving average of recent buffer allocations. Here, rather than
3295  * a true average we want a fast-attack, slow-decline behavior: we
3296  * immediately follow any increase.
3297  */
3298  if (smoothed_alloc <= (float) recent_alloc)
3299  smoothed_alloc = recent_alloc;
3300  else
3301  smoothed_alloc += ((float) recent_alloc - smoothed_alloc) /
3302  smoothing_samples;
3303 
3304  /* Scale the estimate by a GUC to allow more aggressive tuning. */
3305  upcoming_alloc_est = (int) (smoothed_alloc * bgwriter_lru_multiplier);
3306 
3307  /*
3308  * If recent_alloc remains at zero for many cycles, smoothed_alloc will
3309  * eventually underflow to zero, and the underflows produce annoying
3310  * kernel warnings on some platforms. Once upcoming_alloc_est has gone to
3311  * zero, there's no point in tracking smaller and smaller values of
3312  * smoothed_alloc, so just reset it to exactly zero to avoid this
3313  * syndrome. It will pop back up as soon as recent_alloc increases.
3314  */
3315  if (upcoming_alloc_est == 0)
3316  smoothed_alloc = 0;
3317 
3318  /*
3319  * Even in cases where there's been little or no buffer allocation
3320  * activity, we want to make a small amount of progress through the buffer
3321  * cache so that as many reusable buffers as possible are clean after an
3322  * idle period.
3323  *
3324  * (scan_whole_pool_milliseconds / BgWriterDelay) computes how many times
3325  * the BGW will be called during the scan_whole_pool time; slice the
3326  * buffer pool into that many sections.
3327  */
3328  min_scan_buffers = (int) (NBuffers / (scan_whole_pool_milliseconds / BgWriterDelay));
3329 
3330  if (upcoming_alloc_est < (min_scan_buffers + reusable_buffers_est))
3331  {
3332 #ifdef BGW_DEBUG
3333  elog(DEBUG2, "bgwriter: alloc_est=%d too small, using min=%d + reusable_est=%d",
3334  upcoming_alloc_est, min_scan_buffers, reusable_buffers_est);
3335 #endif
3336  upcoming_alloc_est = min_scan_buffers + reusable_buffers_est;
3337  }
3338 
3339  /*
3340  * Now write out dirty reusable buffers, working forward from the
3341  * next_to_clean point, until we have lapped the strategy scan, or cleaned
3342  * enough buffers to match our estimate of the next cycle's allocation
3343  * requirements, or hit the bgwriter_lru_maxpages limit.
3344  */
3345 
3346  num_to_scan = bufs_to_lap;
3347  num_written = 0;
3348  reusable_buffers = reusable_buffers_est;
3349 
3350  /* Execute the LRU scan */
3351  while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
3352  {
3353  int sync_state = SyncOneBuffer(next_to_clean, true,
3354  wb_context);
3355 
3356  if (++next_to_clean >= NBuffers)
3357  {
3358  next_to_clean = 0;
3359  next_passes++;
3360  }
3361  num_to_scan--;
3362 
3363  if (sync_state & BUF_WRITTEN)
3364  {
3365  reusable_buffers++;
3366  if (++num_written >= bgwriter_lru_maxpages)
3367  {
3369  break;
3370  }
3371  }
3372  else if (sync_state & BUF_REUSABLE)
3373  reusable_buffers++;
3374  }
3375 
3376  PendingBgWriterStats.buf_written_clean += num_written;
3377 
3378 #ifdef BGW_DEBUG
3379  elog(DEBUG1, "bgwriter: recent_alloc=%u smoothed=%.2f delta=%ld ahead=%d density=%.2f reusable_est=%d upcoming_est=%d scanned=%d wrote=%d reusable=%d",
3380  recent_alloc, smoothed_alloc, strategy_delta, bufs_ahead,
3381  smoothed_density, reusable_buffers_est, upcoming_alloc_est,
3382  bufs_to_lap - num_to_scan,
3383  num_written,
3384  reusable_buffers - reusable_buffers_est);
3385 #endif
3386 
3387  /*
3388  * Consider the above scan as being like a new allocation scan.
3389  * Characterize its density and update the smoothed one based on it. This
3390  * effectively halves the moving average period in cases where both the
3391  * strategy and the background writer are doing some useful scanning,
3392  * which is helpful because a long memory isn't as desirable on the
3393  * density estimates.
3394  */
3395  new_strategy_delta = bufs_to_lap - num_to_scan;
3396  new_recent_alloc = reusable_buffers - reusable_buffers_est;
3397  if (new_strategy_delta > 0 && new_recent_alloc > 0)
3398  {
3399  scans_per_alloc = (float) new_strategy_delta / (float) new_recent_alloc;
3400  smoothed_density += (scans_per_alloc - smoothed_density) /
3401  smoothing_samples;
3402 
3403 #ifdef BGW_DEBUG
3404  elog(DEBUG2, "bgwriter: cleaner density alloc=%u scan=%ld density=%.2f new smoothed=%.2f",
3405  new_recent_alloc, new_strategy_delta,
3406  scans_per_alloc, smoothed_density);
3407 #endif
3408  }
3409 
3410  /* Return true if OK to hibernate */
3411  return (bufs_to_lap == 0 && recent_alloc == 0);
3412 }
int BgWriterDelay
Definition: bgwriter.c:57
#define BUF_REUSABLE
Definition: bufmgr.c:76
double bgwriter_lru_multiplier
Definition: bufmgr.c:141
static int SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
Definition: bufmgr.c:3429
int bgwriter_lru_maxpages
Definition: bufmgr.c:140
#define BUF_WRITTEN
Definition: bufmgr.c:75
unsigned int uint32
Definition: c.h:506
signed int int32
Definition: c.h:494
#define DEBUG2
Definition: elog.h:29
#define DEBUG1
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:224
int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc)
Definition: freelist.c:394
int NBuffers
Definition: globals.c:139
PgStat_BgWriterStats PendingBgWriterStats
PgStat_Counter buf_written_clean
Definition: pgstat.h:255
PgStat_Counter maxwritten_clean
Definition: pgstat.h:256
PgStat_Counter buf_alloc
Definition: pgstat.h:257

References Assert, bgwriter_lru_maxpages, bgwriter_lru_multiplier, BgWriterDelay, PgStat_BgWriterStats::buf_alloc, BUF_REUSABLE, BUF_WRITTEN, PgStat_BgWriterStats::buf_written_clean, DEBUG1, DEBUG2, elog, PgStat_BgWriterStats::maxwritten_clean, NBuffers, PendingBgWriterStats, StrategySyncStart(), and SyncOneBuffer().

Referenced by BackgroundWriterMain().

◆ BufferGetBlock()

static Block BufferGetBlock ( Buffer  buffer)
inlinestatic

Definition at line 375 of file bufmgr.h.

376 {
377  Assert(BufferIsValid(buffer));
378 
379  if (BufferIsLocal(buffer))
380  return LocalBufferBlockPointers[-buffer - 1];
381  else
382  return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
383 }
#define BufferIsLocal(buffer)
Definition: buf.h:37
PGDLLIMPORT Block * LocalBufferBlockPointers
Definition: localbuf.c:45
void * Block
Definition: bufmgr.h:25
PGDLLIMPORT char * BufferBlocks
Definition: buf_init.c:22
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:359
size_t Size
Definition: c.h:605

References Assert, BufferBlocks, BufferIsLocal, BufferIsValid(), and LocalBufferBlockPointers.

Referenced by BufferGetPage(), WaitReadBuffers(), and XLogSaveBufferForHint().

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)

Definition at line 3667 of file bufmgr.c.

3668 {
3669  BufferDesc *bufHdr;
3670 
3671  Assert(BufferIsPinned(buffer));
3672 
3673  if (BufferIsLocal(buffer))
3674  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
3675  else
3676  bufHdr = GetBufferDescriptor(buffer - 1);
3677 
3678  /* pinned, so OK to read tag without spinlock */
3679  return bufHdr->tag.blockNum;
3680 }
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:473
BufferTag tag
BlockNumber blockNum
Definition: buf_internals.h:98

References Assert, buftag::blockNum, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, GetBufferDescriptor(), GetLocalBufferDescriptor(), and BufferDesc::tag.

Referenced by _bt_binsrch_insert(), _bt_bottomupdel_pass(), _bt_check_unique(), _bt_checkpage(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_doinsert(), _bt_endpoint(), _bt_finish_split(), _bt_first(), _bt_getroot(), _bt_insert_parent(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_moveright(), _bt_newlevel(), _bt_pagedel(), _bt_readnextpage(), _bt_readpage(), _bt_restore_meta(), _bt_search(), _bt_simpledel_pass(), _bt_split(), _bt_unlink_halfdead_page(), _bt_walk_left(), _hash_addovflpage(), _hash_checkpage(), _hash_doinsert(), _hash_first(), _hash_freeovflpage(), _hash_getnewbuf(), _hash_readnext(), _hash_readpage(), _hash_splitbucket(), allocNewBuffer(), blinsert(), BloomInitMetapage(), brin_doinsert(), brin_doupdate(), brin_getinsertbuffer(), brin_initialize_empty_new_buffer(), brin_page_cleanup(), brin_xlog_insert_update(), brinbuild(), brinGetTupleForHeapBlock(), collectMatchBitmap(), createPostingTree(), dataBeginPlaceToPageLeaf(), dataPrepareDownlink(), doPickSplit(), entryPrepareDownlink(), fill_seq_fork_with_data(), ginEntryInsert(), ginFindParents(), ginFinishSplit(), ginPlaceToPage(), ginRedoDeleteListPages(), ginRedoUpdateMetapage(), ginScanToDelete(), gistbufferinginserttuples(), gistbuild(), gistcheckpage(), gistdeletepage(), gistformdownlink(), gistinserttuples(), gistMemorizeAllDownlinks(), gistplacetopage(), gistRelocateBuildBuffersOnSplit(), gistScanPage(), hash_xlog_add_ovfl_page(), heap_delete(), heap_fetch_next_buffer(), heap_hot_search_buffer(), heap_insert(), heap_multi_insert(), heap_page_is_all_visible(), heap_page_prune_and_freeze(), heap_prepare_pagescan(), heap_update(), heap_xlog_confirm(), heap_xlog_lock(), heapam_scan_analyze_next_block(), heapgettup(), heapgettup_pagemode(), index_compute_xid_horizon_for_tuples(), lazy_scan_noprune(), lazy_scan_prune(), makeSublist(), moveLeafs(), moveRightIfItNeeded(), pgstathashindex(), ReadBufferBI(), RelationAddBlocks(), RelationGetBufferForTuple(), RelationPutHeapTuple(), revmap_get_buffer(), revmap_physical_extend(), ScanSourceDatabasePgClassPage(), spgAddNodeAction(), spgbuild(), spgdoinsert(), SpGistSetLastUsedPage(), spgSplitNodeAction(), spgWalk(), startScanEntry(), terminate_brin_buildstate(), vacuumLeafPage(), visibilitymap_clear(), visibilitymap_get_status(), visibilitymap_pin(), visibilitymap_pin_ok(), visibilitymap_set(), and WaitReadBuffers().

◆ BufferGetLSNAtomic()

XLogRecPtr BufferGetLSNAtomic ( Buffer  buffer)

Definition at line 3928 of file bufmgr.c.

3929 {
3930  BufferDesc *bufHdr = GetBufferDescriptor(buffer - 1);
3931  char *page = BufferGetPage(buffer);
3932  XLogRecPtr lsn;
3933  uint32 buf_state;
3934 
3935  /*
3936  * If we don't need locking for correctness, fastpath out.
3937  */
3938  if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
3939  return PageGetLSN(page);
3940 
3941  /* Make sure we've got a real buffer, and that we hold a pin on it. */
3942  Assert(BufferIsValid(buffer));
3943  Assert(BufferIsPinned(buffer));
3944 
3945  buf_state = LockBufHdr(bufHdr);
3946  lsn = PageGetLSN(page);
3947  UnlockBufHdr(bufHdr, buf_state);
3948 
3949  return lsn;
3950 }
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:5688
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:408
static XLogRecPtr PageGetLSN(Page page)
Definition: bufpage.h:383
#define XLogHintBitIsNeeded()
Definition: xlog.h:118
uint64 XLogRecPtr
Definition: xlogdefs.h:21

References Assert, PrivateRefCountEntry::buffer, BufferGetPage(), BufferIsLocal, BufferIsPinned, BufferIsValid(), GetBufferDescriptor(), LockBufHdr(), PageGetLSN(), UnlockBufHdr(), and XLogHintBitIsNeeded.

Referenced by _bt_killitems(), _bt_readpage(), gistdoinsert(), gistFindPath(), gistkillitems(), gistScanPage(), SetHintBits(), and XLogSaveBufferForHint().

◆ BufferGetPage()

static Page BufferGetPage ( Buffer  buffer)
inlinestatic

Definition at line 408 of file bufmgr.h.

409 {
410  return (Page) BufferGetBlock(buffer);
411 }
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:375
Pointer Page
Definition: bufpage.h:78

References BufferGetBlock().

Referenced by _bt_allocbuf(), _bt_binsrch(), _bt_binsrch_insert(), _bt_bottomupdel_pass(), _bt_check_unique(), _bt_checkpage(), _bt_clear_incomplete_split(), _bt_conditionallockbuf(), _bt_dedup_pass(), _bt_delete_or_dedup_one_page(), _bt_delitems_delete(), _bt_delitems_delete_check(), _bt_delitems_vacuum(), _bt_endpoint(), _bt_findinsertloc(), _bt_finish_split(), _bt_get_endpoint(), _bt_getmeta(), _bt_getroot(), _bt_getstackbuf(), _bt_gettrueroot(), _bt_insert_parent(), _bt_insertonpg(), _bt_killitems(), _bt_leftsib_splitflag(), _bt_lock_subtree_parent(), _bt_lockbuf(), _bt_mark_page_halfdead(), _bt_moveright(), _bt_newlevel(), _bt_pagedel(), _bt_readnextpage(), _bt_readpage(), _bt_restore_meta(), _bt_rightsib_halfdeadflag(), _bt_search(), _bt_search_insert(), _bt_set_cleanup_info(), _bt_simpledel_pass(), _bt_split(), _bt_stepright(), _bt_unlink_halfdead_page(), _bt_unlockbuf(), _bt_upgradelockbufcleanup(), _bt_vacuum_needs_cleanup(), _bt_walk_left(), _hash_addovflpage(), _hash_checkpage(), _hash_doinsert(), _hash_expandtable(), _hash_finish_split(), _hash_first(), _hash_freeovflpage(), _hash_get_newblock_from_oldbucket(), _hash_get_oldblock_from_newbucket(), _hash_getbucketbuf_from_hashkey(), _hash_getcachedmetap(), _hash_getinitbuf(), _hash_getnewbuf(), _hash_init(), _hash_init_metabuffer(), _hash_initbitmapbuffer(), _hash_initbuf(), _hash_kill_items(), _hash_pgaddmultitup(), _hash_pgaddtup(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), allocNewBuffer(), blgetbitmap(), blinsert(), BloomNewBuffer(), blvacuumcleanup(), brin_can_do_samepage_update(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_initialize_empty_new_buffer(), brin_page_cleanup(), brin_start_evacuating_page(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinGetStats(), brinGetTupleForHeapBlock(), brininsert(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), brinSetHeapBlockItemptr(), bt_metap(), bt_page_items_internal(), bt_recheck_sibling_links(), bt_rootdescend(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), btvacuumpage(), BufferGetLSNAtomic(), collect_corrupt_items(), collect_visibility_data(), collectMatchBitmap(), collectMatchesForHeapRow(), count_nondeletable_pages(), createPostingTree(), dataBeginPlaceToPage(), dataBeginPlaceToPageInternal(), dataBeginPlaceToPageLeaf(), dataExecPlaceToPage(), dataExecPlaceToPageInternal(), dataLocateItem(), dataPlaceToPageLeafRecompress(), dataPrepareDownlink(), dataSplitPageInternal(), do_setval(), doPickSplit(), entryExecPlaceToPage(), entryIsEnoughSpace(), entryLoadMoreItems(), entryLocateEntry(), entryLocateLeafEntry(), entryPrepareDownlink(), entrySplitPage(), fill_seq_fork_with_data(), FreeSpaceMapPrepareTruncateRel(), fsm_readbuf(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), generic_redo(), GenericXLogFinish(), GenericXLogRegisterBuffer(), get_raw_page_internal(), GetBTPageStatistics(), GetRecordedFreeSpace(), GetVisibilityMapPins(), ginbulkdelete(), ginDeletePage(), ginEntryInsert(), ginFindLeafPage(), ginFindParents(), ginFinishOldSplit(), ginFinishSplit(), ginGetStats(), ginHeapTupleFastInsert(), GinInitBuffer(), GinInitMetabuffer(), ginInsertCleanup(), ginInsertValue(), GinNewBuffer(), ginPlaceToPage(), ginRedoClearIncompleteSplit(), ginRedoCreatePTree(), ginRedoDeleteListPages(), ginRedoDeletePage(), ginRedoInsert(), ginRedoInsertData(), ginRedoInsertEntry(), ginRedoInsertListPage(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginScanToDelete(), ginStepRight(), ginTraverseLock(), ginUpdateStats(), ginvacuumcleanup(), ginVacuumEntryPage(), ginVacuumPostingTreeLeaf(), ginVacuumPostingTreeLeaves(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistbuild(), gistcheckpage(), gistdeletepage(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistfixsplit(), gistformdownlink(), gistGetMaxLevel(), GISTInitBuffer(), gistkillitems(), gistMemorizeAllDownlinks(), gistNewBuffer(), gistplacetopage(), gistProcessItup(), gistRedoClearFollowRight(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), gistScanPage(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hash_bitmap_info(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_force_common(), heap_freeze_prepared_tuples(), heap_get_latest_tid(), heap_hot_search_buffer(), heap_index_delete_tuples(), heap_inplace_update(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_is_all_visible(), heap_page_prune_and_freeze(), heap_page_prune_execute(), heap_page_prune_opt(), heap_pre_freeze_checks(), heap_prepare_pagescan(), heap_update(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), heap_xlog_update(), heap_xlog_visible(), heapam_index_build_range_scan(), heapam_index_validate_scan(), heapam_scan_analyze_next_tuple(), heapam_scan_bitmap_next_block(), heapam_scan_bitmap_next_tuple(), heapam_scan_sample_next_tuple(), heapgettup_continue_page(), heapgettup_pagemode(), heapgettup_start_page(), index_compute_xid_horizon_for_tuples(), initBloomState(), lazy_scan_heap(), lazy_vacuum_heap_page(), lazy_vacuum_heap_rel(), log_heap_prune_and_freeze(), log_heap_update(), log_newpage_buffer(), log_newpage_range(), log_split_page(), MarkBufferDirtyHint(), moveLeafs(), moveRightIfItNeeded(), nextval_internal(), palloc_btree_page(), pg_visibility(), pgstat_btree_page(), pgstat_gist_page(), pgstat_hash_page(), pgstat_heap(), pgstatginindex_internal(), pgstathashindex(), pgstatindex_impl(), read_seq_tuple(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), RelationPutHeapTuple(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), scanPostingTree(), ScanSourceDatabasePgClass(), seq_redo(), shiftList(), spgAddNodeAction(), spgbuild(), spgdoinsert(), spgGetCache(), SpGistGetBuffer(), SpGistInitBuffer(), SpGistNewBuffer(), SpGistSetLastUsedPage(), SpGistUpdateMetaPage(), spgprocesspending(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), spgvacuumpage(), spgWalk(), startScanEntry(), statapprox_heap(), terminate_brin_buildstate(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_prepare_truncate(), visibilitymap_set(), vm_readbuf(), writeListPage(), XLogCheckBufferNeedsBackup(), XLogReadBufferExtended(), XLogReadBufferForRedoExtended(), XLogRecordPageWithFreeSpace(), XLogRegisterBuffer(), XLogSaveBufferForHint(), xlogVacuumPage(), and ZeroBuffer().

◆ BufferGetPageSize()

◆ BufferGetTag()

void BufferGetTag ( Buffer  buffer,
RelFileLocator rlocator,
ForkNumber forknum,
BlockNumber blknum 
)

Definition at line 3688 of file bufmgr.c.

3690 {
3691  BufferDesc *bufHdr;
3692 
3693  /* Do the same checks as BufferGetBlockNumber. */
3694  Assert(BufferIsPinned(buffer));
3695 
3696  if (BufferIsLocal(buffer))
3697  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
3698  else
3699  bufHdr = GetBufferDescriptor(buffer - 1);
3700 
3701  /* pinned, so OK to read tag without spinlock */
3702  *rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
3703  *forknum = BufTagGetForkNum(&bufHdr->tag);
3704  *blknum = bufHdr->tag.blockNum;
3705 }
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)

References Assert, buftag::blockNum, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufTagGetForkNum(), BufTagGetRelFileLocator(), GetBufferDescriptor(), GetLocalBufferDescriptor(), and BufferDesc::tag.

Referenced by fsm_search_avail(), ginRedoInsertEntry(), log_newpage_buffer(), ResolveCminCmaxDuringDecoding(), XLogRegisterBuffer(), and XLogSaveBufferForHint().

◆ BufferIsDirty()

bool BufferIsDirty ( Buffer  buffer)

Definition at line 2442 of file bufmgr.c.

2443 {
2444  BufferDesc *bufHdr;
2445 
2446  if (BufferIsLocal(buffer))
2447  {
2448  int bufid = -buffer - 1;
2449 
2450  bufHdr = GetLocalBufferDescriptor(bufid);
2451  }
2452  else
2453  {
2454  bufHdr = GetBufferDescriptor(buffer - 1);
2455  }
2456 
2457  Assert(BufferIsPinned(buffer));
2459  LW_EXCLUSIVE));
2460 
2461  return pg_atomic_read_u32(&bufHdr->state) & BM_DIRTY;
2462 }
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:234
#define BM_DIRTY
Definition: buf_internals.h:61
static LWLock * BufferDescriptorGetContentLock(const BufferDesc *bdesc)
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1939
@ LW_EXCLUSIVE
Definition: lwlock.h:114
pg_atomic_uint32 state

References Assert, BM_DIRTY, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsPinned, GetBufferDescriptor(), GetLocalBufferDescriptor(), LW_EXCLUSIVE, LWLockHeldByMeInMode(), pg_atomic_read_u32(), and BufferDesc::state.

Referenced by XLogRegisterBuffer().

◆ BufferIsExclusiveLocked()

bool BufferIsExclusiveLocked ( Buffer  buffer)

Definition at line 2413 of file bufmgr.c.

2414 {
2415  BufferDesc *bufHdr;
2416 
2417  if (BufferIsLocal(buffer))
2418  {
2419  int bufid = -buffer - 1;
2420 
2421  bufHdr = GetLocalBufferDescriptor(bufid);
2422  }
2423  else
2424  {
2425  bufHdr = GetBufferDescriptor(buffer - 1);
2426  }
2427 
2428  Assert(BufferIsPinned(buffer));
2430  LW_EXCLUSIVE);
2431 }

References Assert, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsPinned, GetBufferDescriptor(), GetLocalBufferDescriptor(), LW_EXCLUSIVE, and LWLockHeldByMeInMode().

Referenced by XLogRegisterBuffer().

◆ BufferIsPermanent()

bool BufferIsPermanent ( Buffer  buffer)

Definition at line 3898 of file bufmgr.c.

3899 {
3900  BufferDesc *bufHdr;
3901 
3902  /* Local buffers are used only for temp relations. */
3903  if (BufferIsLocal(buffer))
3904  return false;
3905 
3906  /* Make sure we've got a real buffer, and that we hold a pin on it. */
3907  Assert(BufferIsValid(buffer));
3908  Assert(BufferIsPinned(buffer));
3909 
3910  /*
3911  * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
3912  * need not bother with the buffer header spinlock. Even if someone else
3913  * changes the buffer header state while we're doing this, the state is
3914  * changed atomically, so we'll read the old value or the new value, but
3915  * not random garbage.
3916  */
3917  bufHdr = GetBufferDescriptor(buffer - 1);
3918  return (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT) != 0;
3919 }
#define BM_PERMANENT
Definition: buf_internals.h:69

References Assert, BM_PERMANENT, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferIsValid(), GetBufferDescriptor(), pg_atomic_read_u32(), and BufferDesc::state.

Referenced by SetHintBits().

◆ BufferIsValid()

static bool BufferIsValid ( Buffer  bufnum)
inlinestatic

Definition at line 359 of file bufmgr.h.

360 {
361  Assert(bufnum <= NBuffers);
362  Assert(bufnum >= -NLocBuffer);
363 
364  return bufnum != InvalidBuffer;
365 }
#define InvalidBuffer
Definition: buf.h:25
PGDLLIMPORT int NBuffers
Definition: globals.c:139
PGDLLIMPORT int NLocBuffer
Definition: localbuf.c:42

References Assert, InvalidBuffer, NBuffers, and NLocBuffer.

Referenced by _bt_clear_incomplete_split(), _bt_endpoint(), _bt_first(), _bt_get_endpoint(), _bt_insertonpg(), _bt_readpage(), _bt_relandgetbuf(), _bt_search(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_dropscanbuf(), _hash_freeovflpage(), _hash_getbucketbuf_from_hashkey(), _hash_getcachedmetap(), _hash_readnext(), _hash_readpage(), _hash_readprev(), autoprewarm_database_main(), brin_doinsert(), brin_doupdate(), brin_getinsertbuffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinGetTupleForHeapBlock(), brininsert(), brinsummarize(), bt_recheck_sibling_links(), bt_rootdescend(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), BufferGetBlock(), BufferGetLSNAtomic(), BufferGetPageSize(), BufferIsPermanent(), ConditionalLockBufferForCleanup(), DebugPrintBufferRefcount(), doPickSplit(), entryGetItem(), entryLoadMoreItems(), ExecStoreBufferHeapTuple(), ExecStorePinnedBufferHeapTuple(), FreeSpaceMapPrepareTruncateRel(), fsm_search(), fsm_vacuum_page(), generic_redo(), GetPrivateRefCount(), GetPrivateRefCountEntry(), GetRecordedFreeSpace(), GetVisibilityMapPins(), ginPlaceToPage(), ginRedoClearIncompleteSplit(), ginRedoDeletePage(), ginRedoInsert(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginScanToDelete(), gistinserttuples(), gistkillitems(), gistplacetopage(), gistRedoClearFollowRight(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageUpdateRecord(), gistXLogSplit(), gistXLogUpdate(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), heap_endscan(), heap_fetch_next_buffer(), heap_index_delete_tuples(), heap_lock_tuple(), heap_rescan(), heap_update(), heap_vac_scan_next_block(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), heap_xlog_update(), heap_xlog_visible(), heapam_index_fetch_reset(), heapam_scan_analyze_next_block(), heapam_scan_sample_next_block(), heapam_tuple_lock(), heapam_tuple_satisfies_snapshot(), heapgettup(), heapgettup_continue_page(), heapgettup_pagemode(), heapgettup_start_page(), IsBufferCleanupOK(), lazy_scan_heap(), lazy_vacuum_heap_rel(), log_heap_visible(), MarkBufferDirty(), MarkBufferDirtyHint(), read_stream_next_buffer(), ReadRecentBuffer(), ReleaseAndReadBuffer(), ReleaseBuffer(), ResOwnerReleaseBufferPin(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), statapprox_heap(), tts_buffer_heap_clear(), tts_buffer_heap_copyslot(), tts_buffer_heap_materialize(), tts_buffer_heap_store_tuple(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_pin(), visibilitymap_pin_ok(), visibilitymap_prepare_truncate(), visibilitymap_set(), XLogPrefetcherNextBlock(), XLogReadBufferExtended(), and XLogReadBufferForRedoExtended().

◆ BufferShmemSize()

Size BufferShmemSize ( void  )

Definition at line 160 of file buf_init.c.

161 {
162  Size size = 0;
163 
164  /* size of buffer descriptors */
166  /* to allow aligning buffer descriptors */
168 
169  /* size of data pages, plus alignment padding */
171  size = add_size(size, mul_size(NBuffers, BLCKSZ));
172 
173  /* size of stuff controlled by freelist.c */
175 
176  /* size of I/O condition variables */
179  /* to allow aligning the above */
181 
182  /* size of checkpoint sort array in bufmgr.c */
184 
185  return size;
186 }
Size StrategyShmemSize(void)
Definition: freelist.c:453
#define PG_IO_ALIGN_SIZE
#define PG_CACHE_LINE_SIZE
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
static pg_noinline void Size size
Definition: slab.c:607

References add_size(), mul_size(), NBuffers, PG_CACHE_LINE_SIZE, PG_IO_ALIGN_SIZE, size, and StrategyShmemSize().

Referenced by CalculateShmemSize().

◆ CheckBufferIsPinnedOnce()

void CheckBufferIsPinnedOnce ( Buffer  buffer)

Definition at line 5132 of file bufmgr.c.

5133 {
5134  if (BufferIsLocal(buffer))
5135  {
5136  if (LocalRefCount[-buffer - 1] != 1)
5137  elog(ERROR, "incorrect local pin count: %d",
5138  LocalRefCount[-buffer - 1]);
5139  }
5140  else
5141  {
5142  if (GetPrivateRefCount(buffer) != 1)
5143  elog(ERROR, "incorrect local pin count: %d",
5144  GetPrivateRefCount(buffer));
5145  }
5146 }
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:415
#define ERROR
Definition: elog.h:39
int32 * LocalRefCount
Definition: localbuf.c:46

References PrivateRefCountEntry::buffer, BufferIsLocal, elog, ERROR, GetPrivateRefCount(), and LocalRefCount.

Referenced by GetVictimBuffer(), and LockBufferForCleanup().

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)

Definition at line 3653 of file bufmgr.c.

3654 {
3655  BufferSync(flags);
3656 }
static void BufferSync(int flags)
Definition: bufmgr.c:2855

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

Definition at line 5111 of file bufmgr.c.

5112 {
5113  BufferDesc *buf;
5114 
5115  Assert(BufferIsPinned(buffer));
5116  if (BufferIsLocal(buffer))
5117  return true; /* act as though we got it */
5118 
5119  buf = GetBufferDescriptor(buffer - 1);
5120 
5122  LW_EXCLUSIVE);
5123 }
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1341
static char * buf
Definition: pg_test_fsync.c:73

References Assert, buf, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsPinned, GetBufferDescriptor(), LW_EXCLUSIVE, and LWLockConditionalAcquire().

Referenced by _bt_conditionallockbuf(), BloomNewBuffer(), ConditionalLockBufferForCleanup(), GinNewBuffer(), gistNewBuffer(), RelationGetBufferForTuple(), spgdoinsert(), SpGistGetBuffer(), SpGistNewBuffer(), and SpGistUpdateMetaPage().

◆ ConditionalLockBufferForCleanup()

bool ConditionalLockBufferForCleanup ( Buffer  buffer)

Definition at line 5326 of file bufmgr.c.

5327 {
5328  BufferDesc *bufHdr;
5329  uint32 buf_state,
5330  refcount;
5331 
5332  Assert(BufferIsValid(buffer));
5333 
5334  if (BufferIsLocal(buffer))
5335  {
5336  refcount = LocalRefCount[-buffer - 1];
5337  /* There should be exactly one pin */
5338  Assert(refcount > 0);
5339  if (refcount != 1)
5340  return false;
5341  /* Nobody else to wait for */
5342  return true;
5343  }
5344 
5345  /* There should be exactly one local pin */
5346  refcount = GetPrivateRefCount(buffer);
5347  Assert(refcount);
5348  if (refcount != 1)
5349  return false;
5350 
5351  /* Try to acquire lock */
5352  if (!ConditionalLockBuffer(buffer))
5353  return false;
5354 
5355  bufHdr = GetBufferDescriptor(buffer - 1);
5356  buf_state = LockBufHdr(bufHdr);
5357  refcount = BUF_STATE_GET_REFCOUNT(buf_state);
5358 
5359  Assert(refcount > 0);
5360  if (refcount == 1)
5361  {
5362  /* Successfully acquired exclusive lock with pincount 1 */
5363  UnlockBufHdr(bufHdr, buf_state);
5364  return true;
5365  }
5366 
5367  /* Failed, so release the lock */
5368  UnlockBufHdr(bufHdr, buf_state);
5369  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
5370  return false;
5371 }
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:51
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:5111
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5085
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:197

References Assert, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BUFFER_LOCK_UNLOCK, BufferIsLocal, BufferIsValid(), ConditionalLockBuffer(), GetBufferDescriptor(), GetPrivateRefCount(), LocalRefCount, LockBuffer(), LockBufHdr(), PrivateRefCountEntry::refcount, and UnlockBufHdr().

Referenced by _hash_finish_split(), _hash_getbuf_with_condlock_cleanup(), heap_page_prune_opt(), and lazy_scan_heap().

◆ CreateAndCopyRelationData()

void CreateAndCopyRelationData ( RelFileLocator  src_rlocator,
RelFileLocator  dst_rlocator,
bool  permanent 
)

Definition at line 4724 of file bufmgr.c.

4726 {
4727  char relpersistence;
4728  SMgrRelation src_rel;
4729  SMgrRelation dst_rel;
4730 
4731  /* Set the relpersistence. */
4732  relpersistence = permanent ?
4733  RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
4734 
4735  src_rel = smgropen(src_rlocator, INVALID_PROC_NUMBER);
4736  dst_rel = smgropen(dst_rlocator, INVALID_PROC_NUMBER);
4737 
4738  /*
4739  * Create and copy all forks of the relation. During create database we
4740  * have a separate cleanup mechanism which deletes complete database
4741  * directory. Therefore, each individual relation doesn't need to be
4742  * registered for cleanup.
4743  */
4744  RelationCreateStorage(dst_rlocator, relpersistence, false);
4745 
4746  /* copy main fork. */
4747  RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, MAIN_FORKNUM,
4748  permanent);
4749 
4750  /* copy those extra forks that exist */
4751  for (ForkNumber forkNum = MAIN_FORKNUM + 1;
4752  forkNum <= MAX_FORKNUM; forkNum++)
4753  {
4754  if (smgrexists(src_rel, forkNum))
4755  {
4756  smgrcreate(dst_rel, forkNum, false);
4757 
4758  /*
4759  * WAL log creation if the relation is persistent, or this is the
4760  * init fork of an unlogged relation.
4761  */
4762  if (permanent || forkNum == INIT_FORKNUM)
4763  log_smgrcreate(&dst_rlocator, forkNum);
4764 
4765  /* Copy a fork's data, block by block. */
4766  RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, forkNum,
4767  permanent);
4768  }
4769  }
4770 }
static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, RelFileLocator dstlocator, ForkNumber forkNum, bool permanent)
Definition: bufmgr.c:4633
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
ForkNumber
Definition: relpath.h:48
@ MAIN_FORKNUM
Definition: relpath.h:50
@ INIT_FORKNUM
Definition: relpath.h:53
#define MAX_FORKNUM
Definition: relpath.h:62
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
Definition: smgr.c:198
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:411
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:398
SMgrRelation RelationCreateStorage(RelFileLocator rlocator, char relpersistence, bool register_delete)
Definition: storage.c:121
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
Definition: storage.c:186

References INIT_FORKNUM, INVALID_PROC_NUMBER, log_smgrcreate(), MAIN_FORKNUM, MAX_FORKNUM, RelationCopyStorageUsingBuffer(), RelationCreateStorage(), smgrcreate(), smgrexists(), and smgropen().

Referenced by CreateDatabaseUsingWalLog().

◆ DebugPrintBufferRefcount()

char* DebugPrintBufferRefcount ( Buffer  buffer)

Definition at line 3608 of file bufmgr.c.

3609 {
3610  BufferDesc *buf;
3611  int32 loccount;
3612  char *path;
3613  char *result;
3614  ProcNumber backend;
3615  uint32 buf_state;
3616 
3617  Assert(BufferIsValid(buffer));
3618  if (BufferIsLocal(buffer))
3619  {
3620  buf = GetLocalBufferDescriptor(-buffer - 1);
3621  loccount = LocalRefCount[-buffer - 1];
3622  backend = MyProcNumber;
3623  }
3624  else
3625  {
3626  buf = GetBufferDescriptor(buffer - 1);
3627  loccount = GetPrivateRefCount(buffer);
3628  backend = INVALID_PROC_NUMBER;
3629  }
3630 
3631  /* theoretically we should lock the bufhdr here */
3632  path = relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
3633  BufTagGetForkNum(&buf->tag));
3634  buf_state = pg_atomic_read_u32(&buf->state);
3635 
3636  result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
3637  buffer, path,
3638  buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
3639  BUF_STATE_GET_REFCOUNT(buf_state), loccount);
3640  pfree(path);
3641  return result;
3642 }
#define BUF_FLAG_MASK
Definition: buf_internals.h:48
ProcNumber MyProcNumber
Definition: globals.c:87
void pfree(void *pointer)
Definition: mcxt.c:1520
int ProcNumber
Definition: procnumber.h:24
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define relpathbackend(rlocator, backend, forknum)
Definition: relpath.h:85

References Assert, buf, BUF_FLAG_MASK, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsValid(), BufTagGetForkNum(), BufTagGetRelFileLocator(), GetBufferDescriptor(), GetLocalBufferDescriptor(), GetPrivateRefCount(), INVALID_PROC_NUMBER, LocalRefCount, MyProcNumber, pfree(), pg_atomic_read_u32(), psprintf(), and relpathbackend.

Referenced by CheckForBufferLeaks(), CheckForLocalBufferLeaks(), and ResOwnerPrintBufferPin().

◆ DropDatabaseBuffers()

void DropDatabaseBuffers ( Oid  dbid)

Definition at line 4329 of file bufmgr.c.

4330 {
4331  int i;
4332 
4333  /*
4334  * We needn't consider local buffers, since by assumption the target
4335  * database isn't our own.
4336  */
4337 
4338  for (i = 0; i < NBuffers; i++)
4339  {
4340  BufferDesc *bufHdr = GetBufferDescriptor(i);
4341  uint32 buf_state;
4342 
4343  /*
4344  * As in DropRelationBuffers, an unlocked precheck should be safe and
4345  * saves some cycles.
4346  */
4347  if (bufHdr->tag.dbOid != dbid)
4348  continue;
4349 
4350  buf_state = LockBufHdr(bufHdr);
4351  if (bufHdr->tag.dbOid == dbid)
4352  InvalidateBuffer(bufHdr); /* releases spinlock */
4353  else
4354  UnlockBufHdr(bufHdr, buf_state);
4355  }
4356 }
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1726
int i
Definition: isn.c:73
Oid dbOid
Definition: buf_internals.h:95

References buftag::dbOid, GetBufferDescriptor(), i, InvalidateBuffer(), LockBufHdr(), NBuffers, BufferDesc::tag, and UnlockBufHdr().

Referenced by createdb_failure_callback(), dbase_redo(), dropdb(), and movedb().

◆ DropRelationBuffers()

void DropRelationBuffers ( struct SMgrRelationData smgr_reln,
ForkNumber forkNum,
int  nforks,
BlockNumber firstDelBlock 
)

◆ DropRelationsAllBuffers()

void DropRelationsAllBuffers ( struct SMgrRelationData **  smgr_reln,
int  nlocators 
)

◆ EvictUnpinnedBuffer()

bool EvictUnpinnedBuffer ( Buffer  buf)

Definition at line 6023 of file bufmgr.c.

6024 {
6025  BufferDesc *desc;
6026  uint32 buf_state;
6027  bool result;
6028 
6029  /* Make sure we can pin the buffer. */
6032 
6034  desc = GetBufferDescriptor(buf - 1);
6035 
6036  /* Lock the header and check if it's valid. */
6037  buf_state = LockBufHdr(desc);
6038  if ((buf_state & BM_VALID) == 0)
6039  {
6040  UnlockBufHdr(desc, buf_state);
6041  return false;
6042  }
6043 
6044  /* Check that it's not pinned already. */
6045  if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
6046  {
6047  UnlockBufHdr(desc, buf_state);
6048  return false;
6049  }
6050 
6051  PinBuffer_Locked(desc); /* releases spinlock */
6052 
6053  /* If it was dirty, try to clean it once. */
6054  if (buf_state & BM_DIRTY)
6055  {
6059  }
6060 
6061  /* This will return false if it becomes dirty or someone else pins it. */
6062  result = InvalidateVictimBuffer(desc);
6063 
6064  UnpinBuffer(desc);
6065 
6066  return result;
6067 }
#define BM_VALID
Definition: buf_internals.h:62
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition: bufmgr.c:3727
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:2706
static bool InvalidateVictimBuffer(BufferDesc *buf_hdr)
Definition: bufmgr.c:1824
static void ReservePrivateRefCountEntry(void)
Definition: bufmgr.c:249
static void UnpinBuffer(BufferDesc *buf)
Definition: bufmgr.c:2749
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1170
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1783
@ LW_SHARED
Definition: lwlock.h:115
@ IOOBJECT_RELATION
Definition: pgstat.h:280
@ IOCONTEXT_NORMAL
Definition: pgstat.h:290
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:442

References Assert, BM_DIRTY, BM_VALID, buf, BUF_STATE_GET_REFCOUNT, BufferDescriptorGetContentLock(), BufferIsLocal, CurrentResourceOwner, FlushBuffer(), GetBufferDescriptor(), InvalidateVictimBuffer(), IOCONTEXT_NORMAL, IOOBJECT_RELATION, LockBufHdr(), LW_SHARED, LWLockAcquire(), LWLockRelease(), PinBuffer_Locked(), ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), UnlockBufHdr(), and UnpinBuffer().

Referenced by pg_buffercache_evict().

◆ ExtendBufferedRel()

Buffer ExtendBufferedRel ( BufferManagerRelation  bmr,
ForkNumber  forkNum,
BufferAccessStrategy  strategy,
uint32  flags 
)

Definition at line 845 of file bufmgr.c.

849 {
850  Buffer buf;
851  uint32 extend_by = 1;
852 
853  ExtendBufferedRelBy(bmr, forkNum, strategy, flags, extend_by,
854  &buf, &extend_by);
855 
856  return buf;
857 }
int Buffer
Definition: buf.h:23
BlockNumber ExtendBufferedRelBy(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, Buffer *buffers, uint32 *extended_by)
Definition: bufmgr.c:877

References buf, and ExtendBufferedRelBy().

Referenced by _bt_allocbuf(), _hash_getnewbuf(), BloomNewBuffer(), brinbuild(), brinbuildempty(), fill_seq_fork_with_data(), ginbuildempty(), GinNewBuffer(), gistbuildempty(), gistNewBuffer(), ReadBuffer_common(), revmap_physical_extend(), and SpGistNewBuffer().

◆ ExtendBufferedRelBy()

BlockNumber ExtendBufferedRelBy ( BufferManagerRelation  bmr,
ForkNumber  fork,
BufferAccessStrategy  strategy,
uint32  flags,
uint32  extend_by,
Buffer buffers,
uint32 extended_by 
)

Definition at line 877 of file bufmgr.c.

884 {
885  Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
886  Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
887  Assert(extend_by > 0);
888 
889  if (bmr.smgr == NULL)
890  {
891  bmr.smgr = RelationGetSmgr(bmr.rel);
892  bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
893  }
894 
895  return ExtendBufferedRelCommon(bmr, fork, strategy, flags,
896  extend_by, InvalidBlockNumber,
897  buffers, extended_by);
898 }
#define InvalidBlockNumber
Definition: block.h:33
static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, BlockNumber extend_upto, Buffer *buffers, uint32 *extended_by)
Definition: bufmgr.c:2089
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:567
struct SMgrRelationData * smgr
Definition: bufmgr.h:103
Form_pg_class rd_rel
Definition: rel.h:111

References Assert, ExtendBufferedRelCommon(), InvalidBlockNumber, RelationData::rd_rel, BufferManagerRelation::rel, RelationGetSmgr(), BufferManagerRelation::relpersistence, and BufferManagerRelation::smgr.

Referenced by ExtendBufferedRel(), and RelationAddBlocks().

◆ ExtendBufferedRelTo()

Buffer ExtendBufferedRelTo ( BufferManagerRelation  bmr,
ForkNumber  fork,
BufferAccessStrategy  strategy,
uint32  flags,
BlockNumber  extend_to,
ReadBufferMode  mode 
)

Definition at line 909 of file bufmgr.c.

915 {
917  uint32 extended_by = 0;
918  Buffer buffer = InvalidBuffer;
919  Buffer buffers[64];
920 
921  Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
922  Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
923  Assert(extend_to != InvalidBlockNumber && extend_to > 0);
924 
925  if (bmr.smgr == NULL)
926  {
927  bmr.smgr = RelationGetSmgr(bmr.rel);
928  bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
929  }
930 
931  /*
932  * If desired, create the file if it doesn't exist. If
933  * smgr_cached_nblocks[fork] is positive then it must exist, no need for
934  * an smgrexists call.
935  */
936  if ((flags & EB_CREATE_FORK_IF_NEEDED) &&
937  (bmr.smgr->smgr_cached_nblocks[fork] == 0 ||
939  !smgrexists(bmr.smgr, fork))
940  {
942 
943  /* recheck, fork might have been created concurrently */
944  if (!smgrexists(bmr.smgr, fork))
945  smgrcreate(bmr.smgr, fork, flags & EB_PERFORMING_RECOVERY);
946 
948  }
949 
950  /*
951  * If requested, invalidate size cache, so that smgrnblocks asks the
952  * kernel.
953  */
954  if (flags & EB_CLEAR_SIZE_CACHE)
956 
957  /*
958  * Estimate how many pages we'll need to extend by. This avoids acquiring
959  * unnecessarily many victim buffers.
960  */
961  current_size = smgrnblocks(bmr.smgr, fork);
962 
963  /*
964  * Since no-one else can be looking at the page contents yet, there is no
965  * difference between an exclusive lock and a cleanup-strength lock. Note
966  * that we pass the original mode to ReadBuffer_common() below, when
967  * falling back to reading the buffer to a concurrent relation extension.
968  */
970  flags |= EB_LOCK_TARGET;
971 
972  while (current_size < extend_to)
973  {
974  uint32 num_pages = lengthof(buffers);
975  BlockNumber first_block;
976 
977  if ((uint64) current_size + num_pages > extend_to)
978  num_pages = extend_to - current_size;
979 
980  first_block = ExtendBufferedRelCommon(bmr, fork, strategy, flags,
981  num_pages, extend_to,
982  buffers, &extended_by);
983 
984  current_size = first_block + extended_by;
985  Assert(num_pages != 0 || current_size >= extend_to);
986 
987  for (uint32 i = 0; i < extended_by; i++)
988  {
989  if (first_block + i != extend_to - 1)
990  ReleaseBuffer(buffers[i]);
991  else
992  buffer = buffers[i];
993  }
994  }
995 
996  /*
997  * It's possible that another backend concurrently extended the relation.
998  * In that case read the buffer.
999  *
1000  * XXX: Should we control this via a flag?
1001  */
1002  if (buffer == InvalidBuffer)
1003  {
1004  Assert(extended_by == 0);
1005  buffer = ReadBuffer_common(bmr.rel, bmr.smgr, 0,
1006  fork, extend_to - 1, mode, strategy);
1007  }
1008 
1009  return buffer;
1010 }
uint32 BlockNumber
Definition: block.h:31
static Buffer ReadBuffer_common(Relation rel, SMgrRelation smgr, char smgr_persistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:1152
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4850
#define lengthof(array)
Definition: c.h:788
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:430
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:480
#define ExclusiveLock
Definition: lockdefs.h:42
static PgChecksumMode mode
Definition: pg_checksums.c:56
int64 current_size
Definition: pg_checksums.c:64
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:655
BlockNumber smgr_cached_nblocks[MAX_FORKNUM+1]
Definition: smgr.h:46

References Assert, PrivateRefCountEntry::buffer, current_size, EB_CLEAR_SIZE_CACHE, EB_CREATE_FORK_IF_NEEDED, EB_LOCK_TARGET, EB_PERFORMING_RECOVERY, ExclusiveLock, ExtendBufferedRelCommon(), i, InvalidBlockNumber, InvalidBuffer, lengthof, LockRelationForExtension(), mode, RBM_ZERO_AND_CLEANUP_LOCK, RBM_ZERO_AND_LOCK, RelationData::rd_rel, ReadBuffer_common(), BufferManagerRelation::rel, RelationGetSmgr(), ReleaseBuffer(), BufferManagerRelation::relpersistence, BufferManagerRelation::smgr, SMgrRelationData::smgr_cached_nblocks, smgrcreate(), smgrexists(), smgrnblocks(), and UnlockRelationForExtension().

Referenced by fsm_extend(), vm_extend(), and XLogReadBufferExtended().

◆ FlushDatabaseBuffers()

void FlushDatabaseBuffers ( Oid  dbid)

Definition at line 4788 of file bufmgr.c.

4789 {
4790  int i;
4791  BufferDesc *bufHdr;
4792 
4793  for (i = 0; i < NBuffers; i++)
4794  {
4795  uint32 buf_state;
4796 
4797  bufHdr = GetBufferDescriptor(i);
4798 
4799  /*
4800  * As in DropRelationBuffers, an unlocked precheck should be safe and
4801  * saves some cycles.
4802  */
4803  if (bufHdr->tag.dbOid != dbid)
4804  continue;
4805 
4806  /* Make sure we can handle the pin */
4809 
4810  buf_state = LockBufHdr(bufHdr);
4811  if (bufHdr->tag.dbOid == dbid &&
4812  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4813  {
4814  PinBuffer_Locked(bufHdr);
4818  UnpinBuffer(bufHdr);
4819  }
4820  else
4821  UnlockBufHdr(bufHdr, buf_state);
4822  }
4823 }

References BM_DIRTY, BM_VALID, BufferDescriptorGetContentLock(), CurrentResourceOwner, buftag::dbOid, FlushBuffer(), GetBufferDescriptor(), i, IOCONTEXT_NORMAL, IOOBJECT_RELATION, LockBufHdr(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NBuffers, PinBuffer_Locked(), ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), BufferDesc::tag, UnlockBufHdr(), and UnpinBuffer().

Referenced by dbase_redo().

◆ FlushOneBuffer()

void FlushOneBuffer ( Buffer  buffer)

Definition at line 4830 of file bufmgr.c.

4831 {
4832  BufferDesc *bufHdr;
4833 
4834  /* currently not needed, but no fundamental reason not to support */
4835  Assert(!BufferIsLocal(buffer));
4836 
4837  Assert(BufferIsPinned(buffer));
4838 
4839  bufHdr = GetBufferDescriptor(buffer - 1);
4840 
4842 
4844 }
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1895

References Assert, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsPinned, FlushBuffer(), GetBufferDescriptor(), IOCONTEXT_NORMAL, IOOBJECT_RELATION, and LWLockHeldByMe().

Referenced by hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), and XLogReadBufferForRedoExtended().

◆ FlushRelationBuffers()

void FlushRelationBuffers ( Relation  rel)

Definition at line 4435 of file bufmgr.c.

4436 {
4437  int i;
4438  BufferDesc *bufHdr;
4439  SMgrRelation srel = RelationGetSmgr(rel);
4440 
4441  if (RelationUsesLocalBuffers(rel))
4442  {
4443  for (i = 0; i < NLocBuffer; i++)
4444  {
4445  uint32 buf_state;
4446  instr_time io_start;
4447 
4448  bufHdr = GetLocalBufferDescriptor(i);
4449  if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
4450  ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
4451  (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4452  {
4453  ErrorContextCallback errcallback;
4454  Page localpage;
4455 
4456  localpage = (char *) LocalBufHdrGetBlock(bufHdr);
4457 
4458  /* Setup error traceback support for ereport() */
4460  errcallback.arg = (void *) bufHdr;
4461  errcallback.previous = error_context_stack;
4462  error_context_stack = &errcallback;
4463 
4464  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
4465 
4467 
4468  smgrwrite(srel,
4469  BufTagGetForkNum(&bufHdr->tag),
4470  bufHdr->tag.blockNum,
4471  localpage,
4472  false);
4473 
4476  io_start, 1);
4477 
4478  buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED);
4479  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
4480 
4482 
4483  /* Pop the error context stack */
4484  error_context_stack = errcallback.previous;
4485  }
4486  }
4487 
4488  return;
4489  }
4490 
4491  for (i = 0; i < NBuffers; i++)
4492  {
4493  uint32 buf_state;
4494 
4495  bufHdr = GetBufferDescriptor(i);
4496 
4497  /*
4498  * As in DropRelationBuffers, an unlocked precheck should be safe and
4499  * saves some cycles.
4500  */
4501  if (!BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator))
4502  continue;
4503 
4504  /* Make sure we can handle the pin */
4507 
4508  buf_state = LockBufHdr(bufHdr);
4509  if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
4510  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4511  {
4512  PinBuffer_Locked(bufHdr);
4516  UnpinBuffer(bufHdr);
4517  }
4518  else
4519  UnlockBufHdr(bufHdr, buf_state);
4520  }
4521 }
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:290
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
#define BM_JUST_DIRTIED
Definition: buf_internals.h:66
bool track_io_timing
Definition: bufmgr.c:142
#define LocalBufHdrGetBlock(bufHdr)
Definition: bufmgr.c:71
static void local_buffer_write_error_callback(void *arg)
Definition: bufmgr.c:5641
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1542
ErrorContextCallback * error_context_stack
Definition: elog.c:94
BufferUsage pgBufferUsage
Definition: instrument.c:20
int NLocBuffer
Definition: localbuf.c:42
@ IOOBJECT_TEMP_RELATION
Definition: pgstat.h:281
@ IOOP_WRITE
Definition: pgstat.h:304
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 RelationUsesLocalBuffers(relation)
Definition: rel.h:637
static void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition: smgr.h:121
int64 local_blks_written
Definition: instrument.h:33
struct ErrorContextCallback * previous
Definition: elog.h:295
void(* callback)(void *arg)
Definition: elog.h:296
RelFileLocator rd_locator
Definition: rel.h:57

References ErrorContextCallback::arg, buftag::blockNum, BM_DIRTY, BM_JUST_DIRTIED, BM_VALID, BufferDescriptorGetContentLock(), BufTagGetForkNum(), BufTagMatchesRelFileLocator(), ErrorContextCallback::callback, CurrentResourceOwner, error_context_stack, FlushBuffer(), GetBufferDescriptor(), GetLocalBufferDescriptor(), i, IOCONTEXT_NORMAL, IOOBJECT_RELATION, IOOBJECT_TEMP_RELATION, IOOP_WRITE, BufferUsage::local_blks_written, local_buffer_write_error_callback(), LocalBufHdrGetBlock, LockBufHdr(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NBuffers, NLocBuffer, PageSetChecksumInplace(), pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgBufferUsage, pgstat_count_io_op_time(), pgstat_prepare_io_time(), PinBuffer_Locked(), ErrorContextCallback::previous, RelationData::rd_locator, RelationGetSmgr(), RelationUsesLocalBuffers, ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), smgrwrite(), BufferDesc::state, BufferDesc::tag, track_io_timing, UnlockBufHdr(), and UnpinBuffer().

Referenced by fill_seq_with_data(), heapam_relation_copy_data(), and index_copy_data().

◆ FlushRelationsAllBuffers()

void FlushRelationsAllBuffers ( struct SMgrRelationData **  smgrs,
int  nrels 
)

◆ FreeAccessStrategy()

void FreeAccessStrategy ( BufferAccessStrategy  strategy)

Definition at line 681 of file freelist.c.

682 {
683  /* don't crash if called on a "default" strategy */
684  if (strategy != NULL)
685  pfree(strategy);
686 }

References pfree().

Referenced by blgetbitmap(), FreeBulkInsertState(), heap_endscan(), initscan(), parallel_vacuum_main(), and RelationCopyStorageUsingBuffer().

◆ GetAccessStrategy()

BufferAccessStrategy GetAccessStrategy ( BufferAccessStrategyType  btype)

Definition at line 541 of file freelist.c.

542 {
543  int ring_size_kb;
544 
545  /*
546  * Select ring size to use. See buffer/README for rationales.
547  *
548  * Note: if you change the ring size for BAS_BULKREAD, see also
549  * SYNC_SCAN_REPORT_INTERVAL in access/heap/syncscan.c.
550  */
551  switch (btype)
552  {
553  case BAS_NORMAL:
554  /* if someone asks for NORMAL, just give 'em a "default" object */
555  return NULL;
556 
557  case BAS_BULKREAD:
558  ring_size_kb = 256;
559  break;
560  case BAS_BULKWRITE:
561  ring_size_kb = 16 * 1024;
562  break;
563  case BAS_VACUUM:
564  ring_size_kb = 2048;
565  break;
566 
567  default:
568  elog(ERROR, "unrecognized buffer access strategy: %d",
569  (int) btype);
570  return NULL; /* keep compiler quiet */
571  }
572 
573  return GetAccessStrategyWithSize(btype, ring_size_kb);
574 }
BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype, int ring_size_kb)
Definition: freelist.c:584

References BAS_BULKREAD, BAS_BULKWRITE, BAS_NORMAL, BAS_VACUUM, elog, ERROR, and GetAccessStrategyWithSize().

Referenced by blgetbitmap(), bt_check_every_level(), collect_corrupt_items(), collect_visibility_data(), GetBulkInsertState(), initscan(), pgstat_index(), pgstathashindex(), pgstatindex_impl(), RelationCopyStorageUsingBuffer(), ScanSourceDatabasePgClass(), statapprox_heap(), and verify_heapam().

◆ GetAccessStrategyBufferCount()

int GetAccessStrategyBufferCount ( BufferAccessStrategy  strategy)

Definition at line 624 of file freelist.c.

625 {
626  if (strategy == NULL)
627  return 0;
628 
629  return strategy->nbuffers;
630 }

References BufferAccessStrategyData::nbuffers.

Referenced by parallel_vacuum_init().

◆ GetAccessStrategyPinLimit()

int GetAccessStrategyPinLimit ( BufferAccessStrategy  strategy)

Definition at line 647 of file freelist.c.

648 {
649  if (strategy == NULL)
650  return NBuffers;
651 
652  switch (strategy->btype)
653  {
654  case BAS_BULKREAD:
655 
656  /*
657  * Since BAS_BULKREAD uses StrategyRejectBuffer(), dirty buffers
658  * shouldn't be a problem and the caller is free to pin up to the
659  * entire ring at once.
660  */
661  return strategy->nbuffers;
662 
663  default:
664 
665  /*
666  * Tell caller not to pin more than half the buffers in the ring.
667  * This is a trade-off between look ahead distance and deferring
668  * writeback and associated WAL traffic.
669  */
670  return strategy->nbuffers / 2;
671  }
672 }
BufferAccessStrategyType btype
Definition: freelist.c:75

References BAS_BULKREAD, BufferAccessStrategyData::btype, BufferAccessStrategyData::nbuffers, and NBuffers.

Referenced by read_stream_begin_relation().

◆ GetAccessStrategyWithSize()

BufferAccessStrategy GetAccessStrategyWithSize ( BufferAccessStrategyType  btype,
int  ring_size_kb 
)

Definition at line 584 of file freelist.c.

585 {
586  int ring_buffers;
587  BufferAccessStrategy strategy;
588 
589  Assert(ring_size_kb >= 0);
590 
591  /* Figure out how many buffers ring_size_kb is */
592  ring_buffers = ring_size_kb / (BLCKSZ / 1024);
593 
594  /* 0 means unlimited, so no BufferAccessStrategy required */
595  if (ring_buffers == 0)
596  return NULL;
597 
598  /* Cap to 1/8th of shared_buffers */
599  ring_buffers = Min(NBuffers / 8, ring_buffers);
600 
601  /* NBuffers should never be less than 16, so this shouldn't happen */
602  Assert(ring_buffers > 0);
603 
604  /* Allocate the object and initialize all elements to zeroes */
605  strategy = (BufferAccessStrategy)
606  palloc0(offsetof(BufferAccessStrategyData, buffers) +
607  ring_buffers * sizeof(Buffer));
608 
609  /* Set fields that don't start out zero */
610  strategy->btype = btype;
611  strategy->nbuffers = ring_buffers;
612 
613  return strategy;
614 }
struct BufferAccessStrategyData * BufferAccessStrategy
Definition: buf.h:44
#define Min(x, y)
Definition: c.h:1004
void * palloc0(Size size)
Definition: mcxt.c:1346

References Assert, BufferAccessStrategyData::btype, Min, BufferAccessStrategyData::nbuffers, NBuffers, and palloc0().

Referenced by do_autovacuum(), ExecVacuum(), GetAccessStrategy(), and parallel_vacuum_main().

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )

Definition at line 5300 of file bufmgr.c.

5301 {
5302  int bufid = GetStartupBufferPinWaitBufId();
5303 
5304  /*
5305  * If we get woken slowly then it's possible that the Startup process was
5306  * already woken by other backends before we got here. Also possible that
5307  * we get here by multiple interrupts or interrupts at inappropriate
5308  * times, so make sure we do nothing if the bufid is not set.
5309  */
5310  if (bufid < 0)
5311  return false;
5312 
5313  if (GetPrivateRefCount(bufid + 1) > 0)
5314  return true;
5315 
5316  return false;
5317 }
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:671

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and ProcessRecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

Definition at line 4882 of file bufmgr.c.

4883 {
4884  Assert(BufferIsPinned(buffer));
4886  if (BufferIsLocal(buffer))
4887  LocalRefCount[-buffer - 1]++;
4888  else
4889  {
4890  PrivateRefCountEntry *ref;
4891 
4892  ref = GetPrivateRefCountEntry(buffer, true);
4893  Assert(ref != NULL);
4894  ref->refcount++;
4895  }
4897 }
static void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition: bufmgr.c:341

References Assert, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, CurrentResourceOwner, GetPrivateRefCountEntry(), LocalRefCount, PrivateRefCountEntry::refcount, ResourceOwnerEnlarge(), and ResourceOwnerRememberBuffer().

Referenced by _bt_steppage(), btrestrpos(), entryLoadMoreItems(), ReadBufferBI(), RelationAddBlocks(), scanPostingTree(), startScanEntry(), and tts_buffer_heap_store_tuple().

◆ InitBufferPool()

void InitBufferPool ( void  )

Definition at line 68 of file buf_init.c.

69 {
70  bool foundBufs,
71  foundDescs,
72  foundIOCV,
73  foundBufCkpt;
74 
75  /* Align descriptors to a cacheline boundary. */
77  ShmemInitStruct("Buffer Descriptors",
78  NBuffers * sizeof(BufferDescPadded),
79  &foundDescs);
80 
81  /* Align buffer pool on IO page size boundary. */
82  BufferBlocks = (char *)
84  ShmemInitStruct("Buffer Blocks",
85  NBuffers * (Size) BLCKSZ + PG_IO_ALIGN_SIZE,
86  &foundBufs));
87 
88  /* Align condition variables to cacheline boundary. */
90  ShmemInitStruct("Buffer IO Condition Variables",
92  &foundIOCV);
93 
94  /*
95  * The array used to sort to-be-checkpointed buffer ids is located in
96  * shared memory, to avoid having to allocate significant amounts of
97  * memory at runtime. As that'd be in the middle of a checkpoint, or when
98  * the checkpointer is restarted, memory allocation failures would be
99  * painful.
100  */
102  ShmemInitStruct("Checkpoint BufferIds",
103  NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
104 
105  if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
106  {
107  /* should find all of these, or none of them */
108  Assert(foundDescs && foundBufs && foundIOCV && foundBufCkpt);
109  /* note: this path is only taken in EXEC_BACKEND case */
110  }
111  else
112  {
113  int i;
114 
115  /*
116  * Initialize all the buffer headers.
117  */
118  for (i = 0; i < NBuffers; i++)
119  {
121 
122  ClearBufferTag(&buf->tag);
123 
124  pg_atomic_init_u32(&buf->state, 0);
125  buf->wait_backend_pgprocno = INVALID_PROC_NUMBER;
126 
127  buf->buf_id = i;
128 
129  /*
130  * Initially link all the buffers together as unused. Subsequent
131  * management of this list is done by freelist.c.
132  */
133  buf->freeNext = i + 1;
134 
137 
139  }
140 
141  /* Correct last entry of linked list */
143  }
144 
145  /* Init other shared buffer-management stuff */
146  StrategyInitialize(!foundDescs);
147 
148  /* Initialize per-backend file flush context */
151 }
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:216
CkptSortItem * CkptBufferIds
Definition: buf_init.c:25
char * BufferBlocks
Definition: buf_init.c:22
WritebackContext BackendWritebackContext
Definition: buf_init.c:24
ConditionVariableMinimallyPadded * BufferIOCVArray
Definition: buf_init.c:23
BufferDescPadded * BufferDescriptors
Definition: buf_init.c:21
#define FREENEXT_END_OF_LIST
static void ClearBufferTag(BufferTag *tag)
static ConditionVariable * BufferDescriptorGetIOCV(const BufferDesc *bdesc)
void WritebackContextInit(WritebackContext *context, int *max_pending)
Definition: bufmgr.c:5830
int backend_flush_after
Definition: bufmgr.c:172
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:804
void ConditionVariableInit(ConditionVariable *cv)
void StrategyInitialize(bool init)
Definition: freelist.c:474
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:709
@ LWTRANCHE_BUFFER_CONTENT
Definition: lwlock.h:187
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387

References Assert, backend_flush_after, BackendWritebackContext, buf, BufferBlocks, BufferDescriptorGetContentLock(), BufferDescriptorGetIOCV(), BufferDescriptors, BufferIOCVArray, CkptBufferIds, ClearBufferTag(), ConditionVariableInit(), BufferDesc::freeNext, FREENEXT_END_OF_LIST, GetBufferDescriptor(), i, INVALID_PROC_NUMBER, LWLockInitialize(), LWTRANCHE_BUFFER_CONTENT, NBuffers, pg_atomic_init_u32(), PG_IO_ALIGN_SIZE, ShmemInitStruct(), StrategyInitialize(), TYPEALIGN, and WritebackContextInit().

Referenced by CreateOrAttachShmemStructs().

◆ InitBufferPoolAccess()

void InitBufferPoolAccess ( void  )

Definition at line 3519 of file bufmgr.c.

3520 {
3521  HASHCTL hash_ctl;
3522 
3523  memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
3524 
3525  hash_ctl.keysize = sizeof(int32);
3526  hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
3527 
3528  PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
3529  HASH_ELEM | HASH_BLOBS);
3530 
3531  /*
3532  * AtProcExit_Buffers needs LWLock access, and thereby has to be called at
3533  * the corresponding phase of backend shutdown.
3534  */
3535  Assert(MyProc != NULL);
3537 }
static void AtProcExit_Buffers(int code, Datum arg)
Definition: bufmgr.c:3544
struct PrivateRefCountEntry PrivateRefCountEntry
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition: bufmgr.c:207
static HTAB * PrivateRefCountHash
Definition: bufmgr.c:208
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:365
PGPROC * MyProc
Definition: proc.c:66
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76

References Assert, AtProcExit_Buffers(), HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, HASHCTL::keysize, MyProc, on_shmem_exit(), PrivateRefCountArray, and PrivateRefCountHash.

Referenced by BaseInit().

◆ IsBufferCleanupOK()

bool IsBufferCleanupOK ( Buffer  buffer)

Definition at line 5382 of file bufmgr.c.

5383 {
5384  BufferDesc *bufHdr;
5385  uint32 buf_state;
5386 
5387  Assert(BufferIsValid(buffer));
5388 
5389  if (BufferIsLocal(buffer))
5390  {
5391  /* There should be exactly one pin */
5392  if (LocalRefCount[-buffer - 1] != 1)
5393  return false;
5394  /* Nobody else to wait for */
5395  return true;
5396  }
5397 
5398  /* There should be exactly one local pin */
5399  if (GetPrivateRefCount(buffer) != 1)
5400  return false;
5401 
5402  bufHdr = GetBufferDescriptor(buffer - 1);
5403 
5404  /* caller must hold exclusive lock on buffer */
5406  LW_EXCLUSIVE));
5407 
5408  buf_state = LockBufHdr(bufHdr);
5409 
5410  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5411  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
5412  {
5413  /* pincount is OK. */
5414  UnlockBufHdr(bufHdr, buf_state);
5415  return true;
5416  }
5417 
5418  UnlockBufHdr(bufHdr, buf_state);
5419  return false;
5420 }

References Assert, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsValid(), GetBufferDescriptor(), GetPrivateRefCount(), LocalRefCount, LockBufHdr(), LW_EXCLUSIVE, LWLockHeldByMeInMode(), and UnlockBufHdr().

Referenced by _hash_doinsert(), _hash_expandtable(), _hash_splitbucket(), and hashbucketcleanup().

◆ LimitAdditionalLocalPins()

void LimitAdditionalLocalPins ( uint32 additional_pins)

Definition at line 290 of file localbuf.c.

291 {
292  uint32 max_pins;
293 
294  if (*additional_pins <= 1)
295  return;
296 
297  /*
298  * In contrast to LimitAdditionalPins() other backends don't play a role
299  * here. We can allow up to NLocBuffer pins in total, but it might not be
300  * initialized yet so read num_temp_buffers.
301  */
302  max_pins = (num_temp_buffers - NLocalPinnedBuffers);
303 
304  if (*additional_pins >= max_pins)
305  *additional_pins = max_pins;
306 }
int num_temp_buffers
Definition: guc_tables.c:538
static int NLocalPinnedBuffers
Definition: localbuf.c:53

References NLocalPinnedBuffers, and num_temp_buffers.

Referenced by ExtendBufferedRelLocal(), and read_stream_begin_relation().

◆ LimitAdditionalPins()

void LimitAdditionalPins ( uint32 additional_pins)

Definition at line 2058 of file bufmgr.c.

2059 {
2060  uint32 max_backends;
2061  int max_proportional_pins;
2062 
2063  if (*additional_pins <= 1)
2064  return;
2065 
2066  max_backends = MaxBackends + NUM_AUXILIARY_PROCS;
2067  max_proportional_pins = NBuffers / max_backends;
2068 
2069  /*
2070  * Subtract the approximate number of buffers already pinned by this
2071  * backend. We get the number of "overflowed" pins for free, but don't
2072  * know the number of pins in PrivateRefCountArray. The cost of
2073  * calculating that exactly doesn't seem worth it, so just assume the max.
2074  */
2075  max_proportional_pins -= PrivateRefCountOverflowed + REFCOUNT_ARRAY_ENTRIES;
2076 
2077  if (max_proportional_pins <= 0)
2078  max_proportional_pins = 1;
2079 
2080  if (*additional_pins > max_proportional_pins)
2081  *additional_pins = max_proportional_pins;
2082 }
#define REFCOUNT_ARRAY_ENTRIES
Definition: bufmgr.c:95
int MaxBackends
Definition: globals.c:143
#define NUM_AUXILIARY_PROCS
Definition: proc.h:440

References MaxBackends, NBuffers, NUM_AUXILIARY_PROCS, PrivateRefCountOverflowed, and REFCOUNT_ARRAY_ENTRIES.

Referenced by ExtendBufferedRelShared(), and read_stream_begin_relation().

◆ LockBuffer()

void LockBuffer ( Buffer  buffer,
int  mode 
)

Definition at line 5085 of file bufmgr.c.

5086 {
5087  BufferDesc *buf;
5088 
5089  Assert(BufferIsPinned(buffer));
5090  if (BufferIsLocal(buffer))
5091  return; /* local buffers need no lock */
5092 
5093  buf = GetBufferDescriptor(buffer - 1);
5094 
5095  if (mode == BUFFER_LOCK_UNLOCK)
5097  else if (mode == BUFFER_LOCK_SHARE)
5099  else if (mode == BUFFER_LOCK_EXCLUSIVE)
5101  else
5102  elog(ERROR, "unrecognized buffer lock mode: %d", mode);
5103 }
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:198
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:199

References Assert, buf, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsPinned, elog, ERROR, GetBufferDescriptor(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), and mode.

Referenced by _bt_lockbuf(), _bt_unlockbuf(), _bt_upgradelockbufcleanup(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_finish_split(), _hash_first(), _hash_freeovflpage(), _hash_getbuf(), _hash_getbuf_with_strategy(), _hash_getcachedmetap(), _hash_init(), _hash_kill_items(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), blbulkdelete(), blgetbitmap(), blinsert(), BloomInitMetapage(), BloomNewBuffer(), blvacuumcleanup(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_page_cleanup(), bringetbitmap(), brinGetStats(), brinGetTupleForHeapBlock(), brininsert(), brinLockRevmapPageForUpdate(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), brinsummarize(), bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), bt_recheck_sibling_links(), collect_corrupt_items(), collect_visibility_data(), collectMatchBitmap(), ConditionalLockBufferForCleanup(), count_nondeletable_pages(), entryLoadMoreItems(), FreeSpaceMapPrepareTruncateRel(), fsm_readbuf(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), get_raw_page_internal(), GetVisibilityMapPins(), ginbulkdelete(), ginEntryInsert(), ginFindLeafPage(), ginFindParents(), ginFinishOldSplit(), ginFinishSplit(), ginGetStats(), ginHeapTupleFastInsert(), ginInsertCleanup(), ginInsertValue(), GinNewBuffer(), ginScanToDelete(), ginStepRight(), ginTraverseLock(), ginUpdateStats(), ginvacuumcleanup(), ginVacuumPostingTreeLeaves(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistfinishsplit(), gistfixsplit(), gistformdownlink(), gistGetMaxLevel(), gistinserttuples(), gistkillitems(), gistNewBuffer(), gistProcessItup(), gistScanPage(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_get_latest_tid(), heap_index_delete_tuples(), heap_inplace_update(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_page_prune_opt(), heap_prepare_pagescan(), heap_update(), heap_xlog_visible(), heapam_index_build_range_scan(), heapam_index_fetch_tuple(), heapam_index_validate_scan(), heapam_relation_copy_for_cluster(), heapam_scan_analyze_next_block(), heapam_scan_bitmap_next_block(), heapam_scan_sample_next_tuple(), heapam_tuple_satisfies_snapshot(), heapgettup(), initBloomState(), lazy_scan_heap(), lazy_scan_new_or_empty(), lazy_vacuum_heap_rel(), LockBufferForCleanup(), log_newpage_range(), palloc_btree_page(), pg_visibility(), pgrowlocks(), pgstat_btree_page(), pgstat_gist_page(), pgstat_heap(), pgstatginindex_internal(), pgstathashindex(), pgstatindex_impl(), read_seq_tuple(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), ScanSourceDatabasePgClass(), shiftList(), spgdoinsert(), spgGetCache(), SpGistNewBuffer(), spgprocesspending(), spgvacuumpage(), spgWalk(), startScanEntry(), statapprox_heap(), summarize_range(), UnlockReleaseBuffer(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_prepare_truncate(), visibilitymap_set(), vm_readbuf(), XLogReadBufferForRedoExtended(), XLogRecordPageWithFreeSpace(), and ZeroBuffer().

◆ LockBufferForCleanup()

void LockBufferForCleanup ( Buffer  buffer)

Definition at line 5165 of file bufmgr.c.

5166 {
5167  BufferDesc *bufHdr;
5168  TimestampTz waitStart = 0;
5169  bool waiting = false;
5170  bool logged_recovery_conflict = false;
5171 
5172  Assert(BufferIsPinned(buffer));
5173  Assert(PinCountWaitBuf == NULL);
5174 
5175  CheckBufferIsPinnedOnce(buffer);
5176 
5177  /* Nobody else to wait for */
5178  if (BufferIsLocal(buffer))
5179  return;
5180 
5181  bufHdr = GetBufferDescriptor(buffer - 1);
5182 
5183  for (;;)
5184  {
5185  uint32 buf_state;
5186 
5187  /* Try to acquire lock */
5189  buf_state = LockBufHdr(bufHdr);
5190 
5191  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5192  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
5193  {
5194  /* Successfully acquired exclusive lock with pincount 1 */
5195  UnlockBufHdr(bufHdr, buf_state);
5196 
5197  /*
5198  * Emit the log message if recovery conflict on buffer pin was
5199  * resolved but the startup process waited longer than
5200  * deadlock_timeout for it.
5201  */
5202  if (logged_recovery_conflict)
5204  waitStart, GetCurrentTimestamp(),
5205  NULL, false);
5206 
5207  if (waiting)
5208  {
5209  /* reset ps display to remove the suffix if we added one */
5211  waiting = false;
5212  }
5213  return;
5214  }
5215  /* Failed, so mark myself as waiting for pincount 1 */
5216  if (buf_state & BM_PIN_COUNT_WAITER)
5217  {
5218  UnlockBufHdr(bufHdr, buf_state);
5219  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
5220  elog(ERROR, "multiple backends attempting to wait for pincount 1");
5221  }
5223  PinCountWaitBuf = bufHdr;
5224  buf_state |= BM_PIN_COUNT_WAITER;
5225  UnlockBufHdr(bufHdr, buf_state);
5226  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
5227 
5228  /* Wait to be signaled by UnpinBuffer() */
5229  if (InHotStandby)
5230  {
5231  if (!waiting)
5232  {
5233  /* adjust the process title to indicate that it's waiting */
5234  set_ps_display_suffix("waiting");
5235  waiting = true;
5236  }
5237 
5238  /*
5239  * Emit the log message if the startup process is waiting longer
5240  * than deadlock_timeout for recovery conflict on buffer pin.
5241  *
5242  * Skip this if first time through because the startup process has
5243  * not started waiting yet in this case. So, the wait start
5244  * timestamp is set after this logic.
5245  */
5246  if (waitStart != 0 && !logged_recovery_conflict)
5247  {
5249 
5250  if (TimestampDifferenceExceeds(waitStart, now,
5251  DeadlockTimeout))
5252  {
5254  waitStart, now, NULL, true);
5255  logged_recovery_conflict = true;
5256  }
5257  }
5258 
5259  /*
5260  * Set the wait start timestamp if logging is enabled and first
5261  * time through.
5262  */
5263  if (log_recovery_conflict_waits && waitStart == 0)
5264  waitStart = GetCurrentTimestamp();
5265 
5266  /* Publish the bufid that Startup process waits on */
5267  SetStartupBufferPinWaitBufId(buffer - 1);
5268  /* Set alarm and then wait to be signaled by UnpinBuffer() */
5270  /* Reset the published bufid */
5272  }
5273  else
5274  ProcWaitForSignal(WAIT_EVENT_BUFFER_PIN);
5275 
5276  /*
5277  * Remove flag marking us as waiter. Normally this will not be set
5278  * anymore, but ProcWaitForSignal() can return for other signals as
5279  * well. We take care to only reset the flag if we're the waiter, as
5280  * theoretically another backend could have started waiting. That's
5281  * impossible with the current usages due to table level locking, but
5282  * better be safe.
5283  */
5284  buf_state = LockBufHdr(bufHdr);
5285  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5287  buf_state &= ~BM_PIN_COUNT_WAITER;
5288  UnlockBufHdr(bufHdr, buf_state);
5289 
5290  PinCountWaitBuf = NULL;
5291  /* Loop back and try again */
5292  }
5293 }
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1790
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1654
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1618
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:67
void CheckBufferIsPinnedOnce(Buffer buffer)
Definition: bufmgr.c:5132
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:175
int64 TimestampTz
Definition: timestamp.h:39
static volatile sig_atomic_t waiting
Definition: latch.c:162
@ PROCSIG_RECOVERY_CONFLICT_BUFFERPIN
Definition: procsignal.h:47
void set_ps_display_remove_suffix(void)
Definition: ps_status.c:421
void set_ps_display_suffix(const char *suffix)
Definition: ps_status.c:369
int DeadlockTimeout
Definition: proc.c:57
void SetStartupBufferPinWaitBufId(int bufid)
Definition: proc.c:659
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1866
void ResolveRecoveryConflictWithBufferPin(void)
Definition: standby.c:792
bool log_recovery_conflict_waits
Definition: standby.c:41
void LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start, TimestampTz now, VirtualTransactionId *wait_list, bool still_waiting)
Definition: standby.c:273
int wait_backend_pgprocno
#define InHotStandby
Definition: xlogutils.h:57

References Assert, BM_PIN_COUNT_WAITER, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferIsLocal, BufferIsPinned, CheckBufferIsPinnedOnce(), DeadlockTimeout, elog, ERROR, GetBufferDescriptor(), GetCurrentTimestamp(), InHotStandby, LockBuffer(), LockBufHdr(), log_recovery_conflict_waits, LogRecoveryConflict(), MyProcNumber, now(), PinCountWaitBuf, PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, ProcWaitForSignal(), ResolveRecoveryConflictWithBufferPin(), set_ps_display_remove_suffix(), set_ps_display_suffix(), SetStartupBufferPinWaitBufId(), TimestampDifferenceExceeds(), UnlockBufHdr(), BufferDesc::wait_backend_pgprocno, and waiting.

Referenced by _bt_upgradelockbufcleanup(), ginVacuumPostingTree(), hashbulkdelete(), heap_force_common(), lazy_scan_heap(), XLogReadBufferForRedoExtended(), and ZeroBuffer().

◆ MarkBufferDirty()

void MarkBufferDirty ( Buffer  buffer)

Definition at line 2474 of file bufmgr.c.

2475 {
2476  BufferDesc *bufHdr;
2477  uint32 buf_state;
2478  uint32 old_buf_state;
2479 
2480  if (!BufferIsValid(buffer))
2481  elog(ERROR, "bad buffer ID: %d", buffer);
2482 
2483  if (BufferIsLocal(buffer))
2484  {
2485  MarkLocalBufferDirty(buffer);
2486  return;
2487  }
2488 
2489  bufHdr = GetBufferDescriptor(buffer - 1);
2490 
2491  Assert(BufferIsPinned(buffer));
2493  LW_EXCLUSIVE));
2494 
2495  old_buf_state = pg_atomic_read_u32(&bufHdr->state);
2496  for (;;)
2497  {
2498  if (old_buf_state & BM_LOCKED)
2499  old_buf_state = WaitBufHdrUnlocked(bufHdr);
2500 
2501  buf_state = old_buf_state;
2502 
2503  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
2504  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
2505 
2506  if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
2507  buf_state))
2508  break;
2509  }
2510 
2511  /*
2512  * If the buffer was not dirty already, do vacuum accounting.
2513  */
2514  if (!(old_buf_state & BM_DIRTY))
2515  {
2516  VacuumPageDirty++;
2518  if (VacuumCostActive)
2520  }
2521 }
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:344
#define BM_LOCKED
Definition: buf_internals.h:60
static uint32 WaitBufHdrUnlocked(BufferDesc *buf)
Definition: bufmgr.c:5718
bool VacuumCostActive
Definition: globals.c:159
int64 VacuumPageDirty
Definition: globals.c:156
int VacuumCostBalance
Definition: globals.c:158
int VacuumCostPageDirty
Definition: globals.c:150
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:449
int64 shared_blks_dirtied
Definition: instrument.h:28

References Assert, BM_DIRTY, BM_JUST_DIRTIED, BM_LOCKED, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsPinned, BufferIsValid(), elog, ERROR, GetBufferDescriptor(), LW_EXCLUSIVE, LWLockHeldByMeInMode(), MarkLocalBufferDirty(), pg_atomic_compare_exchange_u32(), pg_atomic_read_u32(), pgBufferUsage, BufferUsage::shared_blks_dirtied, BufferDesc::state, VacuumCostActive, VacuumCostBalance, VacuumCostPageDirty, VacuumPageDirty, and WaitBufHdrUnlocked().

Referenced by _bt_clear_incomplete_split(), _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_newlevel(), _bt_restore_meta(), _bt_set_cleanup_info(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_freeovflpage(), _hash_init(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), addLeafTuple(), brin_doinsert(), brin_doupdate(), brin_initialize_empty_new_buffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinRevmapDesummarizeRange(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), createPostingTree(), dataExecPlaceToPageInternal(), dataExecPlaceToPageLeaf(), do_setval(), doPickSplit(), entryExecPlaceToPage(), fill_seq_fork_with_data(), FreeSpaceMapPrepareTruncateRel(), generic_redo(), GenericXLogFinish(), ginbuild(), ginbuildempty(), ginbulkdelete(), ginDeletePage(), ginHeapTupleFastInsert(), ginPlaceToPage(), ginRedoClearIncompleteSplit(), ginRedoCreatePTree(), ginRedoDeleteListPages(), ginRedoDeletePage(), ginRedoInsert(), ginRedoInsertListPage(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginUpdateStats(), ginVacuumPostingTreeLeaf(), gistbuild(), gistbuildempty(), gistdeletepage(), gistplacetopage(), gistprunepage(), gistRedoClearFollowRight(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), gistvacuumpage(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_finish_speculative(), heap_force_common(), heap_inplace_update(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_prune_and_freeze(), heap_update(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), heap_xlog_update(), heap_xlog_visible(), lazy_scan_new_or_empty(), lazy_scan_prune(), lazy_vacuum_heap_page(), log_newpage_range(), moveLeafs(), nextval_internal(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), revmap_physical_extend(), saveNodeLink(), seq_redo(), shiftList(), spgAddNodeAction(), spgbuild(), SpGistUpdateMetaPage(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), visibilitymap_clear(), visibilitymap_prepare_truncate(), visibilitymap_set(), writeListPage(), and XLogReadBufferForRedoExtended().

◆ MarkBufferDirtyHint()

void MarkBufferDirtyHint ( Buffer  buffer,
bool  buffer_std 
)

Definition at line 4914 of file bufmgr.c.

4915 {
4916  BufferDesc *bufHdr;
4917  Page page = BufferGetPage(buffer);
4918 
4919  if (!BufferIsValid(buffer))
4920  elog(ERROR, "bad buffer ID: %d", buffer);
4921 
4922  if (BufferIsLocal(buffer))
4923  {
4924  MarkLocalBufferDirty(buffer);
4925  return;
4926  }
4927 
4928  bufHdr = GetBufferDescriptor(buffer - 1);
4929 
4930  Assert(GetPrivateRefCount(buffer) > 0);
4931  /* here, either share or exclusive lock is OK */
4933 
4934  /*
4935  * This routine might get called many times on the same page, if we are
4936  * making the first scan after commit of an xact that added/deleted many
4937  * tuples. So, be as quick as we can if the buffer is already dirty. We
4938  * do this by not acquiring spinlock if it looks like the status bits are
4939  * already set. Since we make this test unlocked, there's a chance we
4940  * might fail to notice that the flags have just been cleared, and failed
4941  * to reset them, due to memory-ordering issues. But since this function
4942  * is only intended to be used in cases where failing to write out the
4943  * data would be harmless anyway, it doesn't really matter.
4944  */
4945  if ((pg_atomic_read_u32(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
4947  {
4949  bool dirtied = false;
4950  bool delayChkptFlags = false;
4951  uint32 buf_state;
4952 
4953  /*
4954  * If we need to protect hint bit updates from torn writes, WAL-log a
4955  * full page image of the page. This full page image is only necessary
4956  * if the hint bit update is the first change to the page since the
4957  * last checkpoint.
4958  *
4959  * We don't check full_page_writes here because that logic is included
4960  * when we call XLogInsert() since the value changes dynamically.
4961  */
4962  if (XLogHintBitIsNeeded() &&
4963  (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT))
4964  {
4965  /*
4966  * If we must not write WAL, due to a relfilelocator-specific
4967  * condition or being in recovery, don't dirty the page. We can
4968  * set the hint, just not dirty the page as a result so the hint
4969  * is lost when we evict the page or shutdown.
4970  *
4971  * See src/backend/storage/page/README for longer discussion.
4972  */
4973  if (RecoveryInProgress() ||
4975  return;
4976 
4977  /*
4978  * If the block is already dirty because we either made a change
4979  * or set a hint already, then we don't need to write a full page
4980  * image. Note that aggressive cleaning of blocks dirtied by hint
4981  * bit setting would increase the call rate. Bulk setting of hint
4982  * bits would reduce the call rate...
4983  *
4984  * We must issue the WAL record before we mark the buffer dirty.
4985  * Otherwise we might write the page before we write the WAL. That
4986  * causes a race condition, since a checkpoint might occur between
4987  * writing the WAL record and marking the buffer dirty. We solve
4988  * that with a kluge, but one that is already in use during
4989  * transaction commit to prevent race conditions. Basically, we
4990  * simply prevent the checkpoint WAL record from being written
4991  * until we have marked the buffer dirty. We don't start the
4992  * checkpoint flush until we have marked dirty, so our checkpoint
4993  * must flush the change to disk successfully or the checkpoint
4994  * never gets written, so crash recovery will fix.
4995  *
4996  * It's possible we may enter here without an xid, so it is
4997  * essential that CreateCheckPoint waits for virtual transactions
4998  * rather than full transactionids.
4999  */
5002  delayChkptFlags = true;
5003  lsn = XLogSaveBufferForHint(buffer, buffer_std);
5004  }
5005 
5006  buf_state = LockBufHdr(bufHdr);
5007 
5008  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5009 
5010  if (!(buf_state & BM_DIRTY))
5011  {
5012  dirtied = true; /* Means "will be dirtied by this action" */
5013 
5014  /*
5015  * Set the page LSN if we wrote a backup block. We aren't supposed
5016  * to set this when only holding a share lock but as long as we
5017  * serialise it somehow we're OK. We choose to set LSN while
5018  * holding the buffer header lock, which causes any reader of an
5019  * LSN who holds only a share lock to also obtain a buffer header
5020  * lock before using PageGetLSN(), which is enforced in
5021  * BufferGetLSNAtomic().
5022  *
5023  * If checksums are enabled, you might think we should reset the
5024  * checksum here. That will happen when the page is written
5025  * sometime later in this checkpoint cycle.
5026  */
5027  if (!XLogRecPtrIsInvalid(lsn))
5028  PageSetLSN(page, lsn);
5029  }
5030 
5031  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
5032  UnlockBufHdr(bufHdr, buf_state);
5033 
5034  if (delayChkptFlags)
5036 
5037  if (dirtied)
5038  {
5039  VacuumPageDirty++;
5041  if (VacuumCostActive)
5043  }
5044  }
5045 }
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:388
#define DELAY_CHKPT_START
Definition: proc.h:114
bool RelFileLocatorSkippingWAL(RelFileLocator rlocator)
Definition: storage.c:532
int delayChkptFlags
Definition: proc.h:236
bool RecoveryInProgress(void)
Definition: xlog.c:6290
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
Definition: xloginsert.c:1065

References Assert, BM_DIRTY, BM_JUST_DIRTIED, BM_PERMANENT, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferGetPage(), BufferIsLocal, BufferIsValid(), BufTagGetRelFileLocator(), DELAY_CHKPT_START, PGPROC::delayChkptFlags, elog, ERROR, GetBufferDescriptor(), GetPrivateRefCount(), InvalidXLogRecPtr, LockBufHdr(), LWLockHeldByMe(), MarkLocalBufferDirty(), MyProc, PageSetLSN(), pg_atomic_read_u32(), pgBufferUsage, RecoveryInProgress(), RelFileLocatorSkippingWAL(), BufferUsage::shared_blks_dirtied, BufferDesc::state, BufferDesc::tag, UnlockBufHdr(), VacuumCostActive, VacuumCostBalance, VacuumCostPageDirty, VacuumPageDirty, XLogHintBitIsNeeded, XLogRecPtrIsInvalid, and XLogSaveBufferForHint().

Referenced by _bt_check_unique(), _bt_killitems(), _hash_kill_items(), brin_start_evacuating_page(), btvacuumpage(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), gistkillitems(), heap_page_prune_and_freeze(), read_seq_tuple(), SetHintBits(), and XLogRecordPageWithFreeSpace().

◆ PrefetchBuffer()

PrefetchBufferResult PrefetchBuffer ( Relation  reln,
ForkNumber  forkNum,
BlockNumber  blockNum 
)

Definition at line 638 of file bufmgr.c.

639 {
640  Assert(RelationIsValid(reln));
641  Assert(BlockNumberIsValid(blockNum));
642 
643  if (RelationUsesLocalBuffers(reln))
644  {
645  /* see comments in ReadBufferExtended */
646  if (RELATION_IS_OTHER_TEMP(reln))
647  ereport(ERROR,
648  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
649  errmsg("cannot access temporary tables of other sessions")));
650 
651  /* pass it off to localbuf.c */
652  return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
653  }
654  else
655  {
656  /* pass it to the shared buffer version */
657  return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
658  }
659 }
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:548
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ereport(elevel,...)
Definition: elog.h:149
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition: localbuf.c:69
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:658
#define RelationIsValid(relation)
Definition: rel.h:478

References Assert, BlockNumberIsValid(), ereport, errcode(), errmsg(), ERROR, PrefetchLocalBuffer(), PrefetchSharedBuffer(), RELATION_IS_OTHER_TEMP, RelationGetSmgr(), RelationIsValid, and RelationUsesLocalBuffers.

Referenced by BitmapPrefetch(), count_nondeletable_pages(), and pg_prewarm().

◆ PrefetchSharedBuffer()

PrefetchBufferResult PrefetchSharedBuffer ( struct SMgrRelationData smgr_reln,
ForkNumber  forkNum,
BlockNumber  blockNum 
)

◆ ReadBuffer()

Buffer ReadBuffer ( Relation  reln,
BlockNumber  blockNum 
)

Definition at line 745 of file bufmgr.c.

746 {
747  return ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);
748 }
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:792

References MAIN_FORKNUM, RBM_NORMAL, and ReadBufferExtended().

Referenced by _bt_allocbuf(), _bt_getbuf(), _bt_search_insert(), _hash_getbuf(), _hash_getbuf_with_condlock_cleanup(), blbulkdelete(), blinsert(), BloomNewBuffer(), brin_getinsertbuffer(), brinGetStats(), brinGetTupleForHeapBlock(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), ginFindLeafPage(), ginFindParents(), ginGetStats(), ginHeapTupleFastInsert(), ginInsertCleanup(), GinNewBuffer(), ginStepRight(), ginUpdateStats(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistfixsplit(), gistGetMaxLevel(), gistkillitems(), gistNewBuffer(), gistProcessItup(), gistScanPage(), heap_abort_speculative(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_force_common(), heap_get_latest_tid(), heap_index_delete_tuples(), heap_inplace_update(), heap_lock_tuple(), heap_update(), initBloomState(), pg_visibility(), pgstatginindex_internal(), read_seq_tuple(), RelationGetBufferForTuple(), ReleaseAndReadBuffer(), revmap_get_buffer(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), shiftList(), spgdoinsert(), spgGetCache(), SpGistGetBuffer(), SpGistNewBuffer(), SpGistUpdateMetaPage(), and spgWalk().

◆ ReadBufferExtended()

Buffer ReadBufferExtended ( Relation  reln,
ForkNumber  forkNum,
BlockNumber  blockNum,
ReadBufferMode  mode,
BufferAccessStrategy  strategy 
)
inline

Definition at line 792 of file bufmgr.c.

794 {
795  Buffer buf;
796 
797  /*
798  * Reject attempts to read non-local temporary relations; we would be
799  * likely to get wrong data since we have no visibility into the owning
800  * session's local buffers.
801  */
802  if (RELATION_IS_OTHER_TEMP(reln))
803  ereport(ERROR,
804  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
805  errmsg("cannot access temporary tables of other sessions")));
806 
807  /*
808  * Read the buffer, and update pgstat counters to reflect a cache hit or
809  * miss.
810  */
811  buf = ReadBuffer_common(reln, RelationGetSmgr(reln), 0,
812  forkNum, blockNum, mode, strategy);
813 
814  return buf;
815 }

References buf, ereport, errcode(), errmsg(), ERROR, mode, ReadBuffer_common(), RELATION_IS_OTHER_TEMP, and RelationGetSmgr().

Referenced by _hash_getbuf_with_strategy(), _hash_getinitbuf(), _hash_getnewbuf(), autoprewarm_database_main(), blbulkdelete(), blgetbitmap(), BloomInitMetapage(), blvacuumcleanup(), brin_vacuum_scan(), bt_recheck_sibling_links(), btvacuumpage(), collect_corrupt_items(), collect_visibility_data(), count_nondeletable_pages(), fsm_readbuf(), get_raw_page_internal(), ginbulkdelete(), ginDeletePage(), ginScanToDelete(), ginvacuumcleanup(), ginVacuumPostingTree(), ginVacuumPostingTreeLeaves(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hashbulkdelete(), heapam_scan_sample_next_block(), lazy_scan_heap(), lazy_vacuum_heap_rel(), log_newpage_range(), palloc_btree_page(), pgstat_btree_page(), pgstat_gist_page(), pgstat_heap(), pgstathashindex(), pgstatindex_impl(), ReadBuffer(), ReadBufferBI(), spgprocesspending(), spgvacuumpage(), statapprox_heap(), verify_heapam(), and vm_readbuf().

◆ ReadBufferWithoutRelcache()

Buffer ReadBufferWithoutRelcache ( RelFileLocator  rlocator,
ForkNumber  forkNum,
BlockNumber  blockNum,
ReadBufferMode  mode,
BufferAccessStrategy  strategy,
bool  permanent 
)

Definition at line 829 of file bufmgr.c.

832 {
833  SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
834 
835  return ReadBuffer_common(NULL, smgr,
836  permanent ? RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED,
837  forkNum, blockNum,
838  mode, strategy);
839 }

References INVALID_PROC_NUMBER, mode, ReadBuffer_common(), and smgropen().

Referenced by RelationCopyStorageUsingBuffer(), ScanSourceDatabasePgClass(), and XLogReadBufferExtended().

◆ ReadRecentBuffer()

bool ReadRecentBuffer ( RelFileLocator  rlocator,
ForkNumber  forkNum,
BlockNumber  blockNum,
Buffer  recent_buffer 
)

Definition at line 669 of file bufmgr.c.

671 {
672  BufferDesc *bufHdr;
673  BufferTag tag;
674  uint32 buf_state;
675  bool have_private_ref;
676 
677  Assert(BufferIsValid(recent_buffer));
678 
681  InitBufferTag(&tag, &rlocator, forkNum, blockNum);
682 
683  if (BufferIsLocal(recent_buffer))
684  {
685  int b = -recent_buffer - 1;
686 
687  bufHdr = GetLocalBufferDescriptor(b);
688  buf_state = pg_atomic_read_u32(&bufHdr->state);
689 
690  /* Is it still valid and holding the right tag? */
691  if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
692  {
693  PinLocalBuffer(bufHdr, true);
694 
696 
697  return true;
698  }
699  }
700  else
701  {
702  bufHdr = GetBufferDescriptor(recent_buffer - 1);
703  have_private_ref = GetPrivateRefCount(recent_buffer) > 0;
704 
705  /*
706  * Do we already have this buffer pinned with a private reference? If
707  * so, it must be valid and it is safe to check the tag without
708  * locking. If not, we have to lock the header first and then check.
709  */
710  if (have_private_ref)
711  buf_state = pg_atomic_read_u32(&bufHdr->state);
712  else
713  buf_state = LockBufHdr(bufHdr);
714 
715  if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
716  {
717  /*
718  * It's now safe to pin the buffer. We can't pin first and ask
719  * questions later, because it might confuse code paths like
720  * InvalidateBuffer() if we pinned a random non-matching buffer.
721  */
722  if (have_private_ref)
723  PinBuffer(bufHdr, NULL); /* bump pin count */
724  else
725  PinBuffer_Locked(bufHdr); /* pin for first time */
726 
728 
729  return true;
730  }
731 
732  /* If we locked the header above, now unlock. */
733  if (!have_private_ref)
734  UnlockBufHdr(bufHdr, buf_state);
735  }
736 
737  return false;
738 }
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
static bool PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
Definition: bufmgr.c:2595
int b
Definition: isn.c:70
bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
Definition: localbuf.c:655
int64 local_blks_hit
Definition: instrument.h:30
int64 shared_blks_hit
Definition: instrument.h:26

References Assert, b, BM_VALID, BufferIsLocal, BufferIsValid(), BufferTagsEqual(), CurrentResourceOwner, GetBufferDescriptor(), GetLocalBufferDescriptor(), GetPrivateRefCount(), InitBufferTag(), BufferUsage::local_blks_hit, LockBufHdr(), pg_atomic_read_u32(), pgBufferUsage, PinBuffer(), PinBuffer_Locked(), PinLocalBuffer(), ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), BufferUsage::shared_blks_hit, BufferDesc::state, BufferDesc::tag, and UnlockBufHdr().

Referenced by XLogReadBufferExtended().

◆ RelationGetNumberOfBlocksInFork()

BlockNumber RelationGetNumberOfBlocksInFork ( Relation  relation,
ForkNumber  forkNum 
)

Definition at line 3866 of file bufmgr.c.

3867 {
3868  if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
3869  {
3870  /*
3871  * Not every table AM uses BLCKSZ wide fixed size blocks. Therefore
3872  * tableam returns the size in bytes - but for the purpose of this
3873  * routine, we want the number of blocks. Therefore divide, rounding
3874  * up.
3875  */
3876  uint64 szbytes;
3877 
3878  szbytes = table_relation_size(relation, forkNum);
3879 
3880  return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
3881  }
3882  else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
3883  {
3884  return smgrnblocks(RelationGetSmgr(relation), forkNum);
3885  }
3886  else
3887  Assert(false);
3888 
3889  return 0; /* keep compiler quiet */
3890 }
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition: tableam.h:1878

References Assert, RelationData::rd_rel, RelationGetSmgr(), smgrnblocks(), and table_relation_size().

Referenced by _hash_getnewbuf(), _hash_init(), autoprewarm_database_main(), get_raw_page_internal(), and pg_prewarm().

◆ ReleaseAndReadBuffer()

Buffer ReleaseAndReadBuffer ( Buffer  buffer,
Relation  relation,
BlockNumber  blockNum 
)

Definition at line 2537 of file bufmgr.c.

2540 {
2541  ForkNumber forkNum = MAIN_FORKNUM;
2542  BufferDesc *bufHdr;
2543 
2544  if (BufferIsValid(buffer))
2545  {
2546  Assert(BufferIsPinned(buffer));
2547  if (BufferIsLocal(buffer))
2548  {
2549  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2550  if (bufHdr->tag.blockNum == blockNum &&
2551  BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
2552  BufTagGetForkNum(&bufHdr->tag) == forkNum)
2553  return buffer;
2554  UnpinLocalBuffer(buffer);
2555  }
2556  else
2557  {
2558  bufHdr = GetBufferDescriptor(buffer - 1);
2559  /* we have pin, so it's ok to examine tag without spinlock */
2560  if (bufHdr->tag.blockNum == blockNum &&
2561  BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
2562  BufTagGetForkNum(&bufHdr->tag) == forkNum)
2563  return buffer;
2564  UnpinBuffer(bufHdr);
2565  }
2566  }
2567 
2568  return ReadBuffer(relation, blockNum);
2569 }
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:745
void UnpinLocalBuffer(Buffer buffer)
Definition: localbuf.c:681

References Assert, buftag::blockNum, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferIsValid(), BufTagGetForkNum(), BufTagMatchesRelFileLocator(), GetBufferDescriptor(), GetLocalBufferDescriptor(), MAIN_FORKNUM, RelationData::rd_locator, ReadBuffer(), BufferDesc::tag, UnpinBuffer(), and UnpinLocalBuffer().

Referenced by _bt_relandgetbuf(), ginFindLeafPage(), heapam_index_fetch_tuple(), and heapam_scan_bitmap_next_block().

◆ ReleaseBuffer()

void ReleaseBuffer ( Buffer  buffer)

Definition at line 4850 of file bufmgr.c.

4851 {
4852  if (!BufferIsValid(buffer))
4853  elog(ERROR, "bad buffer ID: %d", buffer);
4854 
4855  if (BufferIsLocal(buffer))
4856  UnpinLocalBuffer(buffer);
4857  else
4858  UnpinBuffer(GetBufferDescriptor(buffer - 1));
4859 }

References PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsValid(), elog, ERROR, GetBufferDescriptor(), UnpinBuffer(), and UnpinLocalBuffer().

Referenced by _bt_allocbuf(), _bt_drop_lock_and_maybe_pin(), _bt_pagedel(), _bt_relbuf(), _bt_search_insert(), _bt_unlink_halfdead_page(), _hash_dropbuf(), _hash_getbuf_with_condlock_cleanup(), autoprewarm_database_main(), blinsert(), BloomNewBuffer(), brin_getinsertbuffer(), brin_vacuum_scan(), bringetbitmap(), brinGetTupleForHeapBlock(), brininsert(), brinRevmapTerminate(), brinsummarize(), collect_corrupt_items(), collect_visibility_data(), entryLoadMoreItems(), ExecEndBitmapHeapScan(), ExecEndIndexOnlyScan(), ExecReScanBitmapHeapScan(), ExtendBufferedRelTo(), FreeBulkInsertState(), freeGinBtreeStack(), fsm_search(), fsm_vacuum_page(), get_actual_variable_endpoint(), get_raw_page_internal(), GetRecordedFreeSpace(), ginDeletePage(), ginFindParents(), ginFinishSplit(), ginFreeScanKeys(), ginInsertCleanup(), GinNewBuffer(), ginScanToDelete(), gistdoinsert(), gistFindCorrectParent(), gistNewBuffer(), gistvacuum_delete_empty_pages(), heap_abort_speculative(), heap_delete(), heap_endscan(), heap_fetch(), heap_fetch_next_buffer(), heap_force_common(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_rescan(), heap_update(), heap_vac_scan_next_block(), heap_xlog_delete(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_update(), heap_xlog_visible(), heapam_index_fetch_reset(), heapam_scan_sample_next_block(), heapam_tuple_lock(), heapgettup(), heapgettup_pagemode(), lazy_scan_heap(), lazy_vacuum_heap_rel(), pg_prewarm(), pg_visibility(), pg_visibility_map(), pg_visibility_map_summary(), pgstatindex_impl(), read_stream_reset(), ReadBufferBI(), RelationAddBlocks(), RelationGetBufferForTuple(), ReleaseBulkInsertStatePin(), revmap_get_buffer(), spgdoinsert(), SpGistGetBuffer(), SpGistNewBuffer(), SpGistUpdateMetaPage(), statapprox_heap(), summarize_range(), terminate_brin_buildstate(), tts_buffer_heap_clear(), tts_buffer_heap_materialize(), tts_buffer_heap_store_tuple(), UnlockReleaseBuffer(), verify_heapam(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_pin(), and XLogReadBufferExtended().

◆ StartReadBuffer()

bool StartReadBuffer ( ReadBuffersOperation operation,
Buffer buffer,
BlockNumber  blocknum,
int  flags 
)

Definition at line 1321 of file bufmgr.c.

1325 {
1326  int nblocks = 1;
1327  bool result;
1328 
1329  result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags);
1330  Assert(nblocks == 1); /* single block can't be short */
1331 
1332  return result;
1333 }
static pg_attribute_always_inline bool StartReadBuffersImpl(ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, int flags)
Definition: bufmgr.c:1211

References Assert, PrivateRefCountEntry::buffer, and StartReadBuffersImpl().

Referenced by read_stream_next_buffer(), and ReadBuffer_common().

◆ StartReadBuffers()

bool StartReadBuffers ( ReadBuffersOperation operation,
Buffer buffers,
BlockNumber  blocknum,
int *  nblocks,
int  flags 
)

Definition at line 1306 of file bufmgr.c.

1311 {
1312  return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags);
1313 }

References StartReadBuffersImpl().

Referenced by read_stream_start_pending_read().

◆ UnlockBuffers()

void UnlockBuffers ( void  )

Definition at line 5057 of file bufmgr.c.

5058 {
5060 
5061  if (buf)
5062  {
5063  uint32 buf_state;
5064 
5065  buf_state = LockBufHdr(buf);
5066 
5067  /*
5068  * Don't complain if flag bit not set; it could have been reset but we
5069  * got a cancel/die interrupt before getting the signal.
5070  */
5071  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5072  buf->wait_backend_pgprocno == MyProcNumber)
5073  buf_state &= ~BM_PIN_COUNT_WAITER;
5074 
5075  UnlockBufHdr(buf, buf_state);
5076 
5077  PinCountWaitBuf = NULL;
5078  }
5079 }

References BM_PIN_COUNT_WAITER, buf, LockBufHdr(), MyProcNumber, PinCountWaitBuf, and UnlockBufHdr().

Referenced by AbortSubTransaction(), AbortTransaction(), AtProcExit_Buffers(), BackgroundWriterMain(), CheckpointerMain(), and WalWriterMain().

◆ UnlockReleaseBuffer()

void UnlockReleaseBuffer ( Buffer  buffer)

Definition at line 4867 of file bufmgr.c.

4868 {
4869  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4870  ReleaseBuffer(buffer);
4871 }

References PrivateRefCountEntry::buffer, BUFFER_LOCK_UNLOCK, LockBuffer(), and ReleaseBuffer().

Referenced by _bt_clear_incomplete_split(), _bt_restore_meta(), _hash_relbuf(), allocNewBuffer(), AlterSequence(), blbulkdelete(), blgetbitmap(), blinsert(), BloomInitMetapage(), blvacuumcleanup(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinGetStats(), brinRevmapDesummarizeRange(), bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), bt_recheck_sibling_links(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), collect_corrupt_items(), collect_visibility_data(), count_nondeletable_pages(), createPostingTree(), do_setval(), doPickSplit(), entryLoadMoreItems(), fill_seq_fork_with_data(), flushCachedPage(), FreeSpaceMapPrepareTruncateRel(), fsm_search(), fsm_set_and_search(), generic_redo(), ginbuild(), ginbuildempty(), ginbulkdelete(), ginGetStats(), ginHeapTupleFastInsert(), ginInsertCleanup(), ginPlaceToPage(), ginRedoClearIncompleteSplit(), ginRedoCreatePTree(), ginRedoDeleteListPages(), ginRedoDeletePage(), ginRedoInsert(), ginRedoInsertListPage(), ginRedoSplit(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginRedoVacuumPage(), ginScanToDelete(), ginStepRight(), ginUpdateStats(), ginvacuumcleanup(), ginVacuumPostingTree(), ginVacuumPostingTreeLeaves(), gistbufferinginserttuples(), gistbuild(), gistbuildempty(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistGetMaxLevel(), gistinserttuples(), gistkillitems(), gistplacetopage(), gistProcessItup(), gistRedoClearFollowRight(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), gistScanPage(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_split_page(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), heap_delete(), heap_finish_speculative(), heap_force_common(), heap_get_latest_tid(), heap_index_delete_tuples(), heap_inplace_update(), heap_insert(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_update(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), heap_xlog_update(), heap_xlog_visible(), heapam_scan_analyze_next_tuple(), initBloomState(), lazy_scan_heap(), lazy_scan_new_or_empty(), lazy_vacuum_heap_rel(), log_newpage_range(), moveLeafs(), nextval_internal(), palloc_btree_page(), pg_sequence_last_value(), pg_visibility(), pgstat_gist_page(), pgstat_heap(), pgstatginindex_internal(), pgstathashindex(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), ResetSequence(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), scanPostingTree(), ScanSourceDatabasePgClass(), seq_redo(), SequenceChangePersistence(), shiftList(), spgAddNodeAction(), spgbuild(), spgdoinsert(), spgGetCache(), SpGistGetBuffer(), SpGistUpdateMetaPage(), spgMatchNodeAction(), spgprocesspending(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), spgvacuumpage(), spgWalk(), statapprox_heap(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_prepare_truncate(), writeListPage(), xlog_redo(), and XLogRecordPageWithFreeSpace().

◆ WaitReadBuffers()

void WaitReadBuffers ( ReadBuffersOperation operation)

Definition at line 1349 of file bufmgr.c.

1350 {
1351  Buffer *buffers;
1352  int nblocks;
1353  BlockNumber blocknum;
1354  ForkNumber forknum;
1355  IOContext io_context;
1356  IOObject io_object;
1357  char persistence;
1358 
1359  /*
1360  * Currently operations are only allowed to include a read of some range,
1361  * with an optional extra buffer that is already pinned at the end. So
1362  * nblocks can be at most one more than io_buffers_len.
1363  */
1364  Assert((operation->nblocks == operation->io_buffers_len) ||
1365  (operation->nblocks == operation->io_buffers_len + 1));
1366 
1367  /* Find the range of the physical read we need to perform. */
1368  nblocks = operation->io_buffers_len;
1369  if (nblocks == 0)
1370  return; /* nothing to do */
1371 
1372  buffers = &operation->buffers[0];
1373  blocknum = operation->blocknum;
1374  forknum = operation->forknum;
1375 
1376  persistence = operation->rel
1377  ? operation->rel->rd_rel->relpersistence
1378  : RELPERSISTENCE_PERMANENT;
1379  if (persistence == RELPERSISTENCE_TEMP)
1380  {
1381  io_context = IOCONTEXT_NORMAL;
1382  io_object = IOOBJECT_TEMP_RELATION;
1383  }
1384  else
1385  {
1386  io_context = IOContextForStrategy(operation->strategy);
1387  io_object = IOOBJECT_RELATION;
1388  }
1389 
1390  /*
1391  * We count all these blocks as read by this backend. This is traditional
1392  * behavior, but might turn out to be not true if we find that someone
1393  * else has beaten us and completed the read of some of these blocks. In
1394  * that case the system globally double-counts, but we traditionally don't
1395  * count this as a "hit", and we don't have a separate counter for "miss,
1396  * but another backend completed the read".
1397  */
1398  if (persistence == RELPERSISTENCE_TEMP)
1399  pgBufferUsage.local_blks_read += nblocks;
1400  else
1401  pgBufferUsage.shared_blks_read += nblocks;
1402 
1403  for (int i = 0; i < nblocks; ++i)
1404  {
1405  int io_buffers_len;
1406  Buffer io_buffers[MAX_IO_COMBINE_LIMIT];
1407  void *io_pages[MAX_IO_COMBINE_LIMIT];
1408  instr_time io_start;
1409  BlockNumber io_first_block;
1410 
1411  /*
1412  * Skip this block if someone else has already completed it. If an
1413  * I/O is already in progress in another backend, this will wait for
1414  * the outcome: either done, or something went wrong and we will
1415  * retry.
1416  */
1417  if (!WaitReadBuffersCanStartIO(buffers[i], false))
1418  {
1419  /*
1420  * Report this as a 'hit' for this backend, even though it must
1421  * have started out as a miss in PinBufferForBlock().
1422  */
1423  TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
1424  operation->smgr->smgr_rlocator.locator.spcOid,
1425  operation->smgr->smgr_rlocator.locator.dbOid,
1426  operation->smgr->smgr_rlocator.locator.relNumber,
1427  operation->smgr->smgr_rlocator.backend,
1428  true);
1429  continue;
1430  }
1431 
1432  /* We found a buffer that we need to read in. */
1433  io_buffers[0] = buffers[i];
1434  io_pages[0] = BufferGetBlock(buffers[i]);
1435  io_first_block = blocknum + i;
1436  io_buffers_len = 1;
1437 
1438  /*
1439  * How many neighboring-on-disk blocks can we can scatter-read into
1440  * other buffers at the same time? In this case we don't wait if we
1441  * see an I/O already in progress. We already hold BM_IO_IN_PROGRESS
1442  * for the head block, so we should get on with that I/O as soon as
1443  * possible. We'll come back to this block again, above.
1444  */
1445  while ((i + 1) < nblocks &&
1446  WaitReadBuffersCanStartIO(buffers[i + 1], true))
1447  {
1448  /* Must be consecutive block numbers. */
1449  Assert(BufferGetBlockNumber(buffers[i + 1]) ==
1450  BufferGetBlockNumber(buffers[i]) + 1);
1451 
1452  io_buffers[io_buffers_len] = buffers[++i];
1453  io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
1454  }
1455 
1457  smgrreadv(operation->smgr, forknum, io_first_block, io_pages, io_buffers_len);
1458  pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
1459  io_buffers_len);
1460 
1461  /* Verify each block we read, and terminate the I/O. */
1462  for (int j = 0; j < io_buffers_len; ++j)
1463  {
1464  BufferDesc *bufHdr;
1465  Block bufBlock;
1466 
1467  if (persistence == RELPERSISTENCE_TEMP)
1468  {
1469  bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
1470  bufBlock = LocalBufHdrGetBlock(bufHdr);
1471  }
1472  else
1473  {
1474  bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
1475  bufBlock = BufHdrGetBlock(bufHdr);
1476  }
1477 
1478  /* check for garbage data */
1479  if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
1481  {
1482  if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages)
1483  {
1484  ereport(WARNING,
1486  errmsg("invalid page in block %u of relation %s; zeroing out page",
1487  io_first_block + j,
1488  relpath(operation->smgr->smgr_rlocator, forknum))));
1489  memset(bufBlock, 0, BLCKSZ);
1490  }
1491  else
1492  ereport(ERROR,
1494  errmsg("invalid page in block %u of relation %s",
1495  io_first_block + j,
1496  relpath(operation->smgr->smgr_rlocator, forknum))));
1497  }
1498 
1499  /* Terminate I/O and set BM_VALID. */
1500  if (persistence == RELPERSISTENCE_TEMP)
1501  {
1502  uint32 buf_state = pg_atomic_read_u32(&bufHdr->state);
1503 
1504  buf_state |= BM_VALID;
1505  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
1506  }
1507  else
1508  {
1509  /* Set BM_VALID, terminate IO, and wake up any waiters */
1510  TerminateBufferIO(bufHdr, false, BM_VALID, true);
1511  }
1512 
1513  /* Report I/Os as completing individually. */
1514  TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
1515  operation->smgr->smgr_rlocator.locator.spcOid,
1516  operation->smgr->smgr_rlocator.locator.dbOid,
1517  operation->smgr->smgr_rlocator.locator.relNumber,
1518  operation->smgr->smgr_rlocator.backend,
1519  false);
1520  }
1521 
1522  VacuumPageMiss += io_buffers_len;
1523  if (VacuumCostActive)
1524  VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
1525  }
1526 }
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3667
static bool WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
Definition: bufmgr.c:1336
bool zero_damaged_pages
Definition: bufmgr.c:139
static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits, bool forget_owner)
Definition: bufmgr.c:5542
#define BufHdrGetBlock(bufHdr)
Definition: bufmgr.c:67
#define MAX_IO_COMBINE_LIMIT
Definition: bufmgr.h:172
bool PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags)
Definition: bufpage.c:88
#define PIV_LOG_WARNING
Definition: bufpage.h:465
#define PIV_REPORT_STAT
Definition: bufpage.h:466
#define WARNING
Definition: elog.h:36
IOContext IOContextForStrategy(BufferAccessStrategy strategy)
Definition: freelist.c:758
int VacuumCostPageMiss
Definition: globals.c:149
int64 VacuumPageMiss
Definition: globals.c:155
int j
Definition: isn.c:74
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:41
IOObject
Definition: pgstat.h:279
IOContext
Definition: pgstat.h:287
@ IOOP_READ
Definition: pgstat.h:302
#define relpath(rlocator, forknum)
Definition: relpath.h:94
void smgrreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void **buffers, BlockNumber nblocks)
Definition: smgr.c:600
int64 shared_blks_read
Definition: instrument.h:27
int64 local_blks_read
Definition: instrument.h:31
ForkNumber forknum
Definition: bufmgr.h:129
int16 io_buffers_len
Definition: bufmgr.h:141
Buffer * buffers
Definition: bufmgr.h:137
BufferAccessStrategy strategy
Definition: bufmgr.h:130
BlockNumber blocknum
Definition: bufmgr.h:138
struct SMgrRelationData * smgr
Definition: bufmgr.h:127
RelFileLocator locator
RelFileNumber relNumber
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:37

References Assert, RelFileLocatorBackend::backend, ReadBuffersOperation::blocknum, BM_VALID, BufferGetBlock(), BufferGetBlockNumber(), ReadBuffersOperation::buffers, BufHdrGetBlock, RelFileLocator::dbOid, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg(), ERROR, ReadBuffersOperation::flags, ReadBuffersOperation::forknum, GetBufferDescriptor(), GetLocalBufferDescriptor(), i, ReadBuffersOperation::io_buffers_len, IOCONTEXT_NORMAL, IOContextForStrategy(), IOOBJECT_RELATION, IOOBJECT_TEMP_RELATION, IOOP_READ, j, BufferUsage::local_blks_read, LocalBufHdrGetBlock, RelFileLocatorBackend::locator, MAX_IO_COMBINE_LIMIT, ReadBuffersOperation::nblocks, PageIsVerifiedExtended(), pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgBufferUsage, pgstat_count_io_op_time(), pgstat_prepare_io_time(), PIV_LOG_WARNING, PIV_REPORT_STAT, RelationData::rd_rel, READ_BUFFERS_ZERO_ON_ERROR, ReadBuffersOperation::rel, RelFileLocator::relNumber, relpath, BufferUsage::shared_blks_read, ReadBuffersOperation::smgr, SMgrRelationData::smgr_rlocator, smgrreadv(), RelFileLocator::spcOid, BufferDesc::state, ReadBuffersOperation::strategy, TerminateBufferIO(), track_io_timing, VacuumCostActive, VacuumCostBalance, VacuumCostPageMiss, VacuumPageMiss, WaitReadBuffersCanStartIO(), WARNING, and zero_damaged_pages.

Referenced by read_stream_next_buffer(), and ReadBuffer_common().

Variable Documentation

◆ backend_flush_after

PGDLLIMPORT int backend_flush_after
extern

Definition at line 172 of file bufmgr.c.

Referenced by InitBufferPool().

◆ bgwriter_flush_after

PGDLLIMPORT int bgwriter_flush_after
extern

Definition at line 171 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

PGDLLIMPORT int bgwriter_lru_maxpages
extern

Definition at line 140 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

PGDLLIMPORT double bgwriter_lru_multiplier
extern

Definition at line 141 of file bufmgr.c.

Referenced by BgBufferSync().

◆ BufferBlocks

PGDLLIMPORT char* BufferBlocks
extern

Definition at line 22 of file buf_init.c.

Referenced by BufferGetBlock(), and InitBufferPool().

◆ checkpoint_flush_after

PGDLLIMPORT int checkpoint_flush_after
extern

Definition at line 170 of file bufmgr.c.

Referenced by BufferSync().

◆ effective_io_concurrency

PGDLLIMPORT int effective_io_concurrency
extern

◆ io_combine_limit

◆ LocalBufferBlockPointers

PGDLLIMPORT Block* LocalBufferBlockPointers
extern

Definition at line 45 of file localbuf.c.

Referenced by BufferGetBlock(), and InitLocalBuffers().

◆ LocalRefCount

◆ maintenance_io_concurrency

◆ NBuffers

◆ NLocBuffer

◆ track_io_timing

◆ zero_damaged_pages

PGDLLIMPORT bool zero_damaged_pages
extern

Definition at line 139 of file bufmgr.c.

Referenced by mdreadv(), and WaitReadBuffers().