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)
 
void BufmgrCommit (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 107 of file bufmgr.h.

◆ BUFFER_LOCK_SHARE

#define BUFFER_LOCK_SHARE   1

Definition at line 106 of file bufmgr.h.

◆ BUFFER_LOCK_UNLOCK

#define BUFFER_LOCK_UNLOCK   0

Definition at line 105 of file bufmgr.h.

◆ DEFAULT_EFFECTIVE_IO_CONCURRENCY

#define DEFAULT_EFFECTIVE_IO_CONCURRENCY   0

Definition at line 78 of file bufmgr.h.

◆ DEFAULT_MAINTENANCE_IO_CONCURRENCY

#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   0

Definition at line 79 of file bufmgr.h.

◆ MAX_IO_CONCURRENCY

#define MAX_IO_CONCURRENCY   1000

Definition at line 97 of file bufmgr.h.

◆ P_NEW

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

Definition at line 100 of file bufmgr.h.

◆ RelationGetNumberOfBlocks

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

Definition at line 156 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 27 of file bufmgr.h.

28 {
29  BAS_NORMAL, /* Normal random access */
30  BAS_BULKREAD, /* Large read-only scan (hint bit updates are
31  * ok) */
32  BAS_BULKWRITE, /* Large multi-block write (e.g. COPY IN) */
33  BAS_VACUUM /* VACUUM */
BufferAccessStrategyType
Definition: bufmgr.h:28
@ BAS_BULKREAD
Definition: bufmgr.h:30
@ BAS_NORMAL
Definition: bufmgr.h:29
@ BAS_VACUUM
Definition: bufmgr.h:33
@ BAS_BULKWRITE
Definition: bufmgr.h:32

◆ ReadBufferMode

Enumerator
RBM_NORMAL 
RBM_ZERO_AND_LOCK 
RBM_ZERO_AND_CLEANUP_LOCK 
RBM_ZERO_ON_ERROR 
RBM_NORMAL_NO_LOG 

Definition at line 37 of file bufmgr.h.

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

Function Documentation

◆ AbortBufferIO()

void AbortBufferIO ( void  )

Definition at line 4642 of file bufmgr.c.

4643 {
4645 
4646  if (buf)
4647  {
4648  uint32 buf_state;
4649 
4650  buf_state = LockBufHdr(buf);
4651  Assert(buf_state & BM_IO_IN_PROGRESS);
4652  if (IsForInput)
4653  {
4654  Assert(!(buf_state & BM_DIRTY));
4655 
4656  /* We'd better not think buffer is valid yet */
4657  Assert(!(buf_state & BM_VALID));
4658  UnlockBufHdr(buf, buf_state);
4659  }
4660  else
4661  {
4662  Assert(buf_state & BM_DIRTY);
4663  UnlockBufHdr(buf, buf_state);
4664  /* Issue notice if this is not the first failure... */
4665  if (buf_state & BM_IO_ERROR)
4666  {
4667  /* Buffer is pinned, so we can read tag without spinlock */
4668  char *path;
4669 
4670  path = relpathperm(BufTagGetRelFileLocator(&buf->tag),
4671  BufTagGetForkNum(&buf->tag));
4672  ereport(WARNING,
4673  (errcode(ERRCODE_IO_ERROR),
4674  errmsg("could not write block %u of %s",
4675  buf->tag.blockNum, path),
4676  errdetail("Multiple failures --- write error might be permanent.")));
4677  pfree(path);
4678  }
4679  }
4681  }
4682 }
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
#define BM_DIRTY
Definition: buf_internals.h:59
#define BM_IO_IN_PROGRESS
Definition: buf_internals.h:62
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)
#define BM_VALID
Definition: buf_internals.h:60
#define BM_IO_ERROR
Definition: buf_internals.h:63
static BufferDesc * InProgressBuf
Definition: bufmgr.c:163
static bool IsForInput
Definition: bufmgr.c:164
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4755
static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits)
Definition: bufmgr.c:4610
unsigned int uint32
Definition: c.h:442
int errdetail(const char *fmt,...)
Definition: elog.c:1039
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define WARNING
Definition: elog.h:32
#define ereport(elevel,...)
Definition: elog.h:145
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1306
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 2594 of file bufmgr.c.

2595 {
2597 
2598  AtEOXact_LocalBuffers(isCommit);
2599 
2601 }
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:2655
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:201
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:598

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

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

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

◆ BgBufferSync()

bool BgBufferSync ( struct WritebackContext wb_context)

Definition at line 2224 of file bufmgr.c.

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

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

245 {
246  Assert(BufferIsValid(buffer));
247 
248  if (BufferIsLocal(buffer))
249  return LocalBufferBlockPointers[-buffer - 1];
250  else
251  return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
252 }
#define BufferIsLocal(buffer)
Definition: buf.h:37
PGDLLIMPORT Block * LocalBufferBlockPointers
Definition: localbuf.c:44
void * Block
Definition: bufmgr.h:24
PGDLLIMPORT char * BufferBlocks
Definition: buf_init.c:22
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:228
size_t Size
Definition: c.h:541

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

Referenced by BufferGetPage(), and XLogSaveBufferForHint().

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)

Definition at line 2763 of file bufmgr.c.

2764 {
2765  BufferDesc *bufHdr;
2766 
2767  Assert(BufferIsPinned(buffer));
2768 
2769  if (BufferIsLocal(buffer))
2770  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2771  else
2772  bufHdr = GetBufferDescriptor(buffer - 1);
2773 
2774  /* pinned, so OK to read tag without spinlock */
2775  return bufHdr->tag.blockNum;
2776 }
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:450
BufferTag tag
BlockNumber blockNum
Definition: buf_internals.h:96

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

3013 {
3014  BufferDesc *bufHdr = GetBufferDescriptor(buffer - 1);
3015  char *page = BufferGetPage(buffer);
3016  XLogRecPtr lsn;
3017  uint32 buf_state;
3018 
3019  /*
3020  * If we don't need locking for correctness, fastpath out.
3021  */
3022  if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
3023  return PageGetLSN(page);
3024 
3025  /* Make sure we've got a real buffer, and that we hold a pin on it. */
3026  Assert(BufferIsValid(buffer));
3027  Assert(BufferIsPinned(buffer));
3028 
3029  buf_state = LockBufHdr(bufHdr);
3030  lsn = PageGetLSN(page);
3031  UnlockBufHdr(bufHdr, buf_state);
3032 
3033  return lsn;
3034 }
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:280
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 280 of file bufmgr.h.

281 {
282  return (Page) BufferGetBlock(buffer);
283 }
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:244
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(), heapgettup_pagemode(), 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 2784 of file bufmgr.c.

2786 {
2787  BufferDesc *bufHdr;
2788 
2789  /* Do the same checks as BufferGetBlockNumber. */
2790  Assert(BufferIsPinned(buffer));
2791 
2792  if (BufferIsLocal(buffer))
2793  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2794  else
2795  bufHdr = GetBufferDescriptor(buffer - 1);
2796 
2797  /* pinned, so OK to read tag without spinlock */
2798  *rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
2799  *forknum = BufTagGetForkNum(&bufHdr->tag);
2800  *blknum = bufHdr->tag.blockNum;
2801 }

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

2983 {
2984  BufferDesc *bufHdr;
2985 
2986  /* Local buffers are used only for temp relations. */
2987  if (BufferIsLocal(buffer))
2988  return false;
2989 
2990  /* Make sure we've got a real buffer, and that we hold a pin on it. */
2991  Assert(BufferIsValid(buffer));
2992  Assert(BufferIsPinned(buffer));
2993 
2994  /*
2995  * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
2996  * need not bother with the buffer header spinlock. Even if someone else
2997  * changes the buffer header state while we're doing this, the state is
2998  * changed atomically, so we'll read the old value or the new value, but
2999  * not random garbage.
3000  */
3001  bufHdr = GetBufferDescriptor(buffer - 1);
3002  return (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT) != 0;
3003 }
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:236
#define BM_PERMANENT
Definition: buf_internals.h:67
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 228 of file bufmgr.h.

229 {
230  Assert(bufnum <= NBuffers);
231  Assert(bufnum >= -NLocBuffer);
232 
233  return bufnum != InvalidBuffer;
234 }
#define InvalidBuffer
Definition: buf.h:25
PGDLLIMPORT int NBuffers
Definition: globals.c:136
PGDLLIMPORT int NLocBuffer
Definition: localbuf.c:41

References Assert(), InvalidBuffer, NBuffers, and NLocBuffer.

Referenced by _bt_clear_incomplete_split(), _bt_endpoint(), _bt_first(), _bt_get_endpoint(), _bt_insertonpg(), _bt_readpage(), _bt_relandgetbuf(), _bt_search(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_dropscanbuf(), _hash_freeovflpage(), _hash_getbucketbuf_from_hashkey(), _hash_getcachedmetap(), _hash_readnext(), _hash_readpage(), _hash_readprev(), autoprewarm_database_main(), brin_doinsert(), brin_doupdate(), brin_getinsertbuffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinGetTupleForHeapBlock(), brininsert(), brinsummarize(), bt_recheck_sibling_links(), bt_rootdescend(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), BufferGetBlock(), BufferGetLSNAtomic(), BufferGetPageSize(), BufferIsPermanent(), ConditionalLockBufferForCleanup(), doPickSplit(), entryGetItem(), entryLoadMoreItems(), ExecStoreBufferHeapTuple(), ExecStorePinnedBufferHeapTuple(), FreeSpaceMapPrepareTruncateRel(), fsm_search(), fsm_vacuum_page(), generic_redo(), GetPrivateRefCount(), GetPrivateRefCountEntry(), GetRecordedFreeSpace(), GetVisibilityMapPins(), ginPlaceToPage(), ginRedoClearIncompleteSplit(), ginRedoDeletePage(), ginRedoInsert(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginScanToDelete(), gistinserttuples(), gistkillitems(), gistplacetopage(), gistRedoClearFollowRight(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageUpdateRecord(), gistXLogSplit(), gistXLogUpdate(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), heap_endscan(), heap_index_delete_tuples(), heap_lock_tuple(), heap_rescan(), heap_update(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_freeze_page(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune(), heap_xlog_update(), heap_xlog_vacuum(), heap_xlog_visible(), heapam_index_fetch_reset(), heapam_scan_sample_next_block(), heapam_tuple_lock(), heapam_tuple_satisfies_snapshot(), heapgetpage(), heapgettup(), heapgettup_pagemode(), IsBufferCleanupOK(), lazy_scan_heap(), lazy_vacuum_heap_page(), 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().

◆ BufmgrCommit()

void BufmgrCommit ( void  )

Definition at line 2749 of file bufmgr.c.

2750 {
2751  /* Nothing to do in bufmgr anymore... */
2752 }

Referenced by PrepareTransaction(), and RecordTransactionCommit().

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)

Definition at line 2739 of file bufmgr.c.

2740 {
2741  BufferSync(flags);
2742 }
static void BufferSync(int flags)
Definition: bufmgr.c:1948

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

Definition at line 4198 of file bufmgr.c.

4199 {
4200  BufferDesc *buf;
4201 
4202  Assert(BufferIsPinned(buffer));
4203  if (BufferIsLocal(buffer))
4204  return true; /* act as though we got it */
4205 
4206  buf = GetBufferDescriptor(buffer - 1);
4207 
4209  LW_EXCLUSIVE);
4210 }
static LWLock * BufferDescriptorGetContentLock(const BufferDesc *bdesc)
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1365
@ LW_EXCLUSIVE
Definition: lwlock.h:112

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

4407 {
4408  BufferDesc *bufHdr;
4409  uint32 buf_state,
4410  refcount;
4411 
4412  Assert(BufferIsValid(buffer));
4413 
4414  if (BufferIsLocal(buffer))
4415  {
4416  refcount = LocalRefCount[-buffer - 1];
4417  /* There should be exactly one pin */
4418  Assert(refcount > 0);
4419  if (refcount != 1)
4420  return false;
4421  /* Nobody else to wait for */
4422  return true;
4423  }
4424 
4425  /* There should be exactly one local pin */
4426  refcount = GetPrivateRefCount(buffer);
4427  Assert(refcount);
4428  if (refcount != 1)
4429  return false;
4430 
4431  /* Try to acquire lock */
4432  if (!ConditionalLockBuffer(buffer))
4433  return false;
4434 
4435  bufHdr = GetBufferDescriptor(buffer - 1);
4436  buf_state = LockBufHdr(bufHdr);
4437  refcount = BUF_STATE_GET_REFCOUNT(buf_state);
4438 
4439  Assert(refcount > 0);
4440  if (refcount == 1)
4441  {
4442  /* Successfully acquired exclusive lock with pincount 1 */
4443  UnlockBufHdr(bufHdr, buf_state);
4444  return true;
4445  }
4446 
4447  /* Failed, so release the lock */
4448  UnlockBufHdr(bufHdr, buf_state);
4449  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4450  return false;
4451 }
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:49
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:4198
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:389
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4172
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:105
int32 * LocalRefCount
Definition: localbuf.c:45

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

3801 {
3802  RelFileLocatorBackend rlocator;
3803  char relpersistence;
3804 
3805  /* Set the relpersistence. */
3806  relpersistence = permanent ?
3807  RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
3808 
3809  /*
3810  * Create and copy all forks of the relation. During create database we
3811  * have a separate cleanup mechanism which deletes complete database
3812  * directory. Therefore, each individual relation doesn't need to be
3813  * registered for cleanup.
3814  */
3815  RelationCreateStorage(dst_rlocator, relpersistence, false);
3816 
3817  /* copy main fork. */
3818  RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, MAIN_FORKNUM,
3819  permanent);
3820 
3821  /* copy those extra forks that exist */
3822  for (ForkNumber forkNum = MAIN_FORKNUM + 1;
3823  forkNum <= MAX_FORKNUM; forkNum++)
3824  {
3825  if (smgrexists(smgropen(src_rlocator, InvalidBackendId), forkNum))
3826  {
3827  smgrcreate(smgropen(dst_rlocator, InvalidBackendId), forkNum, false);
3828 
3829  /*
3830  * WAL log creation if the relation is persistent, or this is the
3831  * init fork of an unlogged relation.
3832  */
3833  if (permanent || forkNum == INIT_FORKNUM)
3834  log_smgrcreate(&dst_rlocator, forkNum);
3835 
3836  /* Copy a fork's data, block by block. */
3837  RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, forkNum,
3838  permanent);
3839  }
3840  }
3841 
3842  /* close source and destination smgr if exists. */
3843  rlocator.backend = InvalidBackendId;
3844 
3845  rlocator.locator = src_rlocator;
3846  smgrcloserellocator(rlocator);
3847 
3848  rlocator.locator = dst_rlocator;
3849  smgrcloserellocator(rlocator);
3850 }
#define InvalidBackendId
Definition: backendid.h:23
static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, RelFileLocator dstlocator, ForkNumber forkNum, bool permanent)
Definition: bufmgr.c:3709
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 3413 of file bufmgr.c.

3414 {
3415  int i;
3416 
3417  /*
3418  * We needn't consider local buffers, since by assumption the target
3419  * database isn't our own.
3420  */
3421 
3422  for (i = 0; i < NBuffers; i++)
3423  {
3424  BufferDesc *bufHdr = GetBufferDescriptor(i);
3425  uint32 buf_state;
3426 
3427  /*
3428  * As in DropRelationBuffers, an unlocked precheck should be
3429  * safe and saves some cycles.
3430  */
3431  if (bufHdr->tag.dbOid != dbid)
3432  continue;
3433 
3434  buf_state = LockBufHdr(bufHdr);
3435  if (bufHdr->tag.dbOid == dbid)
3436  InvalidateBuffer(bufHdr); /* releases spinlock */
3437  else
3438  UnlockBufHdr(bufHdr, buf_state);
3439  }
3440 }
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1485
int i
Definition: isn.c:73
Oid dbOid
Definition: buf_internals.h:93

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

3869 {
3870  int i;
3871  BufferDesc *bufHdr;
3872 
3873  /* Make sure we can handle the pin inside the loop */
3875 
3876  for (i = 0; i < NBuffers; i++)
3877  {
3878  uint32 buf_state;
3879 
3880  bufHdr = GetBufferDescriptor(i);
3881 
3882  /*
3883  * As in DropRelationBuffers, an unlocked precheck should be
3884  * safe and saves some cycles.
3885  */
3886  if (bufHdr->tag.dbOid != dbid)
3887  continue;
3888 
3890 
3891  buf_state = LockBufHdr(bufHdr);
3892  if (bufHdr->tag.dbOid == dbid &&
3893  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3894  {
3895  PinBuffer_Locked(bufHdr);
3897  FlushBuffer(bufHdr, NULL);
3899  UnpinBuffer(bufHdr);
3900  }
3901  else
3902  UnlockBufHdr(bufHdr, buf_state);
3903  }
3904 }
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:1807
static void ReservePrivateRefCountEntry(void)
Definition: bufmgr.c:217
static void UnpinBuffer(BufferDesc *buf)
Definition: bufmgr.c:1850
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln)
Definition: bufmgr.c:2823
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1194
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1802
@ LW_SHARED
Definition: lwlock.h:113

References BM_DIRTY, BM_VALID, BufferDescriptorGetContentLock(), CurrentResourceOwner, buftag::dbOid, FlushBuffer(), GetBufferDescriptor(), i, 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 3911 of file bufmgr.c.

3912 {
3913  BufferDesc *bufHdr;
3914 
3915  /* currently not needed, but no fundamental reason not to support */
3916  Assert(!BufferIsLocal(buffer));
3917 
3918  Assert(BufferIsPinned(buffer));
3919 
3920  bufHdr = GetBufferDescriptor(buffer - 1);
3921 
3923 
3924  FlushBuffer(bufHdr, NULL);
3925 }
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1918

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

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

◆ FlushRelationBuffers()

void FlushRelationBuffers ( Relation  rel)

Definition at line 3519 of file bufmgr.c.

3520 {
3521  int i;
3522  BufferDesc *bufHdr;
3523 
3524  if (RelationUsesLocalBuffers(rel))
3525  {
3526  for (i = 0; i < NLocBuffer; i++)
3527  {
3528  uint32 buf_state;
3529 
3530  bufHdr = GetLocalBufferDescriptor(i);
3531  if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
3532  ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
3533  (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3534  {
3535  ErrorContextCallback errcallback;
3536  Page localpage;
3537 
3538  localpage = (char *) LocalBufHdrGetBlock(bufHdr);
3539 
3540  /* Setup error traceback support for ereport() */
3542  errcallback.arg = (void *) bufHdr;
3543  errcallback.previous = error_context_stack;
3544  error_context_stack = &errcallback;
3545 
3546  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
3547 
3549  BufTagGetForkNum(&bufHdr->tag),
3550  bufHdr->tag.blockNum,
3551  localpage,
3552  false);
3553 
3554  buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED);
3555  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
3556 
3557  /* Pop the error context stack */
3558  error_context_stack = errcallback.previous;
3559  }
3560  }
3561 
3562  return;
3563  }
3564 
3565  /* Make sure we can handle the pin inside the loop */
3567 
3568  for (i = 0; i < NBuffers; i++)
3569  {
3570  uint32 buf_state;
3571 
3572  bufHdr = GetBufferDescriptor(i);
3573 
3574  /*
3575  * As in DropRelationBuffers, an unlocked precheck should be
3576  * safe and saves some cycles.
3577  */
3578  if (!BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator))
3579  continue;
3580 
3582 
3583  buf_state = LockBufHdr(bufHdr);
3584  if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
3585  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3586  {
3587  PinBuffer_Locked(bufHdr);
3589  FlushBuffer(bufHdr, RelationGetSmgr(rel));
3591  UnpinBuffer(bufHdr);
3592  }
3593  else
3594  UnlockBufHdr(bufHdr, buf_state);
3595  }
3596 }
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:64
#define LocalBufHdrGetBlock(bufHdr)
Definition: bufmgr.c:66
static void local_buffer_write_error_callback(void *arg)
Definition: bufmgr.c:4708
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1539
ErrorContextCallback * error_context_stack
Definition: elog.c:94
int NLocBuffer
Definition: localbuf.c:41
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:569
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:635
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:554
struct ErrorContextCallback * previous
Definition: elog.h:234
void(* callback)(void *arg)
Definition: elog.h:235
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, local_buffer_write_error_callback(), LocalBufHdrGetBlock, LockBufHdr(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NBuffers, NLocBuffer, PageSetChecksumInplace(), pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), 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(), and parallel_vacuum_main().

◆ 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:937
#define ERROR
Definition: elog.h:35
void * palloc0(Size size)
Definition: mcxt.c:1230
BufferAccessStrategyType btype
Definition: freelist.c:74

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

4381 {
4382  int bufid = GetStartupBufferPinWaitBufId();
4383 
4384  /*
4385  * If we get woken slowly then it's possible that the Startup process was
4386  * already woken by other backends before we got here. Also possible that
4387  * we get here by multiple interrupts or interrupts at inappropriate
4388  * times, so make sure we do nothing if the bufid is not set.
4389  */
4390  if (bufid < 0)
4391  return false;
4392 
4393  if (GetPrivateRefCount(bufid + 1) > 0)
4394  return true;
4395 
4396  return false;
4397 }
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:645

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and RecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

Definition at line 3969 of file bufmgr.c.

3970 {
3971  Assert(BufferIsPinned(buffer));
3973  if (BufferIsLocal(buffer))
3974  LocalRefCount[-buffer - 1]++;
3975  else
3976  {
3977  PrivateRefCountEntry *ref;
3978 
3979  ref = GetPrivateRefCountEntry(buffer, true);
3980  Assert(ref != NULL);
3981  ref->refcount++;
3982  }
3984 }
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:4895
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:729
@ LWTRANCHE_BUFFER_CONTENT
Definition: lwlock.h:185
#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 2611 of file bufmgr.c.

2612 {
2613  HASHCTL hash_ctl;
2614 
2615  memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
2616 
2617  hash_ctl.keysize = sizeof(int32);
2618  hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
2619 
2620  PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
2621  HASH_ELEM | HASH_BLOBS);
2622 
2623  /*
2624  * AtProcExit_Buffers needs LWLock access, and thereby has to be called at
2625  * the corresponding phase of backend shutdown.
2626  */
2627  Assert(MyProc != NULL);
2629 }
static void AtProcExit_Buffers(int code, Datum arg)
Definition: bufmgr.c:2636
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:68
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 4462 of file bufmgr.c.

4463 {
4464  BufferDesc *bufHdr;
4465  uint32 buf_state;
4466 
4467  Assert(BufferIsValid(buffer));
4468 
4469  if (BufferIsLocal(buffer))
4470  {
4471  /* There should be exactly one pin */
4472  if (LocalRefCount[-buffer - 1] != 1)
4473  return false;
4474  /* Nobody else to wait for */
4475  return true;
4476  }
4477 
4478  /* There should be exactly one local pin */
4479  if (GetPrivateRefCount(buffer) != 1)
4480  return false;
4481 
4482  bufHdr = GetBufferDescriptor(buffer - 1);
4483 
4484  /* caller must hold exclusive lock on buffer */
4486  LW_EXCLUSIVE));
4487 
4488  buf_state = LockBufHdr(bufHdr);
4489 
4490  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
4491  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
4492  {
4493  /* pincount is OK. */
4494  UnlockBufHdr(bufHdr, buf_state);
4495  return true;
4496  }
4497 
4498  UnlockBufHdr(bufHdr, buf_state);
4499  return false;
4500 }
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1962

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

4173 {
4174  BufferDesc *buf;
4175 
4176  Assert(BufferIsPinned(buffer));
4177  if (BufferIsLocal(buffer))
4178  return; /* local buffers need no lock */
4179 
4180  buf = GetBufferDescriptor(buffer - 1);
4181 
4182  if (mode == BUFFER_LOCK_UNLOCK)
4184  else if (mode == BUFFER_LOCK_SHARE)
4186  else if (mode == BUFFER_LOCK_EXCLUSIVE)
4188  else
4189  elog(ERROR, "unrecognized buffer lock mode: %d", mode);
4190 }
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:106
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:107
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_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 4229 of file bufmgr.c.

4230 {
4231  BufferDesc *bufHdr;
4232  char *new_status = NULL;
4233  TimestampTz waitStart = 0;
4234  bool logged_recovery_conflict = false;
4235 
4236  Assert(BufferIsPinned(buffer));
4237  Assert(PinCountWaitBuf == NULL);
4238 
4239  if (BufferIsLocal(buffer))
4240  {
4241  /* There should be exactly one pin */
4242  if (LocalRefCount[-buffer - 1] != 1)
4243  elog(ERROR, "incorrect local pin count: %d",
4244  LocalRefCount[-buffer - 1]);
4245  /* Nobody else to wait for */
4246  return;
4247  }
4248 
4249  /* There should be exactly one local pin */
4250  if (GetPrivateRefCount(buffer) != 1)
4251  elog(ERROR, "incorrect local pin count: %d",
4252  GetPrivateRefCount(buffer));
4253 
4254  bufHdr = GetBufferDescriptor(buffer - 1);
4255 
4256  for (;;)
4257  {
4258  uint32 buf_state;
4259 
4260  /* Try to acquire lock */
4262  buf_state = LockBufHdr(bufHdr);
4263 
4264  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
4265  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
4266  {
4267  /* Successfully acquired exclusive lock with pincount 1 */
4268  UnlockBufHdr(bufHdr, buf_state);
4269 
4270  /*
4271  * Emit the log message if recovery conflict on buffer pin was
4272  * resolved but the startup process waited longer than
4273  * deadlock_timeout for it.
4274  */
4275  if (logged_recovery_conflict)
4277  waitStart, GetCurrentTimestamp(),
4278  NULL, false);
4279 
4280  /* Report change to non-waiting status */
4281  if (new_status)
4282  {
4283  set_ps_display(new_status);
4284  pfree(new_status);
4285  }
4286  return;
4287  }
4288  /* Failed, so mark myself as waiting for pincount 1 */
4289  if (buf_state & BM_PIN_COUNT_WAITER)
4290  {
4291  UnlockBufHdr(bufHdr, buf_state);
4292  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4293  elog(ERROR, "multiple backends attempting to wait for pincount 1");
4294  }
4296  PinCountWaitBuf = bufHdr;
4297  buf_state |= BM_PIN_COUNT_WAITER;
4298  UnlockBufHdr(bufHdr, buf_state);
4299  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4300 
4301  /* Wait to be signaled by UnpinBuffer() */
4302  if (InHotStandby)
4303  {
4304  /* Report change to waiting status */
4305  if (update_process_title && new_status == NULL)
4306  {
4307  const char *old_status;
4308  int len;
4309 
4310  old_status = get_ps_display(&len);
4311  new_status = (char *) palloc(len + 8 + 1);
4312  memcpy(new_status, old_status, len);
4313  strcpy(new_status + len, " waiting");
4314  set_ps_display(new_status);
4315  new_status[len] = '\0'; /* truncate off " waiting" */
4316  }
4317 
4318  /*
4319  * Emit the log message if the startup process is waiting longer
4320  * than deadlock_timeout for recovery conflict on buffer pin.
4321  *
4322  * Skip this if first time through because the startup process has
4323  * not started waiting yet in this case. So, the wait start
4324  * timestamp is set after this logic.
4325  */
4326  if (waitStart != 0 && !logged_recovery_conflict)
4327  {
4329 
4330  if (TimestampDifferenceExceeds(waitStart, now,
4331  DeadlockTimeout))
4332  {
4334  waitStart, now, NULL, true);
4335  logged_recovery_conflict = true;
4336  }
4337  }
4338 
4339  /*
4340  * Set the wait start timestamp if logging is enabled and first
4341  * time through.
4342  */
4343  if (log_recovery_conflict_waits && waitStart == 0)
4344  waitStart = GetCurrentTimestamp();
4345 
4346  /* Publish the bufid that Startup process waits on */
4347  SetStartupBufferPinWaitBufId(buffer - 1);
4348  /* Set alarm and then wait to be signaled by UnpinBuffer() */
4350  /* Reset the published bufid */
4352  }
4353  else
4355 
4356  /*
4357  * Remove flag marking us as waiter. Normally this will not be set
4358  * anymore, but ProcWaitForSignal() can return for other signals as
4359  * well. We take care to only reset the flag if we're the waiter, as
4360  * theoretically another backend could have started waiting. That's
4361  * impossible with the current usages due to table level locking, but
4362  * better be safe.
4363  */
4364  buf_state = LockBufHdr(bufHdr);
4365  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
4367  buf_state &= ~BM_PIN_COUNT_WAITER;
4368  UnlockBufHdr(bufHdr, buf_state);
4369 
4370  PinCountWaitBuf = NULL;
4371  /* Loop back and try again */
4372  }
4373 }
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1719
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1573
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1537
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:65
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:167
int64 TimestampTz
Definition: timestamp.h:39
void * palloc(Size size)
Definition: mcxt.c:1199
const void size_t len
@ PROCSIG_RECOVERY_CONFLICT_BUFFERPIN
Definition: procsignal.h:44
const char * get_ps_display(int *displen)
Definition: ps_status.c:414
bool update_process_title
Definition: ps_status.c:35
void set_ps_display(const char *activity)
Definition: ps_status.c:342
int DeadlockTimeout
Definition: proc.c:60
void SetStartupBufferPinWaitBufId(int bufid)
Definition: proc.c:633
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1878
void ResolveRecoveryConflictWithBufferPin(void)
Definition: standby.c:787
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, get_ps_display(), GetBufferDescriptor(), GetCurrentTimestamp(), GetPrivateRefCount(), InHotStandby, len, LocalRefCount, LockBuffer(), LockBufHdr(), log_recovery_conflict_waits, LogRecoveryConflict(), MyProc, now(), palloc(), pfree(), PG_WAIT_BUFFER_PIN, PGPROC::pgprocno, PinCountWaitBuf, PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, ProcWaitForSignal(), ResolveRecoveryConflictWithBufferPin(), set_ps_display(), SetStartupBufferPinWaitBufId(), TimestampDifferenceExceeds(), UnlockBufHdr(), update_process_title, and BufferDesc::wait_backend_pgprocno.

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

◆ MarkBufferDirty()

void MarkBufferDirty ( Buffer  buffer)

Definition at line 1583 of file bufmgr.c.

1584 {
1585  BufferDesc *bufHdr;
1586  uint32 buf_state;
1587  uint32 old_buf_state;
1588 
1589  if (!BufferIsValid(buffer))
1590  elog(ERROR, "bad buffer ID: %d", buffer);
1591 
1592  if (BufferIsLocal(buffer))
1593  {
1594  MarkLocalBufferDirty(buffer);
1595  return;
1596  }
1597 
1598  bufHdr = GetBufferDescriptor(buffer - 1);
1599 
1600  Assert(BufferIsPinned(buffer));
1602  LW_EXCLUSIVE));
1603 
1604  old_buf_state = pg_atomic_read_u32(&bufHdr->state);
1605  for (;;)
1606  {
1607  if (old_buf_state & BM_LOCKED)
1608  old_buf_state = WaitBufHdrUnlocked(bufHdr);
1609 
1610  buf_state = old_buf_state;
1611 
1612  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
1613  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
1614 
1615  if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
1616  buf_state))
1617  break;
1618  }
1619 
1620  /*
1621  * If the buffer was not dirty already, do vacuum accounting.
1622  */
1623  if (!(old_buf_state & BM_DIRTY))
1624  {
1625  VacuumPageDirty++;
1627  if (VacuumCostActive)
1629  }
1630 }
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:58
static uint32 WaitBufHdrUnlocked(BufferDesc *buf)
Definition: bufmgr.c:4783
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:286
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 4001 of file bufmgr.c.

4002 {
4003  BufferDesc *bufHdr;
4004  Page page = BufferGetPage(buffer);
4005 
4006  if (!BufferIsValid(buffer))
4007  elog(ERROR, "bad buffer ID: %d", buffer);
4008 
4009  if (BufferIsLocal(buffer))
4010  {
4011  MarkLocalBufferDirty(buffer);
4012  return;
4013  }
4014 
4015  bufHdr = GetBufferDescriptor(buffer - 1);
4016 
4017  Assert(GetPrivateRefCount(buffer) > 0);
4018  /* here, either share or exclusive lock is OK */
4020 
4021  /*
4022  * This routine might get called many times on the same page, if we are
4023  * making the first scan after commit of an xact that added/deleted many
4024  * tuples. So, be as quick as we can if the buffer is already dirty. We
4025  * do this by not acquiring spinlock if it looks like the status bits are
4026  * already set. Since we make this test unlocked, there's a chance we
4027  * might fail to notice that the flags have just been cleared, and failed
4028  * to reset them, due to memory-ordering issues. But since this function
4029  * is only intended to be used in cases where failing to write out the
4030  * data would be harmless anyway, it doesn't really matter.
4031  */
4032  if ((pg_atomic_read_u32(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
4034  {
4036  bool dirtied = false;
4037  bool delayChkptFlags = false;
4038  uint32 buf_state;
4039 
4040  /*
4041  * If we need to protect hint bit updates from torn writes, WAL-log a
4042  * full page image of the page. This full page image is only necessary
4043  * if the hint bit update is the first change to the page since the
4044  * last checkpoint.
4045  *
4046  * We don't check full_page_writes here because that logic is included
4047  * when we call XLogInsert() since the value changes dynamically.
4048  */
4049  if (XLogHintBitIsNeeded() &&
4050  (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT))
4051  {
4052  /*
4053  * If we must not write WAL, due to a relfilelocator-specific
4054  * condition or being in recovery, don't dirty the page. We can
4055  * set the hint, just not dirty the page as a result so the hint
4056  * is lost when we evict the page or shutdown.
4057  *
4058  * See src/backend/storage/page/README for longer discussion.
4059  */
4060  if (RecoveryInProgress() ||
4062  return;
4063 
4064  /*
4065  * If the block is already dirty because we either made a change
4066  * or set a hint already, then we don't need to write a full page
4067  * image. Note that aggressive cleaning of blocks dirtied by hint
4068  * bit setting would increase the call rate. Bulk setting of hint
4069  * bits would reduce the call rate...
4070  *
4071  * We must issue the WAL record before we mark the buffer dirty.
4072  * Otherwise we might write the page before we write the WAL. That
4073  * causes a race condition, since a checkpoint might occur between
4074  * writing the WAL record and marking the buffer dirty. We solve
4075  * that with a kluge, but one that is already in use during
4076  * transaction commit to prevent race conditions. Basically, we
4077  * simply prevent the checkpoint WAL record from being written
4078  * until we have marked the buffer dirty. We don't start the
4079  * checkpoint flush until we have marked dirty, so our checkpoint
4080  * must flush the change to disk successfully or the checkpoint
4081  * never gets written, so crash recovery will fix.
4082  *
4083  * It's possible we may enter here without an xid, so it is
4084  * essential that CreateCheckPoint waits for virtual transactions
4085  * rather than full transactionids.
4086  */
4089  delayChkptFlags = true;
4090  lsn = XLogSaveBufferForHint(buffer, buffer_std);
4091  }
4092 
4093  buf_state = LockBufHdr(bufHdr);
4094 
4095  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
4096 
4097  if (!(buf_state & BM_DIRTY))
4098  {
4099  dirtied = true; /* Means "will be dirtied by this action" */
4100 
4101  /*
4102  * Set the page LSN if we wrote a backup block. We aren't supposed
4103  * to set this when only holding a share lock but as long as we
4104  * serialise it somehow we're OK. We choose to set LSN while
4105  * holding the buffer header lock, which causes any reader of an
4106  * LSN who holds only a share lock to also obtain a buffer header
4107  * lock before using PageGetLSN(), which is enforced in
4108  * BufferGetLSNAtomic().
4109  *
4110  * If checksums are enabled, you might think we should reset the
4111  * checksum here. That will happen when the page is written
4112  * sometime later in this checkpoint cycle.
4113  */
4114  if (!XLogRecPtrIsInvalid(lsn))
4115  PageSetLSN(page, lsn);
4116  }
4117 
4118  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
4119  UnlockBufHdr(bufHdr, buf_state);
4120 
4121  if (delayChkptFlags)
4123 
4124  if (dirtied)
4125  {
4126  VacuumPageDirty++;
4128  if (VacuumCostActive)
4130  }
4131  }
4132 }
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:5912
#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 592 of file bufmgr.c.

593 {
594  Assert(RelationIsValid(reln));
595  Assert(BlockNumberIsValid(blockNum));
596 
597  if (RelationUsesLocalBuffers(reln))
598  {
599  /* see comments in ReadBufferExtended */
600  if (RELATION_IS_OTHER_TEMP(reln))
601  ereport(ERROR,
602  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
603  errmsg("cannot access temporary tables of other sessions")));
604 
605  /* pass it off to localbuf.c */
606  return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
607  }
608  else
609  {
610  /* pass it to the shared buffer version */
611  return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
612  }
613 }
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:505
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition: localbuf.c:64
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:656
#define RelationIsValid(relation)
Definition: rel.h:474

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

2696 {
2697  BufferDesc *buf;
2698  int32 loccount;
2699  char *path;
2700  BackendId backend;
2701  uint32 buf_state;
2702 
2703  Assert(BufferIsValid(buffer));
2704  if (BufferIsLocal(buffer))
2705  {
2706  buf = GetLocalBufferDescriptor(-buffer - 1);
2707  loccount = LocalRefCount[-buffer - 1];
2708  backend = MyBackendId;
2709  }
2710  else
2711  {
2712  buf = GetBufferDescriptor(buffer - 1);
2713  loccount = GetPrivateRefCount(buffer);
2714  backend = InvalidBackendId;
2715  }
2716 
2717  /* theoretically we should lock the bufhdr here */
2718  path = relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
2719  BufTagGetForkNum(&buf->tag));
2720  buf_state = pg_atomic_read_u32(&buf->state);
2721  elog(WARNING,
2722  "buffer refcount leak: [%03d] "
2723  "(rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
2724  buffer, path,
2725  buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
2726  BUF_STATE_GET_REFCOUNT(buf_state), loccount);
2727  pfree(path);
2728 }
int BackendId
Definition: backendid.h:21
#define BUF_FLAG_MASK
Definition: buf_internals.h:46
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 712 of file bufmgr.c.

713 {
714  return ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);
715 }
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:759

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

761 {
762  bool hit;
763  Buffer buf;
764 
765  /*
766  * Reject attempts to read non-local temporary relations; we would be
767  * likely to get wrong data since we have no visibility into the owning
768  * session's local buffers.
769  */
770  if (RELATION_IS_OTHER_TEMP(reln))
771  ereport(ERROR,
772  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
773  errmsg("cannot access temporary tables of other sessions")));
774 
775  /*
776  * Read the buffer, and update pgstat counters to reflect a cache hit or
777  * miss.
778  */
780  buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
781  forkNum, blockNum, mode, strategy, &hit);
782  if (hit)
784  return buf;
785 }
static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool *hit)
Definition: bufmgr.c:819
#define pgstat_count_buffer_read(rel)
Definition: pgstat.h:550
#define pgstat_count_buffer_hit(rel)
Definition: pgstat.h:555
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 799 of file bufmgr.c.

802 {
803  bool hit;
804 
805  SMgrRelation smgr = smgropen(rlocator, InvalidBackendId);
806 
807  return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
808  RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
809  mode, strategy, &hit);
810 }

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

625 {
626  BufferDesc *bufHdr;
627  BufferTag tag;
628  uint32 buf_state;
629  bool have_private_ref;
630 
631  Assert(BufferIsValid(recent_buffer));
632 
635  InitBufferTag(&tag, &rlocator, forkNum, blockNum);
636 
637  if (BufferIsLocal(recent_buffer))
638  {
639  int b = -recent_buffer - 1;
640 
641  bufHdr = GetLocalBufferDescriptor(b);
642  buf_state = pg_atomic_read_u32(&bufHdr->state);
643 
644  /* Is it still valid and holding the right tag? */
645  if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
646  {
647  /*
648  * Bump buffer's ref and usage counts. This is equivalent of
649  * PinBuffer for a shared buffer.
650  */
651  if (LocalRefCount[b] == 0)
652  {
654  {
655  buf_state += BUF_USAGECOUNT_ONE;
656  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
657  }
658  }
659  LocalRefCount[b]++;
661 
663 
664  return true;
665  }
666  }
667  else
668  {
669  bufHdr = GetBufferDescriptor(recent_buffer - 1);
670  have_private_ref = GetPrivateRefCount(recent_buffer) > 0;
671 
672  /*
673  * Do we already have this buffer pinned with a private reference? If
674  * so, it must be valid and it is safe to check the tag without
675  * locking. If not, we have to lock the header first and then check.
676  */
677  if (have_private_ref)
678  buf_state = pg_atomic_read_u32(&bufHdr->state);
679  else
680  buf_state = LockBufHdr(bufHdr);
681 
682  if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
683  {
684  /*
685  * It's now safe to pin the buffer. We can't pin first and ask
686  * questions later, because it might confuse code paths like
687  * InvalidateBuffer() if we pinned a random non-matching buffer.
688  */
689  if (have_private_ref)
690  PinBuffer(bufHdr, NULL); /* bump pin count */
691  else
692  PinBuffer_Locked(bufHdr); /* pin for first time */
693 
695 
696  return true;
697  }
698 
699  /* If we locked the header above, now unlock. */
700  if (!have_private_ref)
701  UnlockBufHdr(bufHdr, buf_state);
702  }
703 
704  return false;
705 }
#define BM_MAX_USAGE_COUNT
Definition: buf_internals.h:76
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:50
#define BUF_USAGECOUNT_ONE
Definition: buf_internals.h:44
static bool PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
Definition: bufmgr.c:1704
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 2950 of file bufmgr.c.

2951 {
2952  if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
2953  {
2954  /*
2955  * Not every table AM uses BLCKSZ wide fixed size blocks. Therefore
2956  * tableam returns the size in bytes - but for the purpose of this
2957  * routine, we want the number of blocks. Therefore divide, rounding
2958  * up.
2959  */
2960  uint64 szbytes;
2961 
2962  szbytes = table_relation_size(relation, forkNum);
2963 
2964  return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
2965  }
2966  else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
2967  {
2968  return smgrnblocks(RelationGetSmgr(relation), forkNum);
2969  }
2970  else
2971  Assert(false);
2972 
2973  return 0; /* keep compiler quiet */
2974 }
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:579
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition: tableam.h:1841

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

1649 {
1650  ForkNumber forkNum = MAIN_FORKNUM;
1651  BufferDesc *bufHdr;
1652 
1653  if (BufferIsValid(buffer))
1654  {
1655  Assert(BufferIsPinned(buffer));
1656  if (BufferIsLocal(buffer))
1657  {
1658  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
1659  if (bufHdr->tag.blockNum == blockNum &&
1660  BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
1661  BufTagGetForkNum(&bufHdr->tag) == forkNum)
1662  return buffer;
1664  LocalRefCount[-buffer - 1]--;
1665  }
1666  else
1667  {
1668  bufHdr = GetBufferDescriptor(buffer - 1);
1669  /* we have pin, so it's ok to examine tag without spinlock */
1670  if (bufHdr->tag.blockNum == blockNum &&
1671  BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
1672  BufTagGetForkNum(&bufHdr->tag) == forkNum)
1673  return buffer;
1674  UnpinBuffer(bufHdr);
1675  }
1676  }
1677 
1678  return ReadBuffer(relation, blockNum);
1679 }
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:712
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 3931 of file bufmgr.c.

3932 {
3933  if (!BufferIsValid(buffer))
3934  elog(ERROR, "bad buffer ID: %d", buffer);
3935 
3936  if (BufferIsLocal(buffer))
3937  {
3939 
3940  Assert(LocalRefCount[-buffer - 1] > 0);
3941  LocalRefCount[-buffer - 1]--;
3942  return;
3943  }
3944 
3945  UnpinBuffer(GetBufferDescriptor(buffer - 1));
3946 }

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(), 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 303 of file bufmgr.h.

304 {
305  Assert(relation != NULL);
306 
307  if (old_snapshot_threshold >= 0
308  && (snapshot) != NULL
309  && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
310  || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
311  && !XLogRecPtrIsInvalid((snapshot)->lsn)
312  && PageGetLSN(page) > (snapshot)->lsn)
313  TestForOldSnapshot_impl(snapshot, relation);
314 }
void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation)
Definition: bufmgr.c:5025
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(), heapgettup_pagemode(), scanGetCandidate(), scanPendingInsert(), and spgWalk().

◆ TestForOldSnapshot_impl()

void TestForOldSnapshot_impl ( Snapshot  snapshot,
Relation  relation 
)

Definition at line 5025 of file bufmgr.c.

5026 {
5027  if (RelationAllowsEarlyPruning(relation)
5028  && (snapshot)->whenTaken < GetOldSnapshotThresholdTimestamp())
5029  ereport(ERROR,
5030  (errcode(ERRCODE_SNAPSHOT_TOO_OLD),
5031  errmsg("snapshot too old")));
5032 }
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 4144 of file bufmgr.c.

4145 {
4147 
4148  if (buf)
4149  {
4150  uint32 buf_state;
4151 
4152  buf_state = LockBufHdr(buf);
4153 
4154  /*
4155  * Don't complain if flag bit not set; it could have been reset but we
4156  * got a cancel/die interrupt before getting the signal.
4157  */
4158  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
4159  buf->wait_backend_pgprocno == MyProc->pgprocno)
4160  buf_state &= ~BM_PIN_COUNT_WAITER;
4161 
4162  UnlockBufHdr(buf, buf_state);
4163 
4164  PinCountWaitBuf = NULL;
4165  }
4166 }

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

3955 {
3956  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3957  ReleaseBuffer(buffer);
3958 }
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3931

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