PostgreSQL Source Code  git master
bufmgr.h File Reference
#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
 

Macros

#define BMR_REL(p_rel)   ((BufferManagerRelation){.rel = p_rel})
 
#define BMR_SMGR(p_smgr, p_relpersistence)   ((BufferManagerRelation){.smgr = p_smgr, .relpersistence = p_relpersistence})
 
#define DEFAULT_EFFECTIVE_IO_CONCURRENCY   0
 
#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   0
 
#define MAX_IO_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
 

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)
 
void ReleaseBuffer (Buffer buffer)
 
void UnlockReleaseBuffer (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)
 
void PrintBufferLeakWarning (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)
 
void AbortBufferIO (Buffer buffer)
 
bool BgBufferSync (struct WritebackContext *wb_context)
 
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)
 
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 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 106 of file bufmgr.h.

◆ BMR_SMGR

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

Definition at line 107 of file bufmgr.h.

◆ BUFFER_LOCK_EXCLUSIVE

#define BUFFER_LOCK_EXCLUSIVE   2

Definition at line 159 of file bufmgr.h.

◆ BUFFER_LOCK_SHARE

#define BUFFER_LOCK_SHARE   1

Definition at line 158 of file bufmgr.h.

◆ BUFFER_LOCK_UNLOCK

#define BUFFER_LOCK_UNLOCK   0

Definition at line 157 of file bufmgr.h.

◆ DEFAULT_EFFECTIVE_IO_CONCURRENCY

#define DEFAULT_EFFECTIVE_IO_CONCURRENCY   0

Definition at line 130 of file bufmgr.h.

◆ DEFAULT_MAINTENANCE_IO_CONCURRENCY

#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   0

Definition at line 131 of file bufmgr.h.

◆ MAX_IO_CONCURRENCY

#define MAX_IO_CONCURRENCY   1000

Definition at line 149 of file bufmgr.h.

◆ P_NEW

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

Definition at line 152 of file bufmgr.h.

◆ RelationGetNumberOfBlocks

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

Definition at line 227 of file bufmgr.h.

Typedef Documentation

◆ Block

typedef void* Block

Definition at line 24 of file bufmgr.h.

◆ BufferAccessStrategyType

◆ BufferManagerRelation

◆ ExtendBufferedFlags

◆ PrefetchBufferResult

Enumeration Type Documentation

◆ BufferAccessStrategyType

Enumerator
BAS_NORMAL 
BAS_BULKREAD 
BAS_BULKWRITE 
BAS_VACUUM 

Definition at line 32 of file bufmgr.h.

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

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

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

◆ ReadBufferMode

Enumerator
RBM_NORMAL 
RBM_ZERO_AND_LOCK 
RBM_ZERO_AND_CLEANUP_LOCK 
RBM_ZERO_ON_ERROR 
RBM_NORMAL_NO_LOG 

Definition at line 42 of file bufmgr.h.

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

Function Documentation

◆ AbortBufferIO()

void AbortBufferIO ( Buffer  buffer)

Definition at line 5191 of file bufmgr.c.

5192 {
5193  BufferDesc *buf_hdr = GetBufferDescriptor(buffer - 1);
5194  uint32 buf_state;
5195 
5196  buf_state = LockBufHdr(buf_hdr);
5197  Assert(buf_state & (BM_IO_IN_PROGRESS | BM_TAG_VALID));
5198 
5199  if (!(buf_state & BM_VALID))
5200  {
5201  Assert(!(buf_state & BM_DIRTY));
5202  UnlockBufHdr(buf_hdr, buf_state);
5203  }
5204  else
5205  {
5206  Assert(buf_state & BM_DIRTY);
5207  UnlockBufHdr(buf_hdr, buf_state);
5208 
5209  /* Issue notice if this is not the first failure... */
5210  if (buf_state & BM_IO_ERROR)
5211  {
5212  /* Buffer is pinned, so we can read tag without spinlock */
5213  char *path;
5214 
5215  path = relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag),
5216  BufTagGetForkNum(&buf_hdr->tag));
5217  ereport(WARNING,
5218  (errcode(ERRCODE_IO_ERROR),
5219  errmsg("could not write block %u of %s",
5220  buf_hdr->tag.blockNum, path),
5221  errdetail("Multiple failures --- write error might be permanent.")));
5222  pfree(path);
5223  }
5224  }
5225 
5226  TerminateBufferIO(buf_hdr, false, BM_IO_ERROR);
5227 }
#define BM_TAG_VALID
Definition: buf_internals.h:62
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static BufferDesc * GetBufferDescriptor(uint32 id)
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
#define BM_DIRTY
Definition: buf_internals.h:60
#define BM_IO_IN_PROGRESS
Definition: buf_internals.h:63
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)
#define BM_VALID
Definition: buf_internals.h:61
#define BM_IO_ERROR
Definition: buf_internals.h:64
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:5300
static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits)
Definition: bufmgr.c:5160
unsigned int uint32
Definition: c.h:495
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define WARNING
Definition: elog.h:36
#define ereport(elevel,...)
Definition: elog.h:149
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1456
#define relpathperm(rlocator, forknum)
Definition: relpath.h:90
BufferTag tag
BlockNumber blockNum
Definition: buf_internals.h:97

References Assert(), buftag::blockNum, BM_DIRTY, BM_IO_ERROR, BM_IO_IN_PROGRESS, BM_TAG_VALID, BM_VALID, PrivateRefCountEntry::buffer, BufTagGetForkNum(), BufTagGetRelFileLocator(), ereport, errcode(), errdetail(), errmsg(), GetBufferDescriptor(), LockBufHdr(), pfree(), relpathperm, BufferDesc::tag, TerminateBufferIO(), UnlockBufHdr(), and WARNING.

Referenced by ResourceOwnerReleaseInternal().

◆ AtEOXact_Buffers()

void AtEOXact_Buffers ( bool  isCommit)

Definition at line 3132 of file bufmgr.c.

3133 {
3135 
3136  AtEOXact_LocalBuffers(isCommit);
3137 
3139 }
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:3192
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:198
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:802

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

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

◆ AtProcExit_LocalBuffers()

void AtProcExit_LocalBuffers ( void  )

Definition at line 813 of file localbuf.c.

814 {
815  /*
816  * We shouldn't be holding any remaining pins; if we are, and assertions
817  * aren't enabled, we'll fail later in DropRelationBuffers while trying to
818  * drop the temp rels.
819  */
821 }
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:773

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

◆ BgBufferSync()

bool BgBufferSync ( struct WritebackContext wb_context)

Definition at line 2758 of file bufmgr.c.

2759 {
2760  /* info obtained from freelist.c */
2761  int strategy_buf_id;
2762  uint32 strategy_passes;
2763  uint32 recent_alloc;
2764 
2765  /*
2766  * Information saved between calls so we can determine the strategy
2767  * point's advance rate and avoid scanning already-cleaned buffers.
2768  */
2769  static bool saved_info_valid = false;
2770  static int prev_strategy_buf_id;
2771  static uint32 prev_strategy_passes;
2772  static int next_to_clean;
2773  static uint32 next_passes;
2774 
2775  /* Moving averages of allocation rate and clean-buffer density */
2776  static float smoothed_alloc = 0;
2777  static float smoothed_density = 10.0;
2778 
2779  /* Potentially these could be tunables, but for now, not */
2780  float smoothing_samples = 16;
2781  float scan_whole_pool_milliseconds = 120000.0;
2782 
2783  /* Used to compute how far we scan ahead */
2784  long strategy_delta;
2785  int bufs_to_lap;
2786  int bufs_ahead;
2787  float scans_per_alloc;
2788  int reusable_buffers_est;
2789  int upcoming_alloc_est;
2790  int min_scan_buffers;
2791 
2792  /* Variables for the scanning loop proper */
2793  int num_to_scan;
2794  int num_written;
2795  int reusable_buffers;
2796 
2797  /* Variables for final smoothed_density update */
2798  long new_strategy_delta;
2799  uint32 new_recent_alloc;
2800 
2801  /*
2802  * Find out where the freelist clock sweep currently is, and how many
2803  * buffer allocations have happened since our last call.
2804  */
2805  strategy_buf_id = StrategySyncStart(&strategy_passes, &recent_alloc);
2806 
2807  /* Report buffer alloc counts to pgstat */
2808  PendingBgWriterStats.buf_alloc += recent_alloc;
2809 
2810  /*
2811  * If we're not running the LRU scan, just stop after doing the stats
2812  * stuff. We mark the saved state invalid so that we can recover sanely
2813  * if LRU scan is turned back on later.
2814  */
2815  if (bgwriter_lru_maxpages <= 0)
2816  {
2817  saved_info_valid = false;
2818  return true;
2819  }
2820 
2821  /*
2822  * Compute strategy_delta = how many buffers have been scanned by the
2823  * clock sweep since last time. If first time through, assume none. Then
2824  * see if we are still ahead of the clock sweep, and if so, how many
2825  * buffers we could scan before we'd catch up with it and "lap" it. Note:
2826  * weird-looking coding of xxx_passes comparisons are to avoid bogus
2827  * behavior when the passes counts wrap around.
2828  */
2829  if (saved_info_valid)
2830  {
2831  int32 passes_delta = strategy_passes - prev_strategy_passes;
2832 
2833  strategy_delta = strategy_buf_id - prev_strategy_buf_id;
2834  strategy_delta += (long) passes_delta * NBuffers;
2835 
2836  Assert(strategy_delta >= 0);
2837 
2838  if ((int32) (next_passes - strategy_passes) > 0)
2839  {
2840  /* we're one pass ahead of the strategy point */
2841  bufs_to_lap = strategy_buf_id - next_to_clean;
2842 #ifdef BGW_DEBUG
2843  elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
2844  next_passes, next_to_clean,
2845  strategy_passes, strategy_buf_id,
2846  strategy_delta, bufs_to_lap);
2847 #endif
2848  }
2849  else if (next_passes == strategy_passes &&
2850  next_to_clean >= strategy_buf_id)
2851  {
2852  /* on same pass, but ahead or at least not behind */
2853  bufs_to_lap = NBuffers - (next_to_clean - strategy_buf_id);
2854 #ifdef BGW_DEBUG
2855  elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
2856  next_passes, next_to_clean,
2857  strategy_passes, strategy_buf_id,
2858  strategy_delta, bufs_to_lap);
2859 #endif
2860  }
2861  else
2862  {
2863  /*
2864  * We're behind, so skip forward to the strategy point and start
2865  * cleaning from there.
2866  */
2867 #ifdef BGW_DEBUG
2868  elog(DEBUG2, "bgwriter behind: bgw %u-%u strategy %u-%u delta=%ld",
2869  next_passes, next_to_clean,
2870  strategy_passes, strategy_buf_id,
2871  strategy_delta);
2872 #endif
2873  next_to_clean = strategy_buf_id;
2874  next_passes = strategy_passes;
2875  bufs_to_lap = NBuffers;
2876  }
2877  }
2878  else
2879  {
2880  /*
2881  * Initializing at startup or after LRU scanning had been off. Always
2882  * start at the strategy point.
2883  */
2884 #ifdef BGW_DEBUG
2885  elog(DEBUG2, "bgwriter initializing: strategy %u-%u",
2886  strategy_passes, strategy_buf_id);
2887 #endif
2888  strategy_delta = 0;
2889  next_to_clean = strategy_buf_id;
2890  next_passes = strategy_passes;
2891  bufs_to_lap = NBuffers;
2892  }
2893 
2894  /* Update saved info for next time */
2895  prev_strategy_buf_id = strategy_buf_id;
2896  prev_strategy_passes = strategy_passes;
2897  saved_info_valid = true;
2898 
2899  /*
2900  * Compute how many buffers had to be scanned for each new allocation, ie,
2901  * 1/density of reusable buffers, and track a moving average of that.
2902  *
2903  * If the strategy point didn't move, we don't update the density estimate
2904  */
2905  if (strategy_delta > 0 && recent_alloc > 0)
2906  {
2907  scans_per_alloc = (float) strategy_delta / (float) recent_alloc;
2908  smoothed_density += (scans_per_alloc - smoothed_density) /
2909  smoothing_samples;
2910  }
2911 
2912  /*
2913  * Estimate how many reusable buffers there are between the current
2914  * strategy point and where we've scanned ahead to, based on the smoothed
2915  * density estimate.
2916  */
2917  bufs_ahead = NBuffers - bufs_to_lap;
2918  reusable_buffers_est = (float) bufs_ahead / smoothed_density;
2919 
2920  /*
2921  * Track a moving average of recent buffer allocations. Here, rather than
2922  * a true average we want a fast-attack, slow-decline behavior: we
2923  * immediately follow any increase.
2924  */
2925  if (smoothed_alloc <= (float) recent_alloc)
2926  smoothed_alloc = recent_alloc;
2927  else
2928  smoothed_alloc += ((float) recent_alloc - smoothed_alloc) /
2929  smoothing_samples;
2930 
2931  /* Scale the estimate by a GUC to allow more aggressive tuning. */
2932  upcoming_alloc_est = (int) (smoothed_alloc * bgwriter_lru_multiplier);
2933 
2934  /*
2935  * If recent_alloc remains at zero for many cycles, smoothed_alloc will
2936  * eventually underflow to zero, and the underflows produce annoying
2937  * kernel warnings on some platforms. Once upcoming_alloc_est has gone to
2938  * zero, there's no point in tracking smaller and smaller values of
2939  * smoothed_alloc, so just reset it to exactly zero to avoid this
2940  * syndrome. It will pop back up as soon as recent_alloc increases.
2941  */
2942  if (upcoming_alloc_est == 0)
2943  smoothed_alloc = 0;
2944 
2945  /*
2946  * Even in cases where there's been little or no buffer allocation
2947  * activity, we want to make a small amount of progress through the buffer
2948  * cache so that as many reusable buffers as possible are clean after an
2949  * idle period.
2950  *
2951  * (scan_whole_pool_milliseconds / BgWriterDelay) computes how many times
2952  * the BGW will be called during the scan_whole_pool time; slice the
2953  * buffer pool into that many sections.
2954  */
2955  min_scan_buffers = (int) (NBuffers / (scan_whole_pool_milliseconds / BgWriterDelay));
2956 
2957  if (upcoming_alloc_est < (min_scan_buffers + reusable_buffers_est))
2958  {
2959 #ifdef BGW_DEBUG
2960  elog(DEBUG2, "bgwriter: alloc_est=%d too small, using min=%d + reusable_est=%d",
2961  upcoming_alloc_est, min_scan_buffers, reusable_buffers_est);
2962 #endif
2963  upcoming_alloc_est = min_scan_buffers + reusable_buffers_est;
2964  }
2965 
2966  /*
2967  * Now write out dirty reusable buffers, working forward from the
2968  * next_to_clean point, until we have lapped the strategy scan, or cleaned
2969  * enough buffers to match our estimate of the next cycle's allocation
2970  * requirements, or hit the bgwriter_lru_maxpages limit.
2971  */
2972 
2973  /* Make sure we can handle the pin inside SyncOneBuffer */
2975 
2976  num_to_scan = bufs_to_lap;
2977  num_written = 0;
2978  reusable_buffers = reusable_buffers_est;
2979 
2980  /* Execute the LRU scan */
2981  while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
2982  {
2983  int sync_state = SyncOneBuffer(next_to_clean, true,
2984  wb_context);
2985 
2986  if (++next_to_clean >= NBuffers)
2987  {
2988  next_to_clean = 0;
2989  next_passes++;
2990  }
2991  num_to_scan--;
2992 
2993  if (sync_state & BUF_WRITTEN)
2994  {
2995  reusable_buffers++;
2996  if (++num_written >= bgwriter_lru_maxpages)
2997  {
2999  break;
3000  }
3001  }
3002  else if (sync_state & BUF_REUSABLE)
3003  reusable_buffers++;
3004  }
3005 
3006  PendingBgWriterStats.buf_written_clean += num_written;
3007 
3008 #ifdef BGW_DEBUG
3009  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",
3010  recent_alloc, smoothed_alloc, strategy_delta, bufs_ahead,
3011  smoothed_density, reusable_buffers_est, upcoming_alloc_est,
3012  bufs_to_lap - num_to_scan,
3013  num_written,
3014  reusable_buffers - reusable_buffers_est);
3015 #endif
3016 
3017  /*
3018  * Consider the above scan as being like a new allocation scan.
3019  * Characterize its density and update the smoothed one based on it. This
3020  * effectively halves the moving average period in cases where both the
3021  * strategy and the background writer are doing some useful scanning,
3022  * which is helpful because a long memory isn't as desirable on the
3023  * density estimates.
3024  */
3025  new_strategy_delta = bufs_to_lap - num_to_scan;
3026  new_recent_alloc = reusable_buffers - reusable_buffers_est;
3027  if (new_strategy_delta > 0 && new_recent_alloc > 0)
3028  {
3029  scans_per_alloc = (float) new_strategy_delta / (float) new_recent_alloc;
3030  smoothed_density += (scans_per_alloc - smoothed_density) /
3031  smoothing_samples;
3032 
3033 #ifdef BGW_DEBUG
3034  elog(DEBUG2, "bgwriter: cleaner density alloc=%u scan=%ld density=%.2f new smoothed=%.2f",
3035  new_recent_alloc, new_strategy_delta,
3036  scans_per_alloc, smoothed_density);
3037 #endif
3038  }
3039 
3040  /* Return true if OK to hibernate */
3041  return (bufs_to_lap == 0 && recent_alloc == 0);
3042 }
int BgWriterDelay
Definition: bgwriter.c:61
#define BUF_REUSABLE
Definition: bufmgr.c:72
double bgwriter_lru_multiplier
Definition: bufmgr.c:137
static int SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
Definition: bufmgr.c:3061
int bgwriter_lru_maxpages
Definition: bufmgr.c:136
#define BUF_WRITTEN
Definition: bufmgr.c:71
signed int int32
Definition: c.h:483
#define DEBUG2
Definition: elog.h:29
#define DEBUG1
Definition: elog.h:30
int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc)
Definition: freelist.c:394
int NBuffers
Definition: globals.c:136
PgStat_BgWriterStats PendingBgWriterStats
ResourceOwner CurrentResourceOwner
Definition: resowner.c:147
void ResourceOwnerEnlargeBuffers(ResourceOwner owner)
Definition: resowner.c:972
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, CurrentResourceOwner, DEBUG1, DEBUG2, elog(), PgStat_BgWriterStats::maxwritten_clean, NBuffers, PendingBgWriterStats, ResourceOwnerEnlargeBuffers(), StrategySyncStart(), and SyncOneBuffer().

Referenced by BackgroundWriterMain().

◆ BufferGetBlock()

static Block BufferGetBlock ( Buffer  buffer)
inlinestatic

Definition at line 317 of file bufmgr.h.

318 {
319  Assert(BufferIsValid(buffer));
320 
321  if (BufferIsLocal(buffer))
322  return LocalBufferBlockPointers[-buffer - 1];
323  else
324  return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
325 }
#define BufferIsLocal(buffer)
Definition: buf.h:37
PGDLLIMPORT Block * LocalBufferBlockPointers
Definition: localbuf.c:45
void * Block
Definition: bufmgr.h:24
PGDLLIMPORT char * BufferBlocks
Definition: buf_init.c:22
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:301
size_t Size
Definition: c.h:594

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

Referenced by BufferGetPage(), and XLogSaveBufferForHint().

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)

Definition at line 3290 of file bufmgr.c.

3291 {
3292  BufferDesc *bufHdr;
3293 
3294  Assert(BufferIsPinned(buffer));
3295 
3296  if (BufferIsLocal(buffer))
3297  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
3298  else
3299  bufHdr = GetBufferDescriptor(buffer - 1);
3300 
3301  /* pinned, so OK to read tag without spinlock */
3302  return bufHdr->tag.blockNum;
3303 }
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:438

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(), btbuildempty(), 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_hot_search_buffer(), heap_insert(), heap_multi_insert(), heap_page_is_all_visible(), heap_page_prune(), heap_prune_chain(), heap_update(), heap_xlog_confirm(), heap_xlog_lock(), index_compute_xid_horizon_for_tuples(), lazy_scan_noprune(), lazy_scan_prune(), makeSublist(), moveLeafs(), moveRightIfItNeeded(), pgstathashindex(), ReadBufferBI(), RelationAddBlocks(), RelationGetBufferForTuple(), RelationPutHeapTuple(), revmap_get_buffer(), revmap_physical_extend(), ScanSourceDatabasePgClassPage(), spgAddNodeAction(), spgbuild(), spgbuildempty(), spgdoinsert(), SpGistSetLastUsedPage(), spgSplitNodeAction(), spgWalk(), startScanEntry(), terminate_brin_buildstate(), vacuumLeafPage(), visibilitymap_clear(), visibilitymap_get_status(), visibilitymap_pin(), visibilitymap_pin_ok(), and visibilitymap_set().

◆ BufferGetLSNAtomic()

XLogRecPtr BufferGetLSNAtomic ( Buffer  buffer)

Definition at line 3551 of file bufmgr.c.

3552 {
3553  BufferDesc *bufHdr = GetBufferDescriptor(buffer - 1);
3554  char *page = BufferGetPage(buffer);
3555  XLogRecPtr lsn;
3556  uint32 buf_state;
3557 
3558  /*
3559  * If we don't need locking for correctness, fastpath out.
3560  */
3561  if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
3562  return PageGetLSN(page);
3563 
3564  /* Make sure we've got a real buffer, and that we hold a pin on it. */
3565  Assert(BufferIsValid(buffer));
3566  Assert(BufferIsPinned(buffer));
3567 
3568  buf_state = LockBufHdr(bufHdr);
3569  lsn = PageGetLSN(page);
3570  UnlockBufHdr(bufHdr, buf_state);
3571 
3572  return lsn;
3573 }
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:350
static XLogRecPtr PageGetLSN(Page page)
Definition: bufpage.h:383
#define XLogHintBitIsNeeded()
Definition: xlog.h:115
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 350 of file bufmgr.h.

351 {
352  return (Page) BufferGetBlock(buffer);
353 }
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:317
Pointer Page
Definition: bufpage.h:78

References BufferGetBlock().

Referenced by _bt_allocbuf(), _bt_binsrch(), _bt_binsrch_insert(), _bt_bottomupdel_pass(), _bt_check_unique(), _bt_checkpage(), _bt_clear_incomplete_split(), _bt_conditionallockbuf(), _bt_dedup_pass(), _bt_delete_or_dedup_one_page(), _bt_delitems_delete(), _bt_delitems_delete_check(), _bt_delitems_vacuum(), _bt_endpoint(), _bt_findinsertloc(), _bt_finish_split(), _bt_get_endpoint(), _bt_getmeta(), _bt_getroot(), _bt_getstackbuf(), _bt_gettrueroot(), _bt_insert_parent(), _bt_insertonpg(), _bt_killitems(), _bt_leftsib_splitflag(), _bt_lock_subtree_parent(), _bt_lockbuf(), _bt_mark_page_halfdead(), _bt_moveright(), _bt_newlevel(), _bt_pagedel(), _bt_readnextpage(), _bt_readpage(), _bt_restore_meta(), _bt_rightsib_halfdeadflag(), _bt_search(), _bt_search_insert(), _bt_set_cleanup_info(), _bt_simpledel_pass(), _bt_split(), _bt_stepright(), _bt_unlink_halfdead_page(), _bt_unlockbuf(), _bt_upgradelockbufcleanup(), _bt_vacuum_needs_cleanup(), _bt_walk_left(), _hash_addovflpage(), _hash_checkpage(), _hash_doinsert(), _hash_expandtable(), _hash_finish_split(), _hash_first(), _hash_freeovflpage(), _hash_get_newblock_from_oldbucket(), _hash_get_oldblock_from_newbucket(), _hash_getbucketbuf_from_hashkey(), _hash_getcachedmetap(), _hash_getinitbuf(), _hash_getnewbuf(), _hash_init(), _hash_init_metabuffer(), _hash_initbitmapbuffer(), _hash_initbuf(), _hash_kill_items(), _hash_pgaddmultitup(), _hash_pgaddtup(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), allocNewBuffer(), blgetbitmap(), blinsert(), BloomNewBuffer(), blvacuumcleanup(), brin_can_do_samepage_update(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_initialize_empty_new_buffer(), brin_page_cleanup(), brin_start_evacuating_page(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinGetStats(), brinGetTupleForHeapBlock(), brininsert(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), brinSetHeapBlockItemptr(), bt_metap(), bt_page_items_internal(), bt_recheck_sibling_links(), bt_rootdescend(), btbuildempty(), 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(), 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_execute_prepared(), 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(), heap_page_prune_execute(), heap_page_prune_opt(), heap_prune_chain(), heap_update(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_freeze_page(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune(), heap_xlog_update(), heap_xlog_vacuum(), 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(), heapgetpage(), 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_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(), spgbuildempty(), 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(), and xlogVacuumPage().

◆ BufferGetPageSize()

◆ BufferGetTag()

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

Definition at line 3311 of file bufmgr.c.

3313 {
3314  BufferDesc *bufHdr;
3315 
3316  /* Do the same checks as BufferGetBlockNumber. */
3317  Assert(BufferIsPinned(buffer));
3318 
3319  if (BufferIsLocal(buffer))
3320  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
3321  else
3322  bufHdr = GetBufferDescriptor(buffer - 1);
3323 
3324  /* pinned, so OK to read tag without spinlock */
3325  *rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
3326  *forknum = BufTagGetForkNum(&bufHdr->tag);
3327  *blknum = bufHdr->tag.blockNum;
3328 }

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

◆ BufferIsPermanent()

bool BufferIsPermanent ( Buffer  buffer)

Definition at line 3521 of file bufmgr.c.

3522 {
3523  BufferDesc *bufHdr;
3524 
3525  /* Local buffers are used only for temp relations. */
3526  if (BufferIsLocal(buffer))
3527  return false;
3528 
3529  /* Make sure we've got a real buffer, and that we hold a pin on it. */
3530  Assert(BufferIsValid(buffer));
3531  Assert(BufferIsPinned(buffer));
3532 
3533  /*
3534  * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
3535  * need not bother with the buffer header spinlock. Even if someone else
3536  * changes the buffer header state while we're doing this, the state is
3537  * changed atomically, so we'll read the old value or the new value, but
3538  * not random garbage.
3539  */
3540  bufHdr = GetBufferDescriptor(buffer - 1);
3541  return (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT) != 0;
3542 }
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:236
#define BM_PERMANENT
Definition: buf_internals.h:68
pg_atomic_uint32 state

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

302 {
303  Assert(bufnum <= NBuffers);
304  Assert(bufnum >= -NLocBuffer);
305 
306  return bufnum != InvalidBuffer;
307 }
#define InvalidBuffer
Definition: buf.h:25
PGDLLIMPORT int NBuffers
Definition: globals.c:136
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(), 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_index_delete_tuples(), heap_lock_tuple(), heap_rescan(), heap_update(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_freeze_page(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune(), heap_xlog_update(), heap_xlog_vacuum(), heap_xlog_visible(), heapam_index_fetch_reset(), heapam_scan_sample_next_block(), heapam_tuple_lock(), heapam_tuple_satisfies_snapshot(), heapgetpage(), heapgettup(), heapgettup_continue_page(), heapgettup_pagemode(), heapgettup_start_page(), IsBufferCleanupOK(), lazy_scan_heap(), lazy_vacuum_heap_rel(), log_heap_visible(), MarkBufferDirty(), MarkBufferDirtyHint(), PrintBufferLeakWarning(), ReadRecentBuffer(), ReleaseAndReadBuffer(), ReleaseBuffer(), 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 */
165  size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
166  /* to allow aligning buffer descriptors */
167  size = add_size(size, PG_CACHE_LINE_SIZE);
168 
169  /* size of data pages, plus alignment padding */
170  size = add_size(size, PG_IO_ALIGN_SIZE);
171  size = add_size(size, mul_size(NBuffers, BLCKSZ));
172 
173  /* size of stuff controlled by freelist.c */
174  size = add_size(size, StrategyShmemSize());
175 
176  /* size of I/O condition variables */
177  size = add_size(size, mul_size(NBuffers,
179  /* to allow aligning the above */
180  size = add_size(size, PG_CACHE_LINE_SIZE);
181 
182  /* size of checkpoint sort array in bufmgr.c */
183  size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
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:502
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519

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

Referenced by CalculateShmemSize().

◆ CheckBufferIsPinnedOnce()

void CheckBufferIsPinnedOnce ( Buffer  buffer)

Definition at line 4762 of file bufmgr.c.

4763 {
4764  if (BufferIsLocal(buffer))
4765  {
4766  if (LocalRefCount[-buffer - 1] != 1)
4767  elog(ERROR, "incorrect local pin count: %d",
4768  LocalRefCount[-buffer - 1]);
4769  }
4770  else
4771  {
4772  if (GetPrivateRefCount(buffer) != 1)
4773  elog(ERROR, "incorrect local pin count: %d",
4774  GetPrivateRefCount(buffer));
4775  }
4776 }
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:380
#define ERROR
Definition: elog.h:39
int32 * LocalRefCount
Definition: localbuf.c:46

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

Referenced by GetVictimBuffer(), and LockBufferForCleanup().

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)

Definition at line 3276 of file bufmgr.c.

3277 {
3278  BufferSync(flags);
3279 }
static void BufferSync(int flags)
Definition: bufmgr.c:2479

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

Definition at line 4741 of file bufmgr.c.

4742 {
4743  BufferDesc *buf;
4744 
4745  Assert(BufferIsPinned(buffer));
4746  if (BufferIsLocal(buffer))
4747  return true; /* act as though we got it */
4748 
4749  buf = GetBufferDescriptor(buffer - 1);
4750 
4752  LW_EXCLUSIVE);
4753 }
static LWLock * BufferDescriptorGetContentLock(const BufferDesc *bdesc)
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1366
@ LW_EXCLUSIVE
Definition: lwlock.h:116
static char * buf
Definition: pg_test_fsync.c:67

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

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

◆ ConditionalLockBufferForCleanup()

bool ConditionalLockBufferForCleanup ( Buffer  buffer)

Definition at line 4956 of file bufmgr.c.

4957 {
4958  BufferDesc *bufHdr;
4959  uint32 buf_state,
4960  refcount;
4961 
4962  Assert(BufferIsValid(buffer));
4963 
4964  if (BufferIsLocal(buffer))
4965  {
4966  refcount = LocalRefCount[-buffer - 1];
4967  /* There should be exactly one pin */
4968  Assert(refcount > 0);
4969  if (refcount != 1)
4970  return false;
4971  /* Nobody else to wait for */
4972  return true;
4973  }
4974 
4975  /* There should be exactly one local pin */
4976  refcount = GetPrivateRefCount(buffer);
4977  Assert(refcount);
4978  if (refcount != 1)
4979  return false;
4980 
4981  /* Try to acquire lock */
4982  if (!ConditionalLockBuffer(buffer))
4983  return false;
4984 
4985  bufHdr = GetBufferDescriptor(buffer - 1);
4986  buf_state = LockBufHdr(bufHdr);
4987  refcount = BUF_STATE_GET_REFCOUNT(buf_state);
4988 
4989  Assert(refcount > 0);
4990  if (refcount == 1)
4991  {
4992  /* Successfully acquired exclusive lock with pincount 1 */
4993  UnlockBufHdr(bufHdr, buf_state);
4994  return true;
4995  }
4996 
4997  /* Failed, so release the lock */
4998  UnlockBufHdr(bufHdr, buf_state);
4999  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
5000  return false;
5001 }
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:50
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:4741
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4715
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:157

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

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

◆ CreateAndCopyRelationData()

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

Definition at line 4348 of file bufmgr.c.

4350 {
4351  RelFileLocatorBackend rlocator;
4352  char relpersistence;
4353 
4354  /* Set the relpersistence. */
4355  relpersistence = permanent ?
4356  RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
4357 
4358  /*
4359  * Create and copy all forks of the relation. During create database we
4360  * have a separate cleanup mechanism which deletes complete database
4361  * directory. Therefore, each individual relation doesn't need to be
4362  * registered for cleanup.
4363  */
4364  RelationCreateStorage(dst_rlocator, relpersistence, false);
4365 
4366  /* copy main fork. */
4367  RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, MAIN_FORKNUM,
4368  permanent);
4369 
4370  /* copy those extra forks that exist */
4371  for (ForkNumber forkNum = MAIN_FORKNUM + 1;
4372  forkNum <= MAX_FORKNUM; forkNum++)
4373  {
4374  if (smgrexists(smgropen(src_rlocator, InvalidBackendId), forkNum))
4375  {
4376  smgrcreate(smgropen(dst_rlocator, InvalidBackendId), forkNum, false);
4377 
4378  /*
4379  * WAL log creation if the relation is persistent, or this is the
4380  * init fork of an unlogged relation.
4381  */
4382  if (permanent || forkNum == INIT_FORKNUM)
4383  log_smgrcreate(&dst_rlocator, forkNum);
4384 
4385  /* Copy a fork's data, block by block. */
4386  RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, forkNum,
4387  permanent);
4388  }
4389  }
4390 
4391  /* close source and destination smgr if exists. */
4392  rlocator.backend = InvalidBackendId;
4393 
4394  rlocator.locator = src_rlocator;
4395  smgrcloserellocator(rlocator);
4396 
4397  rlocator.locator = dst_rlocator;
4398  smgrcloserellocator(rlocator);
4399 }
#define InvalidBackendId
Definition: backendid.h:23
static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, RelFileLocator dstlocator, ForkNumber forkNum, bool permanent)
Definition: bufmgr.c:4257
ForkNumber
Definition: relpath.h:48
@ MAIN_FORKNUM
Definition: relpath.h:50
@ INIT_FORKNUM
Definition: relpath.h:53
#define MAX_FORKNUM
Definition: relpath.h:62
void smgrcloserellocator(RelFileLocatorBackend rlocator)
Definition: smgr.c:351
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:374
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
Definition: smgr.c:150
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:251
SMgrRelation RelationCreateStorage(RelFileLocator rlocator, char relpersistence, bool register_delete)
Definition: storage.c:120
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
Definition: storage.c:185
RelFileLocator locator

References RelFileLocatorBackend::backend, INIT_FORKNUM, InvalidBackendId, RelFileLocatorBackend::locator, log_smgrcreate(), MAIN_FORKNUM, MAX_FORKNUM, RelationCopyStorageUsingBuffer(), RelationCreateStorage(), smgrcloserellocator(), smgrcreate(), smgrexists(), and smgropen().

Referenced by CreateDatabaseUsingWalLog().

◆ DropDatabaseBuffers()

void DropDatabaseBuffers ( Oid  dbid)

Definition at line 3952 of file bufmgr.c.

3953 {
3954  int i;
3955 
3956  /*
3957  * We needn't consider local buffers, since by assumption the target
3958  * database isn't our own.
3959  */
3960 
3961  for (i = 0; i < NBuffers; i++)
3962  {
3963  BufferDesc *bufHdr = GetBufferDescriptor(i);
3964  uint32 buf_state;
3965 
3966  /*
3967  * As in DropRelationBuffers, an unlocked precheck should be safe and
3968  * saves some cycles.
3969  */
3970  if (bufHdr->tag.dbOid != dbid)
3971  continue;
3972 
3973  buf_state = LockBufHdr(bufHdr);
3974  if (bufHdr->tag.dbOid == dbid)
3975  InvalidateBuffer(bufHdr); /* releases spinlock */
3976  else
3977  UnlockBufHdr(bufHdr, buf_state);
3978  }
3979 }
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1419
int i
Definition: isn.c:73
Oid dbOid
Definition: buf_internals.h:94

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 
)

◆ ExtendBufferedRel()

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

Definition at line 812 of file bufmgr.c.

816 {
817  Buffer buf;
818  uint32 extend_by = 1;
819 
820  ExtendBufferedRelBy(bmr, forkNum, strategy, flags, extend_by,
821  &buf, &extend_by);
822 
823  return buf;
824 }
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:844

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

851 {
852  Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
853  Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
854  Assert(extend_by > 0);
855 
856  if (bmr.smgr == NULL)
857  {
858  bmr.smgr = RelationGetSmgr(bmr.rel);
859  bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
860  }
861 
862  return ExtendBufferedRelCommon(bmr, fork, strategy, flags,
863  extend_by, InvalidBlockNumber,
864  buffers, extended_by);
865 }
#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:1782
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:572
struct SMgrRelationData * smgr
Definition: bufmgr.h:102
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 876 of file bufmgr.c.

882 {
884  uint32 extended_by = 0;
885  Buffer buffer = InvalidBuffer;
886  Buffer buffers[64];
887 
888  Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
889  Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
890  Assert(extend_to != InvalidBlockNumber && extend_to > 0);
891 
892  if (bmr.smgr == NULL)
893  {
894  bmr.smgr = RelationGetSmgr(bmr.rel);
895  bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
896  }
897 
898  /*
899  * If desired, create the file if it doesn't exist. If
900  * smgr_cached_nblocks[fork] is positive then it must exist, no need for
901  * an smgrexists call.
902  */
903  if ((flags & EB_CREATE_FORK_IF_NEEDED) &&
904  (bmr.smgr->smgr_cached_nblocks[fork] == 0 ||
906  !smgrexists(bmr.smgr, fork))
907  {
909 
910  /* could have been closed while waiting for lock */
911  if (bmr.rel)
912  bmr.smgr = RelationGetSmgr(bmr.rel);
913 
914  /* recheck, fork might have been created concurrently */
915  if (!smgrexists(bmr.smgr, fork))
916  smgrcreate(bmr.smgr, fork, flags & EB_PERFORMING_RECOVERY);
917 
919  }
920 
921  /*
922  * If requested, invalidate size cache, so that smgrnblocks asks the
923  * kernel.
924  */
925  if (flags & EB_CLEAR_SIZE_CACHE)
927 
928  /*
929  * Estimate how many pages we'll need to extend by. This avoids acquiring
930  * unnecessarily many victim buffers.
931  */
932  current_size = smgrnblocks(bmr.smgr, fork);
933 
934  /*
935  * Since no-one else can be looking at the page contents yet, there is no
936  * difference between an exclusive lock and a cleanup-strength lock. Note
937  * that we pass the original mode to ReadBuffer_common() below, when
938  * falling back to reading the buffer to a concurrent relation extension.
939  */
941  flags |= EB_LOCK_TARGET;
942 
943  while (current_size < extend_to)
944  {
945  uint32 num_pages = lengthof(buffers);
946  BlockNumber first_block;
947 
948  if ((uint64) current_size + num_pages > extend_to)
949  num_pages = extend_to - current_size;
950 
951  first_block = ExtendBufferedRelCommon(bmr, fork, strategy, flags,
952  num_pages, extend_to,
953  buffers, &extended_by);
954 
955  current_size = first_block + extended_by;
956  Assert(num_pages != 0 || current_size >= extend_to);
957 
958  for (uint32 i = 0; i < extended_by; i++)
959  {
960  if (first_block + i != extend_to - 1)
961  ReleaseBuffer(buffers[i]);
962  else
963  buffer = buffers[i];
964  }
965  }
966 
967  /*
968  * It's possible that another backend concurrently extended the relation.
969  * In that case read the buffer.
970  *
971  * XXX: Should we control this via a flag?
972  */
973  if (buffer == InvalidBuffer)
974  {
975  bool hit;
976 
977  Assert(extended_by == 0);
978  buffer = ReadBuffer_common(bmr.smgr, bmr.relpersistence,
979  fork, extend_to - 1, mode, strategy,
980  &hit);
981  }
982 
983  return buffer;
984 }
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4480
static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool *hit)
Definition: bufmgr.c:992
#define lengthof(array)
Definition: c.h:777
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:431
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:481
#define ExclusiveLock
Definition: lockdefs.h:42
static PgChecksumMode mode
Definition: pg_checksums.c:56
int64 current_size
Definition: pg_checksums.c:64
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:609
BlockNumber smgr_cached_nblocks[MAX_FORKNUM+1]
Definition: smgr.h:54

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

4418 {
4419  int i;
4420  BufferDesc *bufHdr;
4421 
4422  /* Make sure we can handle the pin inside the loop */
4424 
4425  for (i = 0; i < NBuffers; i++)
4426  {
4427  uint32 buf_state;
4428 
4429  bufHdr = GetBufferDescriptor(i);
4430 
4431  /*
4432  * As in DropRelationBuffers, an unlocked precheck should be safe and
4433  * saves some cycles.
4434  */
4435  if (bufHdr->tag.dbOid != dbid)
4436  continue;
4437 
4439 
4440  buf_state = LockBufHdr(bufHdr);
4441  if (bufHdr->tag.dbOid == dbid &&
4442  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4443  {
4444  PinBuffer_Locked(bufHdr);
4448  UnpinBuffer(bufHdr);
4449  }
4450  else
4451  UnlockBufHdr(bufHdr, buf_state);
4452  }
4453 }
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition: bufmgr.c:3350
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:2336
static void ReservePrivateRefCountEntry(void)
Definition: bufmgr.c:214
static void UnpinBuffer(BufferDesc *buf)
Definition: bufmgr.c:2379
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1808
@ LW_SHARED
Definition: lwlock.h:117
@ IOOBJECT_RELATION
Definition: pgstat.h:278
@ IOCONTEXT_NORMAL
Definition: pgstat.h:288

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(), ResourceOwnerEnlargeBuffers(), BufferDesc::tag, UnlockBufHdr(), and UnpinBuffer().

Referenced by dbase_redo().

◆ FlushOneBuffer()

void FlushOneBuffer ( Buffer  buffer)

Definition at line 4460 of file bufmgr.c.

4461 {
4462  BufferDesc *bufHdr;
4463 
4464  /* currently not needed, but no fundamental reason not to support */
4465  Assert(!BufferIsLocal(buffer));
4466 
4467  Assert(BufferIsPinned(buffer));
4468 
4469  bufHdr = GetBufferDescriptor(buffer - 1);
4470 
4472 
4474 }
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1920

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

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

◆ FlushRelationBuffers()

void FlushRelationBuffers ( Relation  rel)

Definition at line 4058 of file bufmgr.c.

4059 {
4060  int i;
4061  BufferDesc *bufHdr;
4062 
4063  if (RelationUsesLocalBuffers(rel))
4064  {
4065  for (i = 0; i < NLocBuffer; i++)
4066  {
4067  uint32 buf_state;
4068  instr_time io_start;
4069 
4070  bufHdr = GetLocalBufferDescriptor(i);
4071  if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
4072  ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
4073  (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4074  {
4075  ErrorContextCallback errcallback;
4076  Page localpage;
4077 
4078  localpage = (char *) LocalBufHdrGetBlock(bufHdr);
4079 
4080  /* Setup error traceback support for ereport() */
4082  errcallback.arg = (void *) bufHdr;
4083  errcallback.previous = error_context_stack;
4084  error_context_stack = &errcallback;
4085 
4086  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
4087 
4088  io_start = pgstat_prepare_io_time();
4089 
4091  BufTagGetForkNum(&bufHdr->tag),
4092  bufHdr->tag.blockNum,
4093  localpage,
4094  false);
4095 
4098  io_start, 1);
4099 
4100  buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED);
4101  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
4102 
4104 
4105  /* Pop the error context stack */
4106  error_context_stack = errcallback.previous;
4107  }
4108  }
4109 
4110  return;
4111  }
4112 
4113  /* Make sure we can handle the pin inside the loop */
4115 
4116  for (i = 0; i < NBuffers; i++)
4117  {
4118  uint32 buf_state;
4119 
4120  bufHdr = GetBufferDescriptor(i);
4121 
4122  /*
4123  * As in DropRelationBuffers, an unlocked precheck should be safe and
4124  * saves some cycles.
4125  */
4126  if (!BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator))
4127  continue;
4128 
4130 
4131  buf_state = LockBufHdr(bufHdr);
4132  if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
4133  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4134  {
4135  PinBuffer_Locked(bufHdr);
4139  UnpinBuffer(bufHdr);
4140  }
4141  else
4142  UnlockBufHdr(bufHdr, buf_state);
4143  }
4144 }
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:272
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
#define BM_JUST_DIRTIED
Definition: buf_internals.h:65
#define LocalBufHdrGetBlock(bufHdr)
Definition: bufmgr.c:67
static void local_buffer_write_error_callback(void *arg)
Definition: bufmgr.c:5253
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1542
ErrorContextCallback * error_context_stack
Definition: elog.c:95
BufferUsage pgBufferUsage
Definition: instrument.c:20
int NLocBuffer
Definition: localbuf.c:42
@ IOOBJECT_TEMP_RELATION
Definition: pgstat.h:279
@ IOOP_WRITE
Definition: pgstat.h:302
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:112
instr_time pgstat_prepare_io_time(void)
Definition: pgstat_io.c:96
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:638
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition: smgr.c:584
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(), ResourceOwnerEnlargeBuffers(), smgrwrite(), BufferDesc::state, BufferDesc::tag, 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 639 of file freelist.c.

640 {
641  /* don't crash if called on a "default" strategy */
642  if (strategy != NULL)
643  pfree(strategy);
644 }

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 = 256;
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().

◆ 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:993
void * palloc0(Size size)
Definition: mcxt.c:1257
BufferAccessStrategyType btype
Definition: freelist.c:75

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

4931 {
4932  int bufid = GetStartupBufferPinWaitBufId();
4933 
4934  /*
4935  * If we get woken slowly then it's possible that the Startup process was
4936  * already woken by other backends before we got here. Also possible that
4937  * we get here by multiple interrupts or interrupts at inappropriate
4938  * times, so make sure we do nothing if the bufid is not set.
4939  */
4940  if (bufid < 0)
4941  return false;
4942 
4943  if (GetPrivateRefCount(bufid + 1) > 0)
4944  return true;
4945 
4946  return false;
4947 }
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:639

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and ProcessRecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

Definition at line 4512 of file bufmgr.c.

4513 {
4514  Assert(BufferIsPinned(buffer));
4516  if (BufferIsLocal(buffer))
4517  LocalRefCount[-buffer - 1]++;
4518  else
4519  {
4520  PrivateRefCountEntry *ref;
4521 
4522  ref = GetPrivateRefCountEntry(buffer, true);
4523  Assert(ref != NULL);
4524  ref->refcount++;
4525  }
4527 }
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition: bufmgr.c:306
void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:985

References Assert(), PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, CurrentResourceOwner, GetPrivateRefCountEntry(), LocalRefCount, PrivateRefCountEntry::refcount, ResourceOwnerEnlargeBuffers(), 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_PGPROCNO;
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:218
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:5442
int backend_flush_after
Definition: bufmgr.c:161
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:793
void ConditionVariableInit(ConditionVariable *cv)
void StrategyInitialize(bool init)
Definition: freelist.c:474
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:730
@ LWTRANCHE_BUFFER_CONTENT
Definition: lwlock.h:189
#define INVALID_PGPROCNO
Definition: proc.h:85
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396

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

Referenced by CreateSharedMemoryAndSemaphores().

◆ InitBufferPoolAccess()

void InitBufferPoolAccess ( void  )

Definition at line 3149 of file bufmgr.c.

3150 {
3151  HASHCTL hash_ctl;
3152 
3153  memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
3154 
3155  hash_ctl.keysize = sizeof(int32);
3156  hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
3157 
3158  PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
3159  HASH_ELEM | HASH_BLOBS);
3160 
3161  /*
3162  * AtProcExit_Buffers needs LWLock access, and thereby has to be called at
3163  * the corresponding phase of backend shutdown.
3164  */
3165  Assert(MyProc != NULL);
3167 }
static void AtProcExit_Buffers(int code, Datum arg)
Definition: bufmgr.c:3174
struct PrivateRefCountEntry PrivateRefCountEntry
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition: bufmgr.c:196
static HTAB * PrivateRefCountHash
Definition: bufmgr.c:197
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
#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:361
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 5012 of file bufmgr.c.

5013 {
5014  BufferDesc *bufHdr;
5015  uint32 buf_state;
5016 
5017  Assert(BufferIsValid(buffer));
5018 
5019  if (BufferIsLocal(buffer))
5020  {
5021  /* There should be exactly one pin */
5022  if (LocalRefCount[-buffer - 1] != 1)
5023  return false;
5024  /* Nobody else to wait for */
5025  return true;
5026  }
5027 
5028  /* There should be exactly one local pin */
5029  if (GetPrivateRefCount(buffer) != 1)
5030  return false;
5031 
5032  bufHdr = GetBufferDescriptor(buffer - 1);
5033 
5034  /* caller must hold exclusive lock on buffer */
5036  LW_EXCLUSIVE));
5037 
5038  buf_state = LockBufHdr(bufHdr);
5039 
5040  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5041  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
5042  {
5043  /* pincount is OK. */
5044  UnlockBufHdr(bufHdr, buf_state);
5045  return true;
5046  }
5047 
5048  UnlockBufHdr(bufHdr, buf_state);
5049  return false;
5050 }
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1964

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

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

◆ LockBuffer()

void LockBuffer ( Buffer  buffer,
int  mode 
)

Definition at line 4715 of file bufmgr.c.

4716 {
4717  BufferDesc *buf;
4718 
4719  Assert(BufferIsPinned(buffer));
4720  if (BufferIsLocal(buffer))
4721  return; /* local buffers need no lock */
4722 
4723  buf = GetBufferDescriptor(buffer - 1);
4724 
4725  if (mode == BUFFER_LOCK_UNLOCK)
4727  else if (mode == BUFFER_LOCK_SHARE)
4729  else if (mode == BUFFER_LOCK_EXCLUSIVE)
4731  else
4732  elog(ERROR, "unrecognized buffer lock mode: %d", mode);
4733 }
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:158
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:159

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

Referenced by _bt_lockbuf(), _bt_unlockbuf(), _bt_upgradelockbufcleanup(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_finish_split(), _hash_first(), _hash_freeovflpage(), _hash_getbuf(), _hash_getbuf_with_strategy(), _hash_getcachedmetap(), _hash_init(), _hash_kill_items(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), blbulkdelete(), blgetbitmap(), blinsert(), BloomInitMetapage(), BloomNewBuffer(), blvacuumcleanup(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_page_cleanup(), bringetbitmap(), brinGetStats(), brinGetTupleForHeapBlock(), brininsert(), brinLockRevmapPageForUpdate(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), brinsummarize(), bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), bt_recheck_sibling_links(), collect_corrupt_items(), collect_visibility_data(), collectMatchBitmap(), ConditionalLockBufferForCleanup(), count_nondeletable_pages(), entryLoadMoreItems(), FreeSpaceMapPrepareTruncateRel(), fsm_readbuf(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), get_raw_page_internal(), GetVisibilityMapPins(), ginbulkdelete(), ginEntryInsert(), ginFindLeafPage(), ginFindParents(), 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_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(), heapgetpage(), 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(), spgbuildempty(), 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(), and XLogRecordPageWithFreeSpace().

◆ LockBufferForCleanup()

void LockBufferForCleanup ( Buffer  buffer)

Definition at line 4795 of file bufmgr.c.

4796 {
4797  BufferDesc *bufHdr;
4798  TimestampTz waitStart = 0;
4799  bool waiting = false;
4800  bool logged_recovery_conflict = false;
4801 
4802  Assert(BufferIsPinned(buffer));
4803  Assert(PinCountWaitBuf == NULL);
4804 
4805  CheckBufferIsPinnedOnce(buffer);
4806 
4807  /* Nobody else to wait for */
4808  if (BufferIsLocal(buffer))
4809  return;
4810 
4811  bufHdr = GetBufferDescriptor(buffer - 1);
4812 
4813  for (;;)
4814  {
4815  uint32 buf_state;
4816 
4817  /* Try to acquire lock */
4819  buf_state = LockBufHdr(bufHdr);
4820 
4821  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
4822  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
4823  {
4824  /* Successfully acquired exclusive lock with pincount 1 */
4825  UnlockBufHdr(bufHdr, buf_state);
4826 
4827  /*
4828  * Emit the log message if recovery conflict on buffer pin was
4829  * resolved but the startup process waited longer than
4830  * deadlock_timeout for it.
4831  */
4832  if (logged_recovery_conflict)
4834  waitStart, GetCurrentTimestamp(),
4835  NULL, false);
4836 
4837  if (waiting)
4838  {
4839  /* reset ps display to remove the suffix if we added one */
4841  waiting = false;
4842  }
4843  return;
4844  }
4845  /* Failed, so mark myself as waiting for pincount 1 */
4846  if (buf_state & BM_PIN_COUNT_WAITER)
4847  {
4848  UnlockBufHdr(bufHdr, buf_state);
4849  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4850  elog(ERROR, "multiple backends attempting to wait for pincount 1");
4851  }
4853  PinCountWaitBuf = bufHdr;
4854  buf_state |= BM_PIN_COUNT_WAITER;
4855  UnlockBufHdr(bufHdr, buf_state);
4856  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4857 
4858  /* Wait to be signaled by UnpinBuffer() */
4859  if (InHotStandby)
4860  {
4861  if (!waiting)
4862  {
4863  /* adjust the process title to indicate that it's waiting */
4864  set_ps_display_suffix("waiting");
4865  waiting = true;
4866  }
4867 
4868  /*
4869  * Emit the log message if the startup process is waiting longer
4870  * than deadlock_timeout for recovery conflict on buffer pin.
4871  *
4872  * Skip this if first time through because the startup process has
4873  * not started waiting yet in this case. So, the wait start
4874  * timestamp is set after this logic.
4875  */
4876  if (waitStart != 0 && !logged_recovery_conflict)
4877  {
4879 
4880  if (TimestampDifferenceExceeds(waitStart, now,
4881  DeadlockTimeout))
4882  {
4884  waitStart, now, NULL, true);
4885  logged_recovery_conflict = true;
4886  }
4887  }
4888 
4889  /*
4890  * Set the wait start timestamp if logging is enabled and first
4891  * time through.
4892  */
4893  if (log_recovery_conflict_waits && waitStart == 0)
4894  waitStart = GetCurrentTimestamp();
4895 
4896  /* Publish the bufid that Startup process waits on */
4897  SetStartupBufferPinWaitBufId(buffer - 1);
4898  /* Set alarm and then wait to be signaled by UnpinBuffer() */
4900  /* Reset the published bufid */
4902  }
4903  else
4904  ProcWaitForSignal(WAIT_EVENT_BUFFER_PIN);
4905 
4906  /*
4907  * Remove flag marking us as waiter. Normally this will not be set
4908  * anymore, but ProcWaitForSignal() can return for other signals as
4909  * well. We take care to only reset the flag if we're the waiter, as
4910  * theoretically another backend could have started waiting. That's
4911  * impossible with the current usages due to table level locking, but
4912  * better be safe.
4913  */
4914  buf_state = LockBufHdr(bufHdr);
4915  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
4917  buf_state &= ~BM_PIN_COUNT_WAITER;
4918  UnlockBufHdr(bufHdr, buf_state);
4919 
4920  PinCountWaitBuf = NULL;
4921  /* Loop back and try again */
4922  }
4923 }
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1719
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1583
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1547
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:66
void CheckBufferIsPinnedOnce(Buffer buffer)
Definition: bufmgr.c:4762
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:164
int64 TimestampTz
Definition: timestamp.h:39
static volatile sig_atomic_t waiting
Definition: latch.c:160
@ PROCSIG_RECOVERY_CONFLICT_BUFFERPIN
Definition: procsignal.h:47
void set_ps_display_remove_suffix(void)
Definition: ps_status.c:396
void set_ps_display_suffix(const char *suffix)
Definition: ps_status.c:344
int DeadlockTimeout
Definition: proc.c:58
void SetStartupBufferPinWaitBufId(int bufid)
Definition: proc.c:627
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1797
void ResolveRecoveryConflictWithBufferPin(void)
Definition: standby.c:793
bool log_recovery_conflict_waits
Definition: standby.c:43
void LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start, TimestampTz now, VirtualTransactionId *wait_list, bool still_waiting)
Definition: standby.c:274
int wait_backend_pgprocno
int pgprocno
Definition: proc.h:191
#define InHotStandby
Definition: xlogutils.h:57

References Assert(), BM_PIN_COUNT_WAITER, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferIsLocal, BufferIsPinned, CheckBufferIsPinnedOnce(), DeadlockTimeout, elog(), ERROR, GetBufferDescriptor(), GetCurrentTimestamp(), InHotStandby, LockBuffer(), LockBufHdr(), log_recovery_conflict_waits, LogRecoveryConflict(), MyProc, now(), PGPROC::pgprocno, 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(), ReadBuffer_common(), and XLogReadBufferForRedoExtended().

◆ MarkBufferDirty()

void MarkBufferDirty ( Buffer  buffer)

Definition at line 2111 of file bufmgr.c.

2112 {
2113  BufferDesc *bufHdr;
2114  uint32 buf_state;
2115  uint32 old_buf_state;
2116 
2117  if (!BufferIsValid(buffer))
2118  elog(ERROR, "bad buffer ID: %d", buffer);
2119 
2120  if (BufferIsLocal(buffer))
2121  {
2122  MarkLocalBufferDirty(buffer);
2123  return;
2124  }
2125 
2126  bufHdr = GetBufferDescriptor(buffer - 1);
2127 
2128  Assert(BufferIsPinned(buffer));
2130  LW_EXCLUSIVE));
2131 
2132  old_buf_state = pg_atomic_read_u32(&bufHdr->state);
2133  for (;;)
2134  {
2135  if (old_buf_state & BM_LOCKED)
2136  old_buf_state = WaitBufHdrUnlocked(bufHdr);
2137 
2138  buf_state = old_buf_state;
2139 
2140  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
2141  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
2142 
2143  if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
2144  buf_state))
2145  break;
2146  }
2147 
2148  /*
2149  * If the buffer was not dirty already, do vacuum accounting.
2150  */
2151  if (!(old_buf_state & BM_DIRTY))
2152  {
2153  VacuumPageDirty++;
2155  if (VacuumCostActive)
2157  }
2158 }
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:306
#define BM_LOCKED
Definition: buf_internals.h:59
static uint32 WaitBufHdrUnlocked(BufferDesc *buf)
Definition: bufmgr.c:5330
bool VacuumCostActive
Definition: globals.c:156
int64 VacuumPageDirty
Definition: globals.c:153
int VacuumCostBalance
Definition: globals.c:155
int VacuumCostPageDirty
Definition: globals.c:147
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:444
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(), btbuildempty(), 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(), do_setval(), doPickSplit(), 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_freeze_execute_prepared(), heap_inplace_update(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_prune(), heap_update(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_freeze_page(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune(), heap_xlog_update(), heap_xlog_vacuum(), heap_xlog_visible(), lazy_scan_heap(), lazy_scan_new_or_empty(), lazy_vacuum_heap_page(), log_newpage_range(), moveLeafs(), nextval_internal(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), revmap_physical_extend(), saveNodeLink(), seq_redo(), shiftList(), spgAddNodeAction(), spgbuild(), spgbuildempty(), 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 4544 of file bufmgr.c.

4545 {
4546  BufferDesc *bufHdr;
4547  Page page = BufferGetPage(buffer);
4548 
4549  if (!BufferIsValid(buffer))
4550  elog(ERROR, "bad buffer ID: %d", buffer);
4551 
4552  if (BufferIsLocal(buffer))
4553  {
4554  MarkLocalBufferDirty(buffer);
4555  return;
4556  }
4557 
4558  bufHdr = GetBufferDescriptor(buffer - 1);
4559 
4560  Assert(GetPrivateRefCount(buffer) > 0);
4561  /* here, either share or exclusive lock is OK */
4563 
4564  /*
4565  * This routine might get called many times on the same page, if we are
4566  * making the first scan after commit of an xact that added/deleted many
4567  * tuples. So, be as quick as we can if the buffer is already dirty. We
4568  * do this by not acquiring spinlock if it looks like the status bits are
4569  * already set. Since we make this test unlocked, there's a chance we
4570  * might fail to notice that the flags have just been cleared, and failed
4571  * to reset them, due to memory-ordering issues. But since this function
4572  * is only intended to be used in cases where failing to write out the
4573  * data would be harmless anyway, it doesn't really matter.
4574  */
4575  if ((pg_atomic_read_u32(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
4577  {
4579  bool dirtied = false;
4580  bool delayChkptFlags = false;
4581  uint32 buf_state;
4582 
4583  /*
4584  * If we need to protect hint bit updates from torn writes, WAL-log a
4585  * full page image of the page. This full page image is only necessary
4586  * if the hint bit update is the first change to the page since the
4587  * last checkpoint.
4588  *
4589  * We don't check full_page_writes here because that logic is included
4590  * when we call XLogInsert() since the value changes dynamically.
4591  */
4592  if (XLogHintBitIsNeeded() &&
4593  (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT))
4594  {
4595  /*
4596  * If we must not write WAL, due to a relfilelocator-specific
4597  * condition or being in recovery, don't dirty the page. We can
4598  * set the hint, just not dirty the page as a result so the hint
4599  * is lost when we evict the page or shutdown.
4600  *
4601  * See src/backend/storage/page/README for longer discussion.
4602  */
4603  if (RecoveryInProgress() ||
4605  return;
4606 
4607  /*
4608  * If the block is already dirty because we either made a change
4609  * or set a hint already, then we don't need to write a full page
4610  * image. Note that aggressive cleaning of blocks dirtied by hint
4611  * bit setting would increase the call rate. Bulk setting of hint
4612  * bits would reduce the call rate...
4613  *
4614  * We must issue the WAL record before we mark the buffer dirty.
4615  * Otherwise we might write the page before we write the WAL. That
4616  * causes a race condition, since a checkpoint might occur between
4617  * writing the WAL record and marking the buffer dirty. We solve
4618  * that with a kluge, but one that is already in use during
4619  * transaction commit to prevent race conditions. Basically, we
4620  * simply prevent the checkpoint WAL record from being written
4621  * until we have marked the buffer dirty. We don't start the
4622  * checkpoint flush until we have marked dirty, so our checkpoint
4623  * must flush the change to disk successfully or the checkpoint
4624  * never gets written, so crash recovery will fix.
4625  *
4626  * It's possible we may enter here without an xid, so it is
4627  * essential that CreateCheckPoint waits for virtual transactions
4628  * rather than full transactionids.
4629  */
4632  delayChkptFlags = true;
4633  lsn = XLogSaveBufferForHint(buffer, buffer_std);
4634  }
4635 
4636  buf_state = LockBufHdr(bufHdr);
4637 
4638  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
4639 
4640  if (!(buf_state & BM_DIRTY))
4641  {
4642  dirtied = true; /* Means "will be dirtied by this action" */
4643 
4644  /*
4645  * Set the page LSN if we wrote a backup block. We aren't supposed
4646  * to set this when only holding a share lock but as long as we
4647  * serialise it somehow we're OK. We choose to set LSN while
4648  * holding the buffer header lock, which causes any reader of an
4649  * LSN who holds only a share lock to also obtain a buffer header
4650  * lock before using PageGetLSN(), which is enforced in
4651  * BufferGetLSNAtomic().
4652  *
4653  * If checksums are enabled, you might think we should reset the
4654  * checksum here. That will happen when the page is written
4655  * sometime later in this checkpoint cycle.
4656  */
4657  if (!XLogRecPtrIsInvalid(lsn))
4658  PageSetLSN(page, lsn);
4659  }
4660 
4661  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
4662  UnlockBufHdr(bufHdr, buf_state);
4663 
4664  if (delayChkptFlags)
4666 
4667  if (dirtied)
4668  {
4669  VacuumPageDirty++;
4671  if (VacuumCostActive)
4673  }
4674  }
4675 }
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:388
#define DELAY_CHKPT_START
Definition: proc.h:119
bool RelFileLocatorSkippingWAL(RelFileLocator rlocator)
Definition: storage.c:550
int delayChkptFlags
Definition: proc.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:5948
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
Definition: xloginsert.c:1053

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

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

◆ PrefetchBuffer()

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

Definition at line 601 of file bufmgr.c.

602 {
603  Assert(RelationIsValid(reln));
604  Assert(BlockNumberIsValid(blockNum));
605 
606  if (RelationUsesLocalBuffers(reln))
607  {
608  /* see comments in ReadBufferExtended */
609  if (RELATION_IS_OTHER_TEMP(reln))
610  ereport(ERROR,
611  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
612  errmsg("cannot access temporary tables of other sessions")));
613 
614  /* pass it off to localbuf.c */
615  return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
616  }
617  else
618  {
619  /* pass it to the shared buffer version */
620  return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
621  }
622 }
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:511
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition: localbuf.c:69
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:659
#define RelationIsValid(relation)
Definition: rel.h:477

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

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

◆ PrefetchSharedBuffer()

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

◆ PrintBufferLeakWarning()

void PrintBufferLeakWarning ( Buffer  buffer)

Definition at line 3232 of file bufmgr.c.

3233 {
3234  BufferDesc *buf;
3235  int32 loccount;
3236  char *path;
3237  BackendId backend;
3238  uint32 buf_state;
3239 
3240  Assert(BufferIsValid(buffer));
3241  if (BufferIsLocal(buffer))
3242  {
3243  buf = GetLocalBufferDescriptor(-buffer - 1);
3244  loccount = LocalRefCount[-buffer - 1];
3245  backend = MyBackendId;
3246  }
3247  else
3248  {
3249  buf = GetBufferDescriptor(buffer - 1);
3250  loccount = GetPrivateRefCount(buffer);
3251  backend = InvalidBackendId;
3252  }
3253 
3254  /* theoretically we should lock the bufhdr here */
3255  path = relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
3256  BufTagGetForkNum(&buf->tag));
3257  buf_state = pg_atomic_read_u32(&buf->state);
3258  elog(WARNING,
3259  "buffer refcount leak: [%03d] "
3260  "(rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
3261  buffer, path,
3262  buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
3263  BUF_STATE_GET_REFCOUNT(buf_state), loccount);
3264  pfree(path);
3265 }
int BackendId
Definition: backendid.h:21
#define BUF_FLAG_MASK
Definition: buf_internals.h:47
BackendId MyBackendId
Definition: globals.c:85
#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(), elog(), GetBufferDescriptor(), GetLocalBufferDescriptor(), GetPrivateRefCount(), InvalidBackendId, LocalRefCount, MyBackendId, pfree(), pg_atomic_read_u32(), relpathbackend, and WARNING.

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

◆ ReadBuffer()

Buffer ReadBuffer ( Relation  reln,
BlockNumber  blockNum 
)

Definition at line 708 of file bufmgr.c.

709 {
710  return ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);
711 }
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:755

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 
)

Definition at line 755 of file bufmgr.c.

757 {
758  bool hit;
759  Buffer buf;
760 
761  /*
762  * Reject attempts to read non-local temporary relations; we would be
763  * likely to get wrong data since we have no visibility into the owning
764  * session's local buffers.
765  */
766  if (RELATION_IS_OTHER_TEMP(reln))
767  ereport(ERROR,
768  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
769  errmsg("cannot access temporary tables of other sessions")));
770 
771  /*
772  * Read the buffer, and update pgstat counters to reflect a cache hit or
773  * miss.
774  */
776  buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
777  forkNum, blockNum, mode, strategy, &hit);
778  if (hit)
780  return buf;
781 }
#define pgstat_count_buffer_read(rel)
Definition: pgstat.h:633
#define pgstat_count_buffer_hit(rel)
Definition: pgstat.h:638

References buf, ereport, errcode(), errmsg(), ERROR, mode, pgstat_count_buffer_hit, pgstat_count_buffer_read, RelationData::rd_rel, 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(), btbuildempty(), 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_analyze_next_block(), heapgetpage(), lazy_scan_heap(), lazy_vacuum_heap_rel(), log_newpage_range(), palloc_btree_page(), pg_prewarm(), pgstat_btree_page(), pgstat_gist_page(), pgstat_heap(), pgstathashindex(), pgstatindex_impl(), ReadBuffer(), ReadBufferBI(), spgbuildempty(), 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 795 of file bufmgr.c.

798 {
799  bool hit;
800 
801  SMgrRelation smgr = smgropen(rlocator, InvalidBackendId);
802 
803  return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
804  RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
805  mode, strategy, &hit);
806 }

References InvalidBackendId, 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 632 of file bufmgr.c.

634 {
635  BufferDesc *bufHdr;
636  BufferTag tag;
637  uint32 buf_state;
638  bool have_private_ref;
639 
640  Assert(BufferIsValid(recent_buffer));
641 
644  InitBufferTag(&tag, &rlocator, forkNum, blockNum);
645 
646  if (BufferIsLocal(recent_buffer))
647  {
648  int b = -recent_buffer - 1;
649 
650  bufHdr = GetLocalBufferDescriptor(b);
651  buf_state = pg_atomic_read_u32(&bufHdr->state);
652 
653  /* Is it still valid and holding the right tag? */
654  if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
655  {
656  PinLocalBuffer(bufHdr, true);
657 
659 
660  return true;
661  }
662  }
663  else
664  {
665  bufHdr = GetBufferDescriptor(recent_buffer - 1);
666  have_private_ref = GetPrivateRefCount(recent_buffer) > 0;
667 
668  /*
669  * Do we already have this buffer pinned with a private reference? If
670  * so, it must be valid and it is safe to check the tag without
671  * locking. If not, we have to lock the header first and then check.
672  */
673  if (have_private_ref)
674  buf_state = pg_atomic_read_u32(&bufHdr->state);
675  else
676  buf_state = LockBufHdr(bufHdr);
677 
678  if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
679  {
680  /*
681  * It's now safe to pin the buffer. We can't pin first and ask
682  * questions later, because it might confuse code paths like
683  * InvalidateBuffer() if we pinned a random non-matching buffer.
684  */
685  if (have_private_ref)
686  PinBuffer(bufHdr, NULL); /* bump pin count */
687  else
688  PinBuffer_Locked(bufHdr); /* pin for first time */
689 
691 
692  return true;
693  }
694 
695  /* If we locked the header above, now unlock. */
696  if (!have_private_ref)
697  UnlockBufHdr(bufHdr, buf_state);
698  }
699 
700  return false;
701 }
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:2231
int b
Definition: isn.c:70
bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
Definition: localbuf.c:648
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(), ResourceOwnerEnlargeBuffers(), BufferUsage::shared_blks_hit, BufferDesc::state, BufferDesc::tag, and UnlockBufHdr().

Referenced by XLogReadBufferExtended().

◆ RelationGetNumberOfBlocksInFork()

BlockNumber RelationGetNumberOfBlocksInFork ( Relation  relation,
ForkNumber  forkNum 
)

Definition at line 3489 of file bufmgr.c.

3490 {
3491  if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
3492  {
3493  /*
3494  * Not every table AM uses BLCKSZ wide fixed size blocks. Therefore
3495  * tableam returns the size in bytes - but for the purpose of this
3496  * routine, we want the number of blocks. Therefore divide, rounding
3497  * up.
3498  */
3499  uint64 szbytes;
3500 
3501  szbytes = table_relation_size(relation, forkNum);
3502 
3503  return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
3504  }
3505  else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
3506  {
3507  return smgrnblocks(RelationGetSmgr(relation), forkNum);
3508  }
3509  else
3510  Assert(false);
3511 
3512  return 0; /* keep compiler quiet */
3513 }
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition: tableam.h:1865

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

2177 {
2178  ForkNumber forkNum = MAIN_FORKNUM;
2179  BufferDesc *bufHdr;
2180 
2181  if (BufferIsValid(buffer))
2182  {
2183  Assert(BufferIsPinned(buffer));
2184  if (BufferIsLocal(buffer))
2185  {
2186  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2187  if (bufHdr->tag.blockNum == blockNum &&
2188  BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
2189  BufTagGetForkNum(&bufHdr->tag) == forkNum)
2190  return buffer;
2191  UnpinLocalBuffer(buffer);
2192  }
2193  else
2194  {
2195  bufHdr = GetBufferDescriptor(buffer - 1);
2196  /* we have pin, so it's ok to examine tag without spinlock */
2197  if (bufHdr->tag.blockNum == blockNum &&
2198  BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
2199  BufTagGetForkNum(&bufHdr->tag) == forkNum)
2200  return buffer;
2201  UnpinBuffer(bufHdr);
2202  }
2203  }
2204 
2205  return ReadBuffer(relation, blockNum);
2206 }
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:708
void UnpinLocalBuffer(Buffer buffer)
Definition: localbuf.c:674

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

4481 {
4482  if (!BufferIsValid(buffer))
4483  elog(ERROR, "bad buffer ID: %d", buffer);
4484 
4485  if (BufferIsLocal(buffer))
4486  UnpinLocalBuffer(buffer);
4487  else
4488  UnpinBuffer(GetBufferDescriptor(buffer - 1));
4489 }

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

Referenced by _bt_allocbuf(), _bt_drop_lock_and_maybe_pin(), _bt_pagedel(), _bt_relbuf(), _bt_search_insert(), _bt_unlink_halfdead_page(), _hash_dropbuf(), _hash_getbuf_with_condlock_cleanup(), autoprewarm_database_main(), blinsert(), BloomNewBuffer(), brin_getinsertbuffer(), brin_vacuum_scan(), bringetbitmap(), brinGetTupleForHeapBlock(), brininsert(), brinRevmapTerminate(), brinsummarize(), btbuildempty(), collect_corrupt_items(), collect_visibility_data(), entryLoadMoreItems(), ExecEndBitmapHeapScan(), ExecEndIndexOnlyScan(), ExecReScanBitmapHeapScan(), ExtendBufferedRelTo(), FreeBulkInsertState(), freeGinBtreeStack(), 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_force_common(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_rescan(), heap_update(), 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(), heapgetpage(), heapgettup(), heapgettup_pagemode(), lazy_scan_heap(), lazy_vacuum_heap_rel(), pg_prewarm(), pg_visibility(), pg_visibility_map(), pg_visibility_map_summary(), pgstatindex_impl(), ReadBufferBI(), RelationAddBlocks(), RelationGetBufferForTuple(), ReleaseBulkInsertStatePin(), ResourceOwnerReleaseInternal(), 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().

◆ UnlockBuffers()

void UnlockBuffers ( void  )

Definition at line 4687 of file bufmgr.c.

4688 {
4690 
4691  if (buf)
4692  {
4693  uint32 buf_state;
4694 
4695  buf_state = LockBufHdr(buf);
4696 
4697  /*
4698  * Don't complain if flag bit not set; it could have been reset but we
4699  * got a cancel/die interrupt before getting the signal.
4700  */
4701  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
4702  buf->wait_backend_pgprocno == MyProc->pgprocno)
4703  buf_state &= ~BM_PIN_COUNT_WAITER;
4704 
4705  UnlockBufHdr(buf, buf_state);
4706 
4707  PinCountWaitBuf = NULL;
4708  }
4709 }

References BM_PIN_COUNT_WAITER, buf, LockBufHdr(), MyProc, PGPROC::pgprocno, PinCountWaitBuf, and UnlockBufHdr().

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

◆ UnlockReleaseBuffer()

void UnlockReleaseBuffer ( Buffer  buffer)

Definition at line 4497 of file bufmgr.c.

4498 {
4499  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4500  ReleaseBuffer(buffer);
4501 }

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

Referenced by _bt_clear_incomplete_split(), _bt_restore_meta(), _hash_relbuf(), allocNewBuffer(), AlterSequence(), blbulkdelete(), blgetbitmap(), blinsert(), BloomInitMetapage(), blvacuumcleanup(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinGetStats(), brinRevmapDesummarizeRange(), bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), bt_recheck_sibling_links(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), collect_corrupt_items(), collect_visibility_data(), count_nondeletable_pages(), createPostingTree(), do_setval(), doPickSplit(), entryLoadMoreItems(), fill_seq_fork_with_data(), flushCachedPage(), FreeSpaceMapPrepareTruncateRel(), fsm_search(), fsm_set_and_search(), generic_redo(), ginbuild(), ginbuildempty(), ginbulkdelete(), ginFindParents(), 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_freeze_page(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune(), heap_xlog_update(), heap_xlog_vacuum(), 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(), spgbuildempty(), 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().

Variable Documentation

◆ backend_flush_after

PGDLLIMPORT int backend_flush_after
extern

Definition at line 161 of file bufmgr.c.

Referenced by InitBufferPool().

◆ bgwriter_flush_after

PGDLLIMPORT int bgwriter_flush_after
extern

Definition at line 160 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

PGDLLIMPORT int bgwriter_lru_maxpages
extern

Definition at line 136 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

PGDLLIMPORT double bgwriter_lru_multiplier
extern

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

Referenced by BufferSync().

◆ effective_io_concurrency

PGDLLIMPORT int effective_io_concurrency
extern

Definition at line 146 of file bufmgr.c.

Referenced by get_tablespace_io_concurrency(), and tablespace_reloptions().

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

Referenced by mdread(), and ReadBuffer_common().