PostgreSQL Source Code  git master
bufmgr.h File Reference
#include "storage/block.h"
#include "storage/buf.h"
#include "storage/bufpage.h"
#include "storage/relfilenode.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 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 BufferIsValid(bufnum)
 
#define BufferGetBlock(buffer)
 
#define BufferGetPageSize(buffer)
 
#define BufferGetPage(buffer)   ((Page)BufferGetBlock(buffer))
 
#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 (RelFileNode rnode, 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 (RelFileNode rnode, 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 InitBufferPool (void)
 
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 (RelFileNode src_rnode, RelFileNode dst_rnode, bool permanent)
 
void FlushDatabaseBuffers (Oid dbid)
 
void DropRelFileNodeBuffers (struct SMgrRelationData *smgr_reln, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
 
void DropRelFileNodesAllBuffers (struct SMgrRelationData **smgr_reln, int nnodes)
 
void DropDatabaseBuffers (Oid dbid)
 
bool BufferIsPermanent (Buffer buffer)
 
XLogRecPtr BufferGetLSNAtomic (Buffer buffer)
 
Size BufferShmemSize (void)
 
void BufferGetTag (Buffer buffer, RelFileNode *rnode, 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 AtProcExit_LocalBuffers (void)
 
void TestForOldSnapshot_impl (Snapshot snapshot, Relation relation)
 
BufferAccessStrategy GetAccessStrategy (BufferAccessStrategyType btype)
 
void FreeAccessStrategy (BufferAccessStrategy strategy)
 
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 98 of file bufmgr.h.

◆ BUFFER_LOCK_SHARE

#define BUFFER_LOCK_SHARE   1

Definition at line 97 of file bufmgr.h.

◆ BUFFER_LOCK_UNLOCK

#define BUFFER_LOCK_UNLOCK   0

Definition at line 96 of file bufmgr.h.

◆ BufferGetBlock

#define BufferGetBlock (   buffer)
Value:
( \
AssertMacro(BufferIsValid(buffer)), \
BufferIsLocal(buffer) ? \
LocalBufferBlockPointers[-(buffer) - 1] \
: \
(Block) (BufferBlocks + ((Size) ((buffer) - 1)) * BLCKSZ) \
)
void * Block
Definition: bufmgr.h:24
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
PGDLLIMPORT char * BufferBlocks
Definition: buf_init.c:22
size_t Size
Definition: c.h:540

Definition at line 136 of file bufmgr.h.

◆ BufferGetPage

#define BufferGetPage (   buffer)    ((Page)BufferGetBlock(buffer))

Definition at line 169 of file bufmgr.h.

◆ BufferGetPageSize

#define BufferGetPageSize (   buffer)
Value:
( \
AssertMacro(BufferIsValid(buffer)), \
(Size)BLCKSZ \
)

Definition at line 156 of file bufmgr.h.

◆ BufferIsValid

#define BufferIsValid (   bufnum)
Value:
( \
AssertMacro((bufnum) <= NBuffers && (bufnum) >= -NLocBuffer), \
(bufnum) != InvalidBuffer \
)
#define InvalidBuffer
Definition: buf.h:25
PGDLLIMPORT int NBuffers
Definition: globals.c:136
PGDLLIMPORT int NLocBuffer
Definition: localbuf.c:41

Definition at line 123 of file bufmgr.h.

◆ MAX_IO_CONCURRENCY

#define MAX_IO_CONCURRENCY   1000

Definition at line 88 of file bufmgr.h.

◆ P_NEW

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

Definition at line 91 of file bufmgr.h.

◆ RelationGetNumberOfBlocks

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

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

4627 {
4629 
4630  if (buf)
4631  {
4632  uint32 buf_state;
4633 
4634  buf_state = LockBufHdr(buf);
4635  Assert(buf_state & BM_IO_IN_PROGRESS);
4636  if (IsForInput)
4637  {
4638  Assert(!(buf_state & BM_DIRTY));
4639 
4640  /* We'd better not think buffer is valid yet */
4641  Assert(!(buf_state & BM_VALID));
4642  UnlockBufHdr(buf, buf_state);
4643  }
4644  else
4645  {
4646  Assert(buf_state & BM_DIRTY);
4647  UnlockBufHdr(buf, buf_state);
4648  /* Issue notice if this is not the first failure... */
4649  if (buf_state & BM_IO_ERROR)
4650  {
4651  /* Buffer is pinned, so we can read tag without spinlock */
4652  char *path;
4653 
4654  path = relpathperm(buf->tag.rnode, buf->tag.forkNum);
4655  ereport(WARNING,
4656  (errcode(ERRCODE_IO_ERROR),
4657  errmsg("could not write block %u of %s",
4658  buf->tag.blockNum, path),
4659  errdetail("Multiple failures --- write error might be permanent.")));
4660  pfree(path);
4661  }
4662  }
4664  }
4665 }
#define BM_DIRTY
Definition: buf_internals.h:59
#define BM_IO_IN_PROGRESS
Definition: buf_internals.h:62
#define UnlockBufHdr(desc, s)
#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:4736
static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits)
Definition: bufmgr.c:4594
unsigned int uint32
Definition: c.h:441
int errdetail(const char *fmt,...)
Definition: elog.c:1037
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define WARNING
Definition: elog.h:30
#define ereport(elevel,...)
Definition: elog.h:143
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1175
static char * buf
Definition: pg_test_fsync.c:67
#define relpathperm(rnode, forknum)
Definition: relpath.h:83

References Assert(), BM_DIRTY, BM_IO_ERROR, BM_IO_IN_PROGRESS, BM_VALID, buf, 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 2587 of file bufmgr.c.

2588 {
2590 
2591  AtEOXact_LocalBuffers(isCommit);
2592 
2594 }
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:2648
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:201
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:577

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

589 {
590  /*
591  * We shouldn't be holding any remaining pins; if we are, and assertions
592  * aren't enabled, we'll fail later in DropRelFileNodeBuffers while trying
593  * to drop the temp rels.
594  */
596 }
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:548

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

◆ BgBufferSync()

bool BgBufferSync ( struct WritebackContext wb_context)

Definition at line 2217 of file bufmgr.c.

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

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)

Definition at line 2755 of file bufmgr.c.

2756 {
2757  BufferDesc *bufHdr;
2758 
2759  Assert(BufferIsPinned(buffer));
2760 
2761  if (BufferIsLocal(buffer))
2762  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2763  else
2764  bufHdr = GetBufferDescriptor(buffer - 1);
2765 
2766  /* pinned, so OK to read tag without spinlock */
2767  return bufHdr->tag.blockNum;
2768 }
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define GetBufferDescriptor(id)
#define GetLocalBufferDescriptor(id)
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:450
BufferTag tag
BlockNumber blockNum
Definition: buf_internals.h:94

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

3005 {
3006  BufferDesc *bufHdr = GetBufferDescriptor(buffer - 1);
3007  char *page = BufferGetPage(buffer);
3008  XLogRecPtr lsn;
3009  uint32 buf_state;
3010 
3011  /*
3012  * If we don't need locking for correctness, fastpath out.
3013  */
3014  if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
3015  return PageGetLSN(page);
3016 
3017  /* Make sure we've got a real buffer, and that we hold a pin on it. */
3018  Assert(BufferIsValid(buffer));
3019  Assert(BufferIsPinned(buffer));
3020 
3021  buf_state = LockBufHdr(bufHdr);
3022  lsn = PageGetLSN(page);
3023  UnlockBufHdr(bufHdr, buf_state);
3024 
3025  return lsn;
3026 }
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define PageGetLSN(page)
Definition: bufpage.h:365
#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().

◆ BufferGetTag()

void BufferGetTag ( Buffer  buffer,
RelFileNode rnode,
ForkNumber forknum,
BlockNumber blknum 
)

Definition at line 2776 of file bufmgr.c.

2778 {
2779  BufferDesc *bufHdr;
2780 
2781  /* Do the same checks as BufferGetBlockNumber. */
2782  Assert(BufferIsPinned(buffer));
2783 
2784  if (BufferIsLocal(buffer))
2785  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2786  else
2787  bufHdr = GetBufferDescriptor(buffer - 1);
2788 
2789  /* pinned, so OK to read tag without spinlock */
2790  *rnode = bufHdr->tag.rnode;
2791  *forknum = bufHdr->tag.forkNum;
2792  *blknum = bufHdr->tag.blockNum;
2793 }
ForkNumber forkNum
Definition: buf_internals.h:93
RelFileNode rnode
Definition: buf_internals.h:92

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

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

◆ BufferIsPermanent()

bool BufferIsPermanent ( Buffer  buffer)

Definition at line 2974 of file bufmgr.c.

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

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

2742 {
2743  /* Nothing to do in bufmgr anymore... */
2744 }

Referenced by PrepareTransaction(), and RecordTransactionCommit().

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)

Definition at line 2731 of file bufmgr.c.

2732 {
2733  BufferSync(flags);
2734 }
static void BufferSync(int flags)
Definition: bufmgr.c:1941

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

Definition at line 4182 of file bufmgr.c.

4183 {
4184  BufferDesc *buf;
4185 
4186  Assert(BufferIsPinned(buffer));
4187  if (BufferIsLocal(buffer))
4188  return true; /* act as though we got it */
4189 
4190  buf = GetBufferDescriptor(buffer - 1);
4191 
4193  LW_EXCLUSIVE);
4194 }
#define BufferDescriptorGetContentLock(bdesc)
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1367
@ LW_EXCLUSIVE
Definition: lwlock.h:104

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

4391 {
4392  BufferDesc *bufHdr;
4393  uint32 buf_state,
4394  refcount;
4395 
4396  Assert(BufferIsValid(buffer));
4397 
4398  if (BufferIsLocal(buffer))
4399  {
4400  refcount = LocalRefCount[-buffer - 1];
4401  /* There should be exactly one pin */
4402  Assert(refcount > 0);
4403  if (refcount != 1)
4404  return false;
4405  /* Nobody else to wait for */
4406  return true;
4407  }
4408 
4409  /* There should be exactly one local pin */
4410  refcount = GetPrivateRefCount(buffer);
4411  Assert(refcount);
4412  if (refcount != 1)
4413  return false;
4414 
4415  /* Try to acquire lock */
4416  if (!ConditionalLockBuffer(buffer))
4417  return false;
4418 
4419  bufHdr = GetBufferDescriptor(buffer - 1);
4420  buf_state = LockBufHdr(bufHdr);
4421  refcount = BUF_STATE_GET_REFCOUNT(buf_state);
4422 
4423  Assert(refcount > 0);
4424  if (refcount == 1)
4425  {
4426  /* Successfully acquired exclusive lock with pincount 1 */
4427  UnlockBufHdr(bufHdr, buf_state);
4428  return true;
4429  }
4430 
4431  /* Failed, so release the lock */
4432  UnlockBufHdr(bufHdr, buf_state);
4433  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
4434  return false;
4435 }
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:49
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:4182
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:389
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4156
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:96
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 ( RelFileNode  src_rnode,
RelFileNode  dst_rnode,
bool  permanent 
)

Definition at line 3778 of file bufmgr.c.

3780 {
3781  Relation src_rel;
3782  Relation dst_rel;
3783  char relpersistence;
3784 
3785  /* Set the relpersistence. */
3786  relpersistence = permanent ?
3787  RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
3788 
3789  /*
3790  * We can't use a real relcache entry for a relation in some other
3791  * database, but since we're only going to access the fields related to
3792  * physical storage, a fake one is good enough. If we didn't do this and
3793  * used the smgr layer directly, we would have to worry about
3794  * invalidations.
3795  */
3796  src_rel = CreateFakeRelcacheEntry(src_rnode);
3797  dst_rel = CreateFakeRelcacheEntry(dst_rnode);
3798 
3799  /*
3800  * Create and copy all forks of the relation. During create database we
3801  * have a separate cleanup mechanism which deletes complete database
3802  * directory. Therefore, each individual relation doesn't need to be
3803  * registered for cleanup.
3804  */
3805  RelationCreateStorage(dst_rnode, relpersistence, false);
3806 
3807  /* copy main fork. */
3808  RelationCopyStorageUsingBuffer(src_rel, dst_rel, MAIN_FORKNUM, permanent);
3809 
3810  /* copy those extra forks that exist */
3811  for (ForkNumber forkNum = MAIN_FORKNUM + 1;
3812  forkNum <= MAX_FORKNUM; forkNum++)
3813  {
3814  if (smgrexists(RelationGetSmgr(src_rel), forkNum))
3815  {
3816  smgrcreate(RelationGetSmgr(dst_rel), forkNum, false);
3817 
3818  /*
3819  * WAL log creation if the relation is persistent, or this is the
3820  * init fork of an unlogged relation.
3821  */
3822  if (permanent || forkNum == INIT_FORKNUM)
3823  log_smgrcreate(&dst_rnode, forkNum);
3824 
3825  /* Copy a fork's data, block by block. */
3826  RelationCopyStorageUsingBuffer(src_rel, dst_rel, forkNum,
3827  permanent);
3828  }
3829  }
3830 
3831  /* Release fake relcache entries. */
3832  FreeFakeRelcacheEntry(src_rel);
3833  FreeFakeRelcacheEntry(dst_rel);
3834 }
static void RelationCopyStorageUsingBuffer(Relation src, Relation dst, ForkNumber forkNum, bool isunlogged)
Definition: bufmgr.c:3695
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:556
ForkNumber
Definition: relpath.h:41
@ MAIN_FORKNUM
Definition: relpath.h:43
@ INIT_FORKNUM
Definition: relpath.h:46
#define MAX_FORKNUM
Definition: relpath.h:55
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:369
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:247
SMgrRelation RelationCreateStorage(RelFileNode rnode, char relpersistence, bool register_delete)
Definition: storage.c:120
void log_smgrcreate(const RelFileNode *rnode, ForkNumber forkNum)
Definition: storage.c:185
void FreeFakeRelcacheEntry(Relation fakerel)
Definition: xlogutils.c:640
Relation CreateFakeRelcacheEntry(RelFileNode rnode)
Definition: xlogutils.c:597

References CreateFakeRelcacheEntry(), FreeFakeRelcacheEntry(), INIT_FORKNUM, log_smgrcreate(), MAIN_FORKNUM, MAX_FORKNUM, RelationCopyStorageUsingBuffer(), RelationCreateStorage(), RelationGetSmgr(), smgrcreate(), and smgrexists().

Referenced by CreateDatabaseUsingWalLog().

◆ DropDatabaseBuffers()

void DropDatabaseBuffers ( Oid  dbid)

Definition at line 3404 of file bufmgr.c.

3405 {
3406  int i;
3407 
3408  /*
3409  * We needn't consider local buffers, since by assumption the target
3410  * database isn't our own.
3411  */
3412 
3413  for (i = 0; i < NBuffers; i++)
3414  {
3415  BufferDesc *bufHdr = GetBufferDescriptor(i);
3416  uint32 buf_state;
3417 
3418  /*
3419  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3420  * and saves some cycles.
3421  */
3422  if (bufHdr->tag.rnode.dbNode != dbid)
3423  continue;
3424 
3425  buf_state = LockBufHdr(bufHdr);
3426  if (bufHdr->tag.rnode.dbNode == dbid)
3427  InvalidateBuffer(bufHdr); /* releases spinlock */
3428  else
3429  UnlockBufHdr(bufHdr, buf_state);
3430  }
3431 }
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1475
int i
Definition: isn.c:73

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

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

◆ DropRelFileNodeBuffers()

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

◆ DropRelFileNodesAllBuffers()

void DropRelFileNodesAllBuffers ( struct SMgrRelationData **  smgr_reln,
int  nnodes 
)

◆ FlushDatabaseBuffers()

void FlushDatabaseBuffers ( Oid  dbid)

Definition at line 3852 of file bufmgr.c.

3853 {
3854  int i;
3855  BufferDesc *bufHdr;
3856 
3857  /* Make sure we can handle the pin inside the loop */
3859 
3860  for (i = 0; i < NBuffers; i++)
3861  {
3862  uint32 buf_state;
3863 
3864  bufHdr = GetBufferDescriptor(i);
3865 
3866  /*
3867  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3868  * and saves some cycles.
3869  */
3870  if (bufHdr->tag.rnode.dbNode != dbid)
3871  continue;
3872 
3874 
3875  buf_state = LockBufHdr(bufHdr);
3876  if (bufHdr->tag.rnode.dbNode == dbid &&
3877  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3878  {
3879  PinBuffer_Locked(bufHdr);
3881  FlushBuffer(bufHdr, NULL);
3883  UnpinBuffer(bufHdr, true);
3884  }
3885  else
3886  UnlockBufHdr(bufHdr, buf_state);
3887  }
3888 }
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:1797
static void ReservePrivateRefCountEntry(void)
Definition: bufmgr.c:217
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln)
Definition: bufmgr.c:2815
static void UnpinBuffer(BufferDesc *buf, bool fixOwner)
Definition: bufmgr.c:1842
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1196
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1800
@ LW_SHARED
Definition: lwlock.h:105

References BM_DIRTY, BM_VALID, BufferDescriptorGetContentLock, CurrentResourceOwner, RelFileNode::dbNode, FlushBuffer(), GetBufferDescriptor, i, LockBufHdr(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NBuffers, PinBuffer_Locked(), ReservePrivateRefCountEntry(), ResourceOwnerEnlargeBuffers(), buftag::rnode, BufferDesc::tag, UnlockBufHdr, and UnpinBuffer().

Referenced by dbase_redo().

◆ FlushOneBuffer()

void FlushOneBuffer ( Buffer  buffer)

Definition at line 3895 of file bufmgr.c.

3896 {
3897  BufferDesc *bufHdr;
3898 
3899  /* currently not needed, but no fundamental reason not to support */
3900  Assert(!BufferIsLocal(buffer));
3901 
3902  Assert(BufferIsPinned(buffer));
3903 
3904  bufHdr = GetBufferDescriptor(buffer - 1);
3905 
3907 
3908  FlushBuffer(bufHdr, NULL);
3909 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1916

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

3509 {
3510  int i;
3511  BufferDesc *bufHdr;
3512 
3513  if (RelationUsesLocalBuffers(rel))
3514  {
3515  for (i = 0; i < NLocBuffer; i++)
3516  {
3517  uint32 buf_state;
3518 
3519  bufHdr = GetLocalBufferDescriptor(i);
3520  if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
3521  ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
3522  (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3523  {
3524  ErrorContextCallback errcallback;
3525  Page localpage;
3526 
3527  localpage = (char *) LocalBufHdrGetBlock(bufHdr);
3528 
3529  /* Setup error traceback support for ereport() */
3531  errcallback.arg = (void *) bufHdr;
3532  errcallback.previous = error_context_stack;
3533  error_context_stack = &errcallback;
3534 
3535  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
3536 
3538  bufHdr->tag.forkNum,
3539  bufHdr->tag.blockNum,
3540  localpage,
3541  false);
3542 
3543  buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED);
3544  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
3545 
3546  /* Pop the error context stack */
3547  error_context_stack = errcallback.previous;
3548  }
3549  }
3550 
3551  return;
3552  }
3553 
3554  /* Make sure we can handle the pin inside the loop */
3556 
3557  for (i = 0; i < NBuffers; i++)
3558  {
3559  uint32 buf_state;
3560 
3561  bufHdr = GetBufferDescriptor(i);
3562 
3563  /*
3564  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3565  * and saves some cycles.
3566  */
3567  if (!RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
3568  continue;
3569 
3571 
3572  buf_state = LockBufHdr(bufHdr);
3573  if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
3574  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3575  {
3576  PinBuffer_Locked(bufHdr);
3578  FlushBuffer(bufHdr, RelationGetSmgr(rel));
3580  UnpinBuffer(bufHdr, true);
3581  }
3582  else
3583  UnlockBufHdr(bufHdr, buf_state);
3584  }
3585 }
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:277
#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:4690
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1539
Pointer Page
Definition: bufpage.h:78
ErrorContextCallback * error_context_stack
Definition: elog.c:93
int NLocBuffer
Definition: localbuf.c:41
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:622
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:554
struct ErrorContextCallback * previous
Definition: elog.h:232
void(* callback)(void *arg)
Definition: elog.h:233
RelFileNode rd_node
Definition: rel.h:56

References ErrorContextCallback::arg, buftag::blockNum, BM_DIRTY, BM_JUST_DIRTIED, BM_VALID, BufferDescriptorGetContentLock, ErrorContextCallback::callback, CurrentResourceOwner, error_context_stack, FlushBuffer(), buftag::forkNum, 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_node, RelationGetSmgr(), RelationUsesLocalBuffers, RelFileNodeEquals, ReservePrivateRefCountEntry(), ResourceOwnerEnlargeBuffers(), buftag::rnode, 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)
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:986
#define offsetof(type, field)
Definition: c.h:727
#define ERROR
Definition: elog.h:33
void * palloc0(Size size)
Definition: mcxt.c:1099
BufferAccessStrategyType btype
Definition: freelist.c:74

References BAS_BULKREAD, BAS_BULKWRITE, BAS_NORMAL, BAS_VACUUM, BufferAccessStrategyData::btype, elog, ERROR, Min, NBuffers, offsetof, 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 4364 of file bufmgr.c.

4365 {
4366  int bufid = GetStartupBufferPinWaitBufId();
4367 
4368  /*
4369  * If we get woken slowly then it's possible that the Startup process was
4370  * already woken by other backends before we got here. Also possible that
4371  * we get here by multiple interrupts or interrupts at inappropriate
4372  * times, so make sure we do nothing if the bufid is not set.
4373  */
4374  if (bufid < 0)
4375  return false;
4376 
4377  if (GetPrivateRefCount(bufid + 1) > 0)
4378  return true;
4379 
4380  return false;
4381 }
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:645

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and RecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

Definition at line 3953 of file bufmgr.c.

3954 {
3955  Assert(BufferIsPinned(buffer));
3957  if (BufferIsLocal(buffer))
3958  LocalRefCount[-buffer - 1]++;
3959  else
3960  {
3961  PrivateRefCountEntry *ref;
3962 
3963  ref = GetPrivateRefCountEntry(buffer, true);
3964  Assert(ref != NULL);
3965  ref->refcount++;
3966  }
3968 }
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition: bufmgr.c:309
void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:958

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  CLEAR_BUFFERTAG(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:223
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
#define BufferDescriptorGetIOCV(bdesc)
#define CLEAR_BUFFERTAG(a)
Definition: buf_internals.h:97
void WritebackContextInit(WritebackContext *context, int *max_pending)
Definition: bufmgr.c:4871
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:734
@ LWTRANCHE_BUFFER_CONTENT
Definition: lwlock.h:177
#define INVALID_PGPROCNO
Definition: proc.h:83
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, CLEAR_BUFFERTAG, ConditionVariableInit(), 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 2604 of file bufmgr.c.

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

4447 {
4448  BufferDesc *bufHdr;
4449  uint32 buf_state;
4450 
4451  Assert(BufferIsValid(buffer));
4452 
4453  if (BufferIsLocal(buffer))
4454  {
4455  /* There should be exactly one pin */
4456  if (LocalRefCount[-buffer - 1] != 1)
4457  return false;
4458  /* Nobody else to wait for */
4459  return true;
4460  }
4461 
4462  /* There should be exactly one local pin */
4463  if (GetPrivateRefCount(buffer) != 1)
4464  return false;
4465 
4466  bufHdr = GetBufferDescriptor(buffer - 1);
4467 
4468  /* caller must hold exclusive lock on buffer */
4470  LW_EXCLUSIVE));
4471 
4472  buf_state = LockBufHdr(bufHdr);
4473 
4474  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
4475  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
4476  {
4477  /* pincount is OK. */
4478  UnlockBufHdr(bufHdr, buf_state);
4479  return true;
4480  }
4481 
4482  UnlockBufHdr(bufHdr, buf_state);
4483  return false;
4484 }
bool LWLockHeldByMeInMode(LWLock *l, LWLockMode mode)
Definition: lwlock.c:1934

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(), hash_xlog_split_allocate_page(), and hashbucketcleanup().

◆ LockBuffer()

void LockBuffer ( Buffer  buffer,
int  mode 
)

Definition at line 4156 of file bufmgr.c.

4157 {
4158  BufferDesc *buf;
4159 
4160  Assert(BufferIsPinned(buffer));
4161  if (BufferIsLocal(buffer))
4162  return; /* local buffers need no lock */
4163 
4164  buf = GetBufferDescriptor(buffer - 1);
4165 
4166  if (mode == BUFFER_LOCK_UNLOCK)
4168  else if (mode == BUFFER_LOCK_SHARE)
4170  else if (mode == BUFFER_LOCK_EXCLUSIVE)
4172  else
4173  elog(ERROR, "unrecognized buffer lock mode: %d", mode);
4174 }
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:97
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:98
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 4213 of file bufmgr.c.

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

1574 {
1575  BufferDesc *bufHdr;
1576  uint32 buf_state;
1577  uint32 old_buf_state;
1578 
1579  if (!BufferIsValid(buffer))
1580  elog(ERROR, "bad buffer ID: %d", buffer);
1581 
1582  if (BufferIsLocal(buffer))
1583  {
1584  MarkLocalBufferDirty(buffer);
1585  return;
1586  }
1587 
1588  bufHdr = GetBufferDescriptor(buffer - 1);
1589 
1590  Assert(BufferIsPinned(buffer));
1592  LW_EXCLUSIVE));
1593 
1594  old_buf_state = pg_atomic_read_u32(&bufHdr->state);
1595  for (;;)
1596  {
1597  if (old_buf_state & BM_LOCKED)
1598  old_buf_state = WaitBufHdrUnlocked(bufHdr);
1599 
1600  buf_state = old_buf_state;
1601 
1602  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
1603  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
1604 
1605  if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
1606  buf_state))
1607  break;
1608  }
1609 
1610  /*
1611  * If the buffer was not dirty already, do vacuum accounting.
1612  */
1613  if (!(old_buf_state & BM_DIRTY))
1614  {
1615  VacuumPageDirty++;
1617  if (VacuumCostActive)
1619  }
1620 }
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:311
#define BM_LOCKED
Definition: buf_internals.h:58
static uint32 WaitBufHdrUnlocked(BufferDesc *buf)
Definition: bufmgr.c:4764
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_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_scan_prune(), 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 3985 of file bufmgr.c.

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

References Assert(), BM_DIRTY, BM_JUST_DIRTIED, BM_PERMANENT, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock, BufferGetPage, BufferIsLocal, BufferIsValid, DELAY_CHKPT_START, PGPROC::delayChkptFlags, elog, ERROR, GetBufferDescriptor, GetPrivateRefCount(), InvalidXLogRecPtr, LockBufHdr(), LWLockHeldByMe(), MarkLocalBufferDirty(), MyProc, PageSetLSN, pg_atomic_read_u32(), pgBufferUsage, RecoveryInProgress(), RelFileNodeSkippingWAL(), buftag::rnode, 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 }
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
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:643
#define RelationIsValid(relation)
Definition: rel.h:462

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

2689 {
2690  BufferDesc *buf;
2691  int32 loccount;
2692  char *path;
2693  BackendId backend;
2694  uint32 buf_state;
2695 
2696  Assert(BufferIsValid(buffer));
2697  if (BufferIsLocal(buffer))
2698  {
2699  buf = GetLocalBufferDescriptor(-buffer - 1);
2700  loccount = LocalRefCount[-buffer - 1];
2701  backend = MyBackendId;
2702  }
2703  else
2704  {
2705  buf = GetBufferDescriptor(buffer - 1);
2706  loccount = GetPrivateRefCount(buffer);
2707  backend = InvalidBackendId;
2708  }
2709 
2710  /* theoretically we should lock the bufhdr here */
2711  path = relpathbackend(buf->tag.rnode, backend, buf->tag.forkNum);
2712  buf_state = pg_atomic_read_u32(&buf->state);
2713  elog(WARNING,
2714  "buffer refcount leak: [%03d] "
2715  "(rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
2716  buffer, path,
2717  buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
2718  BUF_STATE_GET_REFCOUNT(buf_state), loccount);
2719  pfree(path);
2720 }
int BackendId
Definition: backendid.h:21
#define InvalidBackendId
Definition: backendid.h:23
#define BUF_FLAG_MASK
Definition: buf_internals.h:46
BackendId MyBackendId
Definition: globals.c:85
#define relpathbackend(rnode, backend, forknum)
Definition: relpath.h:78

References Assert(), buf, BUF_FLAG_MASK, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsValid, 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 702 of file bufmgr.c.

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

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

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

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 ( RelFileNode  rnode,
ForkNumber  forkNum,
BlockNumber  blockNum,
ReadBufferMode  mode,
BufferAccessStrategy  strategy,
bool  permanent 
)

Definition at line 789 of file bufmgr.c.

792 {
793  bool hit;
794 
795  SMgrRelation smgr = smgropen(rnode, InvalidBackendId);
796 
797  return ReadBuffer_common(smgr, permanent ? RELPERSISTENCE_PERMANENT :
798  RELPERSISTENCE_UNLOGGED, forkNum, blockNum,
799  mode, strategy, &hit);
800 }
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:146

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

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

◆ ReadRecentBuffer()

bool ReadRecentBuffer ( RelFileNode  rnode,
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  INIT_BUFFERTAG(tag, rnode, forkNum, blockNum);
636 
637  if (BufferIsLocal(recent_buffer))
638  {
639  bufHdr = GetBufferDescriptor(-recent_buffer - 1);
640  buf_state = pg_atomic_read_u32(&bufHdr->state);
641 
642  /* Is it still valid and holding the right tag? */
643  if ((buf_state & BM_VALID) && BUFFERTAGS_EQUAL(tag, bufHdr->tag))
644  {
645  /* Bump local buffer's ref and usage counts. */
647  LocalRefCount[-recent_buffer - 1]++;
649  pg_atomic_write_u32(&bufHdr->state,
650  buf_state + BUF_USAGECOUNT_ONE);
651 
653 
654  return true;
655  }
656  }
657  else
658  {
659  bufHdr = GetBufferDescriptor(recent_buffer - 1);
660  have_private_ref = GetPrivateRefCount(recent_buffer) > 0;
661 
662  /*
663  * Do we already have this buffer pinned with a private reference? If
664  * so, it must be valid and it is safe to check the tag without
665  * locking. If not, we have to lock the header first and then check.
666  */
667  if (have_private_ref)
668  buf_state = pg_atomic_read_u32(&bufHdr->state);
669  else
670  buf_state = LockBufHdr(bufHdr);
671 
672  if ((buf_state & BM_VALID) && BUFFERTAGS_EQUAL(tag, bufHdr->tag))
673  {
674  /*
675  * It's now safe to pin the buffer. We can't pin first and ask
676  * questions later, because it might confuse code paths like
677  * InvalidateBuffer() if we pinned a random non-matching buffer.
678  */
679  if (have_private_ref)
680  PinBuffer(bufHdr, NULL); /* bump pin count */
681  else
682  PinBuffer_Locked(bufHdr); /* pin for first time */
683 
685 
686  return true;
687  }
688 
689  /* If we locked the header above, now unlock. */
690  if (!have_private_ref)
691  UnlockBufHdr(bufHdr, buf_state);
692  }
693 
694  return false;
695 }
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:258
#define INIT_BUFFERTAG(a, xx_rnode, xx_forkNum, xx_blockNum)
#define BM_MAX_USAGE_COUNT
Definition: buf_internals.h:76
#define BUFFERTAGS_EQUAL(a, b)
#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:1694
int64 local_blks_hit
Definition: instrument.h:30
int64 shared_blks_hit
Definition: instrument.h:26

References Assert(), BM_MAX_USAGE_COUNT, BM_VALID, BUF_STATE_GET_USAGECOUNT, BUF_USAGECOUNT_ONE, BufferIsLocal, BufferIsValid, BUFFERTAGS_EQUAL, CurrentResourceOwner, GetBufferDescriptor, GetPrivateRefCount(), INIT_BUFFERTAG, BufferUsage::local_blks_hit, LocalRefCount, LockBufHdr(), pg_atomic_read_u32(), pg_atomic_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 2942 of file bufmgr.c.

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

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

1639 {
1640  ForkNumber forkNum = MAIN_FORKNUM;
1641  BufferDesc *bufHdr;
1642 
1643  if (BufferIsValid(buffer))
1644  {
1645  Assert(BufferIsPinned(buffer));
1646  if (BufferIsLocal(buffer))
1647  {
1648  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
1649  if (bufHdr->tag.blockNum == blockNum &&
1650  RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node) &&
1651  bufHdr->tag.forkNum == forkNum)
1652  return buffer;
1654  LocalRefCount[-buffer - 1]--;
1655  }
1656  else
1657  {
1658  bufHdr = GetBufferDescriptor(buffer - 1);
1659  /* we have pin, so it's ok to examine tag without spinlock */
1660  if (bufHdr->tag.blockNum == blockNum &&
1661  RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node) &&
1662  bufHdr->tag.forkNum == forkNum)
1663  return buffer;
1664  UnpinBuffer(bufHdr, true);
1665  }
1666  }
1667 
1668  return ReadBuffer(relation, blockNum);
1669 }
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:702
void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:967

References Assert(), buftag::blockNum, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferIsValid, CurrentResourceOwner, buftag::forkNum, GetBufferDescriptor, GetLocalBufferDescriptor, LocalRefCount, MAIN_FORKNUM, RelationData::rd_node, ReadBuffer(), RelFileNodeEquals, ResourceOwnerForgetBuffer(), buftag::rnode, 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 3915 of file bufmgr.c.

3916 {
3917  if (!BufferIsValid(buffer))
3918  elog(ERROR, "bad buffer ID: %d", buffer);
3919 
3920  if (BufferIsLocal(buffer))
3921  {
3923 
3924  Assert(LocalRefCount[-buffer - 1] > 0);
3925  LocalRefCount[-buffer - 1]--;
3926  return;
3927  }
3928 
3929  UnpinBuffer(GetBufferDescriptor(buffer - 1), true);
3930 }

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

283 {
284  Assert(relation != NULL);
285 
286  if (old_snapshot_threshold >= 0
287  && (snapshot) != NULL
288  && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
289  || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
290  && !XLogRecPtrIsInvalid((snapshot)->lsn)
291  && PageGetLSN(page) > (snapshot)->lsn)
292  TestForOldSnapshot_impl(snapshot, relation);
293 }
void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation)
Definition: bufmgr.c:4997
int old_snapshot_threshold
Definition: snapmgr.c:78
@ 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 4997 of file bufmgr.c.

4998 {
4999  if (RelationAllowsEarlyPruning(relation)
5000  && (snapshot)->whenTaken < GetOldSnapshotThresholdTimestamp())
5001  ereport(ERROR,
5002  (errcode(ERRCODE_SNAPSHOT_TOO_OLD),
5003  errmsg("snapshot too old")));
5004 }
TimestampTz GetOldSnapshotThresholdTimestamp(void)
Definition: snapmgr.c:1703
#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 4128 of file bufmgr.c.

4129 {
4131 
4132  if (buf)
4133  {
4134  uint32 buf_state;
4135 
4136  buf_state = LockBufHdr(buf);
4137 
4138  /*
4139  * Don't complain if flag bit not set; it could have been reset but we
4140  * got a cancel/die interrupt before getting the signal.
4141  */
4142  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
4143  buf->wait_backend_pgprocno == MyProc->pgprocno)
4144  buf_state &= ~BM_PIN_COUNT_WAITER;
4145 
4146  UnlockBufHdr(buf, buf_state);
4147 
4148  PinCountWaitBuf = NULL;
4149  }
4150 }

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

3939 {
3940  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3941  ReleaseBuffer(buffer);
3942 }
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3915

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