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
 

Macros

#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
 

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
}
 

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)
 
Buffer ReleaseAndReadBuffer (Buffer buffer, Relation relation, BlockNumber blockNum)
 
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 (void)
 
bool BgBufferSync (struct WritebackContext *wb_context)
 
void TestForOldSnapshot_impl (Snapshot snapshot, Relation relation)
 
void InitBufferPool (void)
 
Size BufferShmemSize (void)
 
void AtProcExit_LocalBuffers (void)
 
BufferAccessStrategy GetAccessStrategy (BufferAccessStrategyType btype)
 
void FreeAccessStrategy (BufferAccessStrategy strategy)
 
static bool BufferIsValid (Buffer bufnum)
 
static Block BufferGetBlock (Buffer buffer)
 
static Size BufferGetPageSize (Buffer buffer)
 
static Page BufferGetPage (Buffer buffer)
 
static void TestForOldSnapshot (Snapshot snapshot, Relation relation, Page page)
 

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

◆ BUFFER_LOCK_EXCLUSIVE

#define BUFFER_LOCK_EXCLUSIVE   2

Definition at line 112 of file bufmgr.h.

◆ BUFFER_LOCK_SHARE

#define BUFFER_LOCK_SHARE   1

Definition at line 111 of file bufmgr.h.

◆ BUFFER_LOCK_UNLOCK

#define BUFFER_LOCK_UNLOCK   0

Definition at line 110 of file bufmgr.h.

◆ DEFAULT_EFFECTIVE_IO_CONCURRENCY

#define DEFAULT_EFFECTIVE_IO_CONCURRENCY   0

Definition at line 83 of file bufmgr.h.

◆ DEFAULT_MAINTENANCE_IO_CONCURRENCY

#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   0

Definition at line 84 of file bufmgr.h.

◆ MAX_IO_CONCURRENCY

#define MAX_IO_CONCURRENCY   1000

Definition at line 102 of file bufmgr.h.

◆ P_NEW

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

Definition at line 105 of file bufmgr.h.

◆ RelationGetNumberOfBlocks

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

Definition at line 161 of file bufmgr.h.

Typedef Documentation

◆ Block

typedef void* Block

Definition at line 24 of file bufmgr.h.

◆ BufferAccessStrategyType

◆ 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

◆ 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 ( void  )

Definition at line 4689 of file bufmgr.c.

4690 {
4692 
4693  if (buf)
4694  {
4695  uint32 buf_state;
4696 
4697  buf_state = LockBufHdr(buf);
4698  Assert(buf_state & BM_IO_IN_PROGRESS);
4699  if (IsForInput)
4700  {
4701  Assert(!(buf_state & BM_DIRTY));
4702 
4703  /* We'd better not think buffer is valid yet */
4704  Assert(!(buf_state & BM_VALID));
4705  UnlockBufHdr(buf, buf_state);
4706  }
4707  else
4708  {
4709  Assert(buf_state & BM_DIRTY);
4710  UnlockBufHdr(buf, buf_state);
4711  /* Issue notice if this is not the first failure... */
4712  if (buf_state & BM_IO_ERROR)
4713  {
4714  /* Buffer is pinned, so we can read tag without spinlock */
4715  char *path;
4716 
4717  path = relpathperm(BufTagGetRelFileLocator(&buf->tag),
4718  BufTagGetForkNum(&buf->tag));
4719  ereport(WARNING,
4720  (errcode(ERRCODE_IO_ERROR),
4721  errmsg("could not write block %u of %s",
4722  buf->tag.blockNum, path),
4723  errdetail("Multiple failures --- write error might be permanent.")));
4724  pfree(path);
4725  }
4726  }
4728  }
4729 }
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
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
static BufferDesc * InProgressBuf
Definition: bufmgr.c:163
static bool IsForInput
Definition: bufmgr.c:164
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4802
static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits)
Definition: bufmgr.c:4657
unsigned int uint32
Definition: c.h:490
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:1436
static char * buf
Definition: pg_test_fsync.c:67
#define relpathperm(rlocator, forknum)
Definition: relpath.h:90

References Assert(), BM_DIRTY, BM_IO_ERROR, BM_IO_IN_PROGRESS, BM_VALID, buf, BufTagGetForkNum(), BufTagGetRelFileLocator(), ereport, errcode(), errdetail(), errmsg(), InProgressBuf, IsForInput, LockBufHdr(), pfree(), relpathperm, TerminateBufferIO(), UnlockBufHdr(), and WARNING.

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

◆ AtEOXact_Buffers()

void AtEOXact_Buffers ( bool  isCommit)

Definition at line 2632 of file bufmgr.c.

2633 {
2635 
2636  AtEOXact_LocalBuffers(isCommit);
2637 
2639 }
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:2693
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:201
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:599

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 610 of file localbuf.c.

611 {
612  /*
613  * We shouldn't be holding any remaining pins; if we are, and assertions
614  * aren't enabled, we'll fail later in DropRelationBuffers while trying to
615  * drop the temp rels.
616  */
618 }
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:570

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

◆ BgBufferSync()

bool BgBufferSync ( struct WritebackContext wb_context)

Definition at line 2262 of file bufmgr.c.

2263 {
2264  /* info obtained from freelist.c */
2265  int strategy_buf_id;
2266  uint32 strategy_passes;
2267  uint32 recent_alloc;
2268 
2269  /*
2270  * Information saved between calls so we can determine the strategy
2271  * point's advance rate and avoid scanning already-cleaned buffers.
2272  */
2273  static bool saved_info_valid = false;
2274  static int prev_strategy_buf_id;
2275  static uint32 prev_strategy_passes;
2276  static int next_to_clean;
2277  static uint32 next_passes;
2278 
2279  /* Moving averages of allocation rate and clean-buffer density */
2280  static float smoothed_alloc = 0;
2281  static float smoothed_density = 10.0;
2282 
2283  /* Potentially these could be tunables, but for now, not */
2284  float smoothing_samples = 16;
2285  float scan_whole_pool_milliseconds = 120000.0;
2286 
2287  /* Used to compute how far we scan ahead */
2288  long strategy_delta;
2289  int bufs_to_lap;
2290  int bufs_ahead;
2291  float scans_per_alloc;
2292  int reusable_buffers_est;
2293  int upcoming_alloc_est;
2294  int min_scan_buffers;
2295 
2296  /* Variables for the scanning loop proper */
2297  int num_to_scan;
2298  int num_written;
2299  int reusable_buffers;
2300 
2301  /* Variables for final smoothed_density update */
2302  long new_strategy_delta;
2303  uint32 new_recent_alloc;
2304 
2305  /*
2306  * Find out where the freelist clock sweep currently is, and how many
2307  * buffer allocations have happened since our last call.
2308  */
2309  strategy_buf_id = StrategySyncStart(&strategy_passes, &recent_alloc);
2310 
2311  /* Report buffer alloc counts to pgstat */
2312  PendingBgWriterStats.buf_alloc += recent_alloc;
2313 
2314  /*
2315  * If we're not running the LRU scan, just stop after doing the stats
2316  * stuff. We mark the saved state invalid so that we can recover sanely
2317  * if LRU scan is turned back on later.
2318  */
2319  if (bgwriter_lru_maxpages <= 0)
2320  {
2321  saved_info_valid = false;
2322  return true;
2323  }
2324 
2325  /*
2326  * Compute strategy_delta = how many buffers have been scanned by the
2327  * clock sweep since last time. If first time through, assume none. Then
2328  * see if we are still ahead of the clock sweep, and if so, how many
2329  * buffers we could scan before we'd catch up with it and "lap" it. Note:
2330  * weird-looking coding of xxx_passes comparisons are to avoid bogus
2331  * behavior when the passes counts wrap around.
2332  */
2333  if (saved_info_valid)
2334  {
2335  int32 passes_delta = strategy_passes - prev_strategy_passes;
2336 
2337  strategy_delta = strategy_buf_id - prev_strategy_buf_id;
2338  strategy_delta += (long) passes_delta * NBuffers;
2339 
2340  Assert(strategy_delta >= 0);
2341 
2342  if ((int32) (next_passes - strategy_passes) > 0)
2343  {
2344  /* we're one pass ahead of the strategy point */
2345  bufs_to_lap = strategy_buf_id - next_to_clean;
2346 #ifdef BGW_DEBUG
2347  elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
2348  next_passes, next_to_clean,
2349  strategy_passes, strategy_buf_id,
2350  strategy_delta, bufs_to_lap);
2351 #endif
2352  }
2353  else if (next_passes == strategy_passes &&
2354  next_to_clean >= strategy_buf_id)
2355  {
2356  /* on same pass, but ahead or at least not behind */
2357  bufs_to_lap = NBuffers - (next_to_clean - strategy_buf_id);
2358 #ifdef BGW_DEBUG
2359  elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
2360  next_passes, next_to_clean,
2361  strategy_passes, strategy_buf_id,
2362  strategy_delta, bufs_to_lap);
2363 #endif
2364  }
2365  else
2366  {
2367  /*
2368  * We're behind, so skip forward to the strategy point and start
2369  * cleaning from there.
2370  */
2371 #ifdef BGW_DEBUG
2372  elog(DEBUG2, "bgwriter behind: bgw %u-%u strategy %u-%u delta=%ld",
2373  next_passes, next_to_clean,
2374  strategy_passes, strategy_buf_id,
2375  strategy_delta);
2376 #endif
2377  next_to_clean = strategy_buf_id;
2378  next_passes = strategy_passes;
2379  bufs_to_lap = NBuffers;
2380  }
2381  }
2382  else
2383  {
2384  /*
2385  * Initializing at startup or after LRU scanning had been off. Always
2386  * start at the strategy point.
2387  */
2388 #ifdef BGW_DEBUG
2389  elog(DEBUG2, "bgwriter initializing: strategy %u-%u",
2390  strategy_passes, strategy_buf_id);
2391 #endif
2392  strategy_delta = 0;
2393  next_to_clean = strategy_buf_id;
2394  next_passes = strategy_passes;
2395  bufs_to_lap = NBuffers;
2396  }
2397 
2398  /* Update saved info for next time */
2399  prev_strategy_buf_id = strategy_buf_id;
2400  prev_strategy_passes = strategy_passes;
2401  saved_info_valid = true;
2402 
2403  /*
2404  * Compute how many buffers had to be scanned for each new allocation, ie,
2405  * 1/density of reusable buffers, and track a moving average of that.
2406  *
2407  * If the strategy point didn't move, we don't update the density estimate
2408  */
2409  if (strategy_delta > 0 && recent_alloc > 0)
2410  {
2411  scans_per_alloc = (float) strategy_delta / (float) recent_alloc;
2412  smoothed_density += (scans_per_alloc - smoothed_density) /
2413  smoothing_samples;
2414  }
2415 
2416  /*
2417  * Estimate how many reusable buffers there are between the current
2418  * strategy point and where we've scanned ahead to, based on the smoothed
2419  * density estimate.
2420  */
2421  bufs_ahead = NBuffers - bufs_to_lap;
2422  reusable_buffers_est = (float) bufs_ahead / smoothed_density;
2423 
2424  /*
2425  * Track a moving average of recent buffer allocations. Here, rather than
2426  * a true average we want a fast-attack, slow-decline behavior: we
2427  * immediately follow any increase.
2428  */
2429  if (smoothed_alloc <= (float) recent_alloc)
2430  smoothed_alloc = recent_alloc;
2431  else
2432  smoothed_alloc += ((float) recent_alloc - smoothed_alloc) /
2433  smoothing_samples;
2434 
2435  /* Scale the estimate by a GUC to allow more aggressive tuning. */
2436  upcoming_alloc_est = (int) (smoothed_alloc * bgwriter_lru_multiplier);
2437 
2438  /*
2439  * If recent_alloc remains at zero for many cycles, smoothed_alloc will
2440  * eventually underflow to zero, and the underflows produce annoying
2441  * kernel warnings on some platforms. Once upcoming_alloc_est has gone to
2442  * zero, there's no point in tracking smaller and smaller values of
2443  * smoothed_alloc, so just reset it to exactly zero to avoid this
2444  * syndrome. It will pop back up as soon as recent_alloc increases.
2445  */
2446  if (upcoming_alloc_est == 0)
2447  smoothed_alloc = 0;
2448 
2449  /*
2450  * Even in cases where there's been little or no buffer allocation
2451  * activity, we want to make a small amount of progress through the buffer
2452  * cache so that as many reusable buffers as possible are clean after an
2453  * idle period.
2454  *
2455  * (scan_whole_pool_milliseconds / BgWriterDelay) computes how many times
2456  * the BGW will be called during the scan_whole_pool time; slice the
2457  * buffer pool into that many sections.
2458  */
2459  min_scan_buffers = (int) (NBuffers / (scan_whole_pool_milliseconds / BgWriterDelay));
2460 
2461  if (upcoming_alloc_est < (min_scan_buffers + reusable_buffers_est))
2462  {
2463 #ifdef BGW_DEBUG
2464  elog(DEBUG2, "bgwriter: alloc_est=%d too small, using min=%d + reusable_est=%d",
2465  upcoming_alloc_est, min_scan_buffers, reusable_buffers_est);
2466 #endif
2467  upcoming_alloc_est = min_scan_buffers + reusable_buffers_est;
2468  }
2469 
2470  /*
2471  * Now write out dirty reusable buffers, working forward from the
2472  * next_to_clean point, until we have lapped the strategy scan, or cleaned
2473  * enough buffers to match our estimate of the next cycle's allocation
2474  * requirements, or hit the bgwriter_lru_maxpages limit.
2475  */
2476 
2477  /* Make sure we can handle the pin inside SyncOneBuffer */
2479 
2480  num_to_scan = bufs_to_lap;
2481  num_written = 0;
2482  reusable_buffers = reusable_buffers_est;
2483 
2484  /* Execute the LRU scan */
2485  while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
2486  {
2487  int sync_state = SyncOneBuffer(next_to_clean, true,
2488  wb_context);
2489 
2490  if (++next_to_clean >= NBuffers)
2491  {
2492  next_to_clean = 0;
2493  next_passes++;
2494  }
2495  num_to_scan--;
2496 
2497  if (sync_state & BUF_WRITTEN)
2498  {
2499  reusable_buffers++;
2500  if (++num_written >= bgwriter_lru_maxpages)
2501  {
2503  break;
2504  }
2505  }
2506  else if (sync_state & BUF_REUSABLE)
2507  reusable_buffers++;
2508  }
2509 
2510  PendingBgWriterStats.buf_written_clean += num_written;
2511 
2512 #ifdef BGW_DEBUG
2513  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",
2514  recent_alloc, smoothed_alloc, strategy_delta, bufs_ahead,
2515  smoothed_density, reusable_buffers_est, upcoming_alloc_est,
2516  bufs_to_lap - num_to_scan,
2517  num_written,
2518  reusable_buffers - reusable_buffers_est);
2519 #endif
2520 
2521  /*
2522  * Consider the above scan as being like a new allocation scan.
2523  * Characterize its density and update the smoothed one based on it. This
2524  * effectively halves the moving average period in cases where both the
2525  * strategy and the background writer are doing some useful scanning,
2526  * which is helpful because a long memory isn't as desirable on the
2527  * density estimates.
2528  */
2529  new_strategy_delta = bufs_to_lap - num_to_scan;
2530  new_recent_alloc = reusable_buffers - reusable_buffers_est;
2531  if (new_strategy_delta > 0 && new_recent_alloc > 0)
2532  {
2533  scans_per_alloc = (float) new_strategy_delta / (float) new_recent_alloc;
2534  smoothed_density += (scans_per_alloc - smoothed_density) /
2535  smoothing_samples;
2536 
2537 #ifdef BGW_DEBUG
2538  elog(DEBUG2, "bgwriter: cleaner density alloc=%u scan=%ld density=%.2f new smoothed=%.2f",
2539  new_recent_alloc, new_strategy_delta,
2540  scans_per_alloc, smoothed_density);
2541 #endif
2542  }
2543 
2544  /* Return true if OK to hibernate */
2545  return (bufs_to_lap == 0 && recent_alloc == 0);
2546 }
int BgWriterDelay
Definition: bgwriter.c:61
#define BUF_REUSABLE
Definition: bufmgr.c:71
double bgwriter_lru_multiplier
Definition: bufmgr.c:136
static int SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
Definition: bufmgr.c:2565
int bgwriter_lru_maxpages
Definition: bufmgr.c:135
#define BUF_WRITTEN
Definition: bufmgr.c:70
signed int int32
Definition: c.h:478
#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:146
void ResourceOwnerEnlargeBuffers(ResourceOwner owner)
Definition: resowner.c:950
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 248 of file bufmgr.h.

249 {
250  Assert(BufferIsValid(buffer));
251 
252  if (BufferIsLocal(buffer))
253  return LocalBufferBlockPointers[-buffer - 1];
254  else
255  return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
256 }
#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:232
size_t Size
Definition: c.h:589

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

Referenced by BufferGetPage(), and XLogSaveBufferForHint().

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)

Definition at line 2791 of file bufmgr.c.

2792 {
2793  BufferDesc *bufHdr;
2794 
2795  Assert(BufferIsPinned(buffer));
2796 
2797  if (BufferIsLocal(buffer))
2798  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2799  else
2800  bufHdr = GetBufferDescriptor(buffer - 1);
2801 
2802  /* pinned, so OK to read tag without spinlock */
2803  return bufHdr->tag.blockNum;
2804 }
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:441
BufferTag tag
BlockNumber blockNum
Definition: buf_internals.h:97

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_newroot(), _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(), 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(), RelationAddExtraBlocks(), RelationGetBufferForTuple(), RelationPutHeapTuple(), revmap_get_buffer(), revmap_physical_extend(), ScanSourceDatabasePgClassPage(), spgAddNodeAction(), spgbuild(), spgdoinsert(), SpGistSetLastUsedPage(), spgSplitNodeAction(), spgWalk(), startScanEntry(), terminate_brin_buildstate(), vacuumLeafPage(), visibilitymap_clear(), visibilitymap_get_status(), visibilitymap_pin(), visibilitymap_pin_ok(), visibilitymap_set(), and XLogReadBufferExtended().

◆ BufferGetLSNAtomic()

XLogRecPtr BufferGetLSNAtomic ( Buffer  buffer)

Definition at line 3063 of file bufmgr.c.

3064 {
3065  BufferDesc *bufHdr = GetBufferDescriptor(buffer - 1);
3066  char *page = BufferGetPage(buffer);
3067  XLogRecPtr lsn;
3068  uint32 buf_state;
3069 
3070  /*
3071  * If we don't need locking for correctness, fastpath out.
3072  */
3073  if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
3074  return PageGetLSN(page);
3075 
3076  /* Make sure we've got a real buffer, and that we hold a pin on it. */
3077  Assert(BufferIsValid(buffer));
3078  Assert(BufferIsPinned(buffer));
3079 
3080  buf_state = LockBufHdr(bufHdr);
3081  lsn = PageGetLSN(page);
3082  UnlockBufHdr(bufHdr, buf_state);
3083 
3084  return lsn;
3085 }
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:284
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 284 of file bufmgr.h.

285 {
286  return (Page) BufferGetBlock(buffer);
287 }
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:248
Pointer Page
Definition: bufpage.h:78

References BufferGetBlock().

Referenced by _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_getbuf(), _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_newroot(), _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_next(), _hash_pgaddmultitup(), _hash_pgaddtup(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), allocNewBuffer(), blgetbitmap(), blinsert(), BloomNewBuffer(), blvacuumcleanup(), brin_can_do_samepage_update(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_initialize_empty_new_buffer(), brin_page_cleanup(), brin_start_evacuating_page(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinGetStats(), brinGetTupleForHeapBlock(), brininsert(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), brinSetHeapBlockItemptr(), bt_metap(), bt_page_items_internal(), bt_recheck_sibling_links(), bt_rootdescend(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), btvacuumpage(), BufferGetLSNAtomic(), collect_corrupt_items(), collect_visibility_data(), collectMatchBitmap(), collectMatchesForHeapRow(), count_nondeletable_pages(), createPostingTree(), dataBeginPlaceToPage(), dataBeginPlaceToPageInternal(), dataBeginPlaceToPageLeaf(), dataExecPlaceToPage(), dataExecPlaceToPageInternal(), dataLocateItem(), dataPlaceToPageLeafRecompress(), dataPrepareDownlink(), dataSplitPageInternal(), do_setval(), doPickSplit(), entryExecPlaceToPage(), entryIsEnoughSpace(), entryLoadMoreItems(), entryLocateEntry(), entryLocateLeafEntry(), entryPrepareDownlink(), entrySplitPage(), fill_seq_fork_with_data(), FreeSpaceMapPrepareTruncateRel(), fsm_readbuf(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), generic_redo(), GenericXLogFinish(), GenericXLogRegisterBuffer(), get_raw_page_internal(), GetBTPageStatistics(), GetRecordedFreeSpace(), GetVisibilityMapPins(), ginbulkdelete(), ginDeletePage(), ginEntryInsert(), ginFindLeafPage(), ginFindParents(), 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(), RelationAddExtraBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), RelationPutHeapTuple(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), scanPostingTree(), ScanSourceDatabasePgClass(), seq_redo(), shiftList(), spgAddNodeAction(), spgbuild(), spgdoinsert(), spgGetCache(), SpGistGetBuffer(), SpGistInitBuffer(), SpGistNewBuffer(), SpGistSetLastUsedPage(), SpGistUpdateMetaPage(), spgprocesspending(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), spgvacuumpage(), spgWalk(), startScanEntry(), statapprox_heap(), terminate_brin_buildstate(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_prepare_truncate(), visibilitymap_set(), vm_readbuf(), writeListPage(), XLogCheckBufferNeedsBackup(), XLogReadBufferExtended(), XLogReadBufferForRedoExtended(), XLogRecordPageWithFreeSpace(), XLogRegisterBuffer(), XLogSaveBufferForHint(), and xlogVacuumPage().

◆ BufferGetPageSize()

◆ BufferGetTag()

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

Definition at line 2812 of file bufmgr.c.

2814 {
2815  BufferDesc *bufHdr;
2816 
2817  /* Do the same checks as BufferGetBlockNumber. */
2818  Assert(BufferIsPinned(buffer));
2819 
2820  if (BufferIsLocal(buffer))
2821  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2822  else
2823  bufHdr = GetBufferDescriptor(buffer - 1);
2824 
2825  /* pinned, so OK to read tag without spinlock */
2826  *rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
2827  *forknum = BufTagGetForkNum(&bufHdr->tag);
2828  *blknum = bufHdr->tag.blockNum;
2829 }

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

3034 {
3035  BufferDesc *bufHdr;
3036 
3037  /* Local buffers are used only for temp relations. */
3038  if (BufferIsLocal(buffer))
3039  return false;
3040 
3041  /* Make sure we've got a real buffer, and that we hold a pin on it. */
3042  Assert(BufferIsValid(buffer));
3043  Assert(BufferIsPinned(buffer));
3044 
3045  /*
3046  * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
3047  * need not bother with the buffer header spinlock. Even if someone else
3048  * changes the buffer header state while we're doing this, the state is
3049  * changed atomically, so we'll read the old value or the new value, but
3050  * not random garbage.
3051  */
3052  bufHdr = GetBufferDescriptor(buffer - 1);
3053  return (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT) != 0;
3054 }
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 232 of file bufmgr.h.

233 {
234  Assert(bufnum <= NBuffers);
235  Assert(bufnum >= -NLocBuffer);
236 
237  return bufnum != InvalidBuffer;
238 }
#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_internal(), 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 157 of file buf_init.c.

158 {
159  Size size = 0;
160 
161  /* size of buffer descriptors */
162  size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
163  /* to allow aligning buffer descriptors */
164  size = add_size(size, PG_CACHE_LINE_SIZE);
165 
166  /* size of data pages */
167  size = add_size(size, mul_size(NBuffers, BLCKSZ));
168 
169  /* size of stuff controlled by freelist.c */
170  size = add_size(size, StrategyShmemSize());
171 
172  /* size of I/O condition variables */
173  size = add_size(size, mul_size(NBuffers,
175  /* to allow aligning the above */
176  size = add_size(size, PG_CACHE_LINE_SIZE);
177 
178  /* size of checkpoint sort array in bufmgr.c */
179  size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
180 
181  return size;
182 }
Size StrategyShmemSize(void)
Definition: freelist.c:453
#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, and StrategyShmemSize().

Referenced by CalculateShmemSize().

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)

Definition at line 2777 of file bufmgr.c.

2778 {
2779  BufferSync(flags);
2780 }
static void BufferSync(int flags)
Definition: bufmgr.c:1986

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

Definition at line 4252 of file bufmgr.c.

4253 {
4254  BufferDesc *buf;
4255 
4256  Assert(BufferIsPinned(buffer));
4257  if (BufferIsLocal(buffer))
4258  return true; /* act as though we got it */
4259 
4260  buf = GetBufferDescriptor(buffer - 1);
4261 
4263  LW_EXCLUSIVE);
4264 }
static LWLock * BufferDescriptorGetContentLock(const BufferDesc *bdesc)
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1366
@ LW_EXCLUSIVE
Definition: lwlock.h:115

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

4454 {
4455  BufferDesc *bufHdr;
4456  uint32 buf_state,
4457  refcount;
4458 
4459  Assert(BufferIsValid(buffer));
4460 
4461  if (BufferIsLocal(buffer))
4462  {
4463  refcount = LocalRefCount[-buffer - 1];
4464  /* There should be exactly one pin */
4465  Assert(refcount > 0);
4466  if (refcount != 1)
4467  return false;
4468  /* Nobody else to wait for */
4469  return true;
4470  }
4471 
4472  /* There should be exactly one local pin */
4473  refcount = GetPrivateRefCount(buffer);
4474  Assert(refcount);
4475  if (refcount != 1)
4476  return false;
4477 
4478  /* Try to acquire lock */
4479  if (!ConditionalLockBuffer(buffer))
4480  return false;
4481 
4482  bufHdr = GetBufferDescriptor(buffer - 1);
4483  buf_state = LockBufHdr(bufHdr);
4484  refcount = BUF_STATE_GET_REFCOUNT(buf_state);
4485 
4486  Assert(refcount > 0);
4487  if (refcount == 1)
4488  {
4489  /* Successfully acquired exclusive lock with pincount 1 */
4490  UnlockBufHdr(bufHdr, buf_state);
4491  return true;
4492  }
4493 
4494  /* Failed, so release the lock */
4495  UnlockBufHdr(bufHdr, buf_state);
4496  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4497  return false;
4498 }
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:50
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:4252
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:383
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4226
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:110
int32 * LocalRefCount
Definition: localbuf.c:46

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

3855 {
3856  RelFileLocatorBackend rlocator;
3857  char relpersistence;
3858 
3859  /* Set the relpersistence. */
3860  relpersistence = permanent ?
3861  RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
3862 
3863  /*
3864  * Create and copy all forks of the relation. During create database we
3865  * have a separate cleanup mechanism which deletes complete database
3866  * directory. Therefore, each individual relation doesn't need to be
3867  * registered for cleanup.
3868  */
3869  RelationCreateStorage(dst_rlocator, relpersistence, false);
3870 
3871  /* copy main fork. */
3872  RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, MAIN_FORKNUM,
3873  permanent);
3874 
3875  /* copy those extra forks that exist */
3876  for (ForkNumber forkNum = MAIN_FORKNUM + 1;
3877  forkNum <= MAX_FORKNUM; forkNum++)
3878  {
3879  if (smgrexists(smgropen(src_rlocator, InvalidBackendId), forkNum))
3880  {
3881  smgrcreate(smgropen(dst_rlocator, InvalidBackendId), forkNum, false);
3882 
3883  /*
3884  * WAL log creation if the relation is persistent, or this is the
3885  * init fork of an unlogged relation.
3886  */
3887  if (permanent || forkNum == INIT_FORKNUM)
3888  log_smgrcreate(&dst_rlocator, forkNum);
3889 
3890  /* Copy a fork's data, block by block. */
3891  RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, forkNum,
3892  permanent);
3893  }
3894  }
3895 
3896  /* close source and destination smgr if exists. */
3897  rlocator.backend = InvalidBackendId;
3898 
3899  rlocator.locator = src_rlocator;
3900  smgrcloserellocator(rlocator);
3901 
3902  rlocator.locator = dst_rlocator;
3903  smgrcloserellocator(rlocator);
3904 }
#define InvalidBackendId
Definition: backendid.h:23
static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, RelFileLocator dstlocator, ForkNumber forkNum, bool permanent)
Definition: bufmgr.c:3762
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:346
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:369
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
Definition: smgr.c:146
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:247
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 3464 of file bufmgr.c.

3465 {
3466  int i;
3467 
3468  /*
3469  * We needn't consider local buffers, since by assumption the target
3470  * database isn't our own.
3471  */
3472 
3473  for (i = 0; i < NBuffers; i++)
3474  {
3475  BufferDesc *bufHdr = GetBufferDescriptor(i);
3476  uint32 buf_state;
3477 
3478  /*
3479  * As in DropRelationBuffers, an unlocked precheck should be safe and
3480  * saves some cycles.
3481  */
3482  if (bufHdr->tag.dbOid != dbid)
3483  continue;
3484 
3485  buf_state = LockBufHdr(bufHdr);
3486  if (bufHdr->tag.dbOid == dbid)
3487  InvalidateBuffer(bufHdr); /* releases spinlock */
3488  else
3489  UnlockBufHdr(bufHdr, buf_state);
3490  }
3491 }
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1523
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 
)

◆ FlushDatabaseBuffers()

void FlushDatabaseBuffers ( Oid  dbid)

Definition at line 3922 of file bufmgr.c.

3923 {
3924  int i;
3925  BufferDesc *bufHdr;
3926 
3927  /* Make sure we can handle the pin inside the loop */
3929 
3930  for (i = 0; i < NBuffers; i++)
3931  {
3932  uint32 buf_state;
3933 
3934  bufHdr = GetBufferDescriptor(i);
3935 
3936  /*
3937  * As in DropRelationBuffers, an unlocked precheck should be safe and
3938  * saves some cycles.
3939  */
3940  if (bufHdr->tag.dbOid != dbid)
3941  continue;
3942 
3944 
3945  buf_state = LockBufHdr(bufHdr);
3946  if (bufHdr->tag.dbOid == dbid &&
3947  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3948  {
3949  PinBuffer_Locked(bufHdr);
3953  UnpinBuffer(bufHdr);
3954  }
3955  else
3956  UnlockBufHdr(bufHdr, buf_state);
3957  }
3958 }
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition: bufmgr.c:2851
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:1845
static void ReservePrivateRefCountEntry(void)
Definition: bufmgr.c:217
static void UnpinBuffer(BufferDesc *buf)
Definition: bufmgr.c:1888
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
@ LW_SHARED
Definition: lwlock.h:116
@ 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 3965 of file bufmgr.c.

3966 {
3967  BufferDesc *bufHdr;
3968 
3969  /* currently not needed, but no fundamental reason not to support */
3970  Assert(!BufferIsLocal(buffer));
3971 
3972  Assert(BufferIsPinned(buffer));
3973 
3974  bufHdr = GetBufferDescriptor(buffer - 1);
3975 
3977 
3979 }
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1919

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

3571 {
3572  int i;
3573  BufferDesc *bufHdr;
3574 
3575  if (RelationUsesLocalBuffers(rel))
3576  {
3577  for (i = 0; i < NLocBuffer; i++)
3578  {
3579  uint32 buf_state;
3580 
3581  bufHdr = GetLocalBufferDescriptor(i);
3582  if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
3583  ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
3584  (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3585  {
3586  ErrorContextCallback errcallback;
3587  Page localpage;
3588 
3589  localpage = (char *) LocalBufHdrGetBlock(bufHdr);
3590 
3591  /* Setup error traceback support for ereport() */
3593  errcallback.arg = (void *) bufHdr;
3594  errcallback.previous = error_context_stack;
3595  error_context_stack = &errcallback;
3596 
3597  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
3598 
3600  BufTagGetForkNum(&bufHdr->tag),
3601  bufHdr->tag.blockNum,
3602  localpage,
3603  false);
3604 
3605  buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED);
3606  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
3607 
3609 
3610  /* Pop the error context stack */
3611  error_context_stack = errcallback.previous;
3612  }
3613  }
3614 
3615  return;
3616  }
3617 
3618  /* Make sure we can handle the pin inside the loop */
3620 
3621  for (i = 0; i < NBuffers; i++)
3622  {
3623  uint32 buf_state;
3624 
3625  bufHdr = GetBufferDescriptor(i);
3626 
3627  /*
3628  * As in DropRelationBuffers, an unlocked precheck should be safe and
3629  * saves some cycles.
3630  */
3631  if (!BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator))
3632  continue;
3633 
3635 
3636  buf_state = LockBufHdr(bufHdr);
3637  if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
3638  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3639  {
3640  PinBuffer_Locked(bufHdr);
3644  UnpinBuffer(bufHdr);
3645  }
3646  else
3647  UnlockBufHdr(bufHdr, buf_state);
3648  }
3649 }
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:66
static void local_buffer_write_error_callback(void *arg)
Definition: bufmgr.c:4755
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1539
ErrorContextCallback * error_context_stack
Definition: elog.c:95
int NLocBuffer
Definition: localbuf.c:42
@ IOOBJECT_TEMP_RELATION
Definition: pgstat.h:279
@ IOOP_WRITE
Definition: pgstat.h:302
void pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op)
Definition: pgstat_io.c:66
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:571
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:637
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition: smgr.c:554
struct ErrorContextCallback * previous
Definition: elog.h:295
void(* callback)(void *arg)
Definition: elog.h:296
RelFileLocator rd_locator
Definition: rel.h:56

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, local_buffer_write_error_callback(), LocalBufHdrGetBlock, LockBufHdr(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NBuffers, NLocBuffer, PageSetChecksumInplace(), pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgstat_count_io_op(), 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 596 of file freelist.c.

597 {
598  /* don't crash if called on a "default" strategy */
599  if (strategy != NULL)
600  pfree(strategy);
601 }

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  BufferAccessStrategy strategy;
544  int ring_size;
545 
546  /*
547  * Select ring size to use. See buffer/README for rationales.
548  *
549  * Note: if you change the ring size for BAS_BULKREAD, see also
550  * SYNC_SCAN_REPORT_INTERVAL in access/heap/syncscan.c.
551  */
552  switch (btype)
553  {
554  case BAS_NORMAL:
555  /* if someone asks for NORMAL, just give 'em a "default" object */
556  return NULL;
557 
558  case BAS_BULKREAD:
559  ring_size = 256 * 1024 / BLCKSZ;
560  break;
561  case BAS_BULKWRITE:
562  ring_size = 16 * 1024 * 1024 / BLCKSZ;
563  break;
564  case BAS_VACUUM:
565  ring_size = 256 * 1024 / BLCKSZ;
566  break;
567 
568  default:
569  elog(ERROR, "unrecognized buffer access strategy: %d",
570  (int) btype);
571  return NULL; /* keep compiler quiet */
572  }
573 
574  /* Make sure ring isn't an undue fraction of shared buffers */
575  ring_size = Min(NBuffers / 8, ring_size);
576 
577  /* Allocate the object and initialize all elements to zeroes */
578  strategy = (BufferAccessStrategy)
579  palloc0(offsetof(BufferAccessStrategyData, buffers) +
580  ring_size * sizeof(Buffer));
581 
582  /* Set fields that don't start out zero */
583  strategy->btype = btype;
584  strategy->ring_size = ring_size;
585 
586  return strategy;
587 }
int Buffer
Definition: buf.h:23
struct BufferAccessStrategyData * BufferAccessStrategy
Definition: buf.h:44
#define Min(x, y)
Definition: c.h:988
#define ERROR
Definition: elog.h:39
void * palloc0(Size size)
Definition: mcxt.c:1241
BufferAccessStrategyType btype
Definition: freelist.c:75

References BAS_BULKREAD, BAS_BULKWRITE, BAS_NORMAL, BAS_VACUUM, BufferAccessStrategyData::btype, elog(), ERROR, Min, NBuffers, palloc0(), and BufferAccessStrategyData::ring_size.

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

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )

Definition at line 4427 of file bufmgr.c.

4428 {
4429  int bufid = GetStartupBufferPinWaitBufId();
4430 
4431  /*
4432  * If we get woken slowly then it's possible that the Startup process was
4433  * already woken by other backends before we got here. Also possible that
4434  * we get here by multiple interrupts or interrupts at inappropriate
4435  * times, so make sure we do nothing if the bufid is not set.
4436  */
4437  if (bufid < 0)
4438  return false;
4439 
4440  if (GetPrivateRefCount(bufid + 1) > 0)
4441  return true;
4442 
4443  return false;
4444 }
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:639

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and RecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

Definition at line 4023 of file bufmgr.c.

4024 {
4025  Assert(BufferIsPinned(buffer));
4027  if (BufferIsLocal(buffer))
4028  LocalRefCount[-buffer - 1]++;
4029  else
4030  {
4031  PrivateRefCountEntry *ref;
4032 
4033  ref = GetPrivateRefCountEntry(buffer, true);
4034  Assert(ref != NULL);
4035  ref->refcount++;
4036  }
4038 }
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition: bufmgr.c:309
void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:963

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

Referenced by _bt_steppage(), btrestrpos(), entryLoadMoreItems(), ReadBufferBI(), 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  BufferBlocks = (char *)
82  ShmemInitStruct("Buffer Blocks",
83  NBuffers * (Size) BLCKSZ, &foundBufs);
84 
85  /* Align condition variables to cacheline boundary. */
87  ShmemInitStruct("Buffer IO Condition Variables",
89  &foundIOCV);
90 
91  /*
92  * The array used to sort to-be-checkpointed buffer ids is located in
93  * shared memory, to avoid having to allocate significant amounts of
94  * memory at runtime. As that'd be in the middle of a checkpoint, or when
95  * the checkpointer is restarted, memory allocation failures would be
96  * painful.
97  */
99  ShmemInitStruct("Checkpoint BufferIds",
100  NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
101 
102  if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
103  {
104  /* should find all of these, or none of them */
105  Assert(foundDescs && foundBufs && foundIOCV && foundBufCkpt);
106  /* note: this path is only taken in EXEC_BACKEND case */
107  }
108  else
109  {
110  int i;
111 
112  /*
113  * Initialize all the buffer headers.
114  */
115  for (i = 0; i < NBuffers; i++)
116  {
118 
119  ClearBufferTag(&buf->tag);
120 
121  pg_atomic_init_u32(&buf->state, 0);
122  buf->wait_backend_pgprocno = INVALID_PGPROCNO;
123 
124  buf->buf_id = i;
125 
126  /*
127  * Initially link all the buffers together as unused. Subsequent
128  * management of this list is done by freelist.c.
129  */
130  buf->freeNext = i + 1;
131 
134 
136  }
137 
138  /* Correct last entry of linked list */
140  }
141 
142  /* Init other shared buffer-management stuff */
143  StrategyInitialize(!foundDescs);
144 
145  /* Initialize per-backend file flush context */
148 }
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:4942
int backend_flush_after
Definition: bufmgr.c:160
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:188
#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(), ShmemInitStruct(), StrategyInitialize(), and WritebackContextInit().

Referenced by CreateSharedMemoryAndSemaphores().

◆ InitBufferPoolAccess()

void InitBufferPoolAccess ( void  )

Definition at line 2649 of file bufmgr.c.

2650 {
2651  HASHCTL hash_ctl;
2652 
2653  memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
2654 
2655  hash_ctl.keysize = sizeof(int32);
2656  hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
2657 
2658  PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
2659  HASH_ELEM | HASH_BLOBS);
2660 
2661  /*
2662  * AtProcExit_Buffers needs LWLock access, and thereby has to be called at
2663  * the corresponding phase of backend shutdown.
2664  */
2665  Assert(MyProc != NULL);
2667 }
static void AtProcExit_Buffers(int code, Datum arg)
Definition: bufmgr.c:2674
struct PrivateRefCountEntry PrivateRefCountEntry
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition: bufmgr.c:199
static HTAB * PrivateRefCountHash
Definition: bufmgr.c:200
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 4509 of file bufmgr.c.

4510 {
4511  BufferDesc *bufHdr;
4512  uint32 buf_state;
4513 
4514  Assert(BufferIsValid(buffer));
4515 
4516  if (BufferIsLocal(buffer))
4517  {
4518  /* There should be exactly one pin */
4519  if (LocalRefCount[-buffer - 1] != 1)
4520  return false;
4521  /* Nobody else to wait for */
4522  return true;
4523  }
4524 
4525  /* There should be exactly one local pin */
4526  if (GetPrivateRefCount(buffer) != 1)
4527  return false;
4528 
4529  bufHdr = GetBufferDescriptor(buffer - 1);
4530 
4531  /* caller must hold exclusive lock on buffer */
4533  LW_EXCLUSIVE));
4534 
4535  buf_state = LockBufHdr(bufHdr);
4536 
4537  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
4538  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
4539  {
4540  /* pincount is OK. */
4541  UnlockBufHdr(bufHdr, buf_state);
4542  return true;
4543  }
4544 
4545  UnlockBufHdr(bufHdr, buf_state);
4546  return false;
4547 }
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1963

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

4227 {
4228  BufferDesc *buf;
4229 
4230  Assert(BufferIsPinned(buffer));
4231  if (BufferIsLocal(buffer))
4232  return; /* local buffers need no lock */
4233 
4234  buf = GetBufferDescriptor(buffer - 1);
4235 
4236  if (mode == BUFFER_LOCK_UNLOCK)
4238  else if (mode == BUFFER_LOCK_SHARE)
4240  else if (mode == BUFFER_LOCK_EXCLUSIVE)
4242  else
4243  elog(ERROR, "unrecognized buffer lock mode: %d", mode);
4244 }
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:111
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:112
static PgChecksumMode mode
Definition: pg_checksums.c:65

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_getnewbuf(), _hash_init(), _hash_kill_items(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), blbulkdelete(), blgetbitmap(), blinsert(), BloomNewBuffer(), blvacuumcleanup(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_page_cleanup(), brinbuild(), brinbuildempty(), 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(), fill_seq_fork_with_data(), FreeSpaceMapPrepareTruncateRel(), fsm_readbuf(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), get_raw_page_internal(), GetVisibilityMapPins(), ginbuildempty(), ginbulkdelete(), ginEntryInsert(), ginFindLeafPage(), ginFindParents(), ginFinishSplit(), ginGetStats(), ginHeapTupleFastInsert(), ginInsertCleanup(), ginInsertValue(), GinNewBuffer(), ginScanToDelete(), ginStepRight(), ginTraverseLock(), ginUpdateStats(), ginvacuumcleanup(), ginVacuumPostingTreeLeaves(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistbuildempty(), 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(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), ScanSourceDatabasePgClass(), shiftList(), spgdoinsert(), spgGetCache(), SpGistNewBuffer(), spgprocesspending(), spgvacuumpage(), spgWalk(), startScanEntry(), statapprox_heap(), summarize_range(), UnlockReleaseBuffer(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_prepare_truncate(), visibilitymap_set(), vm_readbuf(), XLogReadBufferExtended(), XLogReadBufferForRedoExtended(), and XLogRecordPageWithFreeSpace().

◆ LockBufferForCleanup()

void LockBufferForCleanup ( Buffer  buffer)

Definition at line 4283 of file bufmgr.c.

4284 {
4285  BufferDesc *bufHdr;
4286  TimestampTz waitStart = 0;
4287  bool waiting = false;
4288  bool logged_recovery_conflict = false;
4289 
4290  Assert(BufferIsPinned(buffer));
4291  Assert(PinCountWaitBuf == NULL);
4292 
4293  if (BufferIsLocal(buffer))
4294  {
4295  /* There should be exactly one pin */
4296  if (LocalRefCount[-buffer - 1] != 1)
4297  elog(ERROR, "incorrect local pin count: %d",
4298  LocalRefCount[-buffer - 1]);
4299  /* Nobody else to wait for */
4300  return;
4301  }
4302 
4303  /* There should be exactly one local pin */
4304  if (GetPrivateRefCount(buffer) != 1)
4305  elog(ERROR, "incorrect local pin count: %d",
4306  GetPrivateRefCount(buffer));
4307 
4308  bufHdr = GetBufferDescriptor(buffer - 1);
4309 
4310  for (;;)
4311  {
4312  uint32 buf_state;
4313 
4314  /* Try to acquire lock */
4316  buf_state = LockBufHdr(bufHdr);
4317 
4318  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
4319  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
4320  {
4321  /* Successfully acquired exclusive lock with pincount 1 */
4322  UnlockBufHdr(bufHdr, buf_state);
4323 
4324  /*
4325  * Emit the log message if recovery conflict on buffer pin was
4326  * resolved but the startup process waited longer than
4327  * deadlock_timeout for it.
4328  */
4329  if (logged_recovery_conflict)
4331  waitStart, GetCurrentTimestamp(),
4332  NULL, false);
4333 
4334  if (waiting)
4335  {
4336  /* reset ps display to remove the suffix if we added one */
4338  waiting = false;
4339  }
4340  return;
4341  }
4342  /* Failed, so mark myself as waiting for pincount 1 */
4343  if (buf_state & BM_PIN_COUNT_WAITER)
4344  {
4345  UnlockBufHdr(bufHdr, buf_state);
4346  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4347  elog(ERROR, "multiple backends attempting to wait for pincount 1");
4348  }
4350  PinCountWaitBuf = bufHdr;
4351  buf_state |= BM_PIN_COUNT_WAITER;
4352  UnlockBufHdr(bufHdr, buf_state);
4353  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4354 
4355  /* Wait to be signaled by UnpinBuffer() */
4356  if (InHotStandby)
4357  {
4358  if (!waiting)
4359  {
4360  /* adjust the process title to indicate that it's waiting */
4361  set_ps_display_suffix("waiting");
4362  waiting = true;
4363  }
4364 
4365  /*
4366  * Emit the log message if the startup process is waiting longer
4367  * than deadlock_timeout for recovery conflict on buffer pin.
4368  *
4369  * Skip this if first time through because the startup process has
4370  * not started waiting yet in this case. So, the wait start
4371  * timestamp is set after this logic.
4372  */
4373  if (waitStart != 0 && !logged_recovery_conflict)
4374  {
4376 
4377  if (TimestampDifferenceExceeds(waitStart, now,
4378  DeadlockTimeout))
4379  {
4381  waitStart, now, NULL, true);
4382  logged_recovery_conflict = true;
4383  }
4384  }
4385 
4386  /*
4387  * Set the wait start timestamp if logging is enabled and first
4388  * time through.
4389  */
4390  if (log_recovery_conflict_waits && waitStart == 0)
4391  waitStart = GetCurrentTimestamp();
4392 
4393  /* Publish the bufid that Startup process waits on */
4394  SetStartupBufferPinWaitBufId(buffer - 1);
4395  /* Set alarm and then wait to be signaled by UnpinBuffer() */
4397  /* Reset the published bufid */
4399  }
4400  else
4402 
4403  /*
4404  * Remove flag marking us as waiter. Normally this will not be set
4405  * anymore, but ProcWaitForSignal() can return for other signals as
4406  * well. We take care to only reset the flag if we're the waiter, as
4407  * theoretically another backend could have started waiting. That's
4408  * impossible with the current usages due to table level locking, but
4409  * better be safe.
4410  */
4411  buf_state = LockBufHdr(bufHdr);
4412  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
4414  buf_state &= ~BM_PIN_COUNT_WAITER;
4415  UnlockBufHdr(bufHdr, buf_state);
4416 
4417  PinCountWaitBuf = NULL;
4418  /* Loop back and try again */
4419  }
4420 }
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1727
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1582
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1546
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:66
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:167
int64 TimestampTz
Definition: timestamp.h:39
static volatile sig_atomic_t waiting
Definition: latch.c:162
@ PROCSIG_RECOVERY_CONFLICT_BUFFERPIN
Definition: procsignal.h:45
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:779
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 PG_WAIT_BUFFER_PIN
Definition: wait_event.h:20
#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, DeadlockTimeout, elog(), ERROR, GetBufferDescriptor(), GetCurrentTimestamp(), GetPrivateRefCount(), InHotStandby, LocalRefCount, LockBuffer(), LockBufHdr(), log_recovery_conflict_waits, LogRecoveryConflict(), MyProc, now(), PG_WAIT_BUFFER_PIN, 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 1621 of file bufmgr.c.

1622 {
1623  BufferDesc *bufHdr;
1624  uint32 buf_state;
1625  uint32 old_buf_state;
1626 
1627  if (!BufferIsValid(buffer))
1628  elog(ERROR, "bad buffer ID: %d", buffer);
1629 
1630  if (BufferIsLocal(buffer))
1631  {
1632  MarkLocalBufferDirty(buffer);
1633  return;
1634  }
1635 
1636  bufHdr = GetBufferDescriptor(buffer - 1);
1637 
1638  Assert(BufferIsPinned(buffer));
1640  LW_EXCLUSIVE));
1641 
1642  old_buf_state = pg_atomic_read_u32(&bufHdr->state);
1643  for (;;)
1644  {
1645  if (old_buf_state & BM_LOCKED)
1646  old_buf_state = WaitBufHdrUnlocked(bufHdr);
1647 
1648  buf_state = old_buf_state;
1649 
1650  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
1651  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
1652 
1653  if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
1654  buf_state))
1655  break;
1656  }
1657 
1658  /*
1659  * If the buffer was not dirty already, do vacuum accounting.
1660  */
1661  if (!(old_buf_state & BM_DIRTY))
1662  {
1663  VacuumPageDirty++;
1665  if (VacuumCostActive)
1667  }
1668 }
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:4830
bool VacuumCostActive
Definition: globals.c:153
int64 VacuumPageDirty
Definition: globals.c:150
int VacuumCostBalance
Definition: globals.c:152
int VacuumCostPageDirty
Definition: globals.c:144
BufferUsage pgBufferUsage
Definition: instrument.c:20
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:289
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_newroot(), _bt_restore_meta(), _bt_set_cleanup_info(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_freeovflpage(), _hash_init(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), addLeafTuple(), brin_doinsert(), brin_doupdate(), brin_initialize_empty_new_buffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinRevmapDesummarizeRange(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), createPostingTree(), 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(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), revmap_physical_extend(), saveNodeLink(), seq_redo(), shiftList(), spgAddNodeAction(), spgbuild(), SpGistUpdateMetaPage(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), visibilitymap_clear(), visibilitymap_prepare_truncate(), visibilitymap_set(), writeListPage(), and XLogReadBufferForRedoExtended().

◆ MarkBufferDirtyHint()

void MarkBufferDirtyHint ( Buffer  buffer,
bool  buffer_std 
)

Definition at line 4055 of file bufmgr.c.

4056 {
4057  BufferDesc *bufHdr;
4058  Page page = BufferGetPage(buffer);
4059 
4060  if (!BufferIsValid(buffer))
4061  elog(ERROR, "bad buffer ID: %d", buffer);
4062 
4063  if (BufferIsLocal(buffer))
4064  {
4065  MarkLocalBufferDirty(buffer);
4066  return;
4067  }
4068 
4069  bufHdr = GetBufferDescriptor(buffer - 1);
4070 
4071  Assert(GetPrivateRefCount(buffer) > 0);
4072  /* here, either share or exclusive lock is OK */
4074 
4075  /*
4076  * This routine might get called many times on the same page, if we are
4077  * making the first scan after commit of an xact that added/deleted many
4078  * tuples. So, be as quick as we can if the buffer is already dirty. We
4079  * do this by not acquiring spinlock if it looks like the status bits are
4080  * already set. Since we make this test unlocked, there's a chance we
4081  * might fail to notice that the flags have just been cleared, and failed
4082  * to reset them, due to memory-ordering issues. But since this function
4083  * is only intended to be used in cases where failing to write out the
4084  * data would be harmless anyway, it doesn't really matter.
4085  */
4086  if ((pg_atomic_read_u32(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
4088  {
4090  bool dirtied = false;
4091  bool delayChkptFlags = false;
4092  uint32 buf_state;
4093 
4094  /*
4095  * If we need to protect hint bit updates from torn writes, WAL-log a
4096  * full page image of the page. This full page image is only necessary
4097  * if the hint bit update is the first change to the page since the
4098  * last checkpoint.
4099  *
4100  * We don't check full_page_writes here because that logic is included
4101  * when we call XLogInsert() since the value changes dynamically.
4102  */
4103  if (XLogHintBitIsNeeded() &&
4104  (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT))
4105  {
4106  /*
4107  * If we must not write WAL, due to a relfilelocator-specific
4108  * condition or being in recovery, don't dirty the page. We can
4109  * set the hint, just not dirty the page as a result so the hint
4110  * is lost when we evict the page or shutdown.
4111  *
4112  * See src/backend/storage/page/README for longer discussion.
4113  */
4114  if (RecoveryInProgress() ||
4116  return;
4117 
4118  /*
4119  * If the block is already dirty because we either made a change
4120  * or set a hint already, then we don't need to write a full page
4121  * image. Note that aggressive cleaning of blocks dirtied by hint
4122  * bit setting would increase the call rate. Bulk setting of hint
4123  * bits would reduce the call rate...
4124  *
4125  * We must issue the WAL record before we mark the buffer dirty.
4126  * Otherwise we might write the page before we write the WAL. That
4127  * causes a race condition, since a checkpoint might occur between
4128  * writing the WAL record and marking the buffer dirty. We solve
4129  * that with a kluge, but one that is already in use during
4130  * transaction commit to prevent race conditions. Basically, we
4131  * simply prevent the checkpoint WAL record from being written
4132  * until we have marked the buffer dirty. We don't start the
4133  * checkpoint flush until we have marked dirty, so our checkpoint
4134  * must flush the change to disk successfully or the checkpoint
4135  * never gets written, so crash recovery will fix.
4136  *
4137  * It's possible we may enter here without an xid, so it is
4138  * essential that CreateCheckPoint waits for virtual transactions
4139  * rather than full transactionids.
4140  */
4143  delayChkptFlags = true;
4144  lsn = XLogSaveBufferForHint(buffer, buffer_std);
4145  }
4146 
4147  buf_state = LockBufHdr(bufHdr);
4148 
4149  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
4150 
4151  if (!(buf_state & BM_DIRTY))
4152  {
4153  dirtied = true; /* Means "will be dirtied by this action" */
4154 
4155  /*
4156  * Set the page LSN if we wrote a backup block. We aren't supposed
4157  * to set this when only holding a share lock but as long as we
4158  * serialise it somehow we're OK. We choose to set LSN while
4159  * holding the buffer header lock, which causes any reader of an
4160  * LSN who holds only a share lock to also obtain a buffer header
4161  * lock before using PageGetLSN(), which is enforced in
4162  * BufferGetLSNAtomic().
4163  *
4164  * If checksums are enabled, you might think we should reset the
4165  * checksum here. That will happen when the page is written
4166  * sometime later in this checkpoint cycle.
4167  */
4168  if (!XLogRecPtrIsInvalid(lsn))
4169  PageSetLSN(page, lsn);
4170  }
4171 
4172  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
4173  UnlockBufHdr(bufHdr, buf_state);
4174 
4175  if (delayChkptFlags)
4177 
4178  if (dirtied)
4179  {
4180  VacuumPageDirty++;
4182  if (VacuumCostActive)
4184  }
4185  }
4186 }
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:5907
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
Definition: xloginsert.c:1019

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

585 {
586  Assert(RelationIsValid(reln));
587  Assert(BlockNumberIsValid(blockNum));
588 
589  if (RelationUsesLocalBuffers(reln))
590  {
591  /* see comments in ReadBufferExtended */
592  if (RELATION_IS_OTHER_TEMP(reln))
593  ereport(ERROR,
594  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
595  errmsg("cannot access temporary tables of other sessions")));
596 
597  /* pass it off to localbuf.c */
598  return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
599  }
600  else
601  {
602  /* pass it to the shared buffer version */
603  return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
604  }
605 }
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:497
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition: localbuf.c:65
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:658
#define RelationIsValid(relation)
Definition: rel.h:476

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

2734 {
2735  BufferDesc *buf;
2736  int32 loccount;
2737  char *path;
2738  BackendId backend;
2739  uint32 buf_state;
2740 
2741  Assert(BufferIsValid(buffer));
2742  if (BufferIsLocal(buffer))
2743  {
2744  buf = GetLocalBufferDescriptor(-buffer - 1);
2745  loccount = LocalRefCount[-buffer - 1];
2746  backend = MyBackendId;
2747  }
2748  else
2749  {
2750  buf = GetBufferDescriptor(buffer - 1);
2751  loccount = GetPrivateRefCount(buffer);
2752  backend = InvalidBackendId;
2753  }
2754 
2755  /* theoretically we should lock the bufhdr here */
2756  path = relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
2757  BufTagGetForkNum(&buf->tag));
2758  buf_state = pg_atomic_read_u32(&buf->state);
2759  elog(WARNING,
2760  "buffer refcount leak: [%03d] "
2761  "(rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
2762  buffer, path,
2763  buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
2764  BUF_STATE_GET_REFCOUNT(buf_state), loccount);
2765  pfree(path);
2766 }
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 704 of file bufmgr.c.

705 {
706  return ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);
707 }
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:751

References MAIN_FORKNUM, RBM_NORMAL, and ReadBufferExtended().

Referenced by _bt_getbuf(), _bt_search_insert(), _hash_getbuf(), _hash_getbuf_with_condlock_cleanup(), blbulkdelete(), blinsert(), BloomNewBuffer(), brin_getinsertbuffer(), brinbuild(), 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 751 of file bufmgr.c.

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

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(), blvacuumcleanup(), brin_vacuum_scan(), brinbuildempty(), bt_recheck_sibling_links(), btvacuumpage(), collect_corrupt_items(), collect_visibility_data(), count_nondeletable_pages(), fill_seq_fork_with_data(), fsm_readbuf(), get_raw_page_internal(), ginbuildempty(), ginbulkdelete(), ginDeletePage(), ginScanToDelete(), ginvacuumcleanup(), ginVacuumPostingTree(), ginVacuumPostingTreeLeaves(), gistbuildempty(), 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(), 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 791 of file bufmgr.c.

794 {
795  bool hit;
796 
797  SMgrRelation smgr = smgropen(rlocator, InvalidBackendId);
798 
799  return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
800  RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
801  mode, strategy, &hit);
802 }

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

617 {
618  BufferDesc *bufHdr;
619  BufferTag tag;
620  uint32 buf_state;
621  bool have_private_ref;
622 
623  Assert(BufferIsValid(recent_buffer));
624 
627  InitBufferTag(&tag, &rlocator, forkNum, blockNum);
628 
629  if (BufferIsLocal(recent_buffer))
630  {
631  int b = -recent_buffer - 1;
632 
633  bufHdr = GetLocalBufferDescriptor(b);
634  buf_state = pg_atomic_read_u32(&bufHdr->state);
635 
636  /* Is it still valid and holding the right tag? */
637  if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
638  {
639  /*
640  * Bump buffer's ref and usage counts. This is equivalent of
641  * PinBuffer for a shared buffer.
642  */
643  if (LocalRefCount[b] == 0)
644  {
646  {
647  buf_state += BUF_USAGECOUNT_ONE;
648  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
649  }
650  }
651  LocalRefCount[b]++;
653 
655 
656  return true;
657  }
658  }
659  else
660  {
661  bufHdr = GetBufferDescriptor(recent_buffer - 1);
662  have_private_ref = GetPrivateRefCount(recent_buffer) > 0;
663 
664  /*
665  * Do we already have this buffer pinned with a private reference? If
666  * so, it must be valid and it is safe to check the tag without
667  * locking. If not, we have to lock the header first and then check.
668  */
669  if (have_private_ref)
670  buf_state = pg_atomic_read_u32(&bufHdr->state);
671  else
672  buf_state = LockBufHdr(bufHdr);
673 
674  if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
675  {
676  /*
677  * It's now safe to pin the buffer. We can't pin first and ask
678  * questions later, because it might confuse code paths like
679  * InvalidateBuffer() if we pinned a random non-matching buffer.
680  */
681  if (have_private_ref)
682  PinBuffer(bufHdr, NULL); /* bump pin count */
683  else
684  PinBuffer_Locked(bufHdr); /* pin for first time */
685 
687 
688  return true;
689  }
690 
691  /* If we locked the header above, now unlock. */
692  if (!have_private_ref)
693  UnlockBufHdr(bufHdr, buf_state);
694  }
695 
696  return false;
697 }
#define BM_MAX_USAGE_COUNT
Definition: buf_internals.h:77
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
#define BUF_STATE_GET_USAGECOUNT(state)
Definition: buf_internals.h:51
#define BUF_USAGECOUNT_ONE
Definition: buf_internals.h:45
static bool PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
Definition: bufmgr.c:1742
int b
Definition: isn.c:70
int64 local_blks_hit
Definition: instrument.h:30
int64 shared_blks_hit
Definition: instrument.h:26

References Assert(), b, BM_MAX_USAGE_COUNT, BM_VALID, BUF_STATE_GET_USAGECOUNT, BUF_USAGECOUNT_ONE, BufferIsLocal, BufferIsValid(), BufferTagsEqual(), CurrentResourceOwner, GetBufferDescriptor(), GetLocalBufferDescriptor(), GetPrivateRefCount(), InitBufferTag(), BufferUsage::local_blks_hit, LocalRefCount, LockBufHdr(), pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgBufferUsage, PinBuffer(), PinBuffer_Locked(), ReservePrivateRefCountEntry(), ResourceOwnerEnlargeBuffers(), ResourceOwnerRememberBuffer(), BufferUsage::shared_blks_hit, BufferDesc::state, BufferDesc::tag, and UnlockBufHdr().

Referenced by XLogReadBufferExtended().

◆ RelationGetNumberOfBlocksInFork()

BlockNumber RelationGetNumberOfBlocksInFork ( Relation  relation,
ForkNumber  forkNum 
)

Definition at line 3001 of file bufmgr.c.

3002 {
3003  if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
3004  {
3005  /*
3006  * Not every table AM uses BLCKSZ wide fixed size blocks. Therefore
3007  * tableam returns the size in bytes - but for the purpose of this
3008  * routine, we want the number of blocks. Therefore divide, rounding
3009  * up.
3010  */
3011  uint64 szbytes;
3012 
3013  szbytes = table_relation_size(relation, forkNum);
3014 
3015  return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
3016  }
3017  else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
3018  {
3019  return smgrnblocks(RelationGetSmgr(relation), forkNum);
3020  }
3021  else
3022  Assert(false);
3023 
3024  return 0; /* keep compiler quiet */
3025 }
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:579
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition: tableam.h:1875

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

1687 {
1688  ForkNumber forkNum = MAIN_FORKNUM;
1689  BufferDesc *bufHdr;
1690 
1691  if (BufferIsValid(buffer))
1692  {
1693  Assert(BufferIsPinned(buffer));
1694  if (BufferIsLocal(buffer))
1695  {
1696  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
1697  if (bufHdr->tag.blockNum == blockNum &&
1698  BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
1699  BufTagGetForkNum(&bufHdr->tag) == forkNum)
1700  return buffer;
1702  LocalRefCount[-buffer - 1]--;
1703  }
1704  else
1705  {
1706  bufHdr = GetBufferDescriptor(buffer - 1);
1707  /* we have pin, so it's ok to examine tag without spinlock */
1708  if (bufHdr->tag.blockNum == blockNum &&
1709  BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
1710  BufTagGetForkNum(&bufHdr->tag) == forkNum)
1711  return buffer;
1712  UnpinBuffer(bufHdr);
1713  }
1714  }
1715 
1716  return ReadBuffer(relation, blockNum);
1717 }
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:704
void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:972

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

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

◆ ReleaseBuffer()

void ReleaseBuffer ( Buffer  buffer)

Definition at line 3985 of file bufmgr.c.

3986 {
3987  if (!BufferIsValid(buffer))
3988  elog(ERROR, "bad buffer ID: %d", buffer);
3989 
3990  if (BufferIsLocal(buffer))
3991  {
3993 
3994  Assert(LocalRefCount[-buffer - 1] > 0);
3995  LocalRefCount[-buffer - 1]--;
3996  return;
3997  }
3998 
3999  UnpinBuffer(GetBufferDescriptor(buffer - 1));
4000 }

References Assert(), PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsValid(), CurrentResourceOwner, elog(), ERROR, GetBufferDescriptor(), LocalRefCount, ResourceOwnerForgetBuffer(), and UnpinBuffer().

Referenced by _bt_drop_lock_and_maybe_pin(), _bt_getbuf(), _bt_pagedel(), _bt_relbuf(), _bt_search_insert(), _bt_unlink_halfdead_page(), _hash_dropbuf(), _hash_getbuf_with_condlock_cleanup(), autoprewarm_database_main(), blinsert(), BloomNewBuffer(), brin_getinsertbuffer(), brin_vacuum_scan(), bringetbitmap(), brinGetTupleForHeapBlock(), brininsert(), brinRevmapTerminate(), brinsummarize(), collect_corrupt_items(), collect_visibility_data(), entryLoadMoreItems(), ExecEndBitmapHeapScan(), ExecEndIndexOnlyScan(), ExecReScanBitmapHeapScan(), 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_internal(), 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(), RelationGetBufferForTuple(), ReleaseBulkInsertStatePin(), ResourceOwnerReleaseInternal(), revmap_get_buffer(), revmap_physical_extend(), 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().

◆ TestForOldSnapshot()

static void TestForOldSnapshot ( Snapshot  snapshot,
Relation  relation,
Page  page 
)
inlinestatic

Definition at line 307 of file bufmgr.h.

308 {
309  Assert(relation != NULL);
310 
311  if (old_snapshot_threshold >= 0
312  && (snapshot) != NULL
313  && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
314  || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
315  && !XLogRecPtrIsInvalid((snapshot)->lsn)
316  && PageGetLSN(page) > (snapshot)->lsn)
317  TestForOldSnapshot_impl(snapshot, relation);
318 }
void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation)
Definition: bufmgr.c:5072
int old_snapshot_threshold
Definition: snapmgr.c:79
@ SNAPSHOT_TOAST
Definition: snapshot.h:74
@ SNAPSHOT_MVCC
Definition: snapshot.h:50

References Assert(), old_snapshot_threshold, PageGetLSN(), SNAPSHOT_MVCC, SNAPSHOT_TOAST, TestForOldSnapshot_impl(), and XLogRecPtrIsInvalid.

Referenced by _bt_get_endpoint(), _bt_moveright(), _bt_readnextpage(), _bt_walk_left(), _hash_first(), _hash_next(), _hash_readnext(), _hash_readprev(), blgetbitmap(), brinGetTupleForHeapBlock(), brinRevmapInitialize(), collectMatchBitmap(), collectMatchesForHeapRow(), ginFindLeafPage(), gistScanPage(), heap_fetch(), heap_get_latest_tid(), heapgetpage(), heapgettup_continue_page(), heapgettup_pagemode(), heapgettup_start_page(), scanGetCandidate(), scanPendingInsert(), and spgWalk().

◆ TestForOldSnapshot_impl()

void TestForOldSnapshot_impl ( Snapshot  snapshot,
Relation  relation 
)

Definition at line 5072 of file bufmgr.c.

5073 {
5074  if (RelationAllowsEarlyPruning(relation)
5075  && (snapshot)->whenTaken < GetOldSnapshotThresholdTimestamp())
5076  ereport(ERROR,
5077  (errcode(ERRCODE_SNAPSHOT_TOO_OLD),
5078  errmsg("snapshot too old")));
5079 }
TimestampTz GetOldSnapshotThresholdTimestamp(void)
Definition: snapmgr.c:1705
#define RelationAllowsEarlyPruning(rel)
Definition: snapmgr.h:38

References ereport, errcode(), errmsg(), ERROR, GetOldSnapshotThresholdTimestamp(), and RelationAllowsEarlyPruning.

Referenced by TestForOldSnapshot().

◆ UnlockBuffers()

void UnlockBuffers ( void  )

Definition at line 4198 of file bufmgr.c.

4199 {
4201 
4202  if (buf)
4203  {
4204  uint32 buf_state;
4205 
4206  buf_state = LockBufHdr(buf);
4207 
4208  /*
4209  * Don't complain if flag bit not set; it could have been reset but we
4210  * got a cancel/die interrupt before getting the signal.
4211  */
4212  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
4213  buf->wait_backend_pgprocno == MyProc->pgprocno)
4214  buf_state &= ~BM_PIN_COUNT_WAITER;
4215 
4216  UnlockBufHdr(buf, buf_state);
4217 
4218  PinCountWaitBuf = NULL;
4219  }
4220 }

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

4009 {
4010  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4011  ReleaseBuffer(buffer);
4012 }
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3985

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(), RelationAddExtraBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), ResetSequence(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), scanPostingTree(), ScanSourceDatabasePgClass(), seq_redo(), SequenceChangePersistence(), shiftList(), spgAddNodeAction(), spgbuild(), spgdoinsert(), spgGetCache(), SpGistGetBuffer(), SpGistUpdateMetaPage(), spgMatchNodeAction(), spgprocesspending(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), spgvacuumpage(), spgWalk(), statapprox_heap(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_prepare_truncate(), writeListPage(), xlog_redo(), and XLogRecordPageWithFreeSpace().

Variable Documentation

◆ backend_flush_after

PGDLLIMPORT int backend_flush_after
extern

Definition at line 160 of file bufmgr.c.

Referenced by InitBufferPool().

◆ bgwriter_flush_after

PGDLLIMPORT int bgwriter_flush_after
extern

Definition at line 159 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

PGDLLIMPORT int bgwriter_lru_maxpages
extern

Definition at line 135 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

PGDLLIMPORT double bgwriter_lru_multiplier
extern

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

Referenced by BufferSync().

◆ effective_io_concurrency

PGDLLIMPORT int effective_io_concurrency
extern

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

Referenced by mdread(), and ReadBuffer_common().