PostgreSQL Source Code git master
Loading...
Searching...
No Matches
bufmgr.h File Reference
#include "port/pg_iovec.h"
#include "storage/aio_types.h"
#include "storage/block.h"
#include "storage/buf.h"
#include "storage/bufpage.h"
#include "storage/relfilelocator.h"
#include "utils/relcache.h"
#include "utils/snapmgr.h"
Include dependency graph for bufmgr.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PrefetchBufferResult
 
struct  BufferManagerRelation
 
struct  ReadBuffersOperation
 

Macros

#define BMR_REL(p_rel)    ((BufferManagerRelation){.rel = p_rel})
 
#define BMR_SMGR(p_smgr, p_relpersistence)    ((BufferManagerRelation){.smgr = p_smgr, .relpersistence = p_relpersistence})
 
#define BMR_GET_SMGR(bmr)    (RelationIsValid((bmr).rel) ? RelationGetSmgr((bmr).rel) : (bmr).smgr)
 
#define READ_BUFFERS_ZERO_ON_ERROR   (1 << 0)
 
#define READ_BUFFERS_ISSUE_ADVICE   (1 << 1)
 
#define READ_BUFFERS_IGNORE_CHECKSUM_FAILURES   (1 << 2)
 
#define READ_BUFFERS_SYNCHRONOUSLY   (1 << 3)
 
#define DEFAULT_EFFECTIVE_IO_CONCURRENCY   16
 
#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   16
 
#define MAX_IO_COMBINE_LIMIT   PG_IOV_MAX
 
#define DEFAULT_IO_COMBINE_LIMIT   Min(MAX_IO_COMBINE_LIMIT, (128 * 1024) / BLCKSZ)
 
#define MAX_IO_CONCURRENCY   1000
 
#define P_NEW   InvalidBlockNumber /* grow the file to get a new page */
 
#define RelationGetNumberOfBlocks(reln)    RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)
 

Typedefs

typedef voidBlock
 
typedef enum BufferAccessStrategyType BufferAccessStrategyType
 
typedef struct PrefetchBufferResult PrefetchBufferResult
 
typedef enum ExtendBufferedFlags ExtendBufferedFlags
 
typedef struct SMgrRelationDataSMgrRelation
 
typedef struct BufferManagerRelation BufferManagerRelation
 
typedef struct ReadBuffersOperation ReadBuffersOperation
 
typedef struct WritebackContext WritebackContext
 
typedef enum BufferLockMode BufferLockMode
 

Enumerations

enum  BufferAccessStrategyType { BAS_NORMAL , BAS_BULKREAD , BAS_BULKWRITE , BAS_VACUUM }
 
enum  ReadBufferMode {
  RBM_NORMAL , RBM_ZERO_AND_LOCK , RBM_ZERO_AND_CLEANUP_LOCK , RBM_ZERO_ON_ERROR ,
  RBM_NORMAL_NO_LOG
}
 
enum  ExtendBufferedFlags {
  EB_SKIP_EXTENSION_LOCK = (1 << 0) , EB_PERFORMING_RECOVERY = (1 << 1) , EB_CREATE_FORK_IF_NEEDED = (1 << 2) , EB_LOCK_FIRST = (1 << 3) ,
  EB_CLEAR_SIZE_CACHE = (1 << 4) , EB_LOCK_TARGET = (1 << 5)
}
 
enum  BufferLockMode { BUFFER_LOCK_UNLOCK , BUFFER_LOCK_SHARE , BUFFER_LOCK_SHARE_EXCLUSIVE , BUFFER_LOCK_EXCLUSIVE }
 

Functions

PrefetchBufferResult PrefetchSharedBuffer (SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
 
PrefetchBufferResult PrefetchBuffer (Relation reln, ForkNumber forkNum, BlockNumber blockNum)
 
bool ReadRecentBuffer (RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, Buffer recent_buffer)
 
Buffer ReadBuffer (Relation reln, BlockNumber blockNum)
 
Buffer ReadBufferExtended (Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
 
Buffer ReadBufferWithoutRelcache (RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool permanent)
 
bool StartReadBuffer (ReadBuffersOperation *operation, Buffer *buffer, BlockNumber blocknum, int flags)
 
bool StartReadBuffers (ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, int flags)
 
bool WaitReadBuffers (ReadBuffersOperation *operation)
 
void ReleaseBuffer (Buffer buffer)
 
void UnlockReleaseBuffer (Buffer buffer)
 
bool BufferIsLockedByMe (Buffer buffer)
 
bool BufferIsLockedByMeInMode (Buffer buffer, BufferLockMode mode)
 
bool BufferIsDirty (Buffer buffer)
 
void MarkBufferDirty (Buffer buffer)
 
void IncrBufferRefCount (Buffer buffer)
 
void CheckBufferIsPinnedOnce (Buffer buffer)
 
Buffer ReleaseAndReadBuffer (Buffer buffer, Relation relation, BlockNumber blockNum)
 
Buffer ExtendBufferedRel (BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
 
BlockNumber ExtendBufferedRelBy (BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, Buffer *buffers, uint32 *extended_by)
 
Buffer ExtendBufferedRelTo (BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, BlockNumber extend_to, ReadBufferMode mode)
 
void InitBufferManagerAccess (void)
 
void AtEOXact_Buffers (bool isCommit)
 
charDebugPrintBufferRefcount (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 (SMgrRelation *smgrs, int nrels)
 
void CreateAndCopyRelationData (RelFileLocator src_rlocator, RelFileLocator dst_rlocator, bool permanent)
 
void FlushDatabaseBuffers (Oid dbid)
 
void DropRelationBuffers (SMgrRelation smgr_reln, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
 
void DropRelationsAllBuffers (SMgrRelation *smgr_reln, int nlocators)
 
void DropDatabaseBuffers (Oid dbid)
 
bool BufferIsPermanent (Buffer buffer)
 
XLogRecPtr BufferGetLSNAtomic (Buffer buffer)
 
void BufferGetTag (Buffer buffer, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
 
void MarkBufferDirtyHint (Buffer buffer, bool buffer_std)
 
bool BufferSetHintBits16 (uint16 *ptr, uint16 val, Buffer buffer)
 
bool BufferBeginSetHintBits (Buffer buffer)
 
void BufferFinishSetHintBits (Buffer buffer, bool mark_dirty, bool buffer_std)
 
void UnlockBuffers (void)
 
void UnlockBuffer (Buffer buffer)
 
void LockBufferInternal (Buffer buffer, BufferLockMode mode)
 
static void LockBuffer (Buffer buffer, BufferLockMode mode)
 
bool ConditionalLockBuffer (Buffer buffer)
 
void LockBufferForCleanup (Buffer buffer)
 
bool ConditionalLockBufferForCleanup (Buffer buffer)
 
bool IsBufferCleanupOK (Buffer buffer)
 
bool HoldingBufferPinThatDelaysRecovery (void)
 
bool BgBufferSync (WritebackContext *wb_context)
 
uint32 GetPinLimit (void)
 
uint32 GetLocalPinLimit (void)
 
uint32 GetAdditionalPinLimit (void)
 
uint32 GetAdditionalLocalPinLimit (void)
 
void LimitAdditionalPins (uint32 *additional_pins)
 
void LimitAdditionalLocalPins (uint32 *additional_pins)
 
bool EvictUnpinnedBuffer (Buffer buf, bool *buffer_flushed)
 
void EvictAllUnpinnedBuffers (int32 *buffers_evicted, int32 *buffers_flushed, int32 *buffers_skipped)
 
void EvictRelUnpinnedBuffers (Relation rel, int32 *buffers_evicted, int32 *buffers_flushed, int32 *buffers_skipped)
 
bool MarkDirtyUnpinnedBuffer (Buffer buf, bool *buffer_already_dirty)
 
void MarkDirtyRelUnpinnedBuffers (Relation rel, int32 *buffers_dirtied, int32 *buffers_already_dirty, int32 *buffers_skipped)
 
void MarkDirtyAllUnpinnedBuffers (int32 *buffers_dirtied, int32 *buffers_already_dirty, int32 *buffers_skipped)
 
void AtProcExit_LocalBuffers (void)
 
BufferAccessStrategy GetAccessStrategy (BufferAccessStrategyType btype)
 
BufferAccessStrategy GetAccessStrategyWithSize (BufferAccessStrategyType btype, int ring_size_kb)
 
int GetAccessStrategyBufferCount (BufferAccessStrategy strategy)
 
int GetAccessStrategyPinLimit (BufferAccessStrategy strategy)
 
void FreeAccessStrategy (BufferAccessStrategy strategy)
 
static bool BufferIsValid (Buffer bufnum)
 
static Block BufferGetBlock (Buffer buffer)
 
static Size BufferGetPageSize (Buffer buffer)
 
static Page BufferGetPage (Buffer buffer)
 

Variables

PGDLLIMPORT int NBuffers
 
PGDLLIMPORT bool zero_damaged_pages
 
PGDLLIMPORT int bgwriter_lru_maxpages
 
PGDLLIMPORT double bgwriter_lru_multiplier
 
PGDLLIMPORT bool track_io_timing
 
PGDLLIMPORT int effective_io_concurrency
 
PGDLLIMPORT int maintenance_io_concurrency
 
PGDLLIMPORT int io_combine_limit
 
PGDLLIMPORT int io_combine_limit_guc
 
PGDLLIMPORT int io_max_combine_limit
 
PGDLLIMPORT int checkpoint_flush_after
 
PGDLLIMPORT int backend_flush_after
 
PGDLLIMPORT int bgwriter_flush_after
 
PGDLLIMPORT const PgAioHandleCallbacks aio_shared_buffer_readv_cb
 
PGDLLIMPORT const PgAioHandleCallbacks aio_local_buffer_readv_cb
 
PGDLLIMPORT charBufferBlocks
 
PGDLLIMPORT int NLocBuffer
 
PGDLLIMPORT BlockLocalBufferBlockPointers
 
PGDLLIMPORT int32LocalRefCount
 

Macro Definition Documentation

◆ BMR_GET_SMGR

#define BMR_GET_SMGR (   bmr)     (RelationIsValid((bmr).rel) ? RelationGetSmgr((bmr).rel) : (bmr).smgr)

Definition at line 118 of file bufmgr.h.

119 : (bmr).smgr)
static int fb(int x)

◆ BMR_REL

#define BMR_REL (   p_rel)     ((BufferManagerRelation){.rel = p_rel})

Definition at line 114 of file bufmgr.h.

115 {.rel = p_rel})

◆ BMR_SMGR

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

Definition at line 116 of file bufmgr.h.

117 {.smgr = p_smgr, .relpersistence = p_relpersistence})

◆ DEFAULT_EFFECTIVE_IO_CONCURRENCY

#define DEFAULT_EFFECTIVE_IO_CONCURRENCY   16

Definition at line 170 of file bufmgr.h.

◆ DEFAULT_IO_COMBINE_LIMIT

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

Definition at line 176 of file bufmgr.h.

◆ DEFAULT_MAINTENANCE_IO_CONCURRENCY

#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   16

Definition at line 171 of file bufmgr.h.

◆ MAX_IO_COMBINE_LIMIT

#define MAX_IO_COMBINE_LIMIT   PG_IOV_MAX

Definition at line 175 of file bufmgr.h.

◆ MAX_IO_CONCURRENCY

#define MAX_IO_CONCURRENCY   1000

Definition at line 197 of file bufmgr.h.

◆ P_NEW

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

Definition at line 200 of file bufmgr.h.

◆ READ_BUFFERS_IGNORE_CHECKSUM_FAILURES

#define READ_BUFFERS_IGNORE_CHECKSUM_FAILURES   (1 << 2)

Definition at line 126 of file bufmgr.h.

◆ READ_BUFFERS_ISSUE_ADVICE

#define READ_BUFFERS_ISSUE_ADVICE   (1 << 1)

Definition at line 124 of file bufmgr.h.

◆ READ_BUFFERS_SYNCHRONOUSLY

#define READ_BUFFERS_SYNCHRONOUSLY   (1 << 3)

Definition at line 128 of file bufmgr.h.

◆ READ_BUFFERS_ZERO_ON_ERROR

#define READ_BUFFERS_ZERO_ON_ERROR   (1 << 0)

Definition at line 122 of file bufmgr.h.

◆ RelationGetNumberOfBlocks

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

Definition at line 309 of file bufmgr.h.

Typedef Documentation

◆ Block

Definition at line 26 of file bufmgr.h.

◆ BufferAccessStrategyType

◆ BufferLockMode

◆ BufferManagerRelation

◆ ExtendBufferedFlags

◆ PrefetchBufferResult

◆ ReadBuffersOperation

Definition at line 156 of file bufmgr.h.

◆ SMgrRelation

Definition at line 97 of file bufmgr.h.

◆ WritebackContext

Definition at line 159 of file bufmgr.h.

Enumeration Type Documentation

◆ BufferAccessStrategyType

Enumerator
BAS_NORMAL 
BAS_BULKREAD 
BAS_BULKWRITE 
BAS_VACUUM 

Definition at line 34 of file bufmgr.h.

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

◆ BufferLockMode

Enumerator
BUFFER_LOCK_UNLOCK 
BUFFER_LOCK_SHARE 
BUFFER_LOCK_SHARE_EXCLUSIVE 
BUFFER_LOCK_EXCLUSIVE 

Definition at line 205 of file bufmgr.h.

206{
208
209 /*
210 * A share lock conflicts with exclusive locks.
211 */
213
214 /*
215 * A share-exclusive lock conflicts with itself and exclusive locks.
216 */
218
219 /*
220 * An exclusive lock conflicts with every other lock type.
221 */
BufferLockMode
Definition bufmgr.h:206
@ BUFFER_LOCK_SHARE_EXCLUSIVE
Definition bufmgr.h:217
@ BUFFER_LOCK_SHARE
Definition bufmgr.h:212
@ BUFFER_LOCK_EXCLUSIVE
Definition bufmgr.h:222
@ BUFFER_LOCK_UNLOCK
Definition bufmgr.h:207

◆ ExtendBufferedFlags

Enumerator
EB_SKIP_EXTENSION_LOCK 
EB_PERFORMING_RECOVERY 
EB_CREATE_FORK_IF_NEEDED 
EB_LOCK_FIRST 
EB_CLEAR_SIZE_CACHE 
EB_LOCK_TARGET 

Definition at line 68 of file bufmgr.h.

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

◆ ReadBufferMode

Enumerator
RBM_NORMAL 
RBM_ZERO_AND_LOCK 
RBM_ZERO_AND_CLEANUP_LOCK 
RBM_ZERO_ON_ERROR 
RBM_NORMAL_NO_LOG 

Definition at line 44 of file bufmgr.h.

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

Function Documentation

◆ AtEOXact_Buffers()

void AtEOXact_Buffers ( bool  isCommit)
extern

Definition at line 4199 of file bufmgr.c.

4200{
4202
4204
4206}
static void CheckForBufferLeaks(void)
Definition bufmgr.c:4263
static int32 PrivateRefCountOverflowed
Definition bufmgr.c:266
#define Assert(condition)
Definition c.h:943
void AtEOXact_LocalBuffers(bool isCommit)
Definition localbuf.c:1019

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

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

◆ AtProcExit_LocalBuffers()

void AtProcExit_LocalBuffers ( void  )
extern

Definition at line 1030 of file localbuf.c.

1031{
1032 /*
1033 * We shouldn't be holding any remaining pins; if we are, and assertions
1034 * aren't enabled, we'll fail later in DropRelationBuffers while trying to
1035 * drop the temp rels.
1036 */
1038}
static void CheckForLocalBufferLeaks(void)
Definition localbuf.c:986

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

◆ BgBufferSync()

bool BgBufferSync ( WritebackContext wb_context)
extern

Definition at line 3831 of file bufmgr.c.

3832{
3833 /* info obtained from freelist.c */
3834 int strategy_buf_id;
3837
3838 /*
3839 * Information saved between calls so we can determine the strategy
3840 * point's advance rate and avoid scanning already-cleaned buffers.
3841 */
3842 static bool saved_info_valid = false;
3843 static int prev_strategy_buf_id;
3845 static int next_to_clean;
3846 static uint32 next_passes;
3847
3848 /* Moving averages of allocation rate and clean-buffer density */
3849 static float smoothed_alloc = 0;
3850 static float smoothed_density = 10.0;
3851
3852 /* Potentially these could be tunables, but for now, not */
3853 float smoothing_samples = 16;
3854 float scan_whole_pool_milliseconds = 120000.0;
3855
3856 /* Used to compute how far we scan ahead */
3857 long strategy_delta;
3858 int bufs_to_lap;
3859 int bufs_ahead;
3860 float scans_per_alloc;
3863 int min_scan_buffers;
3864
3865 /* Variables for the scanning loop proper */
3866 int num_to_scan;
3867 int num_written;
3868 int reusable_buffers;
3869
3870 /* Variables for final smoothed_density update */
3871 long new_strategy_delta;
3873
3874 /*
3875 * Find out where the clock-sweep currently is, and how many buffer
3876 * allocations have happened since our last call.
3877 */
3879
3880 /* Report buffer alloc counts to pgstat */
3882
3883 /*
3884 * If we're not running the LRU scan, just stop after doing the stats
3885 * stuff. We mark the saved state invalid so that we can recover sanely
3886 * if LRU scan is turned back on later.
3887 */
3888 if (bgwriter_lru_maxpages <= 0)
3889 {
3890 saved_info_valid = false;
3891 return true;
3892 }
3893
3894 /*
3895 * Compute strategy_delta = how many buffers have been scanned by the
3896 * clock-sweep since last time. If first time through, assume none. Then
3897 * see if we are still ahead of the clock-sweep, and if so, how many
3898 * buffers we could scan before we'd catch up with it and "lap" it. Note:
3899 * weird-looking coding of xxx_passes comparisons are to avoid bogus
3900 * behavior when the passes counts wrap around.
3901 */
3902 if (saved_info_valid)
3903 {
3905
3908
3909 Assert(strategy_delta >= 0);
3910
3911 if ((int32) (next_passes - strategy_passes) > 0)
3912 {
3913 /* we're one pass ahead of the strategy point */
3915#ifdef BGW_DEBUG
3916 elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3920#endif
3921 }
3922 else if (next_passes == strategy_passes &&
3924 {
3925 /* on same pass, but ahead or at least not behind */
3927#ifdef BGW_DEBUG
3928 elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3932#endif
3933 }
3934 else
3935 {
3936 /*
3937 * We're behind, so skip forward to the strategy point and start
3938 * cleaning from there.
3939 */
3940#ifdef BGW_DEBUG
3941 elog(DEBUG2, "bgwriter behind: bgw %u-%u strategy %u-%u delta=%ld",
3945#endif
3949 }
3950 }
3951 else
3952 {
3953 /*
3954 * Initializing at startup or after LRU scanning had been off. Always
3955 * start at the strategy point.
3956 */
3957#ifdef BGW_DEBUG
3958 elog(DEBUG2, "bgwriter initializing: strategy %u-%u",
3960#endif
3961 strategy_delta = 0;
3965 }
3966
3967 /* Update saved info for next time */
3970 saved_info_valid = true;
3971
3972 /*
3973 * Compute how many buffers had to be scanned for each new allocation, ie,
3974 * 1/density of reusable buffers, and track a moving average of that.
3975 *
3976 * If the strategy point didn't move, we don't update the density estimate
3977 */
3978 if (strategy_delta > 0 && recent_alloc > 0)
3979 {
3983 }
3984
3985 /*
3986 * Estimate how many reusable buffers there are between the current
3987 * strategy point and where we've scanned ahead to, based on the smoothed
3988 * density estimate.
3989 */
3992
3993 /*
3994 * Track a moving average of recent buffer allocations. Here, rather than
3995 * a true average we want a fast-attack, slow-decline behavior: we
3996 * immediately follow any increase.
3997 */
3998 if (smoothed_alloc <= (float) recent_alloc)
4000 else
4003
4004 /* Scale the estimate by a GUC to allow more aggressive tuning. */
4006
4007 /*
4008 * If recent_alloc remains at zero for many cycles, smoothed_alloc will
4009 * eventually underflow to zero, and the underflows produce annoying
4010 * kernel warnings on some platforms. Once upcoming_alloc_est has gone to
4011 * zero, there's no point in tracking smaller and smaller values of
4012 * smoothed_alloc, so just reset it to exactly zero to avoid this
4013 * syndrome. It will pop back up as soon as recent_alloc increases.
4014 */
4015 if (upcoming_alloc_est == 0)
4016 smoothed_alloc = 0;
4017
4018 /*
4019 * Even in cases where there's been little or no buffer allocation
4020 * activity, we want to make a small amount of progress through the buffer
4021 * cache so that as many reusable buffers as possible are clean after an
4022 * idle period.
4023 *
4024 * (scan_whole_pool_milliseconds / BgWriterDelay) computes how many times
4025 * the BGW will be called during the scan_whole_pool time; slice the
4026 * buffer pool into that many sections.
4027 */
4029
4031 {
4032#ifdef BGW_DEBUG
4033 elog(DEBUG2, "bgwriter: alloc_est=%d too small, using min=%d + reusable_est=%d",
4035#endif
4037 }
4038
4039 /*
4040 * Now write out dirty reusable buffers, working forward from the
4041 * next_to_clean point, until we have lapped the strategy scan, or cleaned
4042 * enough buffers to match our estimate of the next cycle's allocation
4043 * requirements, or hit the bgwriter_lru_maxpages limit.
4044 */
4045
4046 num_to_scan = bufs_to_lap;
4047 num_written = 0;
4049
4050 /* Execute the LRU scan */
4051 while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
4052 {
4054 wb_context);
4055
4056 if (++next_to_clean >= NBuffers)
4057 {
4058 next_to_clean = 0;
4059 next_passes++;
4060 }
4061 num_to_scan--;
4062
4063 if (sync_state & BUF_WRITTEN)
4064 {
4067 {
4069 break;
4070 }
4071 }
4072 else if (sync_state & BUF_REUSABLE)
4074 }
4075
4077
4078#ifdef BGW_DEBUG
4079 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",
4082 bufs_to_lap - num_to_scan,
4085#endif
4086
4087 /*
4088 * Consider the above scan as being like a new allocation scan.
4089 * Characterize its density and update the smoothed one based on it. This
4090 * effectively halves the moving average period in cases where both the
4091 * strategy and the background writer are doing some useful scanning,
4092 * which is helpful because a long memory isn't as desirable on the
4093 * density estimates.
4094 */
4095 new_strategy_delta = bufs_to_lap - num_to_scan;
4097 if (new_strategy_delta > 0 && new_recent_alloc > 0)
4098 {
4102
4103#ifdef BGW_DEBUG
4104 elog(DEBUG2, "bgwriter: cleaner density alloc=%u scan=%ld density=%.2f new smoothed=%.2f",
4107#endif
4108 }
4109
4110 /* Return true if OK to hibernate */
4111 return (bufs_to_lap == 0 && recent_alloc == 0);
4112}
int BgWriterDelay
Definition bgwriter.c:59
#define BUF_REUSABLE
Definition bufmgr.c:85
double bgwriter_lru_multiplier
Definition bufmgr.c:191
static int SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
Definition bufmgr.c:4129
int bgwriter_lru_maxpages
Definition bufmgr.c:190
#define BUF_WRITTEN
Definition bufmgr.c:84
int32_t int32
Definition c.h:620
uint32_t uint32
Definition c.h:624
#define DEBUG2
Definition elog.h:30
#define DEBUG1
Definition elog.h:31
#define elog(elevel,...)
Definition elog.h:228
int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc)
Definition freelist.c:331
int NBuffers
Definition globals.c:144
PgStat_BgWriterStats PendingBgWriterStats
PgStat_Counter buf_written_clean
Definition pgstat.h:246
PgStat_Counter maxwritten_clean
Definition pgstat.h:247
PgStat_Counter buf_alloc
Definition pgstat.h:248

References Assert, bgwriter_lru_maxpages, bgwriter_lru_multiplier, BgWriterDelay, PgStat_BgWriterStats::buf_alloc, BUF_REUSABLE, BUF_WRITTEN, PgStat_BgWriterStats::buf_written_clean, DEBUG1, DEBUG2, elog, fb(), PgStat_BgWriterStats::maxwritten_clean, NBuffers, PendingBgWriterStats, StrategySyncStart(), and SyncOneBuffer().

Referenced by BackgroundWriterMain().

◆ BufferBeginSetHintBits()

bool BufferBeginSetHintBits ( Buffer  buffer)
extern

Definition at line 7042 of file bufmgr.c.

7043{
7046
7047 if (BufferIsLocal(buffer))
7048 {
7049 /*
7050 * NB: Will need to check if there is a write in progress, once it is
7051 * possible for writes to be done asynchronously.
7052 */
7053 return true;
7054 }
7055
7056 buf_hdr = GetBufferDescriptor(buffer - 1);
7057
7059}
#define BufferIsLocal(buffer)
Definition buf.h:37
static BufferDesc * GetBufferDescriptor(uint32 id)
static bool SharedBufferBeginSetHintBits(Buffer buffer, BufferDesc *buf_hdr, uint64 *lockstate)
Definition bufmgr.c:6951
uint64_t uint64
Definition c.h:625

References PrivateRefCountEntry::buffer, BufferIsLocal, fb(), GetBufferDescriptor(), and SharedBufferBeginSetHintBits().

Referenced by _bt_check_unique(), _bt_killitems(), _hash_kill_items(), fsm_search_avail(), fsm_vacuum_page(), gistkillitems(), and SetHintBitsExt().

◆ BufferFinishSetHintBits()

void BufferFinishSetHintBits ( Buffer  buffer,
bool  mark_dirty,
bool  buffer_std 
)
extern

Definition at line 7070 of file bufmgr.c.

7071{
7072 if (!BufferIsLocal(buffer))
7075
7076 if (mark_dirty)
7078}
bool BufferIsLockedByMeInMode(Buffer buffer, BufferLockMode mode)
Definition bufmgr.c:3087
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition bufmgr.c:5821

References Assert, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_SHARE_EXCLUSIVE, BufferIsLocal, BufferIsLockedByMeInMode(), fb(), and MarkBufferDirtyHint().

Referenced by _bt_check_unique(), _bt_killitems(), _hash_kill_items(), fsm_search_avail(), fsm_vacuum_page(), gistkillitems(), and HeapTupleSatisfiesMVCCBatch().

◆ BufferGetBlock()

static Block BufferGetBlock ( Buffer  buffer)
inlinestatic

Definition at line 435 of file bufmgr.h.

436{
437 Assert(BufferIsValid(buffer));
438
439 if (BufferIsLocal(buffer))
440 return LocalBufferBlockPointers[-buffer - 1];
441 else
442 return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
443}
PGDLLIMPORT Block * LocalBufferBlockPointers
Definition localbuf.c:48
void * Block
Definition bufmgr.h:26
PGDLLIMPORT char * BufferBlocks
Definition buf_init.c:25
static bool BufferIsValid(Buffer bufnum)
Definition bufmgr.h:419
size_t Size
Definition c.h:689

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

Referenced by AsyncReadBuffers(), buffer_readv_complete_one(), BufferGetPage(), heap_inplace_update_and_unlock(), pg_buffercache_os_pages_internal(), and read_rel_block_ll().

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)
extern

Definition at line 4446 of file bufmgr.c.

4447{
4449
4450 Assert(BufferIsPinned(buffer));
4451
4452 if (BufferIsLocal(buffer))
4453 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
4454 else
4455 bufHdr = GetBufferDescriptor(buffer - 1);
4456
4457 /* pinned, so OK to read tag without spinlock */
4458 return bufHdr->tag.blockNum;
4459}
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
#define BufferIsPinned(bufnum)
Definition bufmgr.c:599

References Assert, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, fb(), GetBufferDescriptor(), and GetLocalBufferDescriptor().

Referenced by _bt_binsrch_insert(), _bt_bottomupdel_pass(), _bt_check_unique(), _bt_checkpage(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_doinsert(), _bt_finish_split(), _bt_getroot(), _bt_insert_parent(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_moveright(), _bt_newlevel(), _bt_pagedel(), _bt_readpage(), _bt_relandgetbuf(), _bt_restore_meta(), _bt_search(), _bt_simpledel_pass(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_checkpage(), _hash_doinsert(), _hash_first(), _hash_freeovflpage(), _hash_getnewbuf(), _hash_readnext(), _hash_readpage(), _hash_splitbucket(), allocNewBuffer(), AsyncReadBuffers(), BitmapHeapScanNextBlock(), blinsert(), BloomInitMetapage(), brin_doinsert(), brin_doupdate(), brin_getinsertbuffer(), brin_initialize_empty_new_buffer(), brin_page_cleanup(), brin_xlog_insert_update(), brinbuild(), brinGetTupleForHeapBlock(), btvacuumpage(), check_index_page(), CheckReadBuffersOperation(), collect_corrupt_items(), collectMatchBitmap(), createPostingTree(), dataBeginPlaceToPageLeaf(), dataPrepareDownlink(), doPickSplit(), entryPrepareDownlink(), fill_seq_fork_with_data(), ginDeletePostingPage(), ginEntryInsert(), ginFindParents(), ginFinishSplit(), ginPlaceToPage(), ginRedoDeleteListPages(), ginRedoUpdateMetapage(), gistbufferinginserttuples(), gistbuild(), gistcheckpage(), gistdeletepage(), gistformdownlink(), gistinserttuples(), gistMemorizeAllDownlinks(), gistplacetopage(), gistRelocateBuildBuffersOnSplit(), gistScanPage(), gistvacuumpage(), hash_xlog_add_ovfl_page(), heap_delete(), heap_fetch_next_buffer(), heap_hot_search_buffer(), heap_insert(), heap_multi_insert(), heap_page_prune_opt(), heap_page_would_be_all_visible(), heap_prepare_pagescan(), heap_update(), heap_xlog_confirm(), heap_xlog_lock(), heapam_index_fetch_tuple(), heapam_scan_analyze_next_block(), heapgettup(), heapgettup_pagemode(), index_compute_xid_horizon_for_tuples(), lazy_scan_heap(), lazy_scan_noprune(), lazy_scan_prune(), lazy_vacuum_heap_rel(), makeSublist(), moveLeafs(), moveRightIfItNeeded(), pgstathashindex(), prune_freeze_setup(), read_buffers(), read_stream_start_pending_read(), ReadBufferBI(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), RelationPutHeapTuple(), revmap_get_buffer(), revmap_physical_extend(), ScanSourceDatabasePgClassPage(), spgAddNodeAction(), spgbuild(), spgdoinsert(), SpGistSetLastUsedPage(), spgSplitNodeAction(), spgvacuumpage(), spgWalk(), StartReadBuffersImpl(), startScanEntry(), statapprox_heap(), terminate_brin_buildstate(), vacuumLeafPage(), verify_heapam(), visibilitymap_clear(), visibilitymap_get_status(), visibilitymap_pin(), visibilitymap_pin_ok(), and visibilitymap_set().

◆ BufferGetLSNAtomic()

XLogRecPtr BufferGetLSNAtomic ( Buffer  buffer)
extern

Definition at line 4713 of file bufmgr.c.

4714{
4715 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4716 Assert(BufferIsValid(buffer));
4717 Assert(BufferIsPinned(buffer));
4718
4719#ifdef PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY
4720 return PageGetLSN(BufferGetPage(buffer));
4721#else
4722 {
4723 char *page = BufferGetPage(buffer);
4725 XLogRecPtr lsn;
4726
4727 /*
4728 * If we don't need locking for correctness, fastpath out.
4729 */
4730 if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
4731 return PageGetLSN(page);
4732
4733 bufHdr = GetBufferDescriptor(buffer - 1);
4735 lsn = PageGetLSN(page);
4737
4738 return lsn;
4739 }
4740#endif
4741}
static void UnlockBufHdr(BufferDesc *desc)
uint64 LockBufHdr(BufferDesc *desc)
Definition bufmgr.c:7518
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:468
static XLogRecPtr PageGetLSN(const PageData *page)
Definition bufpage.h:410
#define XLogHintBitIsNeeded()
Definition xlog.h:123
uint64 XLogRecPtr
Definition xlogdefs.h:21

References Assert, PrivateRefCountEntry::buffer, BufferGetPage(), BufferIsLocal, BufferIsPinned, BufferIsValid(), fb(), GetBufferDescriptor(), LockBufHdr(), PageGetLSN(), UnlockBufHdr(), and XLogHintBitIsNeeded.

Referenced by _bt_drop_lock_and_maybe_pin(), _bt_killitems(), gistdoinsert(), gistFindPath(), gistkillitems(), gistScanPage(), and SetHintBitsExt().

◆ BufferGetPage()

static Page BufferGetPage ( Buffer  buffer)
inlinestatic

Definition at line 468 of file bufmgr.h.

469{
470 return (Page) BufferGetBlock(buffer);
471}
static Block BufferGetBlock(Buffer buffer)
Definition bufmgr.h:435
PageData * Page
Definition bufpage.h:81

References BufferGetBlock().

Referenced by _bt_allocbuf(), _bt_binsrch(), _bt_binsrch_insert(), _bt_bottomupdel_pass(), _bt_check_unique(), _bt_checkpage(), _bt_clear_incomplete_split(), _bt_conditionallockbuf(), _bt_dedup_pass(), _bt_delete_or_dedup_one_page(), _bt_delitems_delete(), _bt_delitems_delete_check(), _bt_delitems_vacuum(), _bt_endpoint(), _bt_findinsertloc(), _bt_finish_split(), _bt_get_endpoint(), _bt_getmeta(), _bt_getroot(), _bt_getstackbuf(), _bt_gettrueroot(), _bt_insert_parent(), _bt_insertonpg(), _bt_killitems(), _bt_leftsib_splitflag(), _bt_lock_and_validate_left(), _bt_lock_subtree_parent(), _bt_lockbuf(), _bt_mark_page_halfdead(), _bt_moveright(), _bt_newlevel(), _bt_pagedel(), _bt_readnextpage(), _bt_readpage(), _bt_relbuf(), _bt_restore_meta(), _bt_rightsib_halfdeadflag(), _bt_search(), _bt_search_insert(), _bt_set_cleanup_info(), _bt_simpledel_pass(), _bt_split(), _bt_stepright(), _bt_unlink_halfdead_page(), _bt_unlockbuf(), _bt_upgradelockbufcleanup(), _bt_vacuum_needs_cleanup(), _hash_addovflpage(), _hash_checkpage(), _hash_doinsert(), _hash_expandtable(), _hash_finish_split(), _hash_first(), _hash_freeovflpage(), _hash_get_newblock_from_oldbucket(), _hash_get_oldblock_from_newbucket(), _hash_getbucketbuf_from_hashkey(), _hash_getcachedmetap(), _hash_getinitbuf(), _hash_getnewbuf(), _hash_init(), _hash_init_metabuffer(), _hash_initbitmapbuffer(), _hash_initbuf(), _hash_kill_items(), _hash_pgaddmultitup(), _hash_pgaddtup(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), allocNewBuffer(), BitmapHeapScanNextBlock(), blgetbitmap(), blinsert(), BloomNewBuffer(), blvacuumcleanup(), brin_can_do_samepage_update(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_initialize_empty_new_buffer(), brin_page_cleanup(), brin_start_evacuating_page(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinGetStats(), brinGetTupleForHeapBlock(), brininsert(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), brinSetHeapBlockItemptr(), bt_metap(), bt_page_items_internal(), bt_recheck_sibling_links(), bt_rootdescend(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), btvacuumpage(), BufferGetLSNAtomic(), BufferSetHintBits16(), check_index_page(), collect_corrupt_items(), collect_visibility_data(), collectMatchBitmap(), collectMatchesForHeapRow(), count_nondeletable_pages(), createPostingTree(), dataBeginPlaceToPage(), dataBeginPlaceToPageInternal(), dataBeginPlaceToPageLeaf(), dataExecPlaceToPage(), dataExecPlaceToPageInternal(), dataLocateItem(), dataPlaceToPageLeafRecompress(), dataPrepareDownlink(), dataSplitPageInternal(), doPickSplit(), entryExecPlaceToPage(), entryIsEnoughSpace(), entryLoadMoreItems(), entryLocateEntry(), entryLocateLeafEntry(), entryPrepareDownlink(), entrySplitPage(), fill_seq_fork_with_data(), FreeSpaceMapPrepareTruncateRel(), fsm_readbuf(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), generic_redo(), GenericXLogFinish(), GenericXLogRegisterBuffer(), get_raw_page_internal(), GetBTPageStatistics(), GetRecordedFreeSpace(), GetVisibilityMapPins(), gin_check_parent_keys_consistency(), gin_check_posting_tree_parent_keys_consistency(), gin_refind_parent(), ginbulkdelete(), ginDeletePostingPage(), ginEntryInsert(), ginFindLeafPage(), ginFindParents(), ginFinishOldSplit(), ginFinishSplit(), ginGetStats(), ginHeapTupleFastInsert(), GinInitBuffer(), GinInitMetabuffer(), ginInsertCleanup(), ginInsertValue(), GinNewBuffer(), ginPlaceToPage(), ginRedoClearIncompleteSplit(), ginRedoCreatePTree(), ginRedoDeleteListPages(), ginRedoDeletePage(), ginRedoInsert(), ginRedoInsertData(), ginRedoInsertEntry(), ginRedoInsertListPage(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginScanPostingTreeToDelete(), ginStepRight(), ginTraverseLock(), ginUpdateStats(), ginvacuumcleanup(), ginVacuumEntryPage(), ginVacuumPostingTreeLeaf(), ginVacuumPostingTreeLeaves(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistbuild(), gistcheckpage(), gistdeletepage(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistfixsplit(), gistformdownlink(), gistGetMaxLevel(), GISTInitBuffer(), gistkillitems(), gistMemorizeAllDownlinks(), gistNewBuffer(), gistplacetopage(), gistProcessItup(), gistRedoClearFollowRight(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), gistScanPage(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hash_bitmap_info(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_force_common(), heap_freeze_prepared_tuples(), heap_get_latest_tid(), heap_hot_search_buffer(), heap_index_delete_tuples(), heap_inplace_update_and_unlock(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_prune_execute(), heap_page_prune_opt(), heap_page_would_be_all_visible(), heap_pre_freeze_checks(), heap_prepare_pagescan(), heap_update(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), heap_xlog_update(), heapam_index_build_range_scan(), heapam_index_validate_scan(), heapam_scan_analyze_next_tuple(), heapam_scan_bitmap_next_tuple(), heapam_scan_sample_next_tuple(), heapgettup_continue_page(), heapgettup_pagemode(), heapgettup_start_page(), index_compute_xid_horizon_for_tuples(), initBloomState(), lazy_scan_heap(), lazy_vacuum_heap_page(), lazy_vacuum_heap_rel(), log_heap_prune_and_freeze(), log_heap_update(), log_newpage_buffer(), log_newpage_range(), log_split_page(), MarkSharedBufferDirtyHint(), modify_rel_block(), moveLeafs(), moveRightIfItNeeded(), nextval_internal(), palloc_btree_page(), pg_get_sequence_data(), pg_visibility(), pgstat_btree_page(), pgstat_gist_page(), pgstat_hash_page(), pgstat_heap(), pgstatginindex_internal(), pgstathashindex(), pgstatindex_impl(), prune_freeze_setup(), read_seq_tuple(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), RelationPutHeapTuple(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), scanPostingTree(), ScanSourceDatabasePgClass(), seq_redo(), SetSequence(), shiftList(), spgAddNodeAction(), spgbuild(), spgdoinsert(), spgGetCache(), SpGistGetBuffer(), SpGistInitBuffer(), SpGistNewBuffer(), SpGistSetLastUsedPage(), SpGistUpdateMetaPage(), spgprocesspending(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), spgvacuumpage(), spgWalk(), startScanEntry(), statapprox_heap(), terminate_brin_buildstate(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_prepare_truncate(), visibilitymap_set(), vm_readbuf(), writeListPage(), XLogCheckBufferNeedsBackup(), XLogReadBufferExtended(), XLogReadBufferForRedoExtended(), XLogRecordPageWithFreeSpace(), XLogRegisterBuffer(), XLogSaveBufferForHint(), xlogVacuumPage(), and ZeroAndLockBuffer().

◆ BufferGetPageSize()

◆ BufferGetTag()

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

Definition at line 4467 of file bufmgr.c.

4469{
4471
4472 /* Do the same checks as BufferGetBlockNumber. */
4473 Assert(BufferIsPinned(buffer));
4474
4475 if (BufferIsLocal(buffer))
4476 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
4477 else
4478 bufHdr = GetBufferDescriptor(buffer - 1);
4479
4480 /* pinned, so OK to read tag without spinlock */
4481 *rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
4482 *forknum = BufTagGetForkNum(&bufHdr->tag);
4483 *blknum = bufHdr->tag.blockNum;
4484}
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)

References Assert, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufTagGetForkNum(), BufTagGetRelFileLocator(), fb(), GetBufferDescriptor(), and GetLocalBufferDescriptor().

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

◆ BufferIsDirty()

bool BufferIsDirty ( Buffer  buffer)
extern

Definition at line 3114 of file bufmgr.c.

3115{
3117
3118 Assert(BufferIsPinned(buffer));
3119
3120 if (BufferIsLocal(buffer))
3121 {
3122 int bufid = -buffer - 1;
3123
3125 /* Content locks are not maintained for local buffers. */
3126 }
3127 else
3128 {
3129 bufHdr = GetBufferDescriptor(buffer - 1);
3132 }
3133
3134 return pg_atomic_read_u64(&bufHdr->state) & BM_DIRTY;
3135}
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition atomics.h:467
#define BM_DIRTY

References Assert, BM_DIRTY, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_SHARE_EXCLUSIVE, BufferIsLocal, BufferIsLockedByMeInMode(), BufferIsPinned, fb(), GetBufferDescriptor(), GetLocalBufferDescriptor(), and pg_atomic_read_u64().

Referenced by heap_multi_insert(), heap_page_will_set_vm(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), log_heap_prune_and_freeze(), XLogRegisterBuffer(), and XLogSaveBufferForHint().

◆ BufferIsLockedByMe()

bool BufferIsLockedByMe ( Buffer  buffer)
extern

Definition at line 3061 of file bufmgr.c.

3062{
3064
3065 Assert(BufferIsPinned(buffer));
3066
3067 if (BufferIsLocal(buffer))
3068 {
3069 /* Content locks are not maintained for local buffers. */
3070 return true;
3071 }
3072 else
3073 {
3074 bufHdr = GetBufferDescriptor(buffer - 1);
3075 return BufferLockHeldByMe(bufHdr);
3076 }
3077}
static bool BufferLockHeldByMe(BufferDesc *buf_hdr)
Definition bufmgr.c:6543

References Assert, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferLockHeldByMe(), fb(), and GetBufferDescriptor().

Referenced by FlushOneBuffer().

◆ BufferIsLockedByMeInMode()

bool BufferIsLockedByMeInMode ( Buffer  buffer,
BufferLockMode  mode 
)
extern

Definition at line 3087 of file bufmgr.c.

3088{
3090
3091 Assert(BufferIsPinned(buffer));
3092
3093 if (BufferIsLocal(buffer))
3094 {
3095 /* Content locks are not maintained for local buffers. */
3096 return true;
3097 }
3098 else
3099 {
3100 bufHdr = GetBufferDescriptor(buffer - 1);
3102 }
3103}
static bool BufferLockHeldByMeInMode(BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:6525
static PgChecksumMode mode

References Assert, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferLockHeldByMeInMode(), fb(), GetBufferDescriptor(), and mode.

Referenced by BufferFinishSetHintBits(), BufferIsDirty(), heap_page_fix_vm_corruption(), HeapTupleSetHintBits(), IsBufferCleanupOK(), MarkBufferDirty(), visibilitymap_set(), and XLogRegisterBuffer().

◆ BufferIsPermanent()

bool BufferIsPermanent ( Buffer  buffer)
extern

Definition at line 4677 of file bufmgr.c.

4678{
4680
4681 /* Local buffers are used only for temp relations. */
4682 if (BufferIsLocal(buffer))
4683 return false;
4684
4685 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4686 Assert(BufferIsValid(buffer));
4687 Assert(BufferIsPinned(buffer));
4688
4689 /*
4690 * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
4691 * need not bother with the buffer header spinlock. Even if someone else
4692 * changes the buffer header state while we're doing this, the state is
4693 * changed atomically, so we'll read the old value or the new value, but
4694 * not random garbage.
4695 */
4696 bufHdr = GetBufferDescriptor(buffer - 1);
4697 return (pg_atomic_read_u64(&bufHdr->state) & BM_PERMANENT) != 0;
4698}
#define BM_PERMANENT

References Assert, BM_PERMANENT, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferIsValid(), fb(), GetBufferDescriptor(), and pg_atomic_read_u64().

Referenced by SetHintBitsExt().

◆ BufferIsValid()

static bool BufferIsValid ( Buffer  bufnum)
inlinestatic

Definition at line 419 of file bufmgr.h.

420{
423
424 return bufnum != InvalidBuffer;
425}
#define InvalidBuffer
Definition buf.h:25
PGDLLIMPORT int NBuffers
Definition globals.c:144
PGDLLIMPORT int NLocBuffer
Definition localbuf.c:45

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

Referenced by _bt_clear_incomplete_split(), _bt_endpoint(), _bt_first(), _bt_get_endpoint(), _bt_insertonpg(), _bt_relandgetbuf(), _bt_search(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_dropscanbuf(), _hash_freeovflpage(), _hash_getbucketbuf_from_hashkey(), _hash_getcachedmetap(), _hash_readnext(), _hash_readpage(), _hash_readprev(), BitmapHeapScanNextBlock(), brin_doinsert(), brin_doupdate(), brin_getinsertbuffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinGetTupleForHeapBlock(), brininsert(), brinsummarize(), bt_recheck_sibling_links(), bt_rootdescend(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), btvacuumscan(), buffer_readv_complete(), BufferGetBlock(), BufferGetLSNAtomic(), BufferGetPageSize(), BufferIsPermanent(), ConditionalLockBufferForCleanup(), DebugPrintBufferRefcount(), doPickSplit(), entryGetItem(), entryLoadMoreItems(), EvictUnpinnedBuffer(), ExecStoreBufferHeapTuple(), ExecStorePinnedBufferHeapTuple(), FreeSpaceMapPrepareTruncateRel(), fsm_search(), fsm_vacuum_page(), generic_redo(), GetPrivateRefCount(), GetPrivateRefCountEntry(), GetRecordedFreeSpace(), GetVisibilityMapPins(), ginPlaceToPage(), ginRedoClearIncompleteSplit(), ginRedoDeletePage(), ginRedoInsert(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginScanPostingTreeToDelete(), gistinserttuples(), gistkillitems(), gistplacetopage(), gistRedoClearFollowRight(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageUpdateRecord(), gistvacuumscan(), gistXLogSplit(), gistXLogUpdate(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), hashbulkdelete(), heap_endscan(), heap_fetch_next_buffer(), heap_index_delete_tuples(), heap_inplace_lock(), heap_lock_tuple(), heap_rescan(), heap_update(), heap_vac_scan_next_block(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), heap_xlog_update(), heapam_index_fetch_end(), heapam_index_fetch_tuple(), heapam_scan_analyze_next_block(), heapam_scan_sample_next_block(), heapam_tuple_lock(), heapam_tuple_satisfies_snapshot(), heapgettup(), heapgettup_continue_page(), heapgettup_pagemode(), heapgettup_start_page(), invalidate_one_block(), IsBufferCleanupOK(), lazy_scan_heap(), lazy_vacuum_heap_rel(), MarkBufferDirty(), MarkBufferDirtyHint(), prune_freeze_setup(), read_stream_for_blocks(), read_stream_next_buffer(), ReadRecentBuffer(), ReleaseAndReadBuffer(), ReleaseBuffer(), ResOwnerReleaseBuffer(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgvacuumscan(), statapprox_heap(), tts_buffer_heap_clear(), tts_buffer_heap_copyslot(), tts_buffer_heap_materialize(), tts_buffer_heap_store_tuple(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_pin(), visibilitymap_pin_ok(), visibilitymap_prepare_truncate(), visibilitymap_set(), XLogPrefetcherNextBlock(), XLogReadBufferExtended(), and XLogReadBufferForRedoExtended().

◆ BufferSetHintBits16()

bool BufferSetHintBits16 ( uint16 ptr,
uint16  val,
Buffer  buffer 
)
extern

Definition at line 7093 of file bufmgr.c.

7094{
7097#ifdef USE_ASSERT_CHECKING
7098 char *page;
7099
7100 /* verify that the address is on the page */
7101 page = BufferGetPage(buffer);
7102 Assert((char *) ptr >= page && (char *) ptr < (page + BLCKSZ));
7103#endif
7104
7105 if (BufferIsLocal(buffer))
7106 {
7107 *ptr = val;
7108
7109 MarkLocalBufferDirty(buffer);
7110
7111 return true;
7112 }
7113
7114 buf_hdr = GetBufferDescriptor(buffer - 1);
7115
7117 {
7118 *ptr = val;
7119
7121
7122 return true;
7123 }
7124
7125 return false;
7126}
static void MarkSharedBufferDirtyHint(Buffer buffer, BufferDesc *bufHdr, uint64 lockstate, bool buffer_std)
Definition bufmgr.c:5696
long val
Definition informix.c:689
void MarkLocalBufferDirty(Buffer buffer)
Definition localbuf.c:492

References Assert, PrivateRefCountEntry::buffer, BufferGetPage(), BufferIsLocal, fb(), GetBufferDescriptor(), MarkLocalBufferDirty(), MarkSharedBufferDirtyHint(), SharedBufferBeginSetHintBits(), and val.

Referenced by SetHintBitsExt().

◆ CheckBufferIsPinnedOnce()

void CheckBufferIsPinnedOnce ( Buffer  buffer)
extern

Definition at line 6637 of file bufmgr.c.

6638{
6639 if (BufferIsLocal(buffer))
6640 {
6641 if (LocalRefCount[-buffer - 1] != 1)
6642 elog(ERROR, "incorrect local pin count: %d",
6643 LocalRefCount[-buffer - 1]);
6644 }
6645 else
6646 {
6647 if (GetPrivateRefCount(buffer) != 1)
6648 elog(ERROR, "incorrect local pin count: %d",
6649 GetPrivateRefCount(buffer));
6650 }
6651}
static int32 GetPrivateRefCount(Buffer buffer)
Definition bufmgr.c:542
#define ERROR
Definition elog.h:40
int32 * LocalRefCount
Definition localbuf.c:49

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

Referenced by GetVictimBuffer(), lazy_scan_heap(), and LockBufferForCleanup().

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)
extern

Definition at line 4432 of file bufmgr.c.

4433{
4434 BufferSync(flags);
4435}
static void BufferSync(int flags)
Definition bufmgr.c:3552

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)
extern

Definition at line 6617 of file bufmgr.c.

6618{
6619 BufferDesc *buf;
6620
6621 Assert(BufferIsPinned(buffer));
6622 if (BufferIsLocal(buffer))
6623 return true; /* act as though we got it */
6624
6625 buf = GetBufferDescriptor(buffer - 1);
6626
6628}
static bool BufferLockConditional(Buffer buffer, BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:6050
static char buf[DEFAULT_XLOG_SEG_SIZE]

References Assert, buf, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BufferIsLocal, BufferIsPinned, BufferLockConditional(), and GetBufferDescriptor().

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

◆ ConditionalLockBufferForCleanup()

bool ConditionalLockBufferForCleanup ( Buffer  buffer)
extern

Definition at line 6843 of file bufmgr.c.

6844{
6847 refcount;
6848
6849 Assert(BufferIsValid(buffer));
6850
6851 /* see AIO related comment in LockBufferForCleanup() */
6852
6853 if (BufferIsLocal(buffer))
6854 {
6855 refcount = LocalRefCount[-buffer - 1];
6856 /* There should be exactly one pin */
6857 Assert(refcount > 0);
6858 if (refcount != 1)
6859 return false;
6860 /* Nobody else to wait for */
6861 return true;
6862 }
6863
6864 /* There should be exactly one local pin */
6865 refcount = GetPrivateRefCount(buffer);
6866 Assert(refcount);
6867 if (refcount != 1)
6868 return false;
6869
6870 /* Try to acquire lock */
6871 if (!ConditionalLockBuffer(buffer))
6872 return false;
6873
6874 bufHdr = GetBufferDescriptor(buffer - 1);
6877
6878 Assert(refcount > 0);
6879 if (refcount == 1)
6880 {
6881 /* Successfully acquired exclusive lock with pincount 1 */
6883 return true;
6884 }
6885
6886 /* Failed, so release the lock */
6889 return false;
6890}
#define BUF_STATE_GET_REFCOUNT(state)
bool ConditionalLockBuffer(Buffer buffer)
Definition bufmgr.c:6617
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:334

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

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

◆ CreateAndCopyRelationData()

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

Definition at line 5462 of file bufmgr.c.

5464{
5465 char relpersistence;
5468
5469 /* Set the relpersistence. */
5470 relpersistence = permanent ?
5472
5475
5476 /*
5477 * Create and copy all forks of the relation. During create database we
5478 * have a separate cleanup mechanism which deletes complete database
5479 * directory. Therefore, each individual relation doesn't need to be
5480 * registered for cleanup.
5481 */
5482 RelationCreateStorage(dst_rlocator, relpersistence, false);
5483
5484 /* copy main fork. */
5486 permanent);
5487
5488 /* copy those extra forks that exist */
5489 for (ForkNumber forkNum = MAIN_FORKNUM + 1;
5490 forkNum <= MAX_FORKNUM; forkNum++)
5491 {
5492 if (smgrexists(src_rel, forkNum))
5493 {
5494 smgrcreate(dst_rel, forkNum, false);
5495
5496 /*
5497 * WAL log creation if the relation is persistent, or this is the
5498 * init fork of an unlogged relation.
5499 */
5500 if (permanent || forkNum == INIT_FORKNUM)
5501 log_smgrcreate(&dst_rlocator, forkNum);
5502
5503 /* Copy a fork's data, block by block. */
5505 permanent);
5506 }
5507 }
5508}
static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, RelFileLocator dstlocator, ForkNumber forkNum, bool permanent)
Definition bufmgr.c:5348
#define INVALID_PROC_NUMBER
Definition procnumber.h:26
ForkNumber
Definition relpath.h:56
@ MAIN_FORKNUM
Definition relpath.h:58
@ INIT_FORKNUM
Definition relpath.h:61
#define MAX_FORKNUM
Definition relpath.h:70
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
Definition smgr.c:240
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition smgr.c:481
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition smgr.c:462
SMgrRelation RelationCreateStorage(RelFileLocator rlocator, char relpersistence, bool register_delete)
Definition storage.c:122
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
Definition storage.c:187

References fb(), INIT_FORKNUM, INVALID_PROC_NUMBER, log_smgrcreate(), MAIN_FORKNUM, MAX_FORKNUM, RelationCopyStorageUsingBuffer(), RelationCreateStorage(), smgrcreate(), smgrexists(), and smgropen().

Referenced by CreateDatabaseUsingWalLog().

◆ DebugPrintBufferRefcount()

char * DebugPrintBufferRefcount ( Buffer  buffer)
extern

Definition at line 4389 of file bufmgr.c.

4390{
4391 BufferDesc *buf;
4393 char *result;
4394 ProcNumber backend;
4396
4397 Assert(BufferIsValid(buffer));
4398 if (BufferIsLocal(buffer))
4399 {
4400 buf = GetLocalBufferDescriptor(-buffer - 1);
4401 loccount = LocalRefCount[-buffer - 1];
4402 backend = MyProcNumber;
4403 }
4404 else
4405 {
4406 buf = GetBufferDescriptor(buffer - 1);
4407 loccount = GetPrivateRefCount(buffer);
4408 backend = INVALID_PROC_NUMBER;
4409 }
4410
4411 /* theoretically we should lock the bufHdr here */
4412 buf_state = pg_atomic_read_u64(&buf->state);
4413
4414 result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%" PRIx64 ", refcount=%u %d)",
4415 buffer,
4417 BufTagGetForkNum(&buf->tag)).str,
4418 buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
4420 return result;
4421}
#define BUF_FLAG_MASK
uint32 result
ProcNumber MyProcNumber
Definition globals.c:92
int ProcNumber
Definition procnumber.h:24
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
#define relpathbackend(rlocator, backend, forknum)
Definition relpath.h:141

References Assert, buf, BUF_FLAG_MASK, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsValid(), BufTagGetForkNum(), BufTagGetRelFileLocator(), fb(), GetBufferDescriptor(), GetLocalBufferDescriptor(), GetPrivateRefCount(), INVALID_PROC_NUMBER, LocalRefCount, MyProcNumber, pg_atomic_read_u64(), psprintf(), relpathbackend, and result.

Referenced by buffer_call_start_io(), buffer_call_terminate_io(), CheckForBufferLeaks(), CheckForLocalBufferLeaks(), and ResOwnerPrintBuffer().

◆ DropDatabaseBuffers()

void DropDatabaseBuffers ( Oid  dbid)
extern

Definition at line 5115 of file bufmgr.c.

5116{
5117 int i;
5118
5119 /*
5120 * We needn't consider local buffers, since by assumption the target
5121 * database isn't our own.
5122 */
5123
5124 for (i = 0; i < NBuffers; i++)
5125 {
5127
5128 /*
5129 * As in DropRelationBuffers, an unlocked precheck should be safe and
5130 * saves some cycles.
5131 */
5132 if (bufHdr->tag.dbOid != dbid)
5133 continue;
5134
5136 if (bufHdr->tag.dbOid == dbid)
5137 InvalidateBuffer(bufHdr); /* releases spinlock */
5138 else
5140 }
5141}
static void InvalidateBuffer(BufferDesc *buf)
Definition bufmgr.c:2361
int i
Definition isn.c:77

References fb(), GetBufferDescriptor(), i, InvalidateBuffer(), LockBufHdr(), NBuffers, and UnlockBufHdr().

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

◆ DropRelationBuffers()

void DropRelationBuffers ( SMgrRelation  smgr_reln,
ForkNumber forkNum,
int  nforks,
BlockNumber firstDelBlock 
)
extern

Definition at line 4765 of file bufmgr.c.

4767{
4768 int i;
4769 int j;
4770 RelFileLocatorBackend rlocator;
4773
4774 rlocator = smgr_reln->smgr_rlocator;
4775
4776 /* If it's a local relation, it's localbuf.c's problem. */
4777 if (RelFileLocatorBackendIsTemp(rlocator))
4778 {
4779 if (rlocator.backend == MyProcNumber)
4780 DropRelationLocalBuffers(rlocator.locator, forkNum, nforks,
4782
4783 return;
4784 }
4785
4786 /*
4787 * To remove all the pages of the specified relation forks from the buffer
4788 * pool, we need to scan the entire buffer pool but we can optimize it by
4789 * finding the buffers from BufMapping table provided we know the exact
4790 * size of each fork of the relation. The exact size is required to ensure
4791 * that we don't leave any buffer for the relation being dropped as
4792 * otherwise the background writer or checkpointer can lead to a PANIC
4793 * error while flushing buffers corresponding to files that don't exist.
4794 *
4795 * To know the exact size, we rely on the size cached for each fork by us
4796 * during recovery which limits the optimization to recovery and on
4797 * standbys but we can easily extend it once we have shared cache for
4798 * relation size.
4799 *
4800 * In recovery, we cache the value returned by the first lseek(SEEK_END)
4801 * and the future writes keeps the cached value up-to-date. See
4802 * smgrextend. It is possible that the value of the first lseek is smaller
4803 * than the actual number of existing blocks in the file due to buggy
4804 * Linux kernels that might not have accounted for the recent write. But
4805 * that should be fine because there must not be any buffers after that
4806 * file size.
4807 */
4808 for (i = 0; i < nforks; i++)
4809 {
4810 /* Get the number of blocks for a relation's fork */
4812
4814 {
4816 break;
4817 }
4818
4819 /* calculate the number of blocks to be invalidated */
4821 }
4822
4823 /*
4824 * We apply the optimization iff the total number of blocks to invalidate
4825 * is below the BUF_DROP_FULL_SCAN_THRESHOLD.
4826 */
4829 {
4830 for (j = 0; j < nforks; j++)
4831 FindAndDropRelationBuffers(rlocator.locator, forkNum[j],
4833 return;
4834 }
4835
4836 for (i = 0; i < NBuffers; i++)
4837 {
4839
4840 /*
4841 * We can make this a tad faster by prechecking the buffer tag before
4842 * we attempt to lock the buffer; this saves a lot of lock
4843 * acquisitions in typical cases. It should be safe because the
4844 * caller must have AccessExclusiveLock on the relation, or some other
4845 * reason to be certain that no one is loading new pages of the rel
4846 * into the buffer pool. (Otherwise we might well miss such pages
4847 * entirely.) Therefore, while the tag might be changing while we
4848 * look at it, it can't be changing *to* a value we care about, only
4849 * *away* from such a value. So false negatives are impossible, and
4850 * false positives are safe because we'll recheck after getting the
4851 * buffer lock.
4852 *
4853 * We could check forkNum and blockNum as well as the rlocator, but
4854 * the incremental win from doing so seems small.
4855 */
4856 if (!BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator.locator))
4857 continue;
4858
4860
4861 for (j = 0; j < nforks; j++)
4862 {
4863 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator.locator) &&
4864 BufTagGetForkNum(&bufHdr->tag) == forkNum[j] &&
4865 bufHdr->tag.blockNum >= firstDelBlock[j])
4866 {
4867 InvalidateBuffer(bufHdr); /* releases spinlock */
4868 break;
4869 }
4870 }
4871 if (j >= nforks)
4873 }
4874}
uint32 BlockNumber
Definition block.h:31
#define InvalidBlockNumber
Definition block.h:33
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition block.h:71
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
#define BUF_DROP_FULL_SCAN_THRESHOLD
Definition bufmgr.c:95
static void FindAndDropRelationBuffers(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber nForkBlock, BlockNumber firstDelBlock)
Definition bufmgr.c:5055
int j
Definition isn.c:78
void DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
Definition localbuf.c:681
#define RelFileLocatorBackendIsTemp(rlocator)
BlockNumber smgrnblocks_cached(SMgrRelation reln, ForkNumber forknum)
Definition smgr.c:847
RelFileLocator locator

References RelFileLocatorBackend::backend, BlockNumberIsValid(), BUF_DROP_FULL_SCAN_THRESHOLD, BufTagGetForkNum(), BufTagMatchesRelFileLocator(), DropRelationLocalBuffers(), fb(), FindAndDropRelationBuffers(), GetBufferDescriptor(), i, InvalidateBuffer(), InvalidBlockNumber, j, RelFileLocatorBackend::locator, LockBufHdr(), MAX_FORKNUM, MyProcNumber, NBuffers, RelFileLocatorBackendIsTemp, smgrnblocks_cached(), and UnlockBufHdr().

Referenced by smgrtruncate().

◆ DropRelationsAllBuffers()

void DropRelationsAllBuffers ( SMgrRelation smgr_reln,
int  nlocators 
)
extern

Definition at line 4885 of file bufmgr.c.

4886{
4887 int i;
4888 int n = 0;
4889 SMgrRelation *rels;
4890 BlockNumber (*block)[MAX_FORKNUM + 1];
4893 bool cached = true;
4894 bool use_bsearch;
4895
4896 if (nlocators == 0)
4897 return;
4898
4899 rels = palloc_array(SMgrRelation, nlocators); /* non-local relations */
4900
4901 /* If it's a local relation, it's localbuf.c's problem. */
4902 for (i = 0; i < nlocators; i++)
4903 {
4904 if (RelFileLocatorBackendIsTemp(smgr_reln[i]->smgr_rlocator))
4905 {
4906 if (smgr_reln[i]->smgr_rlocator.backend == MyProcNumber)
4907 DropRelationAllLocalBuffers(smgr_reln[i]->smgr_rlocator.locator);
4908 }
4909 else
4910 rels[n++] = smgr_reln[i];
4911 }
4912
4913 /*
4914 * If there are no non-local relations, then we're done. Release the
4915 * memory and return.
4916 */
4917 if (n == 0)
4918 {
4919 pfree(rels);
4920 return;
4921 }
4922
4923 /*
4924 * This is used to remember the number of blocks for all the relations
4925 * forks.
4926 */
4927 block = (BlockNumber (*)[MAX_FORKNUM + 1])
4928 palloc(sizeof(BlockNumber) * n * (MAX_FORKNUM + 1));
4929
4930 /*
4931 * We can avoid scanning the entire buffer pool if we know the exact size
4932 * of each of the given relation forks. See DropRelationBuffers.
4933 */
4934 for (i = 0; i < n && cached; i++)
4935 {
4936 for (int j = 0; j <= MAX_FORKNUM; j++)
4937 {
4938 /* Get the number of blocks for a relation's fork. */
4939 block[i][j] = smgrnblocks_cached(rels[i], j);
4940
4941 /* We need to only consider the relation forks that exists. */
4942 if (block[i][j] == InvalidBlockNumber)
4943 {
4944 if (!smgrexists(rels[i], j))
4945 continue;
4946 cached = false;
4947 break;
4948 }
4949
4950 /* calculate the total number of blocks to be invalidated */
4951 nBlocksToInvalidate += block[i][j];
4952 }
4953 }
4954
4955 /*
4956 * We apply the optimization iff the total number of blocks to invalidate
4957 * is below the BUF_DROP_FULL_SCAN_THRESHOLD.
4958 */
4960 {
4961 for (i = 0; i < n; i++)
4962 {
4963 for (int j = 0; j <= MAX_FORKNUM; j++)
4964 {
4965 /* ignore relation forks that doesn't exist */
4966 if (!BlockNumberIsValid(block[i][j]))
4967 continue;
4968
4969 /* drop all the buffers for a particular relation fork */
4970 FindAndDropRelationBuffers(rels[i]->smgr_rlocator.locator,
4971 j, block[i][j], 0);
4972 }
4973 }
4974
4975 pfree(block);
4976 pfree(rels);
4977 return;
4978 }
4979
4980 pfree(block);
4981 locators = palloc_array(RelFileLocator, n); /* non-local relations */
4982 for (i = 0; i < n; i++)
4983 locators[i] = rels[i]->smgr_rlocator.locator;
4984
4985 /*
4986 * For low number of relations to drop just use a simple walk through, to
4987 * save the bsearch overhead. The threshold to use is rather a guess than
4988 * an exactly determined value, as it depends on many factors (CPU and RAM
4989 * speeds, amount of shared buffers etc.).
4990 */
4992
4993 /* sort the list of rlocators if necessary */
4994 if (use_bsearch)
4996
4997 for (i = 0; i < NBuffers; i++)
4998 {
4999 RelFileLocator *rlocator = NULL;
5001
5002 /*
5003 * As in DropRelationBuffers, an unlocked precheck should be safe and
5004 * saves some cycles.
5005 */
5006
5007 if (!use_bsearch)
5008 {
5009 int j;
5010
5011 for (j = 0; j < n; j++)
5012 {
5014 {
5015 rlocator = &locators[j];
5016 break;
5017 }
5018 }
5019 }
5020 else
5021 {
5022 RelFileLocator locator;
5023
5024 locator = BufTagGetRelFileLocator(&bufHdr->tag);
5025 rlocator = bsearch(&locator,
5026 locators, n, sizeof(RelFileLocator),
5028 }
5029
5030 /* buffer doesn't belong to any of the given relfilelocators; skip it */
5031 if (rlocator == NULL)
5032 continue;
5033
5035 if (BufTagMatchesRelFileLocator(&bufHdr->tag, rlocator))
5036 InvalidateBuffer(bufHdr); /* releases spinlock */
5037 else
5039 }
5040
5041 pfree(locators);
5042 pfree(rels);
5043}
static int rlocator_comparator(const void *p1, const void *p2)
Definition bufmgr.c:7491
#define RELS_BSEARCH_THRESHOLD
Definition bufmgr.c:87
#define palloc_array(type, count)
Definition fe_memutils.h:76
void DropRelationAllLocalBuffers(RelFileLocator rlocator)
Definition localbuf.c:718
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc(Size size)
Definition mcxt.c:1387
#define qsort(a, b, c, d)
Definition port.h:495

References BlockNumberIsValid(), BUF_DROP_FULL_SCAN_THRESHOLD, BufTagGetRelFileLocator(), BufTagMatchesRelFileLocator(), DropRelationAllLocalBuffers(), fb(), FindAndDropRelationBuffers(), GetBufferDescriptor(), i, InvalidateBuffer(), InvalidBlockNumber, j, LockBufHdr(), MAX_FORKNUM, MyProcNumber, NBuffers, palloc(), palloc_array, pfree(), qsort, RelFileLocatorBackendIsTemp, RELS_BSEARCH_THRESHOLD, rlocator_comparator(), smgrexists(), smgrnblocks_cached(), and UnlockBufHdr().

Referenced by smgrdounlinkall().

◆ EvictAllUnpinnedBuffers()

void EvictAllUnpinnedBuffers ( int32 buffers_evicted,
int32 buffers_flushed,
int32 buffers_skipped 
)
extern

Definition at line 7982 of file bufmgr.c.

7984{
7985 *buffers_evicted = 0;
7986 *buffers_skipped = 0;
7987 *buffers_flushed = 0;
7988
7989 for (int buf = 1; buf <= NBuffers; buf++)
7990 {
7991 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7993 bool buffer_flushed;
7994
7996
7998 if (!(buf_state & BM_VALID))
7999 continue;
8000
8003
8004 LockBufHdr(desc);
8005
8007 (*buffers_evicted)++;
8008 else
8009 (*buffers_skipped)++;
8010
8011 if (buffer_flushed)
8012 (*buffers_flushed)++;
8013 }
8014}
#define BM_VALID
static bool EvictUnpinnedBufferInternal(BufferDesc *desc, bool *buffer_flushed)
Definition bufmgr.c:7891
static void ReservePrivateRefCountEntry(void)
Definition bufmgr.c:309
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
ResourceOwner CurrentResourceOwner
Definition resowner.c:173
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition resowner.c:449
pg_atomic_uint64 state

References BM_VALID, buf, CHECK_FOR_INTERRUPTS, CurrentResourceOwner, EvictUnpinnedBufferInternal(), fb(), GetBufferDescriptor(), LockBufHdr(), NBuffers, pg_atomic_read_u64(), ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), and BufferDesc::state.

Referenced by pg_buffercache_evict_all().

◆ EvictRelUnpinnedBuffers()

void EvictRelUnpinnedBuffers ( Relation  rel,
int32 buffers_evicted,
int32 buffers_flushed,
int32 buffers_skipped 
)
extern

Definition at line 8032 of file bufmgr.c.

8034{
8036
8037 *buffers_skipped = 0;
8038 *buffers_evicted = 0;
8039 *buffers_flushed = 0;
8040
8041 for (int buf = 1; buf <= NBuffers; buf++)
8042 {
8043 BufferDesc *desc = GetBufferDescriptor(buf - 1);
8045 bool buffer_flushed;
8046
8048
8049 /* An unlocked precheck should be safe and saves some cycles. */
8050 if ((buf_state & BM_VALID) == 0 ||
8052 continue;
8053
8054 /* Make sure we can pin the buffer. */
8057
8058 buf_state = LockBufHdr(desc);
8059
8060 /* recheck, could have changed without the lock */
8061 if ((buf_state & BM_VALID) == 0 ||
8063 {
8064 UnlockBufHdr(desc);
8065 continue;
8066 }
8067
8069 (*buffers_evicted)++;
8070 else
8071 (*buffers_skipped)++;
8072
8073 if (buffer_flushed)
8074 (*buffers_flushed)++;
8075 }
8076}
#define RelationUsesLocalBuffers(relation)
Definition rel.h:648
BufferTag tag
RelFileLocator rd_locator
Definition rel.h:57

References Assert, BM_VALID, buf, BufTagMatchesRelFileLocator(), CHECK_FOR_INTERRUPTS, CurrentResourceOwner, EvictUnpinnedBufferInternal(), fb(), GetBufferDescriptor(), LockBufHdr(), NBuffers, pg_atomic_read_u64(), RelationData::rd_locator, RelationUsesLocalBuffers, ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), BufferDesc::state, BufferDesc::tag, and UnlockBufHdr().

Referenced by evict_rel(), and pg_buffercache_evict_relation().

◆ EvictUnpinnedBuffer()

bool EvictUnpinnedBuffer ( Buffer  buf,
bool buffer_flushed 
)
extern

◆ ExtendBufferedRel()

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

Definition at line 979 of file bufmgr.c.

983{
984 Buffer buf;
985 uint32 extend_by = 1;
986
987 ExtendBufferedRelBy(bmr, forkNum, strategy, flags, extend_by,
988 &buf, &extend_by);
989
990 return buf;
991}
int Buffer
Definition buf.h:23
BlockNumber ExtendBufferedRelBy(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, Buffer *buffers, uint32 *extended_by)
Definition bufmgr.c:1011

References buf, ExtendBufferedRelBy(), and fb().

Referenced by _bt_allocbuf(), _hash_getnewbuf(), BloomNewBuffer(), brinbuild(), brinbuildempty(), fill_seq_fork_with_data(), ginbuildempty(), GinNewBuffer(), gistbuildempty(), gistNewBuffer(), ReadBuffer_common(), revmap_physical_extend(), and SpGistNewBuffer().

◆ ExtendBufferedRelBy()

BlockNumber ExtendBufferedRelBy ( BufferManagerRelation  bmr,
ForkNumber  fork,
BufferAccessStrategy  strategy,
uint32  flags,
uint32  extend_by,
Buffer buffers,
uint32 extended_by 
)
extern

Definition at line 1011 of file bufmgr.c.

1018{
1019 Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
1020 Assert(bmr.smgr == NULL || bmr.relpersistence != '\0');
1021 Assert(extend_by > 0);
1022
1023 if (bmr.relpersistence == '\0')
1024 bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
1025
1026 return ExtendBufferedRelCommon(bmr, fork, strategy, flags,
1028 buffers, extended_by);
1029}
static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, BlockNumber extend_upto, Buffer *buffers, uint32 *extended_by)
Definition bufmgr.c:2742

References Assert, ExtendBufferedRelCommon(), fb(), and InvalidBlockNumber.

Referenced by ExtendBufferedRel(), grow_rel(), and RelationAddBlocks().

◆ ExtendBufferedRelTo()

Buffer ExtendBufferedRelTo ( BufferManagerRelation  bmr,
ForkNumber  fork,
BufferAccessStrategy  strategy,
uint32  flags,
BlockNumber  extend_to,
ReadBufferMode  mode 
)
extern

Definition at line 1040 of file bufmgr.c.

1046{
1048 uint32 extended_by = 0;
1049 Buffer buffer = InvalidBuffer;
1050 Buffer buffers[64];
1051
1052 Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
1053 Assert(bmr.smgr == NULL || bmr.relpersistence != '\0');
1055
1056 if (bmr.relpersistence == '\0')
1057 bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
1058
1059 /*
1060 * If desired, create the file if it doesn't exist. If
1061 * smgr_cached_nblocks[fork] is positive then it must exist, no need for
1062 * an smgrexists call.
1063 */
1064 if ((flags & EB_CREATE_FORK_IF_NEEDED) &&
1065 (BMR_GET_SMGR(bmr)->smgr_cached_nblocks[fork] == 0 ||
1066 BMR_GET_SMGR(bmr)->smgr_cached_nblocks[fork] == InvalidBlockNumber) &&
1068 {
1070
1071 /* recheck, fork might have been created concurrently */
1074
1076 }
1077
1078 /*
1079 * If requested, invalidate size cache, so that smgrnblocks asks the
1080 * kernel.
1081 */
1082 if (flags & EB_CLEAR_SIZE_CACHE)
1083 BMR_GET_SMGR(bmr)->smgr_cached_nblocks[fork] = InvalidBlockNumber;
1084
1085 /*
1086 * Estimate how many pages we'll need to extend by. This avoids acquiring
1087 * unnecessarily many victim buffers.
1088 */
1090
1091 /*
1092 * Since no-one else can be looking at the page contents yet, there is no
1093 * difference between an exclusive lock and a cleanup-strength lock. Note
1094 * that we pass the original mode to ReadBuffer_common() below, when
1095 * falling back to reading the buffer to a concurrent relation extension.
1096 */
1098 flags |= EB_LOCK_TARGET;
1099
1100 while (current_size < extend_to)
1101 {
1102 uint32 num_pages = lengthof(buffers);
1104
1105 if ((uint64) current_size + num_pages > extend_to)
1106 num_pages = extend_to - current_size;
1107
1108 first_block = ExtendBufferedRelCommon(bmr, fork, strategy, flags,
1109 num_pages, extend_to,
1110 buffers, &extended_by);
1111
1113 Assert(num_pages != 0 || current_size >= extend_to);
1114
1115 for (uint32 i = 0; i < extended_by; i++)
1116 {
1117 if (first_block + i != extend_to - 1)
1118 ReleaseBuffer(buffers[i]);
1119 else
1120 buffer = buffers[i];
1121 }
1122 }
1123
1124 /*
1125 * It's possible that another backend concurrently extended the relation.
1126 * In that case read the buffer.
1127 *
1128 * XXX: Should we control this via a flag?
1129 */
1130 if (buffer == InvalidBuffer)
1131 {
1132 Assert(extended_by == 0);
1133 buffer = ReadBuffer_common(bmr.rel, BMR_GET_SMGR(bmr), bmr.relpersistence,
1134 fork, extend_to - 1, mode, strategy);
1135 }
1136
1137 return buffer;
1138}
static Buffer ReadBuffer_common(Relation rel, SMgrRelation smgr, char smgr_persistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition bufmgr.c:1285
void ReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5586
#define BMR_GET_SMGR(bmr)
Definition bufmgr.h:118
#define lengthof(array)
Definition c.h:873
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition lmgr.c:424
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition lmgr.c:474
#define ExclusiveLock
Definition lockdefs.h:42
static int64 current_size
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition smgr.c:819

References Assert, BMR_GET_SMGR, PrivateRefCountEntry::buffer, current_size, EB_CLEAR_SIZE_CACHE, EB_CREATE_FORK_IF_NEEDED, EB_LOCK_TARGET, EB_PERFORMING_RECOVERY, ExclusiveLock, ExtendBufferedRelCommon(), fb(), i, InvalidBlockNumber, InvalidBuffer, lengthof, LockRelationForExtension(), mode, RBM_ZERO_AND_CLEANUP_LOCK, RBM_ZERO_AND_LOCK, ReadBuffer_common(), ReleaseBuffer(), smgrcreate(), smgrexists(), smgrnblocks(), and UnlockRelationForExtension().

Referenced by fsm_extend(), vm_extend(), and XLogReadBufferExtended().

◆ FlushDatabaseBuffers()

void FlushDatabaseBuffers ( Oid  dbid)
extern

Definition at line 5526 of file bufmgr.c.

5527{
5528 int i;
5530
5531 for (i = 0; i < NBuffers; i++)
5532 {
5534
5536
5537 /*
5538 * As in DropRelationBuffers, an unlocked precheck should be safe and
5539 * saves some cycles.
5540 */
5541 if (bufHdr->tag.dbOid != dbid)
5542 continue;
5543
5544 /* Make sure we can handle the pin */
5547
5549 if (bufHdr->tag.dbOid == dbid &&
5551 {
5555 }
5556 else
5558 }
5559}
static void FlushUnlockedBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition bufmgr.c:4626
static void PinBuffer_Locked(BufferDesc *buf)
Definition bufmgr.c:3388
static void UnpinBuffer(BufferDesc *buf)
Definition bufmgr.c:3456
@ IOOBJECT_RELATION
Definition pgstat.h:281
@ IOCONTEXT_NORMAL
Definition pgstat.h:293

References BM_DIRTY, BM_VALID, CurrentResourceOwner, fb(), FlushUnlockedBuffer(), GetBufferDescriptor(), i, IOCONTEXT_NORMAL, IOOBJECT_RELATION, LockBufHdr(), NBuffers, PinBuffer_Locked(), ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), UnlockBufHdr(), and UnpinBuffer().

Referenced by dbase_redo().

◆ FlushOneBuffer()

void FlushOneBuffer ( Buffer  buffer)
extern

Definition at line 5566 of file bufmgr.c.

5567{
5569
5570 /* currently not needed, but no fundamental reason not to support */
5571 Assert(!BufferIsLocal(buffer));
5572
5573 Assert(BufferIsPinned(buffer));
5574
5575 bufHdr = GetBufferDescriptor(buffer - 1);
5576
5577 Assert(BufferIsLockedByMe(buffer));
5578
5580}
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition bufmgr.c:4503
bool BufferIsLockedByMe(Buffer buffer)
Definition bufmgr.c:3061

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

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

◆ FlushRelationBuffers()

void FlushRelationBuffers ( Relation  rel)
extern

Definition at line 5162 of file bufmgr.c.

5163{
5164 int i;
5166 SMgrRelation srel = RelationGetSmgr(rel);
5167
5168 if (RelationUsesLocalBuffers(rel))
5169 {
5170 for (i = 0; i < NLocBuffer; i++)
5171 {
5173
5175 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
5176 ((buf_state = pg_atomic_read_u64(&bufHdr->state)) &
5177 (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
5178 {
5179 ErrorContextCallback errcallback;
5180
5181 /* Setup error traceback support for ereport() */
5183 errcallback.arg = bufHdr;
5184 errcallback.previous = error_context_stack;
5185 error_context_stack = &errcallback;
5186
5187 /* Make sure we can handle the pin */
5190
5191 /*
5192 * Pin/unpin mostly to make valgrind work, but it also seems
5193 * like the right thing to do.
5194 */
5195 PinLocalBuffer(bufHdr, false);
5196
5197
5198 FlushLocalBuffer(bufHdr, srel);
5199
5201
5202 /* Pop the error context stack */
5203 error_context_stack = errcallback.previous;
5204 }
5205 }
5206
5207 return;
5208 }
5209
5210 for (i = 0; i < NBuffers; i++)
5211 {
5213
5215
5216 /*
5217 * As in DropRelationBuffers, an unlocked precheck should be safe and
5218 * saves some cycles.
5219 */
5221 continue;
5222
5223 /* Make sure we can handle the pin */
5226
5228 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
5230 {
5234 }
5235 else
5237 }
5238}
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
static void local_buffer_write_error_callback(void *arg)
Definition bufmgr.c:7475
ErrorContextCallback * error_context_stack
Definition elog.c:99
void FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln)
Definition localbuf.c:183
void UnpinLocalBuffer(Buffer buffer)
Definition localbuf.c:857
bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
Definition localbuf.c:821
int NLocBuffer
Definition localbuf.c:45
static SMgrRelation RelationGetSmgr(Relation rel)
Definition rel.h:578
struct ErrorContextCallback * previous
Definition elog.h:299
void(* callback)(void *arg)
Definition elog.h:300

References ErrorContextCallback::arg, BM_DIRTY, BM_VALID, BufferDescriptorGetBuffer(), BufTagMatchesRelFileLocator(), ErrorContextCallback::callback, CurrentResourceOwner, error_context_stack, fb(), FlushLocalBuffer(), FlushUnlockedBuffer(), GetBufferDescriptor(), GetLocalBufferDescriptor(), i, IOCONTEXT_NORMAL, IOOBJECT_RELATION, local_buffer_write_error_callback(), LockBufHdr(), NBuffers, NLocBuffer, pg_atomic_read_u64(), PinBuffer_Locked(), PinLocalBuffer(), ErrorContextCallback::previous, RelationData::rd_locator, RelationGetSmgr(), RelationUsesLocalBuffers, ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), UnlockBufHdr(), UnpinBuffer(), and UnpinLocalBuffer().

Referenced by fill_seq_with_data(), heapam_relation_copy_data(), and index_copy_data().

◆ FlushRelationsAllBuffers()

void FlushRelationsAllBuffers ( SMgrRelation smgrs,
int  nrels 
)
extern

Definition at line 5250 of file bufmgr.c.

5251{
5252 int i;
5254 bool use_bsearch;
5255
5256 if (nrels == 0)
5257 return;
5258
5259 /* fill-in array for qsort */
5261
5262 for (i = 0; i < nrels; i++)
5263 {
5264 Assert(!RelFileLocatorBackendIsTemp(smgrs[i]->smgr_rlocator));
5265
5266 srels[i].rlocator = smgrs[i]->smgr_rlocator.locator;
5267 srels[i].srel = smgrs[i];
5268 }
5269
5270 /*
5271 * Save the bsearch overhead for low number of relations to sync. See
5272 * DropRelationsAllBuffers for details.
5273 */
5275
5276 /* sort the list of SMgrRelations if necessary */
5277 if (use_bsearch)
5278 qsort(srels, nrels, sizeof(SMgrSortArray), rlocator_comparator);
5279
5280 for (i = 0; i < NBuffers; i++)
5281 {
5285
5286 /*
5287 * As in DropRelationBuffers, an unlocked precheck should be safe and
5288 * saves some cycles.
5289 */
5290
5291 if (!use_bsearch)
5292 {
5293 int j;
5294
5295 for (j = 0; j < nrels; j++)
5296 {
5297 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &srels[j].rlocator))
5298 {
5299 srelent = &srels[j];
5300 break;
5301 }
5302 }
5303 }
5304 else
5305 {
5306 RelFileLocator rlocator;
5307
5308 rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
5309 srelent = bsearch(&rlocator,
5310 srels, nrels, sizeof(SMgrSortArray),
5312 }
5313
5314 /* buffer doesn't belong to any of the given relfilelocators; skip it */
5315 if (srelent == NULL)
5316 continue;
5317
5318 /* Make sure we can handle the pin */
5321
5323 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &srelent->rlocator) &&
5325 {
5329 }
5330 else
5332 }
5333
5334 pfree(srels);
5335}

References Assert, BM_DIRTY, BM_VALID, BufTagGetRelFileLocator(), BufTagMatchesRelFileLocator(), CurrentResourceOwner, fb(), FlushUnlockedBuffer(), GetBufferDescriptor(), i, IOCONTEXT_NORMAL, IOOBJECT_RELATION, j, LockBufHdr(), NBuffers, palloc_array, pfree(), PinBuffer_Locked(), qsort, RelFileLocatorBackendIsTemp, RELS_BSEARCH_THRESHOLD, ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), rlocator_comparator(), UnlockBufHdr(), and UnpinBuffer().

Referenced by smgrdosyncall().

◆ FreeAccessStrategy()

void FreeAccessStrategy ( BufferAccessStrategy  strategy)
extern

Definition at line 608 of file freelist.c.

609{
610 /* don't crash if called on a "default" strategy */
611 if (strategy != NULL)
612 pfree(strategy);
613}

References fb(), and pfree().

Referenced by blgetbitmap(), FreeBulkInsertState(), heap_endscan(), initscan(), parallel_vacuum_main(), and RelationCopyStorageUsingBuffer().

◆ GetAccessStrategy()

BufferAccessStrategy GetAccessStrategy ( BufferAccessStrategyType  btype)
extern

Definition at line 426 of file freelist.c.

427{
428 int ring_size_kb;
429
430 /*
431 * Select ring size to use. See buffer/README for rationales.
432 *
433 * Note: if you change the ring size for BAS_BULKREAD, see also
434 * SYNC_SCAN_REPORT_INTERVAL in access/heap/syncscan.c.
435 */
436 switch (btype)
437 {
438 case BAS_NORMAL:
439 /* if someone asks for NORMAL, just give 'em a "default" object */
440 return NULL;
441
442 case BAS_BULKREAD:
443 {
444 int ring_max_kb;
445
446 /*
447 * The ring always needs to be large enough to allow some
448 * separation in time between providing a buffer to the user
449 * of the strategy and that buffer being reused. Otherwise the
450 * user's pin will prevent reuse of the buffer, even without
451 * concurrent activity.
452 *
453 * We also need to ensure the ring always is large enough for
454 * SYNC_SCAN_REPORT_INTERVAL, as noted above.
455 *
456 * Thus we start out a minimal size and increase the size
457 * further if appropriate.
458 */
459 ring_size_kb = 256;
460
461 /*
462 * There's no point in a larger ring if we won't be allowed to
463 * pin sufficiently many buffers. But we never limit to less
464 * than the minimal size above.
465 */
466 ring_max_kb = GetPinLimit() * (BLCKSZ / 1024);
468
469 /*
470 * We would like the ring to additionally have space for the
471 * configured degree of IO concurrency. While being read in,
472 * buffers can obviously not yet be reused.
473 *
474 * Each IO can be up to io_combine_limit blocks large, and we
475 * want to start up to effective_io_concurrency IOs.
476 *
477 * Note that effective_io_concurrency may be 0, which disables
478 * AIO.
479 */
480 ring_size_kb += (BLCKSZ / 1024) *
482
485 break;
486 }
487 case BAS_BULKWRITE:
488 ring_size_kb = 16 * 1024;
489 break;
490 case BAS_VACUUM:
491 ring_size_kb = 2048;
492 break;
493
494 default:
495 elog(ERROR, "unrecognized buffer access strategy: %d",
496 (int) btype);
497 return NULL; /* keep compiler quiet */
498 }
499
501}
int effective_io_concurrency
Definition bufmgr.c:200
int io_combine_limit
Definition bufmgr.c:215
uint32 GetPinLimit(void)
Definition bufmgr.c:2686
#define Max(x, y)
Definition c.h:1085
BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype, int ring_size_kb)
Definition freelist.c:511

References BAS_BULKREAD, BAS_BULKWRITE, BAS_NORMAL, BAS_VACUUM, effective_io_concurrency, elog, ERROR, fb(), GetAccessStrategyWithSize(), GetPinLimit(), io_combine_limit, and Max.

Referenced by blgetbitmap(), bt_check_every_level(), collect_corrupt_items(), collect_visibility_data(), DataChecksumsWorkerMain(), GetBulkInsertState(), gin_check_parent_keys_consistency(), gin_check_posting_tree_parent_keys_consistency(), initscan(), pgstat_index(), pgstathashindex(), pgstatindex_impl(), RelationCopyStorageUsingBuffer(), ScanSourceDatabasePgClass(), statapprox_heap(), and verify_heapam().

◆ GetAccessStrategyBufferCount()

int GetAccessStrategyBufferCount ( BufferAccessStrategy  strategy)
extern

Definition at line 551 of file freelist.c.

552{
553 if (strategy == NULL)
554 return 0;
555
556 return strategy->nbuffers;
557}

References fb(), and BufferAccessStrategyData::nbuffers.

Referenced by parallel_vacuum_init().

◆ GetAccessStrategyPinLimit()

int GetAccessStrategyPinLimit ( BufferAccessStrategy  strategy)
extern

Definition at line 574 of file freelist.c.

575{
576 if (strategy == NULL)
577 return NBuffers;
578
579 switch (strategy->btype)
580 {
581 case BAS_BULKREAD:
582
583 /*
584 * Since BAS_BULKREAD uses StrategyRejectBuffer(), dirty buffers
585 * shouldn't be a problem and the caller is free to pin up to the
586 * entire ring at once.
587 */
588 return strategy->nbuffers;
589
590 default:
591
592 /*
593 * Tell caller not to pin more than half the buffers in the ring.
594 * This is a trade-off between look ahead distance and deferring
595 * writeback and associated WAL traffic.
596 */
597 return strategy->nbuffers / 2;
598 }
599}
BufferAccessStrategyType btype
Definition freelist.c:77

References BAS_BULKREAD, BufferAccessStrategyData::btype, fb(), BufferAccessStrategyData::nbuffers, and NBuffers.

Referenced by read_stream_begin_impl().

◆ GetAccessStrategyWithSize()

BufferAccessStrategy GetAccessStrategyWithSize ( BufferAccessStrategyType  btype,
int  ring_size_kb 
)
extern

Definition at line 511 of file freelist.c.

512{
513 int ring_buffers;
514 BufferAccessStrategy strategy;
515
516 Assert(ring_size_kb >= 0);
517
518 /* Figure out how many buffers ring_size_kb is */
519 ring_buffers = ring_size_kb / (BLCKSZ / 1024);
520
521 /* 0 means unlimited, so no BufferAccessStrategy required */
522 if (ring_buffers == 0)
523 return NULL;
524
525 /* Cap to 1/8th of shared_buffers */
527
528 /* NBuffers should never be less than 16, so this shouldn't happen */
529 Assert(ring_buffers > 0);
530
531 /* Allocate the object and initialize all elements to zeroes */
532 strategy = (BufferAccessStrategy)
534 ring_buffers * sizeof(Buffer));
535
536 /* Set fields that don't start out zero */
537 strategy->btype = btype;
538 strategy->nbuffers = ring_buffers;
539
540 return strategy;
541}
struct BufferAccessStrategyData * BufferAccessStrategy
Definition buf.h:44
#define Min(x, y)
Definition c.h:1091
void * palloc0(Size size)
Definition mcxt.c:1417

References Assert, BufferAccessStrategyData::btype, fb(), Min, BufferAccessStrategyData::nbuffers, NBuffers, and palloc0().

Referenced by do_autovacuum(), ExecVacuum(), GetAccessStrategy(), and parallel_vacuum_main().

◆ GetAdditionalLocalPinLimit()

uint32 GetAdditionalLocalPinLimit ( void  )
extern

Definition at line 316 of file localbuf.c.

317{
320}
int num_temp_buffers
Definition guc_tables.c:580
static int NLocalPinnedBuffers
Definition localbuf.c:56

References Assert, NLocalPinnedBuffers, and num_temp_buffers.

Referenced by read_stream_start_pending_read().

◆ GetAdditionalPinLimit()

uint32 GetAdditionalPinLimit ( void  )
extern

Definition at line 2698 of file bufmgr.c.

2699{
2701
2702 /*
2703 * We get the number of "overflowed" pins for free, but don't know the
2704 * number of pins in PrivateRefCountArray. The cost of calculating that
2705 * exactly doesn't seem worth it, so just assume the max.
2706 */
2708
2709 /* Is this backend already holding more than its fair share? */
2711 return 0;
2712
2714}
static uint32 MaxProportionalPins
Definition bufmgr.c:271
#define REFCOUNT_ARRAY_ENTRIES
Definition bufmgr.c:145

References fb(), MaxProportionalPins, PrivateRefCountOverflowed, and REFCOUNT_ARRAY_ENTRIES.

Referenced by LimitAdditionalPins(), and read_stream_start_pending_read().

◆ GetLocalPinLimit()

uint32 GetLocalPinLimit ( void  )
extern

Definition at line 308 of file localbuf.c.

309{
310 /* Every backend has its own temporary buffers, and can pin them all. */
311 return num_temp_buffers;
312}

References num_temp_buffers.

Referenced by read_stream_begin_impl().

◆ GetPinLimit()

uint32 GetPinLimit ( void  )
extern

Definition at line 2686 of file bufmgr.c.

2687{
2688 return MaxProportionalPins;
2689}

References MaxProportionalPins.

Referenced by GetAccessStrategy(), and read_stream_begin_impl().

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )
extern

Definition at line 6817 of file bufmgr.c.

6818{
6820
6821 /*
6822 * If we get woken slowly then it's possible that the Startup process was
6823 * already woken by other backends before we got here. Also possible that
6824 * we get here by multiple interrupts or interrupts at inappropriate
6825 * times, so make sure we do nothing if the bufid is not set.
6826 */
6827 if (bufid < 0)
6828 return false;
6829
6830 if (GetPrivateRefCount(bufid + 1) > 0)
6831 return true;
6832
6833 return false;
6834}
int GetStartupBufferPinWaitBufId(void)
Definition proc.c:771

References fb(), GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and ProcessRecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)
extern

Definition at line 5670 of file bufmgr.c.

5671{
5672 Assert(BufferIsPinned(buffer));
5674 if (BufferIsLocal(buffer))
5675 LocalRefCount[-buffer - 1]++;
5676 else
5677 {
5679
5680 ref = GetPrivateRefCountEntry(buffer, true);
5681 Assert(ref != NULL);
5682 ref->data.refcount++;
5683 }
5685}
static void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition bufmgr.c:507

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

Referenced by _bt_steppage(), btrestrpos(), entryLoadMoreItems(), ReadBufferBI(), RelationAddBlocks(), scanPostingTree(), startScanEntry(), and tts_buffer_heap_store_tuple().

◆ InitBufferManagerAccess()

void InitBufferManagerAccess ( void  )
extern

Definition at line 4216 of file bufmgr.c.

4217{
4218 /*
4219 * An advisory limit on the number of pins each backend should hold, based
4220 * on shared_buffers and the maximum number of connections possible.
4221 * That's very pessimistic, but outside toy-sized shared_buffers it should
4222 * allow plenty of pins. LimitAdditionalPins() and
4223 * GetAdditionalPinLimit() can be used to check the remaining balance.
4224 */
4226
4229
4231
4232 /*
4233 * AtProcExit_Buffers needs LWLock access, and thereby has to be called at
4234 * the corresponding phase of backend shutdown.
4235 */
4236 Assert(MyProc != NULL);
4238}
static Buffer PrivateRefCountArrayKeys[REFCOUNT_ARRAY_ENTRIES]
Definition bufmgr.c:263
static void AtProcExit_Buffers(int code, Datum arg)
Definition bufmgr.c:4245
static refcount_hash * PrivateRefCountHash
Definition bufmgr.c:265
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition bufmgr.c:264
int MaxBackends
Definition globals.c:149
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition ipc.c:372
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#define NUM_AUXILIARY_PROCS
Definition proc.h:527
PGPROC * MyProc
Definition proc.c:71

References Assert, AtProcExit_Buffers(), CurrentMemoryContext, fb(), MaxBackends, MaxProportionalPins, MyProc, NBuffers, NUM_AUXILIARY_PROCS, on_shmem_exit(), PrivateRefCountArray, PrivateRefCountArrayKeys, and PrivateRefCountHash.

Referenced by BaseInit().

◆ IsBufferCleanupOK()

bool IsBufferCleanupOK ( Buffer  buffer)
extern

Definition at line 6901 of file bufmgr.c.

6902{
6905
6906 Assert(BufferIsValid(buffer));
6907
6908 /* see AIO related comment in LockBufferForCleanup() */
6909
6910 if (BufferIsLocal(buffer))
6911 {
6912 /* There should be exactly one pin */
6913 if (LocalRefCount[-buffer - 1] != 1)
6914 return false;
6915 /* Nobody else to wait for */
6916 return true;
6917 }
6918
6919 /* There should be exactly one local pin */
6920 if (GetPrivateRefCount(buffer) != 1)
6921 return false;
6922
6923 bufHdr = GetBufferDescriptor(buffer - 1);
6924
6925 /* caller must hold exclusive lock on buffer */
6927
6929
6932 {
6933 /* pincount is OK. */
6935 return true;
6936 }
6937
6939 return false;
6940}

References Assert, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BufferIsLocal, BufferIsLockedByMeInMode(), BufferIsValid(), fb(), GetBufferDescriptor(), GetPrivateRefCount(), LocalRefCount, LockBufHdr(), and UnlockBufHdr().

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

◆ LimitAdditionalLocalPins()

void LimitAdditionalLocalPins ( uint32 additional_pins)
extern

Definition at line 324 of file localbuf.c.

325{
327
328 if (*additional_pins <= 1)
329 return;
330
331 /*
332 * In contrast to LimitAdditionalPins() other backends don't play a role
333 * here. We can allow up to NLocBuffer pins in total, but it might not be
334 * initialized yet so read num_temp_buffers.
335 */
337
340}

References fb(), NLocalPinnedBuffers, and num_temp_buffers.

Referenced by ExtendBufferedRelLocal().

◆ LimitAdditionalPins()

void LimitAdditionalPins ( uint32 additional_pins)
extern

Definition at line 2724 of file bufmgr.c.

2725{
2726 uint32 limit;
2727
2728 if (*additional_pins <= 1)
2729 return;
2730
2731 limit = GetAdditionalPinLimit();
2732 limit = Max(limit, 1);
2733 if (limit < *additional_pins)
2734 *additional_pins = limit;
2735}
uint32 GetAdditionalPinLimit(void)
Definition bufmgr.c:2698

References fb(), GetAdditionalPinLimit(), and Max.

Referenced by ExtendBufferedRelShared().

◆ LockBuffer()

static void LockBuffer ( Buffer  buffer,
BufferLockMode  mode 
)
inlinestatic

Definition at line 334 of file bufmgr.h.

335{
337 UnlockBuffer(buffer);
338 else
339 LockBufferInternal(buffer, mode);
340}
void UnlockBuffer(Buffer buffer)
Definition bufmgr.c:6558
void LockBufferInternal(Buffer buffer, BufferLockMode mode)
Definition bufmgr.c:6574

References BUFFER_LOCK_UNLOCK, LockBufferInternal(), mode, and UnlockBuffer().

Referenced by _bt_lockbuf(), _bt_unlockbuf(), _bt_upgradelockbufcleanup(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_finish_split(), _hash_first(), _hash_freeovflpage(), _hash_getbuf(), _hash_getbuf_with_strategy(), _hash_getcachedmetap(), _hash_init(), _hash_kill_items(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), BitmapHeapScanNextBlock(), blbulkdelete(), blgetbitmap(), blinsert(), BloomInitMetapage(), BloomNewBuffer(), blvacuumcleanup(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_page_cleanup(), bringetbitmap(), brinGetStats(), brinGetTupleForHeapBlock(), brininsert(), brinLockRevmapPageForUpdate(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), brinsummarize(), bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), bt_recheck_sibling_links(), collect_corrupt_items(), collect_visibility_data(), collectMatchBitmap(), ConditionalLockBufferForCleanup(), count_nondeletable_pages(), create_toy_buffer(), entryLoadMoreItems(), ExtendBufferedRelShared(), FreeSpaceMapPrepareTruncateRel(), fsm_readbuf(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), get_raw_page_internal(), GetVictimBuffer(), GetVisibilityMapPins(), gin_check_parent_keys_consistency(), gin_check_posting_tree_parent_keys_consistency(), gin_refind_parent(), ginbulkdelete(), ginEntryInsert(), ginFindLeafPage(), ginFindParents(), ginFinishOldSplit(), ginFinishSplit(), ginGetStats(), ginHeapTupleFastInsert(), ginInsertCleanup(), ginInsertValue(), GinNewBuffer(), ginScanPostingTreeToDelete(), ginStepRight(), ginTraverseLock(), ginUpdateStats(), ginvacuumcleanup(), ginVacuumPostingTreeLeaves(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistfinishsplit(), gistfixsplit(), gistformdownlink(), gistGetMaxLevel(), gistinserttuples(), gistkillitems(), gistNewBuffer(), gistProcessItup(), gistScanPage(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_get_latest_tid(), heap_index_delete_tuples(), heap_inplace_lock(), heap_inplace_unlock(), heap_inplace_update_and_unlock(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_prune_and_freeze(), heap_page_prune_opt(), heap_prepare_pagescan(), heap_update(), 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_sample_next_tuple(), heapam_tuple_satisfies_snapshot(), heapgettup(), initBloomState(), invalidate_one_block(), lazy_scan_heap(), lazy_scan_new_or_empty(), lazy_vacuum_heap_page(), lazy_vacuum_heap_rel(), LockBufferForCleanup(), log_newpage_range(), modify_rel_block(), palloc_btree_page(), pg_visibility(), pgrowlocks(), pgstat_btree_page(), pgstat_gist_page(), pgstat_hash_page(), pgstat_heap(), pgstatginindex_internal(), pgstathashindex(), pgstatindex_impl(), ProcessSingleRelationFork(), read_seq_tuple(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), ScanSourceDatabasePgClass(), shiftList(), spgdoinsert(), spgGetCache(), SpGistNewBuffer(), spgprocesspending(), spgvacuumpage(), spgWalk(), startScanEntry(), statapprox_heap(), summarize_range(), update_most_recent_deletion_info(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_prepare_truncate(), vm_readbuf(), XLogReadBufferForRedoExtended(), XLogRecordPageWithFreeSpace(), and ZeroAndLockBuffer().

◆ LockBufferForCleanup()

void LockBufferForCleanup ( Buffer  buffer)
extern

Definition at line 6670 of file bufmgr.c.

6671{
6673 TimestampTz waitStart = 0;
6674 bool waiting = false;
6675 bool logged_recovery_conflict = false;
6676
6677 Assert(BufferIsPinned(buffer));
6679
6681
6682 /*
6683 * We do not yet need to be worried about in-progress AIOs holding a pin,
6684 * as we, so far, only support doing reads via AIO and this function can
6685 * only be called once the buffer is valid (i.e. no read can be in
6686 * flight).
6687 */
6688
6689 /* Nobody else to wait for */
6690 if (BufferIsLocal(buffer))
6691 return;
6692
6693 bufHdr = GetBufferDescriptor(buffer - 1);
6694
6695 for (;;)
6696 {
6698 uint64 unset_bits = 0;
6699
6700 /* Try to acquire lock */
6703
6706 {
6707 /* Successfully acquired exclusive lock with pincount 1 */
6709
6710 /*
6711 * Emit the log message if recovery conflict on buffer pin was
6712 * resolved but the startup process waited longer than
6713 * deadlock_timeout for it.
6714 */
6717 waitStart, GetCurrentTimestamp(),
6718 NULL, false);
6719
6720 if (waiting)
6721 {
6722 /* reset ps display to remove the suffix if we added one */
6724 waiting = false;
6725 }
6726 return;
6727 }
6728 /* Failed, so mark myself as waiting for pincount 1 */
6730 {
6733 elog(ERROR, "multiple backends attempting to wait for pincount 1");
6734 }
6735 bufHdr->wait_backend_pgprocno = MyProcNumber;
6739 0);
6741
6742 /* Wait to be signaled by UnpinBuffer() */
6743 if (InHotStandby)
6744 {
6745 if (!waiting)
6746 {
6747 /* adjust the process title to indicate that it's waiting */
6748 set_ps_display_suffix("waiting");
6749 waiting = true;
6750 }
6751
6752 /*
6753 * Emit the log message if the startup process is waiting longer
6754 * than deadlock_timeout for recovery conflict on buffer pin.
6755 *
6756 * Skip this if first time through because the startup process has
6757 * not started waiting yet in this case. So, the wait start
6758 * timestamp is set after this logic.
6759 */
6760 if (waitStart != 0 && !logged_recovery_conflict)
6761 {
6763
6764 if (TimestampDifferenceExceeds(waitStart, now,
6766 {
6768 waitStart, now, NULL, true);
6770 }
6771 }
6772
6773 /*
6774 * Set the wait start timestamp if logging is enabled and first
6775 * time through.
6776 */
6777 if (log_recovery_conflict_waits && waitStart == 0)
6778 waitStart = GetCurrentTimestamp();
6779
6780 /* Publish the bufid that Startup process waits on */
6781 SetStartupBufferPinWaitBufId(buffer - 1);
6782 /* Set alarm and then wait to be signaled by UnpinBuffer() */
6784 /* Reset the published bufid */
6786 }
6787 else
6789
6790 /*
6791 * Remove flag marking us as waiter. Normally this will not be set
6792 * anymore, but ProcWaitForSignal() can return for other signals as
6793 * well. We take care to only reset the flag if we're the waiter, as
6794 * theoretically another backend could have started waiting. That's
6795 * impossible with the current usages due to table level locking, but
6796 * better be safe.
6797 */
6799 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
6800 bufHdr->wait_backend_pgprocno == MyProcNumber)
6802
6804 0, unset_bits,
6805 0);
6806
6808 /* Loop back and try again */
6809 }
6810}
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition timestamp.c:1775
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1639
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1603
static uint64 UnlockBufHdrExt(BufferDesc *desc, uint64 old_buf_state, uint64 set_bits, uint64 unset_bits, int refcount_change)
#define BM_PIN_COUNT_WAITER
void CheckBufferIsPinnedOnce(Buffer buffer)
Definition bufmgr.c:6637
static BufferDesc * PinCountWaitBuf
Definition bufmgr.c:228
int64 TimestampTz
Definition timestamp.h:39
void set_ps_display_remove_suffix(void)
Definition ps_status.c:440
void set_ps_display_suffix(const char *suffix)
Definition ps_status.c:388
int DeadlockTimeout
Definition proc.c:62
void SetStartupBufferPinWaitBufId(int bufid)
Definition proc.c:759
void ProcWaitForSignal(uint32 wait_event_info)
Definition proc.c:2015
void ResolveRecoveryConflictWithBufferPin(void)
Definition standby.c:795
bool log_recovery_conflict_waits
Definition standby.c:43
void LogRecoveryConflict(RecoveryConflictReason reason, TimestampTz wait_start, TimestampTz now, VirtualTransactionId *wait_list, bool still_waiting)
Definition standby.c:275
@ RECOVERY_CONFLICT_BUFFERPIN
Definition standby.h:49
static volatile sig_atomic_t waiting
#define InHotStandby
Definition xlogutils.h:60

References Assert, BM_PIN_COUNT_WAITER, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferIsLocal, BufferIsPinned, CheckBufferIsPinnedOnce(), DeadlockTimeout, elog, ERROR, fb(), GetBufferDescriptor(), GetCurrentTimestamp(), InHotStandby, LockBuffer(), LockBufHdr(), log_recovery_conflict_waits, LogRecoveryConflict(), MyProcNumber, now(), PinCountWaitBuf, ProcWaitForSignal(), RECOVERY_CONFLICT_BUFFERPIN, ResolveRecoveryConflictWithBufferPin(), set_ps_display_remove_suffix(), set_ps_display_suffix(), SetStartupBufferPinWaitBufId(), TimestampDifferenceExceeds(), UnlockBufHdr(), UnlockBufHdrExt(), and waiting.

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

◆ LockBufferInternal()

void LockBufferInternal ( Buffer  buffer,
BufferLockMode  mode 
)
extern

Definition at line 6574 of file bufmgr.c.

6575{
6577
6578 /*
6579 * We can't wait if we haven't got a PGPROC. This should only occur
6580 * during bootstrap or shared memory initialization. Put an Assert here
6581 * to catch unsafe coding practices.
6582 */
6584
6585 /* handled in LockBuffer() wrapper */
6587
6588 Assert(BufferIsPinned(buffer));
6589 if (BufferIsLocal(buffer))
6590 return; /* local buffers need no lock */
6591
6592 buf_hdr = GetBufferDescriptor(buffer - 1);
6593
6594 /*
6595 * Test the most frequent lock modes first. While a switch (mode) would be
6596 * nice, at least gcc generates considerably worse code for it.
6597 *
6598 * Call BufferLockAcquire() with a constant argument for mode, to generate
6599 * more efficient code for the different lock modes.
6600 */
6601 if (mode == BUFFER_LOCK_SHARE)
6603 else if (mode == BUFFER_LOCK_EXCLUSIVE)
6607 else
6608 elog(ERROR, "unrecognized buffer lock mode: %d", mode);
6609}
static void BufferLockAcquire(Buffer buffer, BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:5898
bool IsUnderPostmaster
Definition globals.c:122

References Assert, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_SHARE, BUFFER_LOCK_SHARE_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferIsLocal, BufferIsPinned, BufferLockAcquire(), elog, ERROR, fb(), GetBufferDescriptor(), IsUnderPostmaster, mode, and MyProc.

Referenced by LockBuffer().

◆ MarkBufferDirty()

void MarkBufferDirty ( Buffer  buffer)
extern

Definition at line 3147 of file bufmgr.c.

3148{
3152
3153 if (!BufferIsValid(buffer))
3154 elog(ERROR, "bad buffer ID: %d", buffer);
3155
3156 if (BufferIsLocal(buffer))
3157 {
3158 MarkLocalBufferDirty(buffer);
3159 return;
3160 }
3161
3162 bufHdr = GetBufferDescriptor(buffer - 1);
3163
3164 Assert(BufferIsPinned(buffer));
3166
3167 /*
3168 * NB: We have to wait for the buffer header spinlock to be not held, as
3169 * TerminateBufferIO() relies on the spinlock.
3170 */
3172 for (;;)
3173 {
3176
3178
3181
3183 buf_state))
3184 break;
3185 }
3186
3187 /*
3188 * If the buffer was not dirty already, do vacuum accounting.
3189 */
3190 if (!(old_buf_state & BM_DIRTY))
3191 {
3193 if (VacuumCostActive)
3195 }
3196}
static bool pg_atomic_compare_exchange_u64(volatile pg_atomic_uint64 *ptr, uint64 *expected, uint64 newval)
Definition atomics.h:522
#define BM_LOCKED
pg_noinline uint64 WaitBufHdrUnlocked(BufferDesc *buf)
Definition bufmgr.c:7566
bool VacuumCostActive
Definition globals.c:161
int VacuumCostBalance
Definition globals.c:160
int VacuumCostPageDirty
Definition globals.c:156
BufferUsage pgBufferUsage
Definition instrument.c:25
int64 shared_blks_dirtied
Definition instrument.h:28

References Assert, BM_DIRTY, BM_LOCKED, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BufferIsLocal, BufferIsLockedByMeInMode(), BufferIsPinned, BufferIsValid(), elog, ERROR, fb(), GetBufferDescriptor(), MarkLocalBufferDirty(), pg_atomic_compare_exchange_u64(), pg_atomic_read_u64(), pgBufferUsage, BufferUsage::shared_blks_dirtied, VacuumCostActive, VacuumCostBalance, VacuumCostPageDirty, and WaitBufHdrUnlocked().

Referenced by _bt_clear_incomplete_split(), _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_newlevel(), _bt_restore_meta(), _bt_set_cleanup_info(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_freeovflpage(), _hash_init(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), addLeafTuple(), brin_doinsert(), brin_doupdate(), brin_initialize_empty_new_buffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinRevmapDesummarizeRange(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), createPostingTree(), dataExecPlaceToPageInternal(), dataExecPlaceToPageLeaf(), doPickSplit(), entryExecPlaceToPage(), fill_seq_fork_with_data(), FreeSpaceMapPrepareTruncateRel(), generic_redo(), GenericXLogFinish(), ginbuild(), ginbuildempty(), ginbulkdelete(), ginDeletePostingPage(), 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_and_unlock(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_prune_and_freeze(), heap_update(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), heap_xlog_update(), lazy_scan_new_or_empty(), lazy_vacuum_heap_page(), log_newpage_range(), MarkDirtyUnpinnedBufferInternal(), moveLeafs(), nextval_internal(), ProcessSingleRelationFork(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), revmap_physical_extend(), saveNodeLink(), seq_redo(), SetSequence(), 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()

◆ MarkDirtyAllUnpinnedBuffers()

void MarkDirtyAllUnpinnedBuffers ( int32 buffers_dirtied,
int32 buffers_already_dirty,
int32 buffers_skipped 
)
extern

Definition at line 8232 of file bufmgr.c.

8235{
8236 *buffers_dirtied = 0;
8238 *buffers_skipped = 0;
8239
8240 for (int buf = 1; buf <= NBuffers; buf++)
8241 {
8242 BufferDesc *desc = GetBufferDescriptor(buf - 1);
8245
8247
8249 if (!(buf_state & BM_VALID))
8250 continue;
8251
8254
8255 LockBufHdr(desc);
8256
8258 (*buffers_dirtied)++;
8259 else if (buffer_already_dirty)
8260 (*buffers_already_dirty)++;
8261 else
8262 (*buffers_skipped)++;
8263 }
8264}
static bool MarkDirtyUnpinnedBufferInternal(Buffer buf, BufferDesc *desc, bool *buffer_already_dirty)
Definition bufmgr.c:8083

References BM_VALID, buf, CHECK_FOR_INTERRUPTS, CurrentResourceOwner, fb(), GetBufferDescriptor(), LockBufHdr(), MarkDirtyUnpinnedBufferInternal(), NBuffers, pg_atomic_read_u64(), ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), and BufferDesc::state.

Referenced by pg_buffercache_mark_dirty_all().

◆ MarkDirtyRelUnpinnedBuffers()

void MarkDirtyRelUnpinnedBuffers ( Relation  rel,
int32 buffers_dirtied,
int32 buffers_already_dirty,
int32 buffers_skipped 
)
extern

Definition at line 8175 of file bufmgr.c.

8179{
8181
8182 *buffers_dirtied = 0;
8184 *buffers_skipped = 0;
8185
8186 for (int buf = 1; buf <= NBuffers; buf++)
8187 {
8188 BufferDesc *desc = GetBufferDescriptor(buf - 1);
8191
8193
8194 /* An unlocked precheck should be safe and saves some cycles. */
8195 if ((buf_state & BM_VALID) == 0 ||
8197 continue;
8198
8199 /* Make sure we can pin the buffer. */
8202
8203 buf_state = LockBufHdr(desc);
8204
8205 /* recheck, could have changed without the lock */
8206 if ((buf_state & BM_VALID) == 0 ||
8208 {
8209 UnlockBufHdr(desc);
8210 continue;
8211 }
8212
8214 (*buffers_dirtied)++;
8215 else if (buffer_already_dirty)
8216 (*buffers_already_dirty)++;
8217 else
8218 (*buffers_skipped)++;
8219 }
8220}

References Assert, BM_VALID, buf, BufTagMatchesRelFileLocator(), CHECK_FOR_INTERRUPTS, CurrentResourceOwner, fb(), GetBufferDescriptor(), LockBufHdr(), MarkDirtyUnpinnedBufferInternal(), NBuffers, pg_atomic_read_u64(), RelationData::rd_locator, RelationUsesLocalBuffers, ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), BufferDesc::state, BufferDesc::tag, and UnlockBufHdr().

Referenced by pg_buffercache_mark_dirty_relation().

◆ MarkDirtyUnpinnedBuffer()

bool MarkDirtyUnpinnedBuffer ( Buffer  buf,
bool buffer_already_dirty 
)
extern

Definition at line 8139 of file bufmgr.c.

8140{
8141 BufferDesc *desc;
8142 bool buffer_dirtied = false;
8143
8145
8146 /* Make sure we can pin the buffer. */
8149
8150 desc = GetBufferDescriptor(buf - 1);
8151 LockBufHdr(desc);
8152
8154 /* Both can not be true at the same time */
8156
8157 return buffer_dirtied;
8158}

References Assert, buf, BufferIsLocal, CurrentResourceOwner, fb(), GetBufferDescriptor(), LockBufHdr(), MarkDirtyUnpinnedBufferInternal(), ReservePrivateRefCountEntry(), and ResourceOwnerEnlarge().

Referenced by pg_buffercache_mark_dirty().

◆ PrefetchBuffer()

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

Definition at line 787 of file bufmgr.c.

788{
790 Assert(BlockNumberIsValid(blockNum));
791
793 {
794 /* see comments in ReadBufferExtended */
798 errmsg("cannot access temporary tables of other sessions")));
799
800 /* pass it off to localbuf.c */
801 return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
802 }
803 else
804 {
805 /* pass it to the shared buffer version */
806 return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
807 }
808}
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition bufmgr.c:697
int errcode(int sqlerrcode)
Definition elog.c:874
#define ereport(elevel,...)
Definition elog.h:152
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition localbuf.c:72
static char * errmsg
#define RELATION_IS_OTHER_TEMP(relation)
Definition rel.h:669
#define RelationIsValid(relation)
Definition rel.h:491

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

Referenced by count_nondeletable_pages(), invalidate_one_block(), and pg_prewarm().

◆ PrefetchSharedBuffer()

PrefetchBufferResult PrefetchSharedBuffer ( SMgrRelation  smgr_reln,
ForkNumber  forkNum,
BlockNumber  blockNum 
)
extern

Definition at line 697 of file bufmgr.c.

700{
702 BufferTag newTag; /* identity of requested block */
703 uint32 newHash; /* hash value for newTag */
704 LWLock *newPartitionLock; /* buffer partition lock for it */
705 int buf_id;
706
707 Assert(BlockNumberIsValid(blockNum));
708
709 /* create a tag so we can lookup the buffer */
710 InitBufferTag(&newTag, &smgr_reln->smgr_rlocator.locator,
711 forkNum, blockNum);
712
713 /* determine its hash code and partition lock ID */
716
717 /* see if the block is in the buffer pool already */
719 buf_id = BufTableLookup(&newTag, newHash);
721
722 /* If not in buffers, initiate prefetch */
723 if (buf_id < 0)
724 {
725#ifdef USE_PREFETCH
726 /*
727 * Try to initiate an asynchronous read. This returns false in
728 * recovery if the relation file doesn't exist.
729 */
730 if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
731 smgrprefetch(smgr_reln, forkNum, blockNum, 1))
732 {
733 result.initiated_io = true;
734 }
735#endif /* USE_PREFETCH */
736 }
737 else
738 {
739 /*
740 * Report the buffer it was in at that time. The caller may be able
741 * to avoid a buffer table lookup, but it's not pinned and it must be
742 * rechecked!
743 */
744 result.recent_buffer = buf_id + 1;
745 }
746
747 /*
748 * If the block *is* in buffers, we do nothing. This is not really ideal:
749 * the block might be just about to be evicted, which would be stupid
750 * since we know we are going to need it soon. But the only easy answer
751 * is to bump the usage_count, which does not seem like a great solution:
752 * when the caller does ultimately touch the block, usage_count would get
753 * bumped again, resulting in too much favoritism for blocks that are
754 * involved in a prefetch sequence. A real fix would involve some
755 * additional per-buffer state, and it's not clear that there's enough of
756 * a problem to justify that.
757 */
758
759 return result;
760}
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
static LWLock * BufMappingPartitionLock(uint32 hashcode)
int BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
Definition buf_table.c:96
uint32 BufTableHashCode(BufferTag *tagPtr)
Definition buf_table.c:84
int io_direct_flags
Definition fd.c:172
#define IO_DIRECT_DATA
Definition fd.h:54
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
@ LW_SHARED
Definition lwlock.h:105
bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks)
Definition smgr.c:678

References Assert, BlockNumberIsValid(), BufMappingPartitionLock(), BufTableHashCode(), BufTableLookup(), fb(), InitBufferTag(), InvalidBuffer, IO_DIRECT_DATA, io_direct_flags, LW_SHARED, LWLockAcquire(), LWLockRelease(), result, and smgrprefetch().

Referenced by PrefetchBuffer(), and XLogPrefetcherNextBlock().

◆ ReadBuffer()

Buffer ReadBuffer ( Relation  reln,
BlockNumber  blockNum 
)
extern

Definition at line 879 of file bufmgr.c.

880{
882}
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition bufmgr.c:926

References fb(), MAIN_FORKNUM, RBM_NORMAL, and ReadBufferExtended().

Referenced by _bt_allocbuf(), _bt_getbuf(), _bt_relandgetbuf(), _bt_search_insert(), _hash_getbuf(), _hash_getbuf_with_condlock_cleanup(), blbulkdelete(), blinsert(), BloomNewBuffer(), brin_getinsertbuffer(), brinGetStats(), brinGetTupleForHeapBlock(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), ginFindLeafPage(), ginFindParents(), ginGetStats(), ginHeapTupleFastInsert(), ginInsertCleanup(), GinNewBuffer(), ginStepRight(), ginUpdateStats(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistfixsplit(), gistGetMaxLevel(), gistkillitems(), gistNewBuffer(), gistProcessItup(), gistScanPage(), heap_abort_speculative(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_force_common(), heap_get_latest_tid(), heap_index_delete_tuples(), heap_lock_tuple(), heap_update(), heapam_index_fetch_tuple(), 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 
)
externinline

Definition at line 926 of file bufmgr.c.

928{
929 Buffer buf;
930
931 /*
932 * Reject attempts to read non-local temporary relations; we would be
933 * likely to get wrong data since we have no visibility into the owning
934 * session's local buffers.
935 */
939 errmsg("cannot access temporary tables of other sessions")));
940
941 /*
942 * Read the buffer, and update pgstat counters to reflect a cache hit or
943 * miss.
944 */
946 forkNum, blockNum, mode, strategy);
947
948 return buf;
949}

References buf, ereport, errcode(), errmsg, ERROR, fb(), mode, ReadBuffer_common(), RELATION_IS_OTHER_TEMP, and RelationGetSmgr().

Referenced by _hash_getbuf_with_strategy(), _hash_getinitbuf(), _hash_getnewbuf(), BloomInitMetapage(), bt_recheck_sibling_links(), btvacuumpage(), count_nondeletable_pages(), create_toy_buffer(), fsm_readbuf(), get_raw_page_internal(), gin_check_parent_keys_consistency(), gin_check_posting_tree_parent_keys_consistency(), gin_refind_parent(), ginbulkdelete(), ginScanPostingTreeToDelete(), ginVacuumPostingTree(), ginVacuumPostingTreeLeaves(), gistvacuum_delete_empty_pages(), gistvacuumpage(), heapam_scan_sample_next_block(), log_newpage_range(), modify_rel_block(), palloc_btree_page(), pgstat_btree_page(), pgstat_gist_page(), pgstat_hash_page(), pgstat_heap(), pgstatindex_impl(), ProcessSingleRelationFork(), ReadBuffer(), ReadBufferBI(), spgprocesspending(), and vm_readbuf().

◆ ReadBufferWithoutRelcache()

Buffer ReadBufferWithoutRelcache ( RelFileLocator  rlocator,
ForkNumber  forkNum,
BlockNumber  blockNum,
ReadBufferMode  mode,
BufferAccessStrategy  strategy,
bool  permanent 
)
extern

Definition at line 963 of file bufmgr.c.

966{
967 SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
968
969 return ReadBuffer_common(NULL, smgr,
971 forkNum, blockNum,
972 mode, strategy);
973}

References fb(), INVALID_PROC_NUMBER, mode, ReadBuffer_common(), and smgropen().

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

◆ ReadRecentBuffer()

bool ReadRecentBuffer ( RelFileLocator  rlocator,
ForkNumber  forkNum,
BlockNumber  blockNum,
Buffer  recent_buffer 
)
extern

Definition at line 818 of file bufmgr.c.

820{
822 BufferTag tag;
824
825 Assert(BufferIsValid(recent_buffer));
826
829 InitBufferTag(&tag, &rlocator, forkNum, blockNum);
830
831 if (BufferIsLocal(recent_buffer))
832 {
833 int b = -recent_buffer - 1;
834
837
838 /* Is it still valid and holding the right tag? */
839 if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
840 {
841 PinLocalBuffer(bufHdr, true);
842
844
845 return true;
846 }
847 }
848 else
849 {
850 bufHdr = GetBufferDescriptor(recent_buffer - 1);
851
852 /*
853 * Is it still valid and holding the right tag? We do an unlocked tag
854 * comparison first, to make it unlikely that we'll increment the
855 * usage counter of the wrong buffer, if someone calls us with a very
856 * out of date recent_buffer. Then we'll check it again if we get the
857 * pin.
858 */
859 if (BufferTagsEqual(&tag, &bufHdr->tag) &&
860 PinBuffer(bufHdr, NULL, true))
861 {
862 if (BufferTagsEqual(&tag, &bufHdr->tag))
863 {
865 return true;
866 }
868 }
869 }
870
871 return false;
872}
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
static bool PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy, bool skip_if_not_valid)
Definition bufmgr.c:3272
int b
Definition isn.c:74
int64 local_blks_hit
Definition instrument.h:30
int64 shared_blks_hit
Definition instrument.h:26

References Assert, b, BM_VALID, BufferIsLocal, BufferIsValid(), BufferTagsEqual(), CurrentResourceOwner, fb(), GetBufferDescriptor(), GetLocalBufferDescriptor(), InitBufferTag(), BufferUsage::local_blks_hit, pg_atomic_read_u64(), pgBufferUsage, PinBuffer(), PinLocalBuffer(), ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), BufferUsage::shared_blks_hit, and UnpinBuffer().

Referenced by invalidate_one_block(), and XLogReadBufferExtended().

◆ RelationGetNumberOfBlocksInFork()

BlockNumber RelationGetNumberOfBlocksInFork ( Relation  relation,
ForkNumber  forkNum 
)
extern

Definition at line 4645 of file bufmgr.c.

4646{
4647 if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
4648 {
4649 /*
4650 * Not every table AM uses BLCKSZ wide fixed size blocks. Therefore
4651 * tableam returns the size in bytes - but for the purpose of this
4652 * routine, we want the number of blocks. Therefore divide, rounding
4653 * up.
4654 */
4656
4657 szbytes = table_relation_size(relation, forkNum);
4658
4659 return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
4660 }
4661 else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
4662 {
4663 return smgrnblocks(RelationGetSmgr(relation), forkNum);
4664 }
4665 else
4666 Assert(false);
4667
4668 return 0; /* keep compiler quiet */
4669}
Form_pg_class rd_rel
Definition rel.h:111
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition tableam.h:1940

References Assert, fb(), RelationData::rd_rel, RelationGetSmgr(), smgrnblocks(), and table_relation_size().

Referenced by _hash_getnewbuf(), _hash_init(), autoprewarm_database_main(), get_raw_page_internal(), pg_prewarm(), and ProcessSingleRelationFork().

◆ ReleaseAndReadBuffer()

Buffer ReleaseAndReadBuffer ( Buffer  buffer,
Relation  relation,
BlockNumber  blockNum 
)
extern

Definition at line 3212 of file bufmgr.c.

3215{
3216 ForkNumber forkNum = MAIN_FORKNUM;
3218
3219 if (BufferIsValid(buffer))
3220 {
3221 Assert(BufferIsPinned(buffer));
3222 if (BufferIsLocal(buffer))
3223 {
3224 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
3225 if (bufHdr->tag.blockNum == blockNum &&
3226 BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
3227 BufTagGetForkNum(&bufHdr->tag) == forkNum)
3228 return buffer;
3229 UnpinLocalBuffer(buffer);
3230 }
3231 else
3232 {
3233 bufHdr = GetBufferDescriptor(buffer - 1);
3234 /* we have pin, so it's ok to examine tag without spinlock */
3235 if (bufHdr->tag.blockNum == blockNum &&
3236 BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
3237 BufTagGetForkNum(&bufHdr->tag) == forkNum)
3238 return buffer;
3240 }
3241 }
3242
3243 return ReadBuffer(relation, blockNum);
3244}
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition bufmgr.c:879

References Assert, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferIsValid(), BufTagGetForkNum(), BufTagMatchesRelFileLocator(), fb(), GetBufferDescriptor(), GetLocalBufferDescriptor(), MAIN_FORKNUM, RelationData::rd_locator, ReadBuffer(), UnpinBuffer(), and UnpinLocalBuffer().

Referenced by ginFindLeafPage().

◆ ReleaseBuffer()

void ReleaseBuffer ( Buffer  buffer)
extern

Definition at line 5586 of file bufmgr.c.

5587{
5588 if (!BufferIsValid(buffer))
5589 elog(ERROR, "bad buffer ID: %d", buffer);
5590
5591 if (BufferIsLocal(buffer))
5592 UnpinLocalBuffer(buffer);
5593 else
5594 UnpinBuffer(GetBufferDescriptor(buffer - 1));
5595}

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

Referenced by _bt_allocbuf(), _bt_pagedel(), _bt_search_insert(), _bt_unlink_halfdead_page(), _hash_dropbuf(), _hash_getbuf_with_condlock_cleanup(), autoprewarm_database_main(), BitmapHeapScanNextBlock(), blinsert(), BloomNewBuffer(), brin_getinsertbuffer(), brin_vacuum_scan(), bringetbitmap(), brinGetTupleForHeapBlock(), brininsert(), brinRevmapTerminate(), brinsummarize(), buffer_create_toy(), collect_corrupt_items(), collect_visibility_data(), entryLoadMoreItems(), ExecEndIndexOnlyScan(), ExtendBufferedRelTo(), FreeBulkInsertState(), freeGinBtreeStack(), fsm_search(), get_actual_variable_endpoint(), GetRecordedFreeSpace(), ginFindParents(), ginFinishSplit(), ginFreeScanKeys(), ginInsertCleanup(), GinNewBuffer(), gistdoinsert(), gistFindCorrectParent(), gistNewBuffer(), gistvacuum_delete_empty_pages(), grow_rel(), heap_abort_speculative(), heap_delete(), heap_endscan(), heap_fetch(), heap_fetch_next_buffer(), heap_force_common(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_rescan(), heap_update(), heap_vac_scan_next_block(), heap_xlog_delete(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_update(), heapam_index_fetch_end(), heapam_index_fetch_tuple(), heapam_scan_sample_next_block(), heapam_tuple_lock(), heapgettup(), heapgettup_pagemode(), lazy_scan_heap(), lazy_vacuum_heap_rel(), pg_prewarm(), pg_visibility(), pg_visibility_map(), pgstatindex_impl(), read_buffers(), read_rel_block_ll(), read_stream_for_blocks(), read_stream_reset(), ReadBufferBI(), RelationAddBlocks(), ReleaseBulkInsertStatePin(), revmap_get_buffer(), spgdoinsert(), SpGistGetBuffer(), SpGistNewBuffer(), SpGistUpdateMetaPage(), statapprox_heap(), summarize_range(), terminate_brin_buildstate(), tts_buffer_heap_clear(), tts_buffer_heap_materialize(), tts_buffer_heap_store_tuple(), verify_heapam(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_pin(), and XLogReadBufferExtended().

◆ StartReadBuffer()

bool StartReadBuffer ( ReadBuffersOperation operation,
Buffer buffer,
BlockNumber  blocknum,
int  flags 
)
extern

Definition at line 1628 of file bufmgr.c.

1632{
1633 int nblocks = 1;
1634 bool result;
1635
1636 result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags,
1637 false /* single block, no forwarding */ );
1638 Assert(nblocks == 1); /* single block can't be short */
1639
1640 return result;
1641}
static pg_attribute_always_inline bool StartReadBuffersImpl(ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, int flags, bool allow_forwarding)
Definition bufmgr.c:1368
static DataChecksumsWorkerOperation operation

References Assert, PrivateRefCountEntry::buffer, operation, result, and StartReadBuffersImpl().

Referenced by read_stream_next_buffer(), and ReadBuffer_common().

◆ StartReadBuffers()

bool StartReadBuffers ( ReadBuffersOperation operation,
Buffer buffers,
BlockNumber  blockNum,
int nblocks,
int  flags 
)
extern

Definition at line 1609 of file bufmgr.c.

1614{
1615 return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags,
1616 true /* expect forwarded buffers */ );
1617}

References operation, and StartReadBuffersImpl().

Referenced by read_buffers(), and read_stream_start_pending_read().

◆ UnlockBuffer()

void UnlockBuffer ( Buffer  buffer)
extern

Definition at line 6558 of file bufmgr.c.

6559{
6561
6562 Assert(BufferIsPinned(buffer));
6563 if (BufferIsLocal(buffer))
6564 return; /* local buffers need no lock */
6565
6566 buf_hdr = GetBufferDescriptor(buffer - 1);
6567 BufferLockUnlock(buffer, buf_hdr);
6568}
static void BufferLockUnlock(Buffer buffer, BufferDesc *buf_hdr)
Definition bufmgr.c:6014

References Assert, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferLockUnlock(), fb(), and GetBufferDescriptor().

Referenced by LockBuffer().

◆ UnlockBuffers()

void UnlockBuffers ( void  )
extern

Definition at line 5852 of file bufmgr.c.

5853{
5855
5856 if (buf)
5857 {
5859 uint64 unset_bits = 0;
5860
5862
5863 /*
5864 * Don't complain if flag bit not set; it could have been reset but we
5865 * got a cancel/die interrupt before getting the signal.
5866 */
5867 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5868 buf->wait_backend_pgprocno == MyProcNumber)
5870
5872 0, unset_bits,
5873 0);
5874
5876 }
5877}

References BM_PIN_COUNT_WAITER, buf, fb(), LockBufHdr(), MyProcNumber, PinCountWaitBuf, and UnlockBufHdrExt().

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

◆ UnlockReleaseBuffer()

void UnlockReleaseBuffer ( Buffer  buffer)
extern

Definition at line 5603 of file bufmgr.c.

5604{
5605 int mode;
5606 BufferDesc *buf;
5608 uint64 sub;
5610
5611 Assert(BufferIsPinned(buffer));
5612
5613 if (BufferIsLocal(buffer))
5614 {
5615 UnpinLocalBuffer(buffer);
5616 return;
5617 }
5618
5620
5621 buf = GetBufferDescriptor(buffer - 1);
5622
5624
5625 /* compute state modification for lock release */
5627
5628 /* compute state modification for pin release */
5629 ref = GetPrivateRefCountEntry(buffer, false);
5630 Assert(ref != NULL);
5631 Assert(ref->data.refcount > 0);
5632 ref->data.refcount--;
5633
5634 /* no more backend local pins, reduce shared pin count */
5635 if (likely(ref->data.refcount == 0))
5636 {
5637 /* See comment in UnpinBufferNoOwner() */
5639
5640 sub |= BUF_REFCOUNT_ONE;
5642 }
5643
5644 /* perform the lock and pin release in one atomic op */
5645 lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
5646
5647 /* wake up waiters for the lock */
5649
5650 /* wake up waiter for the pin release */
5653
5654 /*
5655 * Now okay to allow cancel/die interrupts again, which were held when the
5656 * lock was acquired.
5657 */
5659}
static uint64 pg_atomic_sub_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 sub_)
Definition atomics.h:578
#define BUF_REFCOUNT_ONE
static void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
#define BufHdrGetBlock(bufHdr)
Definition bufmgr.c:76
static int BufferLockDisownInternal(Buffer buffer, BufferDesc *buf_hdr)
Definition bufmgr.c:6285
static void WakePinCountWaiter(BufferDesc *buf)
Definition bufmgr.c:3420
static void BufferLockProcessRelease(BufferDesc *buf_hdr, BufferLockMode mode, uint64 lockstate)
Definition bufmgr.c:6470
static uint64 BufferLockReleaseSub(BufferLockMode mode)
Definition bufmgr.c:6441
static void ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
Definition bufmgr.c:565
#define likely(x)
Definition c.h:437
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition memdebug.h:27
#define RESUME_INTERRUPTS()
Definition miscadmin.h:138

References Assert, BM_PIN_COUNT_WAITER, buf, BUF_REFCOUNT_ONE, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferLockDisownInternal(), BufferLockProcessRelease(), BufferLockReleaseSub(), BufHdrGetBlock, CurrentResourceOwner, fb(), ForgetPrivateRefCountEntry(), GetBufferDescriptor(), GetPrivateRefCountEntry(), likely, mode, pg_atomic_sub_fetch_u64(), ResourceOwnerForgetBuffer(), RESUME_INTERRUPTS, UnpinLocalBuffer(), VALGRIND_MAKE_MEM_NOACCESS, and WakePinCountWaiter().

Referenced by _bt_clear_incomplete_split(), _bt_relbuf(), _bt_restore_meta(), _hash_relbuf(), allocNewBuffer(), AlterSequence(), blbulkdelete(), blgetbitmap(), blinsert(), BloomInitMetapage(), blvacuumcleanup(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinGetStats(), brinRevmapDesummarizeRange(), bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), bt_recheck_sibling_links(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), collect_corrupt_items(), collect_visibility_data(), count_nondeletable_pages(), createPostingTree(), doPickSplit(), entryLoadMoreItems(), fill_seq_fork_with_data(), flushCachedPage(), FreeSpaceMapPrepareTruncateRel(), fsm_search(), fsm_set_and_search(), fsm_vacuum_page(), generic_redo(), get_raw_page_internal(), GetVictimBuffer(), gin_check_parent_keys_consistency(), gin_check_posting_tree_parent_keys_consistency(), gin_refind_parent(), ginbuild(), ginbuildempty(), ginbulkdelete(), ginGetStats(), ginHeapTupleFastInsert(), ginInsertCleanup(), ginPlaceToPage(), ginRedoClearIncompleteSplit(), ginRedoCreatePTree(), ginRedoDeleteListPages(), ginRedoDeletePage(), ginRedoInsert(), ginRedoInsertListPage(), ginRedoSplit(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginRedoVacuumPage(), ginScanPostingTreeToDelete(), 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_fetch(), heap_finish_speculative(), heap_force_common(), heap_get_latest_tid(), heap_index_delete_tuples(), heap_insert(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_update(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), heap_xlog_update(), heapam_scan_analyze_next_tuple(), initBloomState(), invalidate_one_block(), lazy_scan_heap(), lazy_scan_new_or_empty(), lazy_vacuum_heap_rel(), log_newpage_range(), modify_rel_block(), moveLeafs(), nextval_internal(), palloc_btree_page(), pg_get_sequence_data(), pg_sequence_last_value(), pg_visibility(), pgstat_gist_page(), pgstat_heap(), pgstatginindex_internal(), pgstathashindex(), pgstatindex_impl(), ProcessSingleRelationFork(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), ResetSequence(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), scanPostingTree(), ScanSourceDatabasePgClass(), seq_redo(), SequenceChangePersistence(), SetSequence(), shiftList(), spgAddNodeAction(), spgbuild(), spgdoinsert(), spgGetCache(), SpGistGetBuffer(), SpGistUpdateMetaPage(), spgMatchNodeAction(), spgprocesspending(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), spgvacuumpage(), spgWalk(), statapprox_heap(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_prepare_truncate(), writeListPage(), xlog_redo(), and XLogRecordPageWithFreeSpace().

◆ WaitReadBuffers()

bool WaitReadBuffers ( ReadBuffersOperation operation)
extern

Definition at line 1750 of file bufmgr.c.

1751{
1752 PgAioReturn *aio_ret = &operation->io_return;
1755 bool needed_wait = false;
1756
1757 if (operation->persistence == RELPERSISTENCE_TEMP)
1758 {
1761 }
1762 else
1763 {
1766 }
1767
1768 /*
1769 * If we get here without an IO operation having been issued, the
1770 * io_method == IOMETHOD_SYNC path must have been used. Otherwise the
1771 * caller should not have called WaitReadBuffers().
1772 *
1773 * In the case of IOMETHOD_SYNC, we start - as we used to before the
1774 * introducing of AIO - the IO in WaitReadBuffers(). This is done as part
1775 * of the retry logic below, no extra code is required.
1776 *
1777 * This path is expected to eventually go away.
1778 */
1779 if (!pgaio_wref_valid(&operation->io_wref) && io_method != IOMETHOD_SYNC)
1780 elog(ERROR, "waiting for read operation that didn't read");
1781
1782 /*
1783 * To handle partial reads, and IOMETHOD_SYNC, we re-issue IO until we're
1784 * done. We may need multiple retries, not just because we could get
1785 * multiple partial reads, but also because some of the remaining
1786 * to-be-read buffers may have been read in by other backends, limiting
1787 * the IO size.
1788 */
1789 while (true)
1790 {
1792
1794
1795 /*
1796 * If there is an IO associated with the operation, we may need to
1797 * wait for it.
1798 */
1799 if (pgaio_wref_valid(&operation->io_wref))
1800 {
1801 /*
1802 * Track the time spent waiting for the IO to complete. As
1803 * tracking a wait even if we don't actually need to wait
1804 *
1805 * a) is not cheap, due to the timestamping overhead
1806 *
1807 * b) reports some time as waiting, even if we never waited
1808 *
1809 * we first check if we already know the IO is complete.
1810 *
1811 * Note that operation->io_return is uninitialized for foreign IO,
1812 * so we cannot use the cheaper PGAIO_RS_UNKNOWN pre-check.
1813 */
1814 if ((operation->foreign_io || aio_ret->result.status == PGAIO_RS_UNKNOWN) &&
1815 !pgaio_wref_check_done(&operation->io_wref))
1816 {
1818
1819 pgaio_wref_wait(&operation->io_wref);
1820 needed_wait = true;
1821
1822 /*
1823 * The IO operation itself was already counted earlier, in
1824 * AsyncReadBuffers(), this just accounts for the wait time.
1825 */
1827 io_start, 0, 0);
1828 }
1829 else
1830 {
1832 }
1833
1834 if (unlikely(operation->foreign_io))
1835 {
1836 Buffer buffer = operation->buffers[operation->nblocks_done];
1837 BufferDesc *desc = BufferIsLocal(buffer) ?
1838 GetLocalBufferDescriptor(-buffer - 1) :
1839 GetBufferDescriptor(buffer - 1);
1841
1842 if (buf_state & BM_VALID)
1843 {
1844 BlockNumber blocknum = operation->blocknum + operation->nblocks_done;
1845
1846 operation->nblocks_done += 1;
1847 Assert(operation->nblocks_done <= operation->nblocks);
1848
1849 /*
1850 * Track this as a 'hit' for this backend. The backend
1851 * performing the IO will track it as a 'read'.
1852 */
1854 operation->rel, operation->persistence,
1855 operation->smgr, operation->forknum,
1856 blocknum);
1857 }
1858
1859 /*
1860 * If the foreign IO failed and left the buffer invalid,
1861 * nblocks_done is not incremented. The retry loop below will
1862 * call AsyncReadBuffers() which will attempt the IO itself.
1863 */
1864 }
1865 else
1866 {
1867 /*
1868 * We now are sure the IO completed. Check the results. This
1869 * includes reporting on errors if there were any.
1870 */
1872 }
1873 }
1874
1875 /*
1876 * Most of the time, the one IO we already started, will read in
1877 * everything. But we need to deal with partial reads and buffers not
1878 * needing IO anymore.
1879 */
1880 if (operation->nblocks_done == operation->nblocks)
1881 break;
1882
1884
1885 /*
1886 * If the IO completed only partially, we need to perform additional
1887 * work, consider that a form of having had to wait.
1888 */
1889 needed_wait = true;
1890
1891 /*
1892 * This may only complete the IO partially, either because some
1893 * buffers were already valid, or because of a partial read.
1894 *
1895 * NB: In contrast to after the AsyncReadBuffers() call in
1896 * StartReadBuffers(), we do *not* reduce
1897 * ReadBuffersOperation->nblocks here, callers expect the full
1898 * operation to be completed at this point (as more operations may
1899 * have been queued).
1900 */
1902 }
1903
1905
1906 /* NB: READ_DONE tracepoint was already executed in completion callback */
1907 return needed_wait;
1908}
int io_method
Definition aio.c:74
bool pgaio_wref_valid(PgAioWaitRef *iow)
Definition aio.c:971
bool pgaio_wref_check_done(PgAioWaitRef *iow)
Definition aio.c:1005
void pgaio_wref_wait(PgAioWaitRef *iow)
Definition aio.c:991
@ IOMETHOD_SYNC
Definition aio.h:34
@ PGAIO_RS_UNKNOWN
Definition aio_types.h:80
bool track_io_timing
Definition bufmgr.c:192
static void CheckReadBuffersOperation(ReadBuffersOperation *operation, bool is_complete)
Definition bufmgr.c:1647
static void ProcessReadBuffersResult(ReadBuffersOperation *operation)
Definition bufmgr.c:1705
static pg_attribute_always_inline void TrackBufferHit(IOObject io_object, IOContext io_context, Relation rel, char persistence, SMgrRelation smgr, ForkNumber forknum, BlockNumber blocknum)
Definition bufmgr.c:1674
static bool AsyncReadBuffers(ReadBuffersOperation *operation, int *nblocks_progress)
Definition bufmgr.c:1929
#define unlikely(x)
Definition c.h:438
IOContext IOContextForStrategy(BufferAccessStrategy strategy)
Definition freelist.c:712
IOObject
Definition pgstat.h:280
@ IOOBJECT_TEMP_RELATION
Definition pgstat.h:282
IOContext
Definition pgstat.h:289
@ IOOP_READ
Definition pgstat.h:319
instr_time pgstat_prepare_io_time(bool track_io_guc)
Definition pgstat_io.c:91
void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt, uint64 bytes)
Definition pgstat_io.c:122

References Assert, AsyncReadBuffers(), BM_VALID, PrivateRefCountEntry::buffer, BufferIsLocal, CHECK_FOR_INTERRUPTS, CheckReadBuffersOperation(), elog, ERROR, fb(), GetBufferDescriptor(), GetLocalBufferDescriptor(), io_method, IOCONTEXT_NORMAL, IOContextForStrategy(), IOMETHOD_SYNC, IOOBJECT_RELATION, IOOBJECT_TEMP_RELATION, IOOP_READ, operation, pg_atomic_read_u64(), PGAIO_RS_UNKNOWN, pgaio_wref_check_done(), pgaio_wref_valid(), pgaio_wref_wait(), pgstat_count_io_op_time(), pgstat_prepare_io_time(), ProcessReadBuffersResult(), BufferDesc::state, track_io_timing, TrackBufferHit(), and unlikely.

Referenced by read_buffers(), read_stream_next_buffer(), and ReadBuffer_common().

Variable Documentation

◆ aio_local_buffer_readv_cb

PGDLLIMPORT const PgAioHandleCallbacks aio_local_buffer_readv_cb
extern

Definition at line 8947 of file bufmgr.c.

8947 {
8948 .stage = local_buffer_readv_stage,
8949
8950 /*
8951 * Note that this, in contrast to the shared_buffers case, uses
8952 * complete_local, as only the issuing backend has access to the required
8953 * datastructures. This is important in case the IO completion may be
8954 * consumed incidentally by another backend.
8955 */
8956 .complete_local = local_buffer_readv_complete,
8957 .report = buffer_readv_report,
8958};
static PgAioResult local_buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8931
static void local_buffer_readv_stage(PgAioHandle *ioh, uint8 cb_data)
Definition bufmgr.c:8925
static void buffer_readv_report(PgAioResult result, const PgAioTargetData *td, int elevel)
Definition bufmgr.c:8779

◆ aio_shared_buffer_readv_cb

PGDLLIMPORT const PgAioHandleCallbacks aio_shared_buffer_readv_cb
extern

Definition at line 8938 of file bufmgr.c.

8938 {
8940 .complete_shared = shared_buffer_readv_complete,
8941 /* need a local callback to report checksum failures */
8942 .complete_local = shared_buffer_readv_complete_local,
8943 .report = buffer_readv_report,
8944};
static PgAioResult shared_buffer_readv_complete_local(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8894
static void shared_buffer_readv_stage(PgAioHandle *ioh, uint8 cb_data)
Definition bufmgr.c:8874
static PgAioResult shared_buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8880

◆ backend_flush_after

PGDLLIMPORT int backend_flush_after
extern

Definition at line 225 of file bufmgr.c.

Referenced by BufferManagerShmemAttach(), and BufferManagerShmemInit().

◆ bgwriter_flush_after

PGDLLIMPORT int bgwriter_flush_after
extern

Definition at line 224 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

PGDLLIMPORT int bgwriter_lru_maxpages
extern

Definition at line 190 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

PGDLLIMPORT double bgwriter_lru_multiplier
extern

Definition at line 191 of file bufmgr.c.

Referenced by BgBufferSync().

◆ BufferBlocks

PGDLLIMPORT char* BufferBlocks
extern

Definition at line 25 of file buf_init.c.

Referenced by BufferGetBlock(), and BufferManagerShmemRequest().

◆ checkpoint_flush_after

PGDLLIMPORT int checkpoint_flush_after
extern

Definition at line 223 of file bufmgr.c.

Referenced by BufferSync().

◆ effective_io_concurrency

PGDLLIMPORT int effective_io_concurrency
extern

◆ io_combine_limit

◆ io_combine_limit_guc

PGDLLIMPORT int io_combine_limit_guc
extern

Definition at line 216 of file bufmgr.c.

Referenced by assign_io_max_combine_limit().

◆ io_max_combine_limit

◆ LocalBufferBlockPointers

PGDLLIMPORT Block* LocalBufferBlockPointers
extern

Definition at line 48 of file localbuf.c.

Referenced by BufferGetBlock(), and InitLocalBuffers().

◆ LocalRefCount

◆ maintenance_io_concurrency

◆ NBuffers

◆ NLocBuffer

◆ track_io_timing

◆ zero_damaged_pages

PGDLLIMPORT bool zero_damaged_pages
extern

Definition at line 189 of file bufmgr.c.

Referenced by AsyncReadBuffers(), mdreadv(), and read_rel_block_ll().