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 READ_BUFFERS_ZERO_ON_ERROR   (1 << 0)
 
#define READ_BUFFERS_ISSUE_ADVICE   (1 << 1)
 
#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 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)
}
 

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 191 of file bufmgr.h.

◆ BUFFER_LOCK_SHARE

#define BUFFER_LOCK_SHARE   1

Definition at line 190 of file bufmgr.h.

◆ BUFFER_LOCK_UNLOCK

#define BUFFER_LOCK_UNLOCK   0

Definition at line 189 of file bufmgr.h.

◆ DEFAULT_EFFECTIVE_IO_CONCURRENCY

#define DEFAULT_EFFECTIVE_IO_CONCURRENCY   0

Definition at line 158 of file bufmgr.h.

◆ DEFAULT_IO_COMBINE_LIMIT

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

Definition at line 165 of file bufmgr.h.

◆ DEFAULT_MAINTENANCE_IO_CONCURRENCY

#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   0

Definition at line 159 of file bufmgr.h.

◆ MAX_IO_COMBINE_LIMIT

#define MAX_IO_COMBINE_LIMIT   PG_IOV_MAX

Definition at line 164 of file bufmgr.h.

◆ MAX_IO_CONCURRENCY

#define MAX_IO_CONCURRENCY   1000

Definition at line 181 of file bufmgr.h.

◆ P_NEW

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

Definition at line 184 of file bufmgr.h.

◆ READ_BUFFERS_ISSUE_ADVICE

#define READ_BUFFERS_ISSUE_ADVICE   (1 << 1)

Definition at line 113 of file bufmgr.h.

◆ READ_BUFFERS_ZERO_ON_ERROR

#define READ_BUFFERS_ZERO_ON_ERROR   (1 << 0)

Definition at line 111 of file bufmgr.h.

◆ RelationGetNumberOfBlocks

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

Definition at line 273 of file bufmgr.h.

Typedef Documentation

◆ Block

typedef void* Block

Definition at line 25 of file bufmgr.h.

◆ BufferAccessStrategyType

◆ BufferManagerRelation

◆ ExtendBufferedFlags

◆ PrefetchBufferResult

◆ 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

Function Documentation

◆ AtEOXact_Buffers()

void AtEOXact_Buffers ( bool  isCommit)

Definition at line 3571 of file bufmgr.c.

3572 {
3574 
3575  AtEOXact_LocalBuffers(isCommit);
3576 
3578 }
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:3631
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:237
#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 3200 of file bufmgr.c.

3201 {
3202  /* info obtained from freelist.c */
3203  int strategy_buf_id;
3204  uint32 strategy_passes;
3205  uint32 recent_alloc;
3206 
3207  /*
3208  * Information saved between calls so we can determine the strategy
3209  * point's advance rate and avoid scanning already-cleaned buffers.
3210  */
3211  static bool saved_info_valid = false;
3212  static int prev_strategy_buf_id;
3213  static uint32 prev_strategy_passes;
3214  static int next_to_clean;
3215  static uint32 next_passes;
3216 
3217  /* Moving averages of allocation rate and clean-buffer density */
3218  static float smoothed_alloc = 0;
3219  static float smoothed_density = 10.0;
3220 
3221  /* Potentially these could be tunables, but for now, not */
3222  float smoothing_samples = 16;
3223  float scan_whole_pool_milliseconds = 120000.0;
3224 
3225  /* Used to compute how far we scan ahead */
3226  long strategy_delta;
3227  int bufs_to_lap;
3228  int bufs_ahead;
3229  float scans_per_alloc;
3230  int reusable_buffers_est;
3231  int upcoming_alloc_est;
3232  int min_scan_buffers;
3233 
3234  /* Variables for the scanning loop proper */
3235  int num_to_scan;
3236  int num_written;
3237  int reusable_buffers;
3238 
3239  /* Variables for final smoothed_density update */
3240  long new_strategy_delta;
3241  uint32 new_recent_alloc;
3242 
3243  /*
3244  * Find out where the freelist clock sweep currently is, and how many
3245  * buffer allocations have happened since our last call.
3246  */
3247  strategy_buf_id = StrategySyncStart(&strategy_passes, &recent_alloc);
3248 
3249  /* Report buffer alloc counts to pgstat */
3250  PendingBgWriterStats.buf_alloc += recent_alloc;
3251 
3252  /*
3253  * If we're not running the LRU scan, just stop after doing the stats
3254  * stuff. We mark the saved state invalid so that we can recover sanely
3255  * if LRU scan is turned back on later.
3256  */
3257  if (bgwriter_lru_maxpages <= 0)
3258  {
3259  saved_info_valid = false;
3260  return true;
3261  }
3262 
3263  /*
3264  * Compute strategy_delta = how many buffers have been scanned by the
3265  * clock sweep since last time. If first time through, assume none. Then
3266  * see if we are still ahead of the clock sweep, and if so, how many
3267  * buffers we could scan before we'd catch up with it and "lap" it. Note:
3268  * weird-looking coding of xxx_passes comparisons are to avoid bogus
3269  * behavior when the passes counts wrap around.
3270  */
3271  if (saved_info_valid)
3272  {
3273  int32 passes_delta = strategy_passes - prev_strategy_passes;
3274 
3275  strategy_delta = strategy_buf_id - prev_strategy_buf_id;
3276  strategy_delta += (long) passes_delta * NBuffers;
3277 
3278  Assert(strategy_delta >= 0);
3279 
3280  if ((int32) (next_passes - strategy_passes) > 0)
3281  {
3282  /* we're one pass ahead of the strategy point */
3283  bufs_to_lap = strategy_buf_id - next_to_clean;
3284 #ifdef BGW_DEBUG
3285  elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3286  next_passes, next_to_clean,
3287  strategy_passes, strategy_buf_id,
3288  strategy_delta, bufs_to_lap);
3289 #endif
3290  }
3291  else if (next_passes == strategy_passes &&
3292  next_to_clean >= strategy_buf_id)
3293  {
3294  /* on same pass, but ahead or at least not behind */
3295  bufs_to_lap = NBuffers - (next_to_clean - strategy_buf_id);
3296 #ifdef BGW_DEBUG
3297  elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3298  next_passes, next_to_clean,
3299  strategy_passes, strategy_buf_id,
3300  strategy_delta, bufs_to_lap);
3301 #endif
3302  }
3303  else
3304  {
3305  /*
3306  * We're behind, so skip forward to the strategy point and start
3307  * cleaning from there.
3308  */
3309 #ifdef BGW_DEBUG
3310  elog(DEBUG2, "bgwriter behind: bgw %u-%u strategy %u-%u delta=%ld",
3311  next_passes, next_to_clean,
3312  strategy_passes, strategy_buf_id,
3313  strategy_delta);
3314 #endif
3315  next_to_clean = strategy_buf_id;
3316  next_passes = strategy_passes;
3317  bufs_to_lap = NBuffers;
3318  }
3319  }
3320  else
3321  {
3322  /*
3323  * Initializing at startup or after LRU scanning had been off. Always
3324  * start at the strategy point.
3325  */
3326 #ifdef BGW_DEBUG
3327  elog(DEBUG2, "bgwriter initializing: strategy %u-%u",
3328  strategy_passes, strategy_buf_id);
3329 #endif
3330  strategy_delta = 0;
3331  next_to_clean = strategy_buf_id;
3332  next_passes = strategy_passes;
3333  bufs_to_lap = NBuffers;
3334  }
3335 
3336  /* Update saved info for next time */
3337  prev_strategy_buf_id = strategy_buf_id;
3338  prev_strategy_passes = strategy_passes;
3339  saved_info_valid = true;
3340 
3341  /*
3342  * Compute how many buffers had to be scanned for each new allocation, ie,
3343  * 1/density of reusable buffers, and track a moving average of that.
3344  *
3345  * If the strategy point didn't move, we don't update the density estimate
3346  */
3347  if (strategy_delta > 0 && recent_alloc > 0)
3348  {
3349  scans_per_alloc = (float) strategy_delta / (float) recent_alloc;
3350  smoothed_density += (scans_per_alloc - smoothed_density) /
3351  smoothing_samples;
3352  }
3353 
3354  /*
3355  * Estimate how many reusable buffers there are between the current
3356  * strategy point and where we've scanned ahead to, based on the smoothed
3357  * density estimate.
3358  */
3359  bufs_ahead = NBuffers - bufs_to_lap;
3360  reusable_buffers_est = (float) bufs_ahead / smoothed_density;
3361 
3362  /*
3363  * Track a moving average of recent buffer allocations. Here, rather than
3364  * a true average we want a fast-attack, slow-decline behavior: we
3365  * immediately follow any increase.
3366  */
3367  if (smoothed_alloc <= (float) recent_alloc)
3368  smoothed_alloc = recent_alloc;
3369  else
3370  smoothed_alloc += ((float) recent_alloc - smoothed_alloc) /
3371  smoothing_samples;
3372 
3373  /* Scale the estimate by a GUC to allow more aggressive tuning. */
3374  upcoming_alloc_est = (int) (smoothed_alloc * bgwriter_lru_multiplier);
3375 
3376  /*
3377  * If recent_alloc remains at zero for many cycles, smoothed_alloc will
3378  * eventually underflow to zero, and the underflows produce annoying
3379  * kernel warnings on some platforms. Once upcoming_alloc_est has gone to
3380  * zero, there's no point in tracking smaller and smaller values of
3381  * smoothed_alloc, so just reset it to exactly zero to avoid this
3382  * syndrome. It will pop back up as soon as recent_alloc increases.
3383  */
3384  if (upcoming_alloc_est == 0)
3385  smoothed_alloc = 0;
3386 
3387  /*
3388  * Even in cases where there's been little or no buffer allocation
3389  * activity, we want to make a small amount of progress through the buffer
3390  * cache so that as many reusable buffers as possible are clean after an
3391  * idle period.
3392  *
3393  * (scan_whole_pool_milliseconds / BgWriterDelay) computes how many times
3394  * the BGW will be called during the scan_whole_pool time; slice the
3395  * buffer pool into that many sections.
3396  */
3397  min_scan_buffers = (int) (NBuffers / (scan_whole_pool_milliseconds / BgWriterDelay));
3398 
3399  if (upcoming_alloc_est < (min_scan_buffers + reusable_buffers_est))
3400  {
3401 #ifdef BGW_DEBUG
3402  elog(DEBUG2, "bgwriter: alloc_est=%d too small, using min=%d + reusable_est=%d",
3403  upcoming_alloc_est, min_scan_buffers, reusable_buffers_est);
3404 #endif
3405  upcoming_alloc_est = min_scan_buffers + reusable_buffers_est;
3406  }
3407 
3408  /*
3409  * Now write out dirty reusable buffers, working forward from the
3410  * next_to_clean point, until we have lapped the strategy scan, or cleaned
3411  * enough buffers to match our estimate of the next cycle's allocation
3412  * requirements, or hit the bgwriter_lru_maxpages limit.
3413  */
3414 
3415  num_to_scan = bufs_to_lap;
3416  num_written = 0;
3417  reusable_buffers = reusable_buffers_est;
3418 
3419  /* Execute the LRU scan */
3420  while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
3421  {
3422  int sync_state = SyncOneBuffer(next_to_clean, true,
3423  wb_context);
3424 
3425  if (++next_to_clean >= NBuffers)
3426  {
3427  next_to_clean = 0;
3428  next_passes++;
3429  }
3430  num_to_scan--;
3431 
3432  if (sync_state & BUF_WRITTEN)
3433  {
3434  reusable_buffers++;
3435  if (++num_written >= bgwriter_lru_maxpages)
3436  {
3438  break;
3439  }
3440  }
3441  else if (sync_state & BUF_REUSABLE)
3442  reusable_buffers++;
3443  }
3444 
3445  PendingBgWriterStats.buf_written_clean += num_written;
3446 
3447 #ifdef BGW_DEBUG
3448  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",
3449  recent_alloc, smoothed_alloc, strategy_delta, bufs_ahead,
3450  smoothed_density, reusable_buffers_est, upcoming_alloc_est,
3451  bufs_to_lap - num_to_scan,
3452  num_written,
3453  reusable_buffers - reusable_buffers_est);
3454 #endif
3455 
3456  /*
3457  * Consider the above scan as being like a new allocation scan.
3458  * Characterize its density and update the smoothed one based on it. This
3459  * effectively halves the moving average period in cases where both the
3460  * strategy and the background writer are doing some useful scanning,
3461  * which is helpful because a long memory isn't as desirable on the
3462  * density estimates.
3463  */
3464  new_strategy_delta = bufs_to_lap - num_to_scan;
3465  new_recent_alloc = reusable_buffers - reusable_buffers_est;
3466  if (new_strategy_delta > 0 && new_recent_alloc > 0)
3467  {
3468  scans_per_alloc = (float) new_strategy_delta / (float) new_recent_alloc;
3469  smoothed_density += (scans_per_alloc - smoothed_density) /
3470  smoothing_samples;
3471 
3472 #ifdef BGW_DEBUG
3473  elog(DEBUG2, "bgwriter: cleaner density alloc=%u scan=%ld density=%.2f new smoothed=%.2f",
3474  new_recent_alloc, new_strategy_delta,
3475  scans_per_alloc, smoothed_density);
3476 #endif
3477  }
3478 
3479  /* Return true if OK to hibernate */
3480  return (bufs_to_lap == 0 && recent_alloc == 0);
3481 }
int BgWriterDelay
Definition: bgwriter.c:57
#define BUF_REUSABLE
Definition: bufmgr.c:77
double bgwriter_lru_multiplier
Definition: bufmgr.c:169
static int SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
Definition: bufmgr.c:3498
int bgwriter_lru_maxpages
Definition: bufmgr.c:168
#define BUF_WRITTEN
Definition: bufmgr.c:76
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:140
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 367 of file bufmgr.h.

368 {
369  Assert(BufferIsValid(buffer));
370 
371  if (BufferIsLocal(buffer))
372  return LocalBufferBlockPointers[-buffer - 1];
373  else
374  return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
375 }
#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:351
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 3736 of file bufmgr.c.

3737 {
3738  BufferDesc *bufHdr;
3739 
3740  Assert(BufferIsPinned(buffer));
3741 
3742  if (BufferIsLocal(buffer))
3743  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
3744  else
3745  bufHdr = GetBufferDescriptor(buffer - 1);
3746 
3747  /* pinned, so OK to read tag without spinlock */
3748  return bufHdr->tag.blockNum;
3749 }
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:501
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(), RelationCopyStorageUsingBuffer(), 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 3997 of file bufmgr.c.

3998 {
3999  BufferDesc *bufHdr = GetBufferDescriptor(buffer - 1);
4000  char *page = BufferGetPage(buffer);
4001  XLogRecPtr lsn;
4002  uint32 buf_state;
4003 
4004  /*
4005  * If we don't need locking for correctness, fastpath out.
4006  */
4007  if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
4008  return PageGetLSN(page);
4009 
4010  /* Make sure we've got a real buffer, and that we hold a pin on it. */
4011  Assert(BufferIsValid(buffer));
4012  Assert(BufferIsPinned(buffer));
4013 
4014  buf_state = LockBufHdr(bufHdr);
4015  lsn = PageGetLSN(page);
4016  UnlockBufHdr(bufHdr, buf_state);
4017 
4018  return lsn;
4019 }
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:5774
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:400
static XLogRecPtr PageGetLSN(Page page)
Definition: bufpage.h:386
#define XLogHintBitIsNeeded()
Definition: xlog.h:120
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 400 of file bufmgr.h.

401 {
402  return (Page) BufferGetBlock(buffer);
403 }
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:367
Pointer Page
Definition: bufpage.h:81

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

◆ BufferGetPageSize()

◆ BufferGetTag()

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

Definition at line 3757 of file bufmgr.c.

3759 {
3760  BufferDesc *bufHdr;
3761 
3762  /* Do the same checks as BufferGetBlockNumber. */
3763  Assert(BufferIsPinned(buffer));
3764 
3765  if (BufferIsLocal(buffer))
3766  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
3767  else
3768  bufHdr = GetBufferDescriptor(buffer - 1);
3769 
3770  /* pinned, so OK to read tag without spinlock */
3771  *rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
3772  *forknum = BufTagGetForkNum(&bufHdr->tag);
3773  *blknum = bufHdr->tag.blockNum;
3774 }
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 2511 of file bufmgr.c.

2512 {
2513  BufferDesc *bufHdr;
2514 
2515  if (BufferIsLocal(buffer))
2516  {
2517  int bufid = -buffer - 1;
2518 
2519  bufHdr = GetLocalBufferDescriptor(bufid);
2520  }
2521  else
2522  {
2523  bufHdr = GetBufferDescriptor(buffer - 1);
2524  }
2525 
2526  Assert(BufferIsPinned(buffer));
2528  LW_EXCLUSIVE));
2529 
2530  return pg_atomic_read_u32(&bufHdr->state) & BM_DIRTY;
2531 }
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:232
#define BM_DIRTY
Definition: buf_internals.h:61
static LWLock * BufferDescriptorGetContentLock(const BufferDesc *bdesc)
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1937
@ 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 2482 of file bufmgr.c.

2483 {
2484  BufferDesc *bufHdr;
2485 
2486  if (BufferIsLocal(buffer))
2487  {
2488  int bufid = -buffer - 1;
2489 
2490  bufHdr = GetLocalBufferDescriptor(bufid);
2491  }
2492  else
2493  {
2494  bufHdr = GetBufferDescriptor(buffer - 1);
2495  }
2496 
2497  Assert(BufferIsPinned(buffer));
2499  LW_EXCLUSIVE);
2500 }

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

Referenced by XLogRegisterBuffer().

◆ BufferIsPermanent()

bool BufferIsPermanent ( Buffer  buffer)

Definition at line 3967 of file bufmgr.c.

3968 {
3969  BufferDesc *bufHdr;
3970 
3971  /* Local buffers are used only for temp relations. */
3972  if (BufferIsLocal(buffer))
3973  return false;
3974 
3975  /* Make sure we've got a real buffer, and that we hold a pin on it. */
3976  Assert(BufferIsValid(buffer));
3977  Assert(BufferIsPinned(buffer));
3978 
3979  /*
3980  * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
3981  * need not bother with the buffer header spinlock. Even if someone else
3982  * changes the buffer header state while we're doing this, the state is
3983  * changed atomically, so we'll read the old value or the new value, but
3984  * not random garbage.
3985  */
3986  bufHdr = GetBufferDescriptor(buffer - 1);
3987  return (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT) != 0;
3988 }
#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 351 of file bufmgr.h.

352 {
353  Assert(bufnum <= NBuffers);
354  Assert(bufnum >= -NLocBuffer);
355 
356  return bufnum != InvalidBuffer;
357 }
#define InvalidBuffer
Definition: buf.h:25
PGDLLIMPORT int NBuffers
Definition: globals.c:140
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 5218 of file bufmgr.c.

5219 {
5220  if (BufferIsLocal(buffer))
5221  {
5222  if (LocalRefCount[-buffer - 1] != 1)
5223  elog(ERROR, "incorrect local pin count: %d",
5224  LocalRefCount[-buffer - 1]);
5225  }
5226  else
5227  {
5228  if (GetPrivateRefCount(buffer) != 1)
5229  elog(ERROR, "incorrect local pin count: %d",
5230  GetPrivateRefCount(buffer));
5231  }
5232 }
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:443
#define ERROR
Definition: elog.h:39
int32 * LocalRefCount
Definition: localbuf.c:46

References BufferIsLocal, elog, ERROR, GetPrivateRefCount(), and LocalRefCount.

Referenced by GetVictimBuffer(), and LockBufferForCleanup().

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)

Definition at line 3722 of file bufmgr.c.

3723 {
3724  BufferSync(flags);
3725 }
static void BufferSync(int flags)
Definition: bufmgr.c:2924

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

Definition at line 5197 of file bufmgr.c.

5198 {
5199  BufferDesc *buf;
5200 
5201  Assert(BufferIsPinned(buffer));
5202  if (BufferIsLocal(buffer))
5203  return true; /* act as though we got it */
5204 
5205  buf = GetBufferDescriptor(buffer - 1);
5206 
5208  LW_EXCLUSIVE);
5209 }
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1339
static char * buf
Definition: pg_test_fsync.c:73

References Assert, buf, 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 5412 of file bufmgr.c.

5413 {
5414  BufferDesc *bufHdr;
5415  uint32 buf_state,
5416  refcount;
5417 
5418  Assert(BufferIsValid(buffer));
5419 
5420  if (BufferIsLocal(buffer))
5421  {
5422  refcount = LocalRefCount[-buffer - 1];
5423  /* There should be exactly one pin */
5424  Assert(refcount > 0);
5425  if (refcount != 1)
5426  return false;
5427  /* Nobody else to wait for */
5428  return true;
5429  }
5430 
5431  /* There should be exactly one local pin */
5432  refcount = GetPrivateRefCount(buffer);
5433  Assert(refcount);
5434  if (refcount != 1)
5435  return false;
5436 
5437  /* Try to acquire lock */
5438  if (!ConditionalLockBuffer(buffer))
5439  return false;
5440 
5441  bufHdr = GetBufferDescriptor(buffer - 1);
5442  buf_state = LockBufHdr(bufHdr);
5443  refcount = BUF_STATE_GET_REFCOUNT(buf_state);
5444 
5445  Assert(refcount > 0);
5446  if (refcount == 1)
5447  {
5448  /* Successfully acquired exclusive lock with pincount 1 */
5449  UnlockBufHdr(bufHdr, buf_state);
5450  return true;
5451  }
5452 
5453  /* Failed, so release the lock */
5454  UnlockBufHdr(bufHdr, buf_state);
5455  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
5456  return false;
5457 }
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:51
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:5197
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5171
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:189

References Assert, BUF_STATE_GET_REFCOUNT, BUFFER_LOCK_UNLOCK, BufferIsLocal, BufferIsValid(), ConditionalLockBuffer(), GetBufferDescriptor(), GetPrivateRefCount(), LocalRefCount, LockBuffer(), LockBufHdr(), 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 4810 of file bufmgr.c.

4812 {
4813  char relpersistence;
4814  SMgrRelation src_rel;
4815  SMgrRelation dst_rel;
4816 
4817  /* Set the relpersistence. */
4818  relpersistence = permanent ?
4819  RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
4820 
4821  src_rel = smgropen(src_rlocator, INVALID_PROC_NUMBER);
4822  dst_rel = smgropen(dst_rlocator, INVALID_PROC_NUMBER);
4823 
4824  /*
4825  * Create and copy all forks of the relation. During create database we
4826  * have a separate cleanup mechanism which deletes complete database
4827  * directory. Therefore, each individual relation doesn't need to be
4828  * registered for cleanup.
4829  */
4830  RelationCreateStorage(dst_rlocator, relpersistence, false);
4831 
4832  /* copy main fork. */
4833  RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, MAIN_FORKNUM,
4834  permanent);
4835 
4836  /* copy those extra forks that exist */
4837  for (ForkNumber forkNum = MAIN_FORKNUM + 1;
4838  forkNum <= MAX_FORKNUM; forkNum++)
4839  {
4840  if (smgrexists(src_rel, forkNum))
4841  {
4842  smgrcreate(dst_rel, forkNum, false);
4843 
4844  /*
4845  * WAL log creation if the relation is persistent, or this is the
4846  * init fork of an unlogged relation.
4847  */
4848  if (permanent || forkNum == INIT_FORKNUM)
4849  log_smgrcreate(&dst_rlocator, forkNum);
4850 
4851  /* Copy a fork's data, block by block. */
4852  RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, forkNum,
4853  permanent);
4854  }
4855  }
4856 }
static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, RelFileLocator dstlocator, ForkNumber forkNum, bool permanent)
Definition: bufmgr.c:4702
#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 3677 of file bufmgr.c.

3678 {
3679  BufferDesc *buf;
3680  int32 loccount;
3681  char *path;
3682  char *result;
3683  ProcNumber backend;
3684  uint32 buf_state;
3685 
3686  Assert(BufferIsValid(buffer));
3687  if (BufferIsLocal(buffer))
3688  {
3689  buf = GetLocalBufferDescriptor(-buffer - 1);
3690  loccount = LocalRefCount[-buffer - 1];
3691  backend = MyProcNumber;
3692  }
3693  else
3694  {
3695  buf = GetBufferDescriptor(buffer - 1);
3696  loccount = GetPrivateRefCount(buffer);
3697  backend = INVALID_PROC_NUMBER;
3698  }
3699 
3700  /* theoretically we should lock the bufhdr here */
3701  path = relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
3702  BufTagGetForkNum(&buf->tag));
3703  buf_state = pg_atomic_read_u32(&buf->state);
3704 
3705  result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
3706  buffer, path,
3707  buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
3708  BUF_STATE_GET_REFCOUNT(buf_state), loccount);
3709  pfree(path);
3710  return result;
3711 }
#define BUF_FLAG_MASK
Definition: buf_internals.h:48
ProcNumber MyProcNumber
Definition: globals.c:88
void pfree(void *pointer)
Definition: mcxt.c:1521
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 4398 of file bufmgr.c.

4399 {
4400  int i;
4401 
4402  /*
4403  * We needn't consider local buffers, since by assumption the target
4404  * database isn't our own.
4405  */
4406 
4407  for (i = 0; i < NBuffers; i++)
4408  {
4409  BufferDesc *bufHdr = GetBufferDescriptor(i);
4410  uint32 buf_state;
4411 
4412  /*
4413  * As in DropRelationBuffers, an unlocked precheck should be safe and
4414  * saves some cycles.
4415  */
4416  if (bufHdr->tag.dbOid != dbid)
4417  continue;
4418 
4419  buf_state = LockBufHdr(bufHdr);
4420  if (bufHdr->tag.dbOid == dbid)
4421  InvalidateBuffer(bufHdr); /* releases spinlock */
4422  else
4423  UnlockBufHdr(bufHdr, buf_state);
4424  }
4425 }
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1795
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 6109 of file bufmgr.c.

6110 {
6111  BufferDesc *desc;
6112  uint32 buf_state;
6113  bool result;
6114 
6115  /* Make sure we can pin the buffer. */
6118 
6120  desc = GetBufferDescriptor(buf - 1);
6121 
6122  /* Lock the header and check if it's valid. */
6123  buf_state = LockBufHdr(desc);
6124  if ((buf_state & BM_VALID) == 0)
6125  {
6126  UnlockBufHdr(desc, buf_state);
6127  return false;
6128  }
6129 
6130  /* Check that it's not pinned already. */
6131  if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
6132  {
6133  UnlockBufHdr(desc, buf_state);
6134  return false;
6135  }
6136 
6137  PinBuffer_Locked(desc); /* releases spinlock */
6138 
6139  /* If it was dirty, try to clean it once. */
6140  if (buf_state & BM_DIRTY)
6141  {
6145  }
6146 
6147  /* This will return false if it becomes dirty or someone else pins it. */
6148  result = InvalidateVictimBuffer(desc);
6149 
6150  UnpinBuffer(desc);
6151 
6152  return result;
6153 }
#define BM_VALID
Definition: buf_internals.h:62
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition: bufmgr.c:3796
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:2775
static bool InvalidateVictimBuffer(BufferDesc *buf_hdr)
Definition: bufmgr.c:1893
static void ReservePrivateRefCountEntry(void)
Definition: bufmgr.c:277
static void UnpinBuffer(BufferDesc *buf)
Definition: bufmgr.c:2818
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ 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 873 of file bufmgr.c.

877 {
878  Buffer buf;
879  uint32 extend_by = 1;
880 
881  ExtendBufferedRelBy(bmr, forkNum, strategy, flags, extend_by,
882  &buf, &extend_by);
883 
884  return buf;
885 }
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:905

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

912 {
913  Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
914  Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
915  Assert(extend_by > 0);
916 
917  if (bmr.smgr == NULL)
918  {
919  bmr.smgr = RelationGetSmgr(bmr.rel);
920  bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
921  }
922 
923  return ExtendBufferedRelCommon(bmr, fork, strategy, flags,
924  extend_by, InvalidBlockNumber,
925  buffers, extended_by);
926 }
#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:2158
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 937 of file bufmgr.c.

943 {
945  uint32 extended_by = 0;
946  Buffer buffer = InvalidBuffer;
947  Buffer buffers[64];
948 
949  Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
950  Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
951  Assert(extend_to != InvalidBlockNumber && extend_to > 0);
952 
953  if (bmr.smgr == NULL)
954  {
955  bmr.smgr = RelationGetSmgr(bmr.rel);
956  bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
957  }
958 
959  /*
960  * If desired, create the file if it doesn't exist. If
961  * smgr_cached_nblocks[fork] is positive then it must exist, no need for
962  * an smgrexists call.
963  */
964  if ((flags & EB_CREATE_FORK_IF_NEEDED) &&
965  (bmr.smgr->smgr_cached_nblocks[fork] == 0 ||
967  !smgrexists(bmr.smgr, fork))
968  {
970 
971  /* recheck, fork might have been created concurrently */
972  if (!smgrexists(bmr.smgr, fork))
973  smgrcreate(bmr.smgr, fork, flags & EB_PERFORMING_RECOVERY);
974 
976  }
977 
978  /*
979  * If requested, invalidate size cache, so that smgrnblocks asks the
980  * kernel.
981  */
982  if (flags & EB_CLEAR_SIZE_CACHE)
984 
985  /*
986  * Estimate how many pages we'll need to extend by. This avoids acquiring
987  * unnecessarily many victim buffers.
988  */
989  current_size = smgrnblocks(bmr.smgr, fork);
990 
991  /*
992  * Since no-one else can be looking at the page contents yet, there is no
993  * difference between an exclusive lock and a cleanup-strength lock. Note
994  * that we pass the original mode to ReadBuffer_common() below, when
995  * falling back to reading the buffer to a concurrent relation extension.
996  */
998  flags |= EB_LOCK_TARGET;
999 
1000  while (current_size < extend_to)
1001  {
1002  uint32 num_pages = lengthof(buffers);
1003  BlockNumber first_block;
1004 
1005  if ((uint64) current_size + num_pages > extend_to)
1006  num_pages = extend_to - current_size;
1007 
1008  first_block = ExtendBufferedRelCommon(bmr, fork, strategy, flags,
1009  num_pages, extend_to,
1010  buffers, &extended_by);
1011 
1012  current_size = first_block + extended_by;
1013  Assert(num_pages != 0 || current_size >= extend_to);
1014 
1015  for (uint32 i = 0; i < extended_by; i++)
1016  {
1017  if (first_block + i != extend_to - 1)
1018  ReleaseBuffer(buffers[i]);
1019  else
1020  buffer = buffers[i];
1021  }
1022  }
1023 
1024  /*
1025  * It's possible that another backend concurrently extended the relation.
1026  * In that case read the buffer.
1027  *
1028  * XXX: Should we control this via a flag?
1029  */
1030  if (buffer == InvalidBuffer)
1031  {
1032  Assert(extended_by == 0);
1033  buffer = ReadBuffer_common(bmr.rel, bmr.smgr, bmr.relpersistence,
1034  fork, extend_to - 1, mode, strategy);
1035  }
1036 
1037  return buffer;
1038 }
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:1217
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4936
#define lengthof(array)
Definition: c.h:788
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:420
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:470
#define ExclusiveLock
Definition: lockdefs.h:42
static PgChecksumMode mode
Definition: pg_checksums.c:56
static 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 4874 of file bufmgr.c.

4875 {
4876  int i;
4877  BufferDesc *bufHdr;
4878 
4879  for (i = 0; i < NBuffers; i++)
4880  {
4881  uint32 buf_state;
4882 
4883  bufHdr = GetBufferDescriptor(i);
4884 
4885  /*
4886  * As in DropRelationBuffers, an unlocked precheck should be safe and
4887  * saves some cycles.
4888  */
4889  if (bufHdr->tag.dbOid != dbid)
4890  continue;
4891 
4892  /* Make sure we can handle the pin */
4895 
4896  buf_state = LockBufHdr(bufHdr);
4897  if (bufHdr->tag.dbOid == dbid &&
4898  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4899  {
4900  PinBuffer_Locked(bufHdr);
4904  UnpinBuffer(bufHdr);
4905  }
4906  else
4907  UnlockBufHdr(bufHdr, buf_state);
4908  }
4909 }

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

4917 {
4918  BufferDesc *bufHdr;
4919 
4920  /* currently not needed, but no fundamental reason not to support */
4921  Assert(!BufferIsLocal(buffer));
4922 
4923  Assert(BufferIsPinned(buffer));
4924 
4925  bufHdr = GetBufferDescriptor(buffer - 1);
4926 
4928 
4930 }
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1893

References Assert, 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 4504 of file bufmgr.c.

4505 {
4506  int i;
4507  BufferDesc *bufHdr;
4508  SMgrRelation srel = RelationGetSmgr(rel);
4509 
4510  if (RelationUsesLocalBuffers(rel))
4511  {
4512  for (i = 0; i < NLocBuffer; i++)
4513  {
4514  uint32 buf_state;
4515  instr_time io_start;
4516 
4517  bufHdr = GetLocalBufferDescriptor(i);
4518  if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
4519  ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
4520  (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4521  {
4522  ErrorContextCallback errcallback;
4523  Page localpage;
4524 
4525  localpage = (char *) LocalBufHdrGetBlock(bufHdr);
4526 
4527  /* Setup error traceback support for ereport() */
4529  errcallback.arg = (void *) bufHdr;
4530  errcallback.previous = error_context_stack;
4531  error_context_stack = &errcallback;
4532 
4533  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
4534 
4536 
4537  smgrwrite(srel,
4538  BufTagGetForkNum(&bufHdr->tag),
4539  bufHdr->tag.blockNum,
4540  localpage,
4541  false);
4542 
4545  io_start, 1);
4546 
4547  buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED);
4548  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
4549 
4551 
4552  /* Pop the error context stack */
4553  error_context_stack = errcallback.previous;
4554  }
4555  }
4556 
4557  return;
4558  }
4559 
4560  for (i = 0; i < NBuffers; i++)
4561  {
4562  uint32 buf_state;
4563 
4564  bufHdr = GetBufferDescriptor(i);
4565 
4566  /*
4567  * As in DropRelationBuffers, an unlocked precheck should be safe and
4568  * saves some cycles.
4569  */
4570  if (!BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator))
4571  continue;
4572 
4573  /* Make sure we can handle the pin */
4576 
4577  buf_state = LockBufHdr(bufHdr);
4578  if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
4579  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4580  {
4581  PinBuffer_Locked(bufHdr);
4585  UnpinBuffer(bufHdr);
4586  }
4587  else
4588  UnlockBufHdr(bufHdr, buf_state);
4589  }
4590 }
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:288
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:170
#define LocalBufHdrGetBlock(bufHdr)
Definition: bufmgr.c:72
static void local_buffer_write_error_callback(void *arg)
Definition: bufmgr.c:5727
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_impl().

◆ 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:1347

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

5387 {
5388  int bufid = GetStartupBufferPinWaitBufId();
5389 
5390  /*
5391  * If we get woken slowly then it's possible that the Startup process was
5392  * already woken by other backends before we got here. Also possible that
5393  * we get here by multiple interrupts or interrupts at inappropriate
5394  * times, so make sure we do nothing if the bufid is not set.
5395  */
5396  if (bufid < 0)
5397  return false;
5398 
5399  if (GetPrivateRefCount(bufid + 1) > 0)
5400  return true;
5401 
5402  return false;
5403 }
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:671

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and ProcessRecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

Definition at line 4968 of file bufmgr.c.

4969 {
4970  Assert(BufferIsPinned(buffer));
4972  if (BufferIsLocal(buffer))
4973  LocalRefCount[-buffer - 1]++;
4974  else
4975  {
4976  PrivateRefCountEntry *ref;
4977 
4978  ref = GetPrivateRefCountEntry(buffer, true);
4979  Assert(ref != NULL);
4980  ref->refcount++;
4981  }
4983 }
static void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition: bufmgr.c:369

References Assert, 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:214
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:5916
int backend_flush_after
Definition: bufmgr.c:200
#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:707
@ 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 3588 of file bufmgr.c.

3589 {
3590  HASHCTL hash_ctl;
3591 
3592  memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
3593 
3594  hash_ctl.keysize = sizeof(int32);
3595  hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
3596 
3597  PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
3598  HASH_ELEM | HASH_BLOBS);
3599 
3600  /*
3601  * AtProcExit_Buffers needs LWLock access, and thereby has to be called at
3602  * the corresponding phase of backend shutdown.
3603  */
3604  Assert(MyProc != NULL);
3606 }
static void AtProcExit_Buffers(int code, Datum arg)
Definition: bufmgr.c:3613
struct PrivateRefCountEntry PrivateRefCountEntry
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition: bufmgr.c:235
static HTAB * PrivateRefCountHash
Definition: bufmgr.c:236
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 5468 of file bufmgr.c.

5469 {
5470  BufferDesc *bufHdr;
5471  uint32 buf_state;
5472 
5473  Assert(BufferIsValid(buffer));
5474 
5475  if (BufferIsLocal(buffer))
5476  {
5477  /* There should be exactly one pin */
5478  if (LocalRefCount[-buffer - 1] != 1)
5479  return false;
5480  /* Nobody else to wait for */
5481  return true;
5482  }
5483 
5484  /* There should be exactly one local pin */
5485  if (GetPrivateRefCount(buffer) != 1)
5486  return false;
5487 
5488  bufHdr = GetBufferDescriptor(buffer - 1);
5489 
5490  /* caller must hold exclusive lock on buffer */
5492  LW_EXCLUSIVE));
5493 
5494  buf_state = LockBufHdr(bufHdr);
5495 
5496  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5497  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
5498  {
5499  /* pincount is OK. */
5500  UnlockBufHdr(bufHdr, buf_state);
5501  return true;
5502  }
5503 
5504  UnlockBufHdr(bufHdr, buf_state);
5505  return false;
5506 }

References Assert, BUF_STATE_GET_REFCOUNT, 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:529
static int NLocalPinnedBuffers
Definition: localbuf.c:53

References NLocalPinnedBuffers, and num_temp_buffers.

Referenced by ExtendBufferedRelLocal(), and read_stream_begin_impl().

◆ LimitAdditionalPins()

void LimitAdditionalPins ( uint32 additional_pins)

Definition at line 2127 of file bufmgr.c.

2128 {
2129  uint32 max_backends;
2130  int max_proportional_pins;
2131 
2132  if (*additional_pins <= 1)
2133  return;
2134 
2135  max_backends = MaxBackends + NUM_AUXILIARY_PROCS;
2136  max_proportional_pins = NBuffers / max_backends;
2137 
2138  /*
2139  * Subtract the approximate number of buffers already pinned by this
2140  * backend. We get the number of "overflowed" pins for free, but don't
2141  * know the number of pins in PrivateRefCountArray. The cost of
2142  * calculating that exactly doesn't seem worth it, so just assume the max.
2143  */
2144  max_proportional_pins -= PrivateRefCountOverflowed + REFCOUNT_ARRAY_ENTRIES;
2145 
2146  if (max_proportional_pins <= 0)
2147  max_proportional_pins = 1;
2148 
2149  if (*additional_pins > max_proportional_pins)
2150  *additional_pins = max_proportional_pins;
2151 }
#define REFCOUNT_ARRAY_ENTRIES
Definition: bufmgr.c:96
int MaxBackends
Definition: globals.c:144
#define NUM_AUXILIARY_PROCS
Definition: proc.h:439

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

Referenced by ExtendBufferedRelShared(), and read_stream_begin_impl().

◆ LockBuffer()

void LockBuffer ( Buffer  buffer,
int  mode 
)

Definition at line 5171 of file bufmgr.c.

5172 {
5173  BufferDesc *buf;
5174 
5175  Assert(BufferIsPinned(buffer));
5176  if (BufferIsLocal(buffer))
5177  return; /* local buffers need no lock */
5178 
5179  buf = GetBufferDescriptor(buffer - 1);
5180 
5181  if (mode == BUFFER_LOCK_UNLOCK)
5183  else if (mode == BUFFER_LOCK_SHARE)
5185  else if (mode == BUFFER_LOCK_EXCLUSIVE)
5187  else
5188  elog(ERROR, "unrecognized buffer lock mode: %d", mode);
5189 }
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:190
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:191

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

◆ LockBufferForCleanup()

void LockBufferForCleanup ( Buffer  buffer)

Definition at line 5251 of file bufmgr.c.

5252 {
5253  BufferDesc *bufHdr;
5254  TimestampTz waitStart = 0;
5255  bool waiting = false;
5256  bool logged_recovery_conflict = false;
5257 
5258  Assert(BufferIsPinned(buffer));
5259  Assert(PinCountWaitBuf == NULL);
5260 
5261  CheckBufferIsPinnedOnce(buffer);
5262 
5263  /* Nobody else to wait for */
5264  if (BufferIsLocal(buffer))
5265  return;
5266 
5267  bufHdr = GetBufferDescriptor(buffer - 1);
5268 
5269  for (;;)
5270  {
5271  uint32 buf_state;
5272 
5273  /* Try to acquire lock */
5275  buf_state = LockBufHdr(bufHdr);
5276 
5277  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5278  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
5279  {
5280  /* Successfully acquired exclusive lock with pincount 1 */
5281  UnlockBufHdr(bufHdr, buf_state);
5282 
5283  /*
5284  * Emit the log message if recovery conflict on buffer pin was
5285  * resolved but the startup process waited longer than
5286  * deadlock_timeout for it.
5287  */
5288  if (logged_recovery_conflict)
5290  waitStart, GetCurrentTimestamp(),
5291  NULL, false);
5292 
5293  if (waiting)
5294  {
5295  /* reset ps display to remove the suffix if we added one */
5297  waiting = false;
5298  }
5299  return;
5300  }
5301  /* Failed, so mark myself as waiting for pincount 1 */
5302  if (buf_state & BM_PIN_COUNT_WAITER)
5303  {
5304  UnlockBufHdr(bufHdr, buf_state);
5305  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
5306  elog(ERROR, "multiple backends attempting to wait for pincount 1");
5307  }
5309  PinCountWaitBuf = bufHdr;
5310  buf_state |= BM_PIN_COUNT_WAITER;
5311  UnlockBufHdr(bufHdr, buf_state);
5312  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
5313 
5314  /* Wait to be signaled by UnpinBuffer() */
5315  if (InHotStandby)
5316  {
5317  if (!waiting)
5318  {
5319  /* adjust the process title to indicate that it's waiting */
5320  set_ps_display_suffix("waiting");
5321  waiting = true;
5322  }
5323 
5324  /*
5325  * Emit the log message if the startup process is waiting longer
5326  * than deadlock_timeout for recovery conflict on buffer pin.
5327  *
5328  * Skip this if first time through because the startup process has
5329  * not started waiting yet in this case. So, the wait start
5330  * timestamp is set after this logic.
5331  */
5332  if (waitStart != 0 && !logged_recovery_conflict)
5333  {
5335 
5336  if (TimestampDifferenceExceeds(waitStart, now,
5337  DeadlockTimeout))
5338  {
5340  waitStart, now, NULL, true);
5341  logged_recovery_conflict = true;
5342  }
5343  }
5344 
5345  /*
5346  * Set the wait start timestamp if logging is enabled and first
5347  * time through.
5348  */
5349  if (log_recovery_conflict_waits && waitStart == 0)
5350  waitStart = GetCurrentTimestamp();
5351 
5352  /* Publish the bufid that Startup process waits on */
5353  SetStartupBufferPinWaitBufId(buffer - 1);
5354  /* Set alarm and then wait to be signaled by UnpinBuffer() */
5356  /* Reset the published bufid */
5358  }
5359  else
5360  ProcWaitForSignal(WAIT_EVENT_BUFFER_PIN);
5361 
5362  /*
5363  * Remove flag marking us as waiter. Normally this will not be set
5364  * anymore, but ProcWaitForSignal() can return for other signals as
5365  * well. We take care to only reset the flag if we're the waiter, as
5366  * theoretically another backend could have started waiting. That's
5367  * impossible with the current usages due to table level locking, but
5368  * better be safe.
5369  */
5370  buf_state = LockBufHdr(bufHdr);
5371  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5373  buf_state &= ~BM_PIN_COUNT_WAITER;
5374  UnlockBufHdr(bufHdr, buf_state);
5375 
5376  PinCountWaitBuf = NULL;
5377  /* Loop back and try again */
5378  }
5379 }
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1791
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1655
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1619
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:67
void CheckBufferIsPinnedOnce(Buffer buffer)
Definition: bufmgr.c:5218
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:203
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:60

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

◆ MarkBufferDirty()

void MarkBufferDirty ( Buffer  buffer)

Definition at line 2543 of file bufmgr.c.

2544 {
2545  BufferDesc *bufHdr;
2546  uint32 buf_state;
2547  uint32 old_buf_state;
2548 
2549  if (!BufferIsValid(buffer))
2550  elog(ERROR, "bad buffer ID: %d", buffer);
2551 
2552  if (BufferIsLocal(buffer))
2553  {
2554  MarkLocalBufferDirty(buffer);
2555  return;
2556  }
2557 
2558  bufHdr = GetBufferDescriptor(buffer - 1);
2559 
2560  Assert(BufferIsPinned(buffer));
2562  LW_EXCLUSIVE));
2563 
2564  old_buf_state = pg_atomic_read_u32(&bufHdr->state);
2565  for (;;)
2566  {
2567  if (old_buf_state & BM_LOCKED)
2568  old_buf_state = WaitBufHdrUnlocked(bufHdr);
2569 
2570  buf_state = old_buf_state;
2571 
2572  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
2573  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
2574 
2575  if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
2576  buf_state))
2577  break;
2578  }
2579 
2580  /*
2581  * If the buffer was not dirty already, do vacuum accounting.
2582  */
2583  if (!(old_buf_state & BM_DIRTY))
2584  {
2585  VacuumPageDirty++;
2587  if (VacuumCostActive)
2589  }
2590 }
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:342
#define BM_LOCKED
Definition: buf_internals.h:60
static uint32 WaitBufHdrUnlocked(BufferDesc *buf)
Definition: bufmgr.c:5804
bool VacuumCostActive
Definition: globals.c:160
int64 VacuumPageDirty
Definition: globals.c:157
int VacuumCostBalance
Definition: globals.c:159
int VacuumCostPageDirty
Definition: globals.c:151
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 5000 of file bufmgr.c.

5001 {
5002  BufferDesc *bufHdr;
5003  Page page = BufferGetPage(buffer);
5004 
5005  if (!BufferIsValid(buffer))
5006  elog(ERROR, "bad buffer ID: %d", buffer);
5007 
5008  if (BufferIsLocal(buffer))
5009  {
5010  MarkLocalBufferDirty(buffer);
5011  return;
5012  }
5013 
5014  bufHdr = GetBufferDescriptor(buffer - 1);
5015 
5016  Assert(GetPrivateRefCount(buffer) > 0);
5017  /* here, either share or exclusive lock is OK */
5019 
5020  /*
5021  * This routine might get called many times on the same page, if we are
5022  * making the first scan after commit of an xact that added/deleted many
5023  * tuples. So, be as quick as we can if the buffer is already dirty. We
5024  * do this by not acquiring spinlock if it looks like the status bits are
5025  * already set. Since we make this test unlocked, there's a chance we
5026  * might fail to notice that the flags have just been cleared, and failed
5027  * to reset them, due to memory-ordering issues. But since this function
5028  * is only intended to be used in cases where failing to write out the
5029  * data would be harmless anyway, it doesn't really matter.
5030  */
5031  if ((pg_atomic_read_u32(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
5033  {
5035  bool dirtied = false;
5036  bool delayChkptFlags = false;
5037  uint32 buf_state;
5038 
5039  /*
5040  * If we need to protect hint bit updates from torn writes, WAL-log a
5041  * full page image of the page. This full page image is only necessary
5042  * if the hint bit update is the first change to the page since the
5043  * last checkpoint.
5044  *
5045  * We don't check full_page_writes here because that logic is included
5046  * when we call XLogInsert() since the value changes dynamically.
5047  */
5048  if (XLogHintBitIsNeeded() &&
5049  (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT))
5050  {
5051  /*
5052  * If we must not write WAL, due to a relfilelocator-specific
5053  * condition or being in recovery, don't dirty the page. We can
5054  * set the hint, just not dirty the page as a result so the hint
5055  * is lost when we evict the page or shutdown.
5056  *
5057  * See src/backend/storage/page/README for longer discussion.
5058  */
5059  if (RecoveryInProgress() ||
5061  return;
5062 
5063  /*
5064  * If the block is already dirty because we either made a change
5065  * or set a hint already, then we don't need to write a full page
5066  * image. Note that aggressive cleaning of blocks dirtied by hint
5067  * bit setting would increase the call rate. Bulk setting of hint
5068  * bits would reduce the call rate...
5069  *
5070  * We must issue the WAL record before we mark the buffer dirty.
5071  * Otherwise we might write the page before we write the WAL. That
5072  * causes a race condition, since a checkpoint might occur between
5073  * writing the WAL record and marking the buffer dirty. We solve
5074  * that with a kluge, but one that is already in use during
5075  * transaction commit to prevent race conditions. Basically, we
5076  * simply prevent the checkpoint WAL record from being written
5077  * until we have marked the buffer dirty. We don't start the
5078  * checkpoint flush until we have marked dirty, so our checkpoint
5079  * must flush the change to disk successfully or the checkpoint
5080  * never gets written, so crash recovery will fix.
5081  *
5082  * It's possible we may enter here without an xid, so it is
5083  * essential that CreateCheckPoint waits for virtual transactions
5084  * rather than full transactionids.
5085  */
5088  delayChkptFlags = true;
5089  lsn = XLogSaveBufferForHint(buffer, buffer_std);
5090  }
5091 
5092  buf_state = LockBufHdr(bufHdr);
5093 
5094  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5095 
5096  if (!(buf_state & BM_DIRTY))
5097  {
5098  dirtied = true; /* Means "will be dirtied by this action" */
5099 
5100  /*
5101  * Set the page LSN if we wrote a backup block. We aren't supposed
5102  * to set this when only holding a share lock but as long as we
5103  * serialise it somehow we're OK. We choose to set LSN while
5104  * holding the buffer header lock, which causes any reader of an
5105  * LSN who holds only a share lock to also obtain a buffer header
5106  * lock before using PageGetLSN(), which is enforced in
5107  * BufferGetLSNAtomic().
5108  *
5109  * If checksums are enabled, you might think we should reset the
5110  * checksum here. That will happen when the page is written
5111  * sometime later in this checkpoint cycle.
5112  */
5113  if (!XLogRecPtrIsInvalid(lsn))
5114  PageSetLSN(page, lsn);
5115  }
5116 
5117  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
5118  UnlockBufHdr(bufHdr, buf_state);
5119 
5120  if (delayChkptFlags)
5122 
5123  if (dirtied)
5124  {
5125  VacuumPageDirty++;
5127  if (VacuumCostActive)
5129  }
5130  }
5131 }
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:391
#define DELAY_CHKPT_START
Definition: proc.h:114
bool RelFileLocatorSkippingWAL(RelFileLocator rlocator)
Definition: storage.c:532
int delayChkptFlags
Definition: proc.h:235
bool RecoveryInProgress(void)
Definition: xlog.c:6304
#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, 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 666 of file bufmgr.c.

667 {
668  Assert(RelationIsValid(reln));
669  Assert(BlockNumberIsValid(blockNum));
670 
671  if (RelationUsesLocalBuffers(reln))
672  {
673  /* see comments in ReadBufferExtended */
674  if (RELATION_IS_OTHER_TEMP(reln))
675  ereport(ERROR,
676  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
677  errmsg("cannot access temporary tables of other sessions")));
678 
679  /* pass it off to localbuf.c */
680  return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
681  }
682  else
683  {
684  /* pass it to the shared buffer version */
685  return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
686  }
687 }
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:576
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#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 773 of file bufmgr.c.

774 {
775  return ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);
776 }
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:820

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

822 {
823  Buffer buf;
824 
825  /*
826  * Reject attempts to read non-local temporary relations; we would be
827  * likely to get wrong data since we have no visibility into the owning
828  * session's local buffers.
829  */
830  if (RELATION_IS_OTHER_TEMP(reln))
831  ereport(ERROR,
832  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
833  errmsg("cannot access temporary tables of other sessions")));
834 
835  /*
836  * Read the buffer, and update pgstat counters to reflect a cache hit or
837  * miss.
838  */
839  buf = ReadBuffer_common(reln, RelationGetSmgr(reln), 0,
840  forkNum, blockNum, mode, strategy);
841 
842  return buf;
843 }

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

860 {
861  SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
862 
863  return ReadBuffer_common(NULL, smgr,
864  permanent ? RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED,
865  forkNum, blockNum,
866  mode, strategy);
867 }

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

699 {
700  BufferDesc *bufHdr;
701  BufferTag tag;
702  uint32 buf_state;
703  bool have_private_ref;
704 
705  Assert(BufferIsValid(recent_buffer));
706 
709  InitBufferTag(&tag, &rlocator, forkNum, blockNum);
710 
711  if (BufferIsLocal(recent_buffer))
712  {
713  int b = -recent_buffer - 1;
714 
715  bufHdr = GetLocalBufferDescriptor(b);
716  buf_state = pg_atomic_read_u32(&bufHdr->state);
717 
718  /* Is it still valid and holding the right tag? */
719  if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
720  {
721  PinLocalBuffer(bufHdr, true);
722 
724 
725  return true;
726  }
727  }
728  else
729  {
730  bufHdr = GetBufferDescriptor(recent_buffer - 1);
731  have_private_ref = GetPrivateRefCount(recent_buffer) > 0;
732 
733  /*
734  * Do we already have this buffer pinned with a private reference? If
735  * so, it must be valid and it is safe to check the tag without
736  * locking. If not, we have to lock the header first and then check.
737  */
738  if (have_private_ref)
739  buf_state = pg_atomic_read_u32(&bufHdr->state);
740  else
741  buf_state = LockBufHdr(bufHdr);
742 
743  if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
744  {
745  /*
746  * It's now safe to pin the buffer. We can't pin first and ask
747  * questions later, because it might confuse code paths like
748  * InvalidateBuffer() if we pinned a random non-matching buffer.
749  */
750  if (have_private_ref)
751  PinBuffer(bufHdr, NULL); /* bump pin count */
752  else
753  PinBuffer_Locked(bufHdr); /* pin for first time */
754 
756 
757  return true;
758  }
759 
760  /* If we locked the header above, now unlock. */
761  if (!have_private_ref)
762  UnlockBufHdr(bufHdr, buf_state);
763  }
764 
765  return false;
766 }
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:2664
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 3935 of file bufmgr.c.

3936 {
3937  if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
3938  {
3939  /*
3940  * Not every table AM uses BLCKSZ wide fixed size blocks. Therefore
3941  * tableam returns the size in bytes - but for the purpose of this
3942  * routine, we want the number of blocks. Therefore divide, rounding
3943  * up.
3944  */
3945  uint64 szbytes;
3946 
3947  szbytes = table_relation_size(relation, forkNum);
3948 
3949  return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
3950  }
3951  else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
3952  {
3953  return smgrnblocks(RelationGetSmgr(relation), forkNum);
3954  }
3955  else
3956  Assert(false);
3957 
3958  return 0; /* keep compiler quiet */
3959 }
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition: tableam.h:1868

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

2609 {
2610  ForkNumber forkNum = MAIN_FORKNUM;
2611  BufferDesc *bufHdr;
2612 
2613  if (BufferIsValid(buffer))
2614  {
2615  Assert(BufferIsPinned(buffer));
2616  if (BufferIsLocal(buffer))
2617  {
2618  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2619  if (bufHdr->tag.blockNum == blockNum &&
2620  BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
2621  BufTagGetForkNum(&bufHdr->tag) == forkNum)
2622  return buffer;
2623  UnpinLocalBuffer(buffer);
2624  }
2625  else
2626  {
2627  bufHdr = GetBufferDescriptor(buffer - 1);
2628  /* we have pin, so it's ok to examine tag without spinlock */
2629  if (bufHdr->tag.blockNum == blockNum &&
2630  BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
2631  BufTagGetForkNum(&bufHdr->tag) == forkNum)
2632  return buffer;
2633  UnpinBuffer(bufHdr);
2634  }
2635  }
2636 
2637  return ReadBuffer(relation, blockNum);
2638 }
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:773
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 4936 of file bufmgr.c.

4937 {
4938  if (!BufferIsValid(buffer))
4939  elog(ERROR, "bad buffer ID: %d", buffer);
4940 
4941  if (BufferIsLocal(buffer))
4942  UnpinLocalBuffer(buffer);
4943  else
4944  UnpinBuffer(GetBufferDescriptor(buffer - 1));
4945 }

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

1396 {
1397  int nblocks = 1;
1398  bool result;
1399 
1400  result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags);
1401  Assert(nblocks == 1); /* single block can't be short */
1402 
1403  return result;
1404 }
static pg_attribute_always_inline bool StartReadBuffersImpl(ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, int flags)
Definition: bufmgr.c:1282

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

1382 {
1383  return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags);
1384 }

References StartReadBuffersImpl().

Referenced by read_stream_start_pending_read().

◆ UnlockBuffers()

void UnlockBuffers ( void  )

Definition at line 5143 of file bufmgr.c.

5144 {
5146 
5147  if (buf)
5148  {
5149  uint32 buf_state;
5150 
5151  buf_state = LockBufHdr(buf);
5152 
5153  /*
5154  * Don't complain if flag bit not set; it could have been reset but we
5155  * got a cancel/die interrupt before getting the signal.
5156  */
5157  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5158  buf->wait_backend_pgprocno == MyProcNumber)
5159  buf_state &= ~BM_PIN_COUNT_WAITER;
5160 
5161  UnlockBufHdr(buf, buf_state);
5162 
5163  PinCountWaitBuf = NULL;
5164  }
5165 }

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

4954 {
4955  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4956  ReleaseBuffer(buffer);
4957 }

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

1421 {
1422  Buffer *buffers;
1423  int nblocks;
1424  BlockNumber blocknum;
1425  ForkNumber forknum;
1426  IOContext io_context;
1427  IOObject io_object;
1428  char persistence;
1429 
1430  /*
1431  * Currently operations are only allowed to include a read of some range,
1432  * with an optional extra buffer that is already pinned at the end. So
1433  * nblocks can be at most one more than io_buffers_len.
1434  */
1435  Assert((operation->nblocks == operation->io_buffers_len) ||
1436  (operation->nblocks == operation->io_buffers_len + 1));
1437 
1438  /* Find the range of the physical read we need to perform. */
1439  nblocks = operation->io_buffers_len;
1440  if (nblocks == 0)
1441  return; /* nothing to do */
1442 
1443  buffers = &operation->buffers[0];
1444  blocknum = operation->blocknum;
1445  forknum = operation->forknum;
1446  persistence = operation->persistence;
1447 
1448  if (persistence == RELPERSISTENCE_TEMP)
1449  {
1450  io_context = IOCONTEXT_NORMAL;
1451  io_object = IOOBJECT_TEMP_RELATION;
1452  }
1453  else
1454  {
1455  io_context = IOContextForStrategy(operation->strategy);
1456  io_object = IOOBJECT_RELATION;
1457  }
1458 
1459  /*
1460  * We count all these blocks as read by this backend. This is traditional
1461  * behavior, but might turn out to be not true if we find that someone
1462  * else has beaten us and completed the read of some of these blocks. In
1463  * that case the system globally double-counts, but we traditionally don't
1464  * count this as a "hit", and we don't have a separate counter for "miss,
1465  * but another backend completed the read".
1466  */
1467  if (persistence == RELPERSISTENCE_TEMP)
1468  pgBufferUsage.local_blks_read += nblocks;
1469  else
1470  pgBufferUsage.shared_blks_read += nblocks;
1471 
1472  for (int i = 0; i < nblocks; ++i)
1473  {
1474  int io_buffers_len;
1475  Buffer io_buffers[MAX_IO_COMBINE_LIMIT];
1476  void *io_pages[MAX_IO_COMBINE_LIMIT];
1477  instr_time io_start;
1478  BlockNumber io_first_block;
1479 
1480  /*
1481  * Skip this block if someone else has already completed it. If an
1482  * I/O is already in progress in another backend, this will wait for
1483  * the outcome: either done, or something went wrong and we will
1484  * retry.
1485  */
1486  if (!WaitReadBuffersCanStartIO(buffers[i], false))
1487  {
1488  /*
1489  * Report this as a 'hit' for this backend, even though it must
1490  * have started out as a miss in PinBufferForBlock().
1491  */
1492  TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
1493  operation->smgr->smgr_rlocator.locator.spcOid,
1494  operation->smgr->smgr_rlocator.locator.dbOid,
1495  operation->smgr->smgr_rlocator.locator.relNumber,
1496  operation->smgr->smgr_rlocator.backend,
1497  true);
1498  continue;
1499  }
1500 
1501  /* We found a buffer that we need to read in. */
1502  io_buffers[0] = buffers[i];
1503  io_pages[0] = BufferGetBlock(buffers[i]);
1504  io_first_block = blocknum + i;
1505  io_buffers_len = 1;
1506 
1507  /*
1508  * How many neighboring-on-disk blocks can we can scatter-read into
1509  * other buffers at the same time? In this case we don't wait if we
1510  * see an I/O already in progress. We already hold BM_IO_IN_PROGRESS
1511  * for the head block, so we should get on with that I/O as soon as
1512  * possible. We'll come back to this block again, above.
1513  */
1514  while ((i + 1) < nblocks &&
1515  WaitReadBuffersCanStartIO(buffers[i + 1], true))
1516  {
1517  /* Must be consecutive block numbers. */
1518  Assert(BufferGetBlockNumber(buffers[i + 1]) ==
1519  BufferGetBlockNumber(buffers[i]) + 1);
1520 
1521  io_buffers[io_buffers_len] = buffers[++i];
1522  io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]);
1523  }
1524 
1526  smgrreadv(operation->smgr, forknum, io_first_block, io_pages, io_buffers_len);
1527  pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
1528  io_buffers_len);
1529 
1530  /* Verify each block we read, and terminate the I/O. */
1531  for (int j = 0; j < io_buffers_len; ++j)
1532  {
1533  BufferDesc *bufHdr;
1534  Block bufBlock;
1535 
1536  if (persistence == RELPERSISTENCE_TEMP)
1537  {
1538  bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1);
1539  bufBlock = LocalBufHdrGetBlock(bufHdr);
1540  }
1541  else
1542  {
1543  bufHdr = GetBufferDescriptor(io_buffers[j] - 1);
1544  bufBlock = BufHdrGetBlock(bufHdr);
1545  }
1546 
1547  /* check for garbage data */
1548  if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j,
1550  {
1551  if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages)
1552  {
1553  ereport(WARNING,
1555  errmsg("invalid page in block %u of relation %s; zeroing out page",
1556  io_first_block + j,
1557  relpath(operation->smgr->smgr_rlocator, forknum))));
1558  memset(bufBlock, 0, BLCKSZ);
1559  }
1560  else
1561  ereport(ERROR,
1563  errmsg("invalid page in block %u of relation %s",
1564  io_first_block + j,
1565  relpath(operation->smgr->smgr_rlocator, forknum))));
1566  }
1567 
1568  /* Terminate I/O and set BM_VALID. */
1569  if (persistence == RELPERSISTENCE_TEMP)
1570  {
1571  uint32 buf_state = pg_atomic_read_u32(&bufHdr->state);
1572 
1573  buf_state |= BM_VALID;
1574  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
1575  }
1576  else
1577  {
1578  /* Set BM_VALID, terminate IO, and wake up any waiters */
1579  TerminateBufferIO(bufHdr, false, BM_VALID, true);
1580  }
1581 
1582  /* Report I/Os as completing individually. */
1583  TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
1584  operation->smgr->smgr_rlocator.locator.spcOid,
1585  operation->smgr->smgr_rlocator.locator.dbOid,
1586  operation->smgr->smgr_rlocator.locator.relNumber,
1587  operation->smgr->smgr_rlocator.backend,
1588  false);
1589  }
1590 
1591  VacuumPageMiss += io_buffers_len;
1592  if (VacuumCostActive)
1593  VacuumCostBalance += VacuumCostPageMiss * io_buffers_len;
1594  }
1595 }
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3736
static bool WaitReadBuffersCanStartIO(Buffer buffer, bool nowait)
Definition: bufmgr.c:1407
bool zero_damaged_pages
Definition: bufmgr.c:167
static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits, bool forget_owner)
Definition: bufmgr.c:5628
#define BufHdrGetBlock(bufHdr)
Definition: bufmgr.c:68
#define READ_BUFFERS_ZERO_ON_ERROR
Definition: bufmgr.h:111
#define MAX_IO_COMBINE_LIMIT
Definition: bufmgr.h:164
bool PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags)
Definition: bufpage.c:88
#define PIV_LOG_WARNING
Definition: bufpage.h:468
#define PIV_REPORT_STAT
Definition: bufpage.h:469
#define WARNING
Definition: elog.h:36
IOContext IOContextForStrategy(BufferAccessStrategy strategy)
Definition: freelist.c:758
int VacuumCostPageMiss
Definition: globals.c:150
int64 VacuumPageMiss
Definition: globals.c:156
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:121
int16 io_buffers_len
Definition: bufmgr.h:133
Buffer * buffers
Definition: bufmgr.h:129
BufferAccessStrategy strategy
Definition: bufmgr.h:122
BlockNumber blocknum
Definition: bufmgr.h:130
struct SMgrRelationData * smgr
Definition: bufmgr.h:119
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(), ReadBuffersOperation::persistence, 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, READ_BUFFERS_ZERO_ON_ERROR, 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 200 of file bufmgr.c.

Referenced by InitBufferPool().

◆ bgwriter_flush_after

PGDLLIMPORT int bgwriter_flush_after
extern

Definition at line 199 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

PGDLLIMPORT int bgwriter_lru_maxpages
extern

Definition at line 168 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

PGDLLIMPORT double bgwriter_lru_multiplier
extern

Definition at line 169 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 198 of file bufmgr.c.

Referenced by BufferSync().

◆ effective_io_concurrency

PGDLLIMPORT int effective_io_concurrency
extern

◆ io_combine_limit

PGDLLIMPORT int io_combine_limit
extern

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

Referenced by mdreadv(), and WaitReadBuffers().