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)
 
void 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 BufferManagerShmemInit (void)
 
Size BufferManagerShmemSize (void)
 
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 168 of file bufmgr.h.

◆ DEFAULT_IO_COMBINE_LIMIT

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

Definition at line 174 of file bufmgr.h.

◆ DEFAULT_MAINTENANCE_IO_CONCURRENCY

#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   16

Definition at line 169 of file bufmgr.h.

◆ MAX_IO_COMBINE_LIMIT

#define MAX_IO_COMBINE_LIMIT   PG_IOV_MAX

Definition at line 173 of file bufmgr.h.

◆ MAX_IO_CONCURRENCY

#define MAX_IO_CONCURRENCY   1000

Definition at line 195 of file bufmgr.h.

◆ P_NEW

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

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

Typedef Documentation

◆ Block

Definition at line 26 of file bufmgr.h.

◆ BufferAccessStrategyType

◆ BufferLockMode

◆ BufferManagerRelation

◆ ExtendBufferedFlags

◆ PrefetchBufferResult

◆ ReadBuffersOperation

Definition at line 154 of file bufmgr.h.

◆ SMgrRelation

Definition at line 97 of file bufmgr.h.

◆ WritebackContext

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

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

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

4111{
4113
4115
4117}
static void CheckForBufferLeaks(void)
Definition bufmgr.c:4174
static int32 PrivateRefCountOverflowed
Definition bufmgr.c:266
#define Assert(condition)
Definition c.h:945
void AtEOXact_LocalBuffers(bool isCommit)
Definition localbuf.c:1003

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

1015{
1016 /*
1017 * We shouldn't be holding any remaining pins; if we are, and assertions
1018 * aren't enabled, we'll fail later in DropRelationBuffers while trying to
1019 * drop the temp rels.
1020 */
1022}
static void CheckForLocalBufferLeaks(void)
Definition localbuf.c:970

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

◆ BgBufferSync()

bool BgBufferSync ( WritebackContext wb_context)
extern

Definition at line 3742 of file bufmgr.c.

3743{
3744 /* info obtained from freelist.c */
3745 int strategy_buf_id;
3748
3749 /*
3750 * Information saved between calls so we can determine the strategy
3751 * point's advance rate and avoid scanning already-cleaned buffers.
3752 */
3753 static bool saved_info_valid = false;
3754 static int prev_strategy_buf_id;
3756 static int next_to_clean;
3757 static uint32 next_passes;
3758
3759 /* Moving averages of allocation rate and clean-buffer density */
3760 static float smoothed_alloc = 0;
3761 static float smoothed_density = 10.0;
3762
3763 /* Potentially these could be tunables, but for now, not */
3764 float smoothing_samples = 16;
3765 float scan_whole_pool_milliseconds = 120000.0;
3766
3767 /* Used to compute how far we scan ahead */
3768 long strategy_delta;
3769 int bufs_to_lap;
3770 int bufs_ahead;
3771 float scans_per_alloc;
3774 int min_scan_buffers;
3775
3776 /* Variables for the scanning loop proper */
3777 int num_to_scan;
3778 int num_written;
3779 int reusable_buffers;
3780
3781 /* Variables for final smoothed_density update */
3782 long new_strategy_delta;
3784
3785 /*
3786 * Find out where the clock-sweep currently is, and how many buffer
3787 * allocations have happened since our last call.
3788 */
3790
3791 /* Report buffer alloc counts to pgstat */
3793
3794 /*
3795 * If we're not running the LRU scan, just stop after doing the stats
3796 * stuff. We mark the saved state invalid so that we can recover sanely
3797 * if LRU scan is turned back on later.
3798 */
3799 if (bgwriter_lru_maxpages <= 0)
3800 {
3801 saved_info_valid = false;
3802 return true;
3803 }
3804
3805 /*
3806 * Compute strategy_delta = how many buffers have been scanned by the
3807 * clock-sweep since last time. If first time through, assume none. Then
3808 * see if we are still ahead of the clock-sweep, and if so, how many
3809 * buffers we could scan before we'd catch up with it and "lap" it. Note:
3810 * weird-looking coding of xxx_passes comparisons are to avoid bogus
3811 * behavior when the passes counts wrap around.
3812 */
3813 if (saved_info_valid)
3814 {
3816
3819
3820 Assert(strategy_delta >= 0);
3821
3822 if ((int32) (next_passes - strategy_passes) > 0)
3823 {
3824 /* we're one pass ahead of the strategy point */
3826#ifdef BGW_DEBUG
3827 elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3831#endif
3832 }
3833 else if (next_passes == strategy_passes &&
3835 {
3836 /* on same pass, but ahead or at least not behind */
3838#ifdef BGW_DEBUG
3839 elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3843#endif
3844 }
3845 else
3846 {
3847 /*
3848 * We're behind, so skip forward to the strategy point and start
3849 * cleaning from there.
3850 */
3851#ifdef BGW_DEBUG
3852 elog(DEBUG2, "bgwriter behind: bgw %u-%u strategy %u-%u delta=%ld",
3856#endif
3860 }
3861 }
3862 else
3863 {
3864 /*
3865 * Initializing at startup or after LRU scanning had been off. Always
3866 * start at the strategy point.
3867 */
3868#ifdef BGW_DEBUG
3869 elog(DEBUG2, "bgwriter initializing: strategy %u-%u",
3871#endif
3872 strategy_delta = 0;
3876 }
3877
3878 /* Update saved info for next time */
3881 saved_info_valid = true;
3882
3883 /*
3884 * Compute how many buffers had to be scanned for each new allocation, ie,
3885 * 1/density of reusable buffers, and track a moving average of that.
3886 *
3887 * If the strategy point didn't move, we don't update the density estimate
3888 */
3889 if (strategy_delta > 0 && recent_alloc > 0)
3890 {
3894 }
3895
3896 /*
3897 * Estimate how many reusable buffers there are between the current
3898 * strategy point and where we've scanned ahead to, based on the smoothed
3899 * density estimate.
3900 */
3903
3904 /*
3905 * Track a moving average of recent buffer allocations. Here, rather than
3906 * a true average we want a fast-attack, slow-decline behavior: we
3907 * immediately follow any increase.
3908 */
3909 if (smoothed_alloc <= (float) recent_alloc)
3911 else
3914
3915 /* Scale the estimate by a GUC to allow more aggressive tuning. */
3917
3918 /*
3919 * If recent_alloc remains at zero for many cycles, smoothed_alloc will
3920 * eventually underflow to zero, and the underflows produce annoying
3921 * kernel warnings on some platforms. Once upcoming_alloc_est has gone to
3922 * zero, there's no point in tracking smaller and smaller values of
3923 * smoothed_alloc, so just reset it to exactly zero to avoid this
3924 * syndrome. It will pop back up as soon as recent_alloc increases.
3925 */
3926 if (upcoming_alloc_est == 0)
3927 smoothed_alloc = 0;
3928
3929 /*
3930 * Even in cases where there's been little or no buffer allocation
3931 * activity, we want to make a small amount of progress through the buffer
3932 * cache so that as many reusable buffers as possible are clean after an
3933 * idle period.
3934 *
3935 * (scan_whole_pool_milliseconds / BgWriterDelay) computes how many times
3936 * the BGW will be called during the scan_whole_pool time; slice the
3937 * buffer pool into that many sections.
3938 */
3940
3942 {
3943#ifdef BGW_DEBUG
3944 elog(DEBUG2, "bgwriter: alloc_est=%d too small, using min=%d + reusable_est=%d",
3946#endif
3948 }
3949
3950 /*
3951 * Now write out dirty reusable buffers, working forward from the
3952 * next_to_clean point, until we have lapped the strategy scan, or cleaned
3953 * enough buffers to match our estimate of the next cycle's allocation
3954 * requirements, or hit the bgwriter_lru_maxpages limit.
3955 */
3956
3957 num_to_scan = bufs_to_lap;
3958 num_written = 0;
3960
3961 /* Execute the LRU scan */
3962 while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
3963 {
3965 wb_context);
3966
3967 if (++next_to_clean >= NBuffers)
3968 {
3969 next_to_clean = 0;
3970 next_passes++;
3971 }
3972 num_to_scan--;
3973
3974 if (sync_state & BUF_WRITTEN)
3975 {
3978 {
3980 break;
3981 }
3982 }
3983 else if (sync_state & BUF_REUSABLE)
3985 }
3986
3988
3989#ifdef BGW_DEBUG
3990 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",
3993 bufs_to_lap - num_to_scan,
3996#endif
3997
3998 /*
3999 * Consider the above scan as being like a new allocation scan.
4000 * Characterize its density and update the smoothed one based on it. This
4001 * effectively halves the moving average period in cases where both the
4002 * strategy and the background writer are doing some useful scanning,
4003 * which is helpful because a long memory isn't as desirable on the
4004 * density estimates.
4005 */
4006 new_strategy_delta = bufs_to_lap - num_to_scan;
4008 if (new_strategy_delta > 0 && new_recent_alloc > 0)
4009 {
4013
4014#ifdef BGW_DEBUG
4015 elog(DEBUG2, "bgwriter: cleaner density alloc=%u scan=%ld density=%.2f new smoothed=%.2f",
4018#endif
4019 }
4020
4021 /* Return true if OK to hibernate */
4022 return (bufs_to_lap == 0 && recent_alloc == 0);
4023}
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:4040
int bgwriter_lru_maxpages
Definition bufmgr.c:190
#define BUF_WRITTEN
Definition bufmgr.c:84
int32_t int32
Definition c.h:614
uint32_t uint32
Definition c.h:618
#define DEBUG2
Definition elog.h:29
#define DEBUG1
Definition elog.h:30
#define elog(elevel,...)
Definition elog.h:226
int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc)
Definition freelist.c:321
int NBuffers
Definition globals.c:142
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 6909 of file bufmgr.c.

6910{
6913
6914 if (BufferIsLocal(buffer))
6915 {
6916 /*
6917 * NB: Will need to check if there is a write in progress, once it is
6918 * possible for writes to be done asynchronously.
6919 */
6920 return true;
6921 }
6922
6923 buf_hdr = GetBufferDescriptor(buffer - 1);
6924
6926}
#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:6818
uint64_t uint64
Definition c.h:619

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

6938{
6939 if (!BufferIsLocal(buffer))
6942
6943 if (mark_dirty)
6945}
bool BufferIsLockedByMeInMode(Buffer buffer, BufferLockMode mode)
Definition bufmgr.c:3003
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition bufmgr.c:5688

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

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

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(), read_rel_block_ll(), and XLogSaveBufferForHint().

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)
extern

Definition at line 4357 of file bufmgr.c.

4358{
4360
4361 Assert(BufferIsPinned(buffer));
4362
4363 if (BufferIsLocal(buffer))
4364 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
4365 else
4366 bufHdr = GetBufferDescriptor(buffer - 1);
4367
4368 /* pinned, so OK to read tag without spinlock */
4369 return bufHdr->tag.blockNum;
4370}
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_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_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_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(), visibilitymap_set(), and visibilitymap_set_vmbits().

◆ BufferGetLSNAtomic()

XLogRecPtr BufferGetLSNAtomic ( Buffer  buffer)
extern

Definition at line 4632 of file bufmgr.c.

4633{
4634 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4635 Assert(BufferIsValid(buffer));
4636 Assert(BufferIsPinned(buffer));
4637
4638#ifdef PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY
4639 return PageGetLSN(BufferGetPage(buffer));
4640#else
4641 {
4642 char *page = BufferGetPage(buffer);
4644 XLogRecPtr lsn;
4645
4646 /*
4647 * If we don't need locking for correctness, fastpath out.
4648 */
4649 if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
4650 return PageGetLSN(page);
4651
4652 bufHdr = GetBufferDescriptor(buffer - 1);
4654 lsn = PageGetLSN(page);
4656
4657 return lsn;
4658 }
4659#endif
4660}
static void UnlockBufHdr(BufferDesc *desc)
uint64 LockBufHdr(BufferDesc *desc)
Definition bufmgr.c:7301
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:470
static XLogRecPtr PageGetLSN(const PageData *page)
Definition bufpage.h:411
#define XLogHintBitIsNeeded()
Definition xlog.h:122
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 470 of file bufmgr.h.

471{
472 return (Page) BufferGetBlock(buffer);
473}
static Block BufferGetBlock(Buffer buffer)
Definition bufmgr.h:437
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_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(), heap_xlog_visible(), 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(), visibilitymap_set_vmbits(), 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 4378 of file bufmgr.c.

4380{
4382
4383 /* Do the same checks as BufferGetBlockNumber. */
4384 Assert(BufferIsPinned(buffer));
4385
4386 if (BufferIsLocal(buffer))
4387 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
4388 else
4389 bufHdr = GetBufferDescriptor(buffer - 1);
4390
4391 /* pinned, so OK to read tag without spinlock */
4392 *rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
4393 *forknum = BufTagGetForkNum(&bufHdr->tag);
4394 *blknum = bufHdr->tag.blockNum;
4395}
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(), XLogRegisterBuffer(), and XLogSaveBufferForHint().

◆ BufferIsDirty()

bool BufferIsDirty ( Buffer  buffer)
extern

Definition at line 3030 of file bufmgr.c.

3031{
3033
3034 Assert(BufferIsPinned(buffer));
3035
3036 if (BufferIsLocal(buffer))
3037 {
3038 int bufid = -buffer - 1;
3039
3041 /* Content locks are not maintained for local buffers. */
3042 }
3043 else
3044 {
3045 bufHdr = GetBufferDescriptor(buffer - 1);
3048 }
3049
3050 return pg_atomic_read_u64(&bufHdr->state) & BM_DIRTY;
3051}
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_xlog_multi_insert(), heap_xlog_prune_freeze(), log_heap_prune_and_freeze(), XLogRegisterBuffer(), and XLogSaveBufferForHint().

◆ BufferIsLockedByMe()

bool BufferIsLockedByMe ( Buffer  buffer)
extern

Definition at line 2977 of file bufmgr.c.

2978{
2980
2981 Assert(BufferIsPinned(buffer));
2982
2983 if (BufferIsLocal(buffer))
2984 {
2985 /* Content locks are not maintained for local buffers. */
2986 return true;
2987 }
2988 else
2989 {
2990 bufHdr = GetBufferDescriptor(buffer - 1);
2991 return BufferLockHeldByMe(bufHdr);
2992 }
2993}
static bool BufferLockHeldByMe(BufferDesc *buf_hdr)
Definition bufmgr.c:6410

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

Referenced by FlushOneBuffer().

◆ BufferIsLockedByMeInMode()

bool BufferIsLockedByMeInMode ( Buffer  buffer,
BufferLockMode  mode 
)
extern

Definition at line 3003 of file bufmgr.c.

3004{
3006
3007 Assert(BufferIsPinned(buffer));
3008
3009 if (BufferIsLocal(buffer))
3010 {
3011 /* Content locks are not maintained for local buffers. */
3012 return true;
3013 }
3014 else
3015 {
3016 bufHdr = GetBufferDescriptor(buffer - 1);
3018 }
3019}
static bool BufferLockHeldByMeInMode(BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:6392
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(), visibilitymap_set_vmbits(), and XLogRegisterBuffer().

◆ BufferIsPermanent()

bool BufferIsPermanent ( Buffer  buffer)
extern

Definition at line 4596 of file bufmgr.c.

4597{
4599
4600 /* Local buffers are used only for temp relations. */
4601 if (BufferIsLocal(buffer))
4602 return false;
4603
4604 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4605 Assert(BufferIsValid(buffer));
4606 Assert(BufferIsPinned(buffer));
4607
4608 /*
4609 * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
4610 * need not bother with the buffer header spinlock. Even if someone else
4611 * changes the buffer header state while we're doing this, the state is
4612 * changed atomically, so we'll read the old value or the new value, but
4613 * not random garbage.
4614 */
4615 bufHdr = GetBufferDescriptor(buffer - 1);
4616 return (pg_atomic_read_u64(&bufHdr->state) & BM_PERMANENT) != 0;
4617}
#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 421 of file bufmgr.h.

422{
425
426 return bufnum != InvalidBuffer;
427}
#define InvalidBuffer
Definition buf.h:25
PGDLLIMPORT int NBuffers
Definition globals.c:142
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(), heap_xlog_visible(), heapam_index_fetch_reset(), 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_rel_block(), IsBufferCleanupOK(), lazy_scan_heap(), lazy_vacuum_heap_rel(), log_heap_visible(), MarkBufferDirty(), MarkBufferDirtyHint(), prune_freeze_setup(), 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(), visibilitymap_set_vmbits(), XLogPrefetcherNextBlock(), XLogReadBufferExtended(), and XLogReadBufferForRedoExtended().

◆ BufferManagerShmemInit()

void BufferManagerShmemInit ( void  )
extern

Definition at line 69 of file buf_init.c.

70{
71 bool foundBufs,
75
76 /* Align descriptors to a cacheline boundary. */
78 ShmemInitStruct("Buffer Descriptors",
79 NBuffers * sizeof(BufferDescPadded),
80 &foundDescs);
81
82 /* Align buffer pool on IO page size boundary. */
83 BufferBlocks = (char *)
85 ShmemInitStruct("Buffer Blocks",
87 &foundBufs));
88
89 /* Align condition variables to cacheline boundary. */
91 ShmemInitStruct("Buffer IO Condition Variables",
93 &foundIOCV);
94
95 /*
96 * The array used to sort to-be-checkpointed buffer ids is located in
97 * shared memory, to avoid having to allocate significant amounts of
98 * memory at runtime. As that'd be in the middle of a checkpoint, or when
99 * the checkpointer is restarted, memory allocation failures would be
100 * painful.
101 */
103 ShmemInitStruct("Checkpoint BufferIds",
105
107 {
108 /* should find all of these, or none of them */
110 /* note: this path is only taken in EXEC_BACKEND case */
111 }
112 else
113 {
114 int i;
115
116 /*
117 * Initialize all the buffer headers.
118 */
119 for (i = 0; i < NBuffers; i++)
120 {
122
123 ClearBufferTag(&buf->tag);
124
125 pg_atomic_init_u64(&buf->state, 0);
126 buf->wait_backend_pgprocno = INVALID_PROC_NUMBER;
127
128 buf->buf_id = i;
129
130 pgaio_wref_clear(&buf->io_wref);
131
132 proclist_init(&buf->lock_waiters);
134 }
135 }
136
137 /* Init other shared buffer-management stuff */
139
140 /* Initialize per-backend file flush context */
143}
void pgaio_wref_clear(PgAioWaitRef *iow)
Definition aio.c:964
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition atomics.h:453
CkptSortItem * CkptBufferIds
Definition buf_init.c:26
char * BufferBlocks
Definition buf_init.c:23
WritebackContext BackendWritebackContext
Definition buf_init.c:25
ConditionVariableMinimallyPadded * BufferIOCVArray
Definition buf_init.c:24
BufferDescPadded * BufferDescriptors
Definition buf_init.c:22
static ConditionVariable * BufferDescriptorGetIOCV(const BufferDesc *bdesc)
static void ClearBufferTag(BufferTag *tag)
void WritebackContextInit(WritebackContext *context, int *max_pending)
Definition bufmgr.c:7461
int backend_flush_after
Definition bufmgr.c:225
#define TYPEALIGN(ALIGNVAL, LEN)
Definition c.h:891
void ConditionVariableInit(ConditionVariable *cv)
void StrategyInitialize(bool init)
Definition freelist.c:401
int i
Definition isn.c:77
#define PG_IO_ALIGN_SIZE
static char buf[DEFAULT_XLOG_SEG_SIZE]
static void proclist_init(proclist_head *list)
Definition proclist.h:29
#define INVALID_PROC_NUMBER
Definition procnumber.h:26
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:381

References Assert, backend_flush_after, BackendWritebackContext, buf, BufferBlocks, BufferDescriptorGetIOCV(), BufferDescriptors, BufferIOCVArray, CkptBufferIds, ClearBufferTag(), ConditionVariableInit(), fb(), GetBufferDescriptor(), i, INVALID_PROC_NUMBER, NBuffers, pg_atomic_init_u64(), PG_IO_ALIGN_SIZE, pgaio_wref_clear(), proclist_init(), ShmemInitStruct(), StrategyInitialize(), TYPEALIGN, and WritebackContextInit().

Referenced by CreateOrAttachShmemStructs().

◆ BufferManagerShmemSize()

Size BufferManagerShmemSize ( void  )
extern

Definition at line 152 of file buf_init.c.

153{
154 Size size = 0;
155
156 /* size of buffer descriptors */
157 size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
158 /* to allow aligning buffer descriptors */
159 size = add_size(size, PG_CACHE_LINE_SIZE);
160
161 /* size of data pages, plus alignment padding */
162 size = add_size(size, PG_IO_ALIGN_SIZE);
163 size = add_size(size, mul_size(NBuffers, BLCKSZ));
164
165 /* size of stuff controlled by freelist.c */
166 size = add_size(size, StrategyShmemSize());
167
168 /* size of I/O condition variables */
169 size = add_size(size, mul_size(NBuffers,
171 /* to allow aligning the above */
172 size = add_size(size, PG_CACHE_LINE_SIZE);
173
174 /* size of checkpoint sort array in bufmgr.c */
175 size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
176
177 return size;
178}
Size StrategyShmemSize(void)
Definition freelist.c:380
#define PG_CACHE_LINE_SIZE
Size add_size(Size s1, Size s2)
Definition shmem.c:485
Size mul_size(Size s1, Size s2)
Definition shmem.c:500

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

Referenced by CalculateShmemSize().

◆ BufferSetHintBits16()

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

Definition at line 6960 of file bufmgr.c.

6961{
6964#ifdef USE_ASSERT_CHECKING
6965 char *page;
6966
6967 /* verify that the address is on the page */
6968 page = BufferGetPage(buffer);
6969 Assert((char *) ptr >= page && (char *) ptr < (page + BLCKSZ));
6970#endif
6971
6972 if (BufferIsLocal(buffer))
6973 {
6974 *ptr = val;
6975
6976 MarkLocalBufferDirty(buffer);
6977
6978 return true;
6979 }
6980
6981 buf_hdr = GetBufferDescriptor(buffer - 1);
6982
6984 {
6985 *ptr = val;
6986
6988
6989 return true;
6990 }
6991
6992 return false;
6993}
static void MarkSharedBufferDirtyHint(Buffer buffer, BufferDesc *bufHdr, uint64 lockstate, bool buffer_std)
Definition bufmgr.c:5563
long val
Definition informix.c:689
void MarkLocalBufferDirty(Buffer buffer)
Definition localbuf.c:491

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

6505{
6506 if (BufferIsLocal(buffer))
6507 {
6508 if (LocalRefCount[-buffer - 1] != 1)
6509 elog(ERROR, "incorrect local pin count: %d",
6510 LocalRefCount[-buffer - 1]);
6511 }
6512 else
6513 {
6514 if (GetPrivateRefCount(buffer) != 1)
6515 elog(ERROR, "incorrect local pin count: %d",
6516 GetPrivateRefCount(buffer));
6517 }
6518}
static int32 GetPrivateRefCount(Buffer buffer)
Definition bufmgr.c:542
#define ERROR
Definition elog.h:39
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 4343 of file bufmgr.c.

4344{
4345 BufferSync(flags);
4346}
static void BufferSync(int flags)
Definition bufmgr.c:3463

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)
extern

Definition at line 6484 of file bufmgr.c.

6485{
6486 BufferDesc *buf;
6487
6488 Assert(BufferIsPinned(buffer));
6489 if (BufferIsLocal(buffer))
6490 return true; /* act as though we got it */
6491
6492 buf = GetBufferDescriptor(buffer - 1);
6493
6495}
static bool BufferLockConditional(Buffer buffer, BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:5917

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

6711{
6714 refcount;
6715
6716 Assert(BufferIsValid(buffer));
6717
6718 /* see AIO related comment in LockBufferForCleanup() */
6719
6720 if (BufferIsLocal(buffer))
6721 {
6722 refcount = LocalRefCount[-buffer - 1];
6723 /* There should be exactly one pin */
6724 Assert(refcount > 0);
6725 if (refcount != 1)
6726 return false;
6727 /* Nobody else to wait for */
6728 return true;
6729 }
6730
6731 /* There should be exactly one local pin */
6732 refcount = GetPrivateRefCount(buffer);
6733 Assert(refcount);
6734 if (refcount != 1)
6735 return false;
6736
6737 /* Try to acquire lock */
6738 if (!ConditionalLockBuffer(buffer))
6739 return false;
6740
6741 bufHdr = GetBufferDescriptor(buffer - 1);
6744
6745 Assert(refcount > 0);
6746 if (refcount == 1)
6747 {
6748 /* Successfully acquired exclusive lock with pincount 1 */
6750 return true;
6751 }
6752
6753 /* Failed, so release the lock */
6756 return false;
6757}
#define BUF_STATE_GET_REFCOUNT(state)
bool ConditionalLockBuffer(Buffer buffer)
Definition bufmgr.c:6484
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:332

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

5383{
5384 char relpersistence;
5387
5388 /* Set the relpersistence. */
5389 relpersistence = permanent ?
5391
5394
5395 /*
5396 * Create and copy all forks of the relation. During create database we
5397 * have a separate cleanup mechanism which deletes complete database
5398 * directory. Therefore, each individual relation doesn't need to be
5399 * registered for cleanup.
5400 */
5401 RelationCreateStorage(dst_rlocator, relpersistence, false);
5402
5403 /* copy main fork. */
5405 permanent);
5406
5407 /* copy those extra forks that exist */
5408 for (ForkNumber forkNum = MAIN_FORKNUM + 1;
5409 forkNum <= MAX_FORKNUM; forkNum++)
5410 {
5411 if (smgrexists(src_rel, forkNum))
5412 {
5413 smgrcreate(dst_rel, forkNum, false);
5414
5415 /*
5416 * WAL log creation if the relation is persistent, or this is the
5417 * init fork of an unlogged relation.
5418 */
5419 if (permanent || forkNum == INIT_FORKNUM)
5420 log_smgrcreate(&dst_rlocator, forkNum);
5421
5422 /* Copy a fork's data, block by block. */
5424 permanent);
5425 }
5426 }
5427}
static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, RelFileLocator dstlocator, ForkNumber forkNum, bool permanent)
Definition bufmgr.c:5267
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 4300 of file bufmgr.c.

4301{
4302 BufferDesc *buf;
4304 char *result;
4305 ProcNumber backend;
4307
4308 Assert(BufferIsValid(buffer));
4309 if (BufferIsLocal(buffer))
4310 {
4311 buf = GetLocalBufferDescriptor(-buffer - 1);
4312 loccount = LocalRefCount[-buffer - 1];
4313 backend = MyProcNumber;
4314 }
4315 else
4316 {
4317 buf = GetBufferDescriptor(buffer - 1);
4318 loccount = GetPrivateRefCount(buffer);
4319 backend = INVALID_PROC_NUMBER;
4320 }
4321
4322 /* theoretically we should lock the bufHdr here */
4323 buf_state = pg_atomic_read_u64(&buf->state);
4324
4325 result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%" PRIx64 ", refcount=%u %d)",
4326 buffer,
4328 BufTagGetForkNum(&buf->tag)).str,
4329 buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
4331 return result;
4332}
#define BUF_FLAG_MASK
ProcNumber MyProcNumber
Definition globals.c:90
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(), and relpathbackend.

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

◆ DropDatabaseBuffers()

void DropDatabaseBuffers ( Oid  dbid)
extern

Definition at line 5034 of file bufmgr.c.

5035{
5036 int i;
5037
5038 /*
5039 * We needn't consider local buffers, since by assumption the target
5040 * database isn't our own.
5041 */
5042
5043 for (i = 0; i < NBuffers; i++)
5044 {
5046
5047 /*
5048 * As in DropRelationBuffers, an unlocked precheck should be safe and
5049 * saves some cycles.
5050 */
5051 if (bufHdr->tag.dbOid != dbid)
5052 continue;
5053
5055 if (bufHdr->tag.dbOid == dbid)
5056 InvalidateBuffer(bufHdr); /* releases spinlock */
5057 else
5059 }
5060}
static void InvalidateBuffer(BufferDesc *buf)
Definition bufmgr.c:2283

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

4686{
4687 int i;
4688 int j;
4689 RelFileLocatorBackend rlocator;
4692
4693 rlocator = smgr_reln->smgr_rlocator;
4694
4695 /* If it's a local relation, it's localbuf.c's problem. */
4696 if (RelFileLocatorBackendIsTemp(rlocator))
4697 {
4698 if (rlocator.backend == MyProcNumber)
4699 DropRelationLocalBuffers(rlocator.locator, forkNum, nforks,
4701
4702 return;
4703 }
4704
4705 /*
4706 * To remove all the pages of the specified relation forks from the buffer
4707 * pool, we need to scan the entire buffer pool but we can optimize it by
4708 * finding the buffers from BufMapping table provided we know the exact
4709 * size of each fork of the relation. The exact size is required to ensure
4710 * that we don't leave any buffer for the relation being dropped as
4711 * otherwise the background writer or checkpointer can lead to a PANIC
4712 * error while flushing buffers corresponding to files that don't exist.
4713 *
4714 * To know the exact size, we rely on the size cached for each fork by us
4715 * during recovery which limits the optimization to recovery and on
4716 * standbys but we can easily extend it once we have shared cache for
4717 * relation size.
4718 *
4719 * In recovery, we cache the value returned by the first lseek(SEEK_END)
4720 * and the future writes keeps the cached value up-to-date. See
4721 * smgrextend. It is possible that the value of the first lseek is smaller
4722 * than the actual number of existing blocks in the file due to buggy
4723 * Linux kernels that might not have accounted for the recent write. But
4724 * that should be fine because there must not be any buffers after that
4725 * file size.
4726 */
4727 for (i = 0; i < nforks; i++)
4728 {
4729 /* Get the number of blocks for a relation's fork */
4731
4733 {
4735 break;
4736 }
4737
4738 /* calculate the number of blocks to be invalidated */
4740 }
4741
4742 /*
4743 * We apply the optimization iff the total number of blocks to invalidate
4744 * is below the BUF_DROP_FULL_SCAN_THRESHOLD.
4745 */
4748 {
4749 for (j = 0; j < nforks; j++)
4750 FindAndDropRelationBuffers(rlocator.locator, forkNum[j],
4752 return;
4753 }
4754
4755 for (i = 0; i < NBuffers; i++)
4756 {
4758
4759 /*
4760 * We can make this a tad faster by prechecking the buffer tag before
4761 * we attempt to lock the buffer; this saves a lot of lock
4762 * acquisitions in typical cases. It should be safe because the
4763 * caller must have AccessExclusiveLock on the relation, or some other
4764 * reason to be certain that no one is loading new pages of the rel
4765 * into the buffer pool. (Otherwise we might well miss such pages
4766 * entirely.) Therefore, while the tag might be changing while we
4767 * look at it, it can't be changing *to* a value we care about, only
4768 * *away* from such a value. So false negatives are impossible, and
4769 * false positives are safe because we'll recheck after getting the
4770 * buffer lock.
4771 *
4772 * We could check forkNum and blockNum as well as the rlocator, but
4773 * the incremental win from doing so seems small.
4774 */
4775 if (!BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator.locator))
4776 continue;
4777
4779
4780 for (j = 0; j < nforks; j++)
4781 {
4782 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator.locator) &&
4783 BufTagGetForkNum(&bufHdr->tag) == forkNum[j] &&
4784 bufHdr->tag.blockNum >= firstDelBlock[j])
4785 {
4786 InvalidateBuffer(bufHdr); /* releases spinlock */
4787 break;
4788 }
4789 }
4790 if (j >= nforks)
4792 }
4793}
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:4974
int j
Definition isn.c:78
void DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
Definition localbuf.c:665
#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 4804 of file bufmgr.c.

4805{
4806 int i;
4807 int n = 0;
4808 SMgrRelation *rels;
4809 BlockNumber (*block)[MAX_FORKNUM + 1];
4812 bool cached = true;
4813 bool use_bsearch;
4814
4815 if (nlocators == 0)
4816 return;
4817
4818 rels = palloc_array(SMgrRelation, nlocators); /* non-local relations */
4819
4820 /* If it's a local relation, it's localbuf.c's problem. */
4821 for (i = 0; i < nlocators; i++)
4822 {
4823 if (RelFileLocatorBackendIsTemp(smgr_reln[i]->smgr_rlocator))
4824 {
4825 if (smgr_reln[i]->smgr_rlocator.backend == MyProcNumber)
4826 DropRelationAllLocalBuffers(smgr_reln[i]->smgr_rlocator.locator);
4827 }
4828 else
4829 rels[n++] = smgr_reln[i];
4830 }
4831
4832 /*
4833 * If there are no non-local relations, then we're done. Release the
4834 * memory and return.
4835 */
4836 if (n == 0)
4837 {
4838 pfree(rels);
4839 return;
4840 }
4841
4842 /*
4843 * This is used to remember the number of blocks for all the relations
4844 * forks.
4845 */
4846 block = (BlockNumber (*)[MAX_FORKNUM + 1])
4847 palloc(sizeof(BlockNumber) * n * (MAX_FORKNUM + 1));
4848
4849 /*
4850 * We can avoid scanning the entire buffer pool if we know the exact size
4851 * of each of the given relation forks. See DropRelationBuffers.
4852 */
4853 for (i = 0; i < n && cached; i++)
4854 {
4855 for (int j = 0; j <= MAX_FORKNUM; j++)
4856 {
4857 /* Get the number of blocks for a relation's fork. */
4858 block[i][j] = smgrnblocks_cached(rels[i], j);
4859
4860 /* We need to only consider the relation forks that exists. */
4861 if (block[i][j] == InvalidBlockNumber)
4862 {
4863 if (!smgrexists(rels[i], j))
4864 continue;
4865 cached = false;
4866 break;
4867 }
4868
4869 /* calculate the total number of blocks to be invalidated */
4870 nBlocksToInvalidate += block[i][j];
4871 }
4872 }
4873
4874 /*
4875 * We apply the optimization iff the total number of blocks to invalidate
4876 * is below the BUF_DROP_FULL_SCAN_THRESHOLD.
4877 */
4879 {
4880 for (i = 0; i < n; i++)
4881 {
4882 for (int j = 0; j <= MAX_FORKNUM; j++)
4883 {
4884 /* ignore relation forks that doesn't exist */
4885 if (!BlockNumberIsValid(block[i][j]))
4886 continue;
4887
4888 /* drop all the buffers for a particular relation fork */
4889 FindAndDropRelationBuffers(rels[i]->smgr_rlocator.locator,
4890 j, block[i][j], 0);
4891 }
4892 }
4893
4894 pfree(block);
4895 pfree(rels);
4896 return;
4897 }
4898
4899 pfree(block);
4900 locators = palloc_array(RelFileLocator, n); /* non-local relations */
4901 for (i = 0; i < n; i++)
4902 locators[i] = rels[i]->smgr_rlocator.locator;
4903
4904 /*
4905 * For low number of relations to drop just use a simple walk through, to
4906 * save the bsearch overhead. The threshold to use is rather a guess than
4907 * an exactly determined value, as it depends on many factors (CPU and RAM
4908 * speeds, amount of shared buffers etc.).
4909 */
4911
4912 /* sort the list of rlocators if necessary */
4913 if (use_bsearch)
4915
4916 for (i = 0; i < NBuffers; i++)
4917 {
4918 RelFileLocator *rlocator = NULL;
4920
4921 /*
4922 * As in DropRelationBuffers, an unlocked precheck should be safe and
4923 * saves some cycles.
4924 */
4925
4926 if (!use_bsearch)
4927 {
4928 int j;
4929
4930 for (j = 0; j < n; j++)
4931 {
4933 {
4934 rlocator = &locators[j];
4935 break;
4936 }
4937 }
4938 }
4939 else
4940 {
4941 RelFileLocator locator;
4942
4943 locator = BufTagGetRelFileLocator(&bufHdr->tag);
4944 rlocator = bsearch(&locator,
4945 locators, n, sizeof(RelFileLocator),
4947 }
4948
4949 /* buffer doesn't belong to any of the given relfilelocators; skip it */
4950 if (rlocator == NULL)
4951 continue;
4952
4954 if (BufTagMatchesRelFileLocator(&bufHdr->tag, rlocator))
4955 InvalidateBuffer(bufHdr); /* releases spinlock */
4956 else
4958 }
4959
4960 pfree(locators);
4961 pfree(rels);
4962}
static int rlocator_comparator(const void *p1, const void *p2)
Definition bufmgr.c:7274
#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:702
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 7765 of file bufmgr.c.

7767{
7768 *buffers_evicted = 0;
7769 *buffers_skipped = 0;
7770 *buffers_flushed = 0;
7771
7772 for (int buf = 1; buf <= NBuffers; buf++)
7773 {
7774 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7776 bool buffer_flushed;
7777
7779
7781 if (!(buf_state & BM_VALID))
7782 continue;
7783
7786
7787 LockBufHdr(desc);
7788
7790 (*buffers_evicted)++;
7791 else
7792 (*buffers_skipped)++;
7793
7794 if (buffer_flushed)
7795 (*buffers_flushed)++;
7796 }
7797}
#define BM_VALID
static bool EvictUnpinnedBufferInternal(BufferDesc *desc, bool *buffer_flushed)
Definition bufmgr.c:7674
static void ReservePrivateRefCountEntry(void)
Definition bufmgr.c:309
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
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 7815 of file bufmgr.c.

7817{
7819
7820 *buffers_skipped = 0;
7821 *buffers_evicted = 0;
7822 *buffers_flushed = 0;
7823
7824 for (int buf = 1; buf <= NBuffers; buf++)
7825 {
7826 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7828 bool buffer_flushed;
7829
7831
7832 /* An unlocked precheck should be safe and saves some cycles. */
7833 if ((buf_state & BM_VALID) == 0 ||
7835 continue;
7836
7837 /* Make sure we can pin the buffer. */
7840
7841 buf_state = LockBufHdr(desc);
7842
7843 /* recheck, could have changed without the lock */
7844 if ((buf_state & BM_VALID) == 0 ||
7846 {
7847 UnlockBufHdr(desc);
7848 continue;
7849 }
7850
7852 (*buffers_evicted)++;
7853 else
7854 (*buffers_skipped)++;
7855
7856 if (buffer_flushed)
7857 (*buffers_flushed)++;
7858 }
7859}
#define RelationUsesLocalBuffers(relation)
Definition rel.h:646
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 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 974 of file bufmgr.c.

978{
979 Buffer buf;
980 uint32 extend_by = 1;
981
982 ExtendBufferedRelBy(bmr, forkNum, strategy, flags, extend_by,
983 &buf, &extend_by);
984
985 return buf;
986}
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:1006

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

1013{
1014 Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
1015 Assert(bmr.smgr == NULL || bmr.relpersistence != '\0');
1016 Assert(extend_by > 0);
1017
1018 if (bmr.relpersistence == '\0')
1019 bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
1020
1021 return ExtendBufferedRelCommon(bmr, fork, strategy, flags,
1023 buffers, extended_by);
1024}
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:2665

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

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

5446{
5447 int i;
5449
5450 for (i = 0; i < NBuffers; i++)
5451 {
5453
5455
5456 /*
5457 * As in DropRelationBuffers, an unlocked precheck should be safe and
5458 * saves some cycles.
5459 */
5460 if (bufHdr->tag.dbOid != dbid)
5461 continue;
5462
5463 /* Make sure we can handle the pin */
5466
5468 if (bufHdr->tag.dbOid == dbid &&
5470 {
5474 }
5475 else
5477 }
5478}
static void FlushUnlockedBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition bufmgr.c:4545
static void PinBuffer_Locked(BufferDesc *buf)
Definition bufmgr.c:3299
static void UnpinBuffer(BufferDesc *buf)
Definition bufmgr.c:3367
@ 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 5485 of file bufmgr.c.

5486{
5488
5489 /* currently not needed, but no fundamental reason not to support */
5490 Assert(!BufferIsLocal(buffer));
5491
5492 Assert(BufferIsPinned(buffer));
5493
5494 bufHdr = GetBufferDescriptor(buffer - 1);
5495
5496 Assert(BufferIsLockedByMe(buffer));
5497
5499}
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition bufmgr.c:4414
bool BufferIsLockedByMe(Buffer buffer)
Definition bufmgr.c:2977

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_rel_block(), and XLogReadBufferForRedoExtended().

◆ FlushRelationBuffers()

void FlushRelationBuffers ( Relation  rel)
extern

Definition at line 5081 of file bufmgr.c.

5082{
5083 int i;
5085 SMgrRelation srel = RelationGetSmgr(rel);
5086
5087 if (RelationUsesLocalBuffers(rel))
5088 {
5089 for (i = 0; i < NLocBuffer; i++)
5090 {
5092
5094 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
5095 ((buf_state = pg_atomic_read_u64(&bufHdr->state)) &
5096 (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
5097 {
5098 ErrorContextCallback errcallback;
5099
5100 /* Setup error traceback support for ereport() */
5102 errcallback.arg = bufHdr;
5103 errcallback.previous = error_context_stack;
5104 error_context_stack = &errcallback;
5105
5106 /* Make sure we can handle the pin */
5109
5110 /*
5111 * Pin/unpin mostly to make valgrind work, but it also seems
5112 * like the right thing to do.
5113 */
5114 PinLocalBuffer(bufHdr, false);
5115
5116
5117 FlushLocalBuffer(bufHdr, srel);
5118
5120
5121 /* Pop the error context stack */
5122 error_context_stack = errcallback.previous;
5123 }
5124 }
5125
5126 return;
5127 }
5128
5129 for (i = 0; i < NBuffers; i++)
5130 {
5132
5134
5135 /*
5136 * As in DropRelationBuffers, an unlocked precheck should be safe and
5137 * saves some cycles.
5138 */
5140 continue;
5141
5142 /* Make sure we can handle the pin */
5145
5147 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
5149 {
5153 }
5154 else
5156 }
5157}
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
static void local_buffer_write_error_callback(void *arg)
Definition bufmgr.c:7258
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:841
bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
Definition localbuf.c:805
int NLocBuffer
Definition localbuf.c:45
static SMgrRelation RelationGetSmgr(Relation rel)
Definition rel.h:576
struct ErrorContextCallback * previous
Definition elog.h:297
void(* callback)(void *arg)
Definition elog.h:298

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

5170{
5171 int i;
5173 bool use_bsearch;
5174
5175 if (nrels == 0)
5176 return;
5177
5178 /* fill-in array for qsort */
5180
5181 for (i = 0; i < nrels; i++)
5182 {
5183 Assert(!RelFileLocatorBackendIsTemp(smgrs[i]->smgr_rlocator));
5184
5185 srels[i].rlocator = smgrs[i]->smgr_rlocator.locator;
5186 srels[i].srel = smgrs[i];
5187 }
5188
5189 /*
5190 * Save the bsearch overhead for low number of relations to sync. See
5191 * DropRelationsAllBuffers for details.
5192 */
5194
5195 /* sort the list of SMgrRelations if necessary */
5196 if (use_bsearch)
5197 qsort(srels, nrels, sizeof(SMgrSortArray), rlocator_comparator);
5198
5199 for (i = 0; i < NBuffers; i++)
5200 {
5204
5205 /*
5206 * As in DropRelationBuffers, an unlocked precheck should be safe and
5207 * saves some cycles.
5208 */
5209
5210 if (!use_bsearch)
5211 {
5212 int j;
5213
5214 for (j = 0; j < nrels; j++)
5215 {
5216 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &srels[j].rlocator))
5217 {
5218 srelent = &srels[j];
5219 break;
5220 }
5221 }
5222 }
5223 else
5224 {
5225 RelFileLocator rlocator;
5226
5227 rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
5228 srelent = bsearch(&rlocator,
5229 srels, nrels, sizeof(SMgrSortArray),
5231 }
5232
5233 /* buffer doesn't belong to any of the given relfilelocators; skip it */
5234 if (srelent == NULL)
5235 continue;
5236
5237 /* Make sure we can handle the pin */
5240
5242 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &srelent->rlocator) &&
5244 {
5248 }
5249 else
5251 }
5252
5253 pfree(srels);
5254}

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 643 of file freelist.c.

644{
645 /* don't crash if called on a "default" strategy */
646 if (strategy != NULL)
647 pfree(strategy);
648}

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 461 of file freelist.c.

462{
463 int ring_size_kb;
464
465 /*
466 * Select ring size to use. See buffer/README for rationales.
467 *
468 * Note: if you change the ring size for BAS_BULKREAD, see also
469 * SYNC_SCAN_REPORT_INTERVAL in access/heap/syncscan.c.
470 */
471 switch (btype)
472 {
473 case BAS_NORMAL:
474 /* if someone asks for NORMAL, just give 'em a "default" object */
475 return NULL;
476
477 case BAS_BULKREAD:
478 {
479 int ring_max_kb;
480
481 /*
482 * The ring always needs to be large enough to allow some
483 * separation in time between providing a buffer to the user
484 * of the strategy and that buffer being reused. Otherwise the
485 * user's pin will prevent reuse of the buffer, even without
486 * concurrent activity.
487 *
488 * We also need to ensure the ring always is large enough for
489 * SYNC_SCAN_REPORT_INTERVAL, as noted above.
490 *
491 * Thus we start out a minimal size and increase the size
492 * further if appropriate.
493 */
494 ring_size_kb = 256;
495
496 /*
497 * There's no point in a larger ring if we won't be allowed to
498 * pin sufficiently many buffers. But we never limit to less
499 * than the minimal size above.
500 */
501 ring_max_kb = GetPinLimit() * (BLCKSZ / 1024);
503
504 /*
505 * We would like the ring to additionally have space for the
506 * configured degree of IO concurrency. While being read in,
507 * buffers can obviously not yet be reused.
508 *
509 * Each IO can be up to io_combine_limit blocks large, and we
510 * want to start up to effective_io_concurrency IOs.
511 *
512 * Note that effective_io_concurrency may be 0, which disables
513 * AIO.
514 */
515 ring_size_kb += (BLCKSZ / 1024) *
517
520 break;
521 }
522 case BAS_BULKWRITE:
523 ring_size_kb = 16 * 1024;
524 break;
525 case BAS_VACUUM:
526 ring_size_kb = 2048;
527 break;
528
529 default:
530 elog(ERROR, "unrecognized buffer access strategy: %d",
531 (int) btype);
532 return NULL; /* keep compiler quiet */
533 }
534
536}
int effective_io_concurrency
Definition bufmgr.c:200
int io_combine_limit
Definition bufmgr.c:215
uint32 GetPinLimit(void)
Definition bufmgr.c:2609
#define Max(x, y)
Definition c.h:1087
BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype, int ring_size_kb)
Definition freelist.c:546

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(), 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 586 of file freelist.c.

587{
588 if (strategy == NULL)
589 return 0;
590
591 return strategy->nbuffers;
592}

References fb(), and BufferAccessStrategyData::nbuffers.

Referenced by parallel_vacuum_init().

◆ GetAccessStrategyPinLimit()

int GetAccessStrategyPinLimit ( BufferAccessStrategy  strategy)
extern

Definition at line 609 of file freelist.c.

610{
611 if (strategy == NULL)
612 return NBuffers;
613
614 switch (strategy->btype)
615 {
616 case BAS_BULKREAD:
617
618 /*
619 * Since BAS_BULKREAD uses StrategyRejectBuffer(), dirty buffers
620 * shouldn't be a problem and the caller is free to pin up to the
621 * entire ring at once.
622 */
623 return strategy->nbuffers;
624
625 default:
626
627 /*
628 * Tell caller not to pin more than half the buffers in the ring.
629 * This is a trade-off between look ahead distance and deferring
630 * writeback and associated WAL traffic.
631 */
632 return strategy->nbuffers / 2;
633 }
634}
BufferAccessStrategyType btype
Definition freelist.c:67

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 546 of file freelist.c.

547{
548 int ring_buffers;
549 BufferAccessStrategy strategy;
550
551 Assert(ring_size_kb >= 0);
552
553 /* Figure out how many buffers ring_size_kb is */
554 ring_buffers = ring_size_kb / (BLCKSZ / 1024);
555
556 /* 0 means unlimited, so no BufferAccessStrategy required */
557 if (ring_buffers == 0)
558 return NULL;
559
560 /* Cap to 1/8th of shared_buffers */
562
563 /* NBuffers should never be less than 16, so this shouldn't happen */
564 Assert(ring_buffers > 0);
565
566 /* Allocate the object and initialize all elements to zeroes */
567 strategy = (BufferAccessStrategy)
569 ring_buffers * sizeof(Buffer));
570
571 /* Set fields that don't start out zero */
572 strategy->btype = btype;
573 strategy->nbuffers = ring_buffers;
574
575 return strategy;
576}
struct BufferAccessStrategyData * BufferAccessStrategy
Definition buf.h:44
#define Min(x, y)
Definition c.h:1093
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 315 of file localbuf.c.

316{
319}
int num_temp_buffers
Definition guc_tables.c:562
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 2621 of file bufmgr.c.

2622{
2624
2625 /*
2626 * We get the number of "overflowed" pins for free, but don't know the
2627 * number of pins in PrivateRefCountArray. The cost of calculating that
2628 * exactly doesn't seem worth it, so just assume the max.
2629 */
2631
2632 /* Is this backend already holding more than its fair share? */
2634 return 0;
2635
2637}
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 307 of file localbuf.c.

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

References num_temp_buffers.

Referenced by read_stream_begin_impl().

◆ GetPinLimit()

uint32 GetPinLimit ( void  )
extern

Definition at line 2609 of file bufmgr.c.

2610{
2611 return MaxProportionalPins;
2612}

References MaxProportionalPins.

Referenced by GetAccessStrategy(), and read_stream_begin_impl().

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )
extern

Definition at line 6684 of file bufmgr.c.

6685{
6687
6688 /*
6689 * If we get woken slowly then it's possible that the Startup process was
6690 * already woken by other backends before we got here. Also possible that
6691 * we get here by multiple interrupts or interrupts at inappropriate
6692 * times, so make sure we do nothing if the bufid is not set.
6693 */
6694 if (bufid < 0)
6695 return false;
6696
6697 if (GetPrivateRefCount(bufid + 1) > 0)
6698 return true;
6699
6700 return false;
6701}
int GetStartupBufferPinWaitBufId(void)
Definition proc.c:759

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

Referenced by CheckRecoveryConflictDeadlock(), and ProcessRecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)
extern

Definition at line 5537 of file bufmgr.c.

5538{
5539 Assert(BufferIsPinned(buffer));
5541 if (BufferIsLocal(buffer))
5542 LocalRefCount[-buffer - 1]++;
5543 else
5544 {
5546
5547 ref = GetPrivateRefCountEntry(buffer, true);
5548 Assert(ref != NULL);
5549 ref->data.refcount++;
5550 }
5552}
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 4127 of file bufmgr.c.

4128{
4129 /*
4130 * An advisory limit on the number of pins each backend should hold, based
4131 * on shared_buffers and the maximum number of connections possible.
4132 * That's very pessimistic, but outside toy-sized shared_buffers it should
4133 * allow plenty of pins. LimitAdditionalPins() and
4134 * GetAdditionalPinLimit() can be used to check the remaining balance.
4135 */
4137
4140
4142
4143 /*
4144 * AtProcExit_Buffers needs LWLock access, and thereby has to be called at
4145 * the corresponding phase of backend shutdown.
4146 */
4147 Assert(MyProc != NULL);
4149}
static Buffer PrivateRefCountArrayKeys[REFCOUNT_ARRAY_ENTRIES]
Definition bufmgr.c:263
static void AtProcExit_Buffers(int code, Datum arg)
Definition bufmgr.c:4156
static refcount_hash * PrivateRefCountHash
Definition bufmgr.c:265
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition bufmgr.c:264
int MaxBackends
Definition globals.c:146
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:524
PGPROC * MyProc
Definition proc.c:68

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

6769{
6772
6773 Assert(BufferIsValid(buffer));
6774
6775 /* see AIO related comment in LockBufferForCleanup() */
6776
6777 if (BufferIsLocal(buffer))
6778 {
6779 /* There should be exactly one pin */
6780 if (LocalRefCount[-buffer - 1] != 1)
6781 return false;
6782 /* Nobody else to wait for */
6783 return true;
6784 }
6785
6786 /* There should be exactly one local pin */
6787 if (GetPrivateRefCount(buffer) != 1)
6788 return false;
6789
6790 bufHdr = GetBufferDescriptor(buffer - 1);
6791
6792 /* caller must hold exclusive lock on buffer */
6794
6796
6799 {
6800 /* pincount is OK. */
6802 return true;
6803 }
6804
6806 return false;
6807}

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

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

References fb(), NLocalPinnedBuffers, and num_temp_buffers.

Referenced by ExtendBufferedRelLocal().

◆ LimitAdditionalPins()

void LimitAdditionalPins ( uint32 additional_pins)
extern

Definition at line 2647 of file bufmgr.c.

2648{
2649 uint32 limit;
2650
2651 if (*additional_pins <= 1)
2652 return;
2653
2654 limit = GetAdditionalPinLimit();
2655 limit = Max(limit, 1);
2656 if (limit < *additional_pins)
2657 *additional_pins = limit;
2658}
uint32 GetAdditionalPinLimit(void)
Definition bufmgr.c:2621

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

Referenced by ExtendBufferedRelShared().

◆ LockBuffer()

static void LockBuffer ( Buffer  buffer,
BufferLockMode  mode 
)
inlinestatic

Definition at line 332 of file bufmgr.h.

333{
335 UnlockBuffer(buffer);
336 else
337 LockBufferInternal(buffer, mode);
338}
void UnlockBuffer(Buffer buffer)
Definition bufmgr.c:6425
void LockBufferInternal(Buffer buffer, BufferLockMode mode)
Definition bufmgr.c:6441

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_opt(), heap_prepare_pagescan(), heap_update(), heap_xlog_visible(), heapam_index_build_range_scan(), heapam_index_fetch_tuple(), heapam_index_validate_scan(), heapam_relation_copy_for_cluster(), heapam_scan_analyze_next_block(), heapam_scan_sample_next_tuple(), heapam_tuple_satisfies_snapshot(), heapgettup(), initBloomState(), invalidate_rel_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(), read_seq_tuple(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), ScanSourceDatabasePgClass(), shiftList(), spgdoinsert(), spgGetCache(), SpGistNewBuffer(), spgprocesspending(), spgvacuumpage(), spgWalk(), startScanEntry(), statapprox_heap(), summarize_range(), UnlockReleaseBuffer(), update_most_recent_deletion_info(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_prepare_truncate(), visibilitymap_set(), vm_readbuf(), XLogReadBufferForRedoExtended(), XLogRecordPageWithFreeSpace(), and ZeroAndLockBuffer().

◆ LockBufferForCleanup()

void LockBufferForCleanup ( Buffer  buffer)
extern

Definition at line 6537 of file bufmgr.c.

6538{
6540 TimestampTz waitStart = 0;
6541 bool waiting = false;
6542 bool logged_recovery_conflict = false;
6543
6544 Assert(BufferIsPinned(buffer));
6546
6548
6549 /*
6550 * We do not yet need to be worried about in-progress AIOs holding a pin,
6551 * as we, so far, only support doing reads via AIO and this function can
6552 * only be called once the buffer is valid (i.e. no read can be in
6553 * flight).
6554 */
6555
6556 /* Nobody else to wait for */
6557 if (BufferIsLocal(buffer))
6558 return;
6559
6560 bufHdr = GetBufferDescriptor(buffer - 1);
6561
6562 for (;;)
6563 {
6565 uint64 unset_bits = 0;
6566
6567 /* Try to acquire lock */
6570
6573 {
6574 /* Successfully acquired exclusive lock with pincount 1 */
6576
6577 /*
6578 * Emit the log message if recovery conflict on buffer pin was
6579 * resolved but the startup process waited longer than
6580 * deadlock_timeout for it.
6581 */
6584 waitStart, GetCurrentTimestamp(),
6585 NULL, false);
6586
6587 if (waiting)
6588 {
6589 /* reset ps display to remove the suffix if we added one */
6591 waiting = false;
6592 }
6593 return;
6594 }
6595 /* Failed, so mark myself as waiting for pincount 1 */
6597 {
6600 elog(ERROR, "multiple backends attempting to wait for pincount 1");
6601 }
6602 bufHdr->wait_backend_pgprocno = MyProcNumber;
6606 0);
6608
6609 /* Wait to be signaled by UnpinBuffer() */
6610 if (InHotStandby)
6611 {
6612 if (!waiting)
6613 {
6614 /* adjust the process title to indicate that it's waiting */
6615 set_ps_display_suffix("waiting");
6616 waiting = true;
6617 }
6618
6619 /*
6620 * Emit the log message if the startup process is waiting longer
6621 * than deadlock_timeout for recovery conflict on buffer pin.
6622 *
6623 * Skip this if first time through because the startup process has
6624 * not started waiting yet in this case. So, the wait start
6625 * timestamp is set after this logic.
6626 */
6627 if (waitStart != 0 && !logged_recovery_conflict)
6628 {
6630
6631 if (TimestampDifferenceExceeds(waitStart, now,
6633 {
6635 waitStart, now, NULL, true);
6637 }
6638 }
6639
6640 /*
6641 * Set the wait start timestamp if logging is enabled and first
6642 * time through.
6643 */
6644 if (log_recovery_conflict_waits && waitStart == 0)
6645 waitStart = GetCurrentTimestamp();
6646
6647 /* Publish the bufid that Startup process waits on */
6648 SetStartupBufferPinWaitBufId(buffer - 1);
6649 /* Set alarm and then wait to be signaled by UnpinBuffer() */
6651 /* Reset the published bufid */
6653 }
6654 else
6656
6657 /*
6658 * Remove flag marking us as waiter. Normally this will not be set
6659 * anymore, but ProcWaitForSignal() can return for other signals as
6660 * well. We take care to only reset the flag if we're the waiter, as
6661 * theoretically another backend could have started waiting. That's
6662 * impossible with the current usages due to table level locking, but
6663 * better be safe.
6664 */
6666 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
6667 bufHdr->wait_backend_pgprocno == MyProcNumber)
6669
6671 0, unset_bits,
6672 0);
6673
6675 /* Loop back and try again */
6676 }
6677}
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:6504
static BufferDesc * PinCountWaitBuf
Definition bufmgr.c:228
int64 TimestampTz
Definition timestamp.h:39
void set_ps_display_remove_suffix(void)
Definition ps_status.c:439
void set_ps_display_suffix(const char *suffix)
Definition ps_status.c:387
int DeadlockTimeout
Definition proc.c:59
void SetStartupBufferPinWaitBufId(int bufid)
Definition proc.c:747
void ProcWaitForSignal(uint32 wait_event_info)
Definition proc.c:2002
void ResolveRecoveryConflictWithBufferPin(void)
Definition standby.c:794
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:46
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 6441 of file bufmgr.c.

6442{
6444
6445 /*
6446 * We can't wait if we haven't got a PGPROC. This should only occur
6447 * during bootstrap or shared memory initialization. Put an Assert here
6448 * to catch unsafe coding practices.
6449 */
6451
6452 /* handled in LockBuffer() wrapper */
6454
6455 Assert(BufferIsPinned(buffer));
6456 if (BufferIsLocal(buffer))
6457 return; /* local buffers need no lock */
6458
6459 buf_hdr = GetBufferDescriptor(buffer - 1);
6460
6461 /*
6462 * Test the most frequent lock modes first. While a switch (mode) would be
6463 * nice, at least gcc generates considerably worse code for it.
6464 *
6465 * Call BufferLockAcquire() with a constant argument for mode, to generate
6466 * more efficient code for the different lock modes.
6467 */
6468 if (mode == BUFFER_LOCK_SHARE)
6470 else if (mode == BUFFER_LOCK_EXCLUSIVE)
6474 else
6475 elog(ERROR, "unrecognized buffer lock mode: %d", mode);
6476}
static void BufferLockAcquire(Buffer buffer, BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:5765
bool IsUnderPostmaster
Definition globals.c:120

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

3064{
3068
3069 if (!BufferIsValid(buffer))
3070 elog(ERROR, "bad buffer ID: %d", buffer);
3071
3072 if (BufferIsLocal(buffer))
3073 {
3074 MarkLocalBufferDirty(buffer);
3075 return;
3076 }
3077
3078 bufHdr = GetBufferDescriptor(buffer - 1);
3079
3080 Assert(BufferIsPinned(buffer));
3082
3083 /*
3084 * NB: We have to wait for the buffer header spinlock to be not held, as
3085 * TerminateBufferIO() relies on the spinlock.
3086 */
3088 for (;;)
3089 {
3092
3094
3097
3099 buf_state))
3100 break;
3101 }
3102
3103 /*
3104 * If the buffer was not dirty already, do vacuum accounting.
3105 */
3106 if (!(old_buf_state & BM_DIRTY))
3107 {
3109 if (VacuumCostActive)
3111 }
3112}
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:7349
bool VacuumCostActive
Definition globals.c:158
int VacuumCostBalance
Definition globals.c:157
int VacuumCostPageDirty
Definition globals.c:153
BufferUsage pgBufferUsage
Definition instrument.c:20
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(), heap_xlog_visible(), lazy_scan_new_or_empty(), lazy_scan_prune(), lazy_vacuum_heap_page(), log_newpage_range(), MarkDirtyUnpinnedBufferInternal(), moveLeafs(), nextval_internal(), 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(), visibilitymap_set_vmbits(), writeListPage(), and XLogReadBufferForRedoExtended().

◆ MarkBufferDirtyHint()

◆ MarkDirtyAllUnpinnedBuffers()

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

Definition at line 8015 of file bufmgr.c.

8018{
8019 *buffers_dirtied = 0;
8021 *buffers_skipped = 0;
8022
8023 for (int buf = 1; buf <= NBuffers; buf++)
8024 {
8025 BufferDesc *desc = GetBufferDescriptor(buf - 1);
8028
8030
8032 if (!(buf_state & BM_VALID))
8033 continue;
8034
8037
8038 LockBufHdr(desc);
8039
8041 (*buffers_dirtied)++;
8042 else if (buffer_already_dirty)
8043 (*buffers_already_dirty)++;
8044 else
8045 (*buffers_skipped)++;
8046 }
8047}
static bool MarkDirtyUnpinnedBufferInternal(Buffer buf, BufferDesc *desc, bool *buffer_already_dirty)
Definition bufmgr.c:7866

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

7962{
7964
7965 *buffers_dirtied = 0;
7967 *buffers_skipped = 0;
7968
7969 for (int buf = 1; buf <= NBuffers; buf++)
7970 {
7971 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7974
7976
7977 /* An unlocked precheck should be safe and saves some cycles. */
7978 if ((buf_state & BM_VALID) == 0 ||
7980 continue;
7981
7982 /* Make sure we can pin the buffer. */
7985
7986 buf_state = LockBufHdr(desc);
7987
7988 /* recheck, could have changed without the lock */
7989 if ((buf_state & BM_VALID) == 0 ||
7991 {
7992 UnlockBufHdr(desc);
7993 continue;
7994 }
7995
7997 (*buffers_dirtied)++;
7998 else if (buffer_already_dirty)
7999 (*buffers_already_dirty)++;
8000 else
8001 (*buffers_skipped)++;
8002 }
8003}

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

7923{
7924 BufferDesc *desc;
7925 bool buffer_dirtied = false;
7926
7928
7929 /* Make sure we can pin the buffer. */
7932
7933 desc = GetBufferDescriptor(buf - 1);
7934 LockBufHdr(desc);
7935
7937 /* Both can not be true at the same time */
7939
7940 return buffer_dirtied;
7941}

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

783{
785 Assert(BlockNumberIsValid(blockNum));
786
788 {
789 /* see comments in ReadBufferExtended */
793 errmsg("cannot access temporary tables of other sessions")));
794
795 /* pass it off to localbuf.c */
796 return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
797 }
798 else
799 {
800 /* pass it to the shared buffer version */
801 return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
802 }
803}
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition bufmgr.c:692
int errcode(int sqlerrcode)
Definition elog.c:874
#define ereport(elevel,...)
Definition elog.h:150
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition localbuf.c:72
static char * errmsg
#define RELATION_IS_OTHER_TEMP(relation)
Definition rel.h:667
#define RelationIsValid(relation)
Definition rel.h:489

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

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

◆ PrefetchSharedBuffer()

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

Definition at line 692 of file bufmgr.c.

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

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

Referenced by PrefetchBuffer(), and XLogPrefetcherNextBlock().

◆ ReadBuffer()

Buffer ReadBuffer ( Relation  reln,
BlockNumber  blockNum 
)
extern

Definition at line 874 of file bufmgr.c.

875{
877}
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition bufmgr.c:921

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

Referenced by _bt_allocbuf(), _bt_getbuf(), _bt_search_insert(), _hash_getbuf(), _hash_getbuf_with_condlock_cleanup(), blbulkdelete(), blinsert(), BloomNewBuffer(), brin_getinsertbuffer(), brinGetStats(), brinGetTupleForHeapBlock(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), ginFindLeafPage(), ginFindParents(), ginGetStats(), ginHeapTupleFastInsert(), ginInsertCleanup(), GinNewBuffer(), ginStepRight(), ginUpdateStats(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistfixsplit(), gistGetMaxLevel(), gistkillitems(), gistNewBuffer(), gistProcessItup(), gistScanPage(), heap_abort_speculative(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_force_common(), heap_get_latest_tid(), heap_index_delete_tuples(), heap_lock_tuple(), heap_update(), initBloomState(), pg_visibility(), pgstatginindex_internal(), read_seq_tuple(), RelationGetBufferForTuple(), ReleaseAndReadBuffer(), revmap_get_buffer(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), shiftList(), spgdoinsert(), spgGetCache(), SpGistGetBuffer(), SpGistNewBuffer(), SpGistUpdateMetaPage(), and spgWalk().

◆ ReadBufferExtended()

Buffer ReadBufferExtended ( Relation  reln,
ForkNumber  forkNum,
BlockNumber  blockNum,
ReadBufferMode  mode,
BufferAccessStrategy  strategy 
)
externinline

Definition at line 921 of file bufmgr.c.

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

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(), 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 958 of file bufmgr.c.

961{
962 SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
963
964 return ReadBuffer_common(NULL, smgr,
966 forkNum, blockNum,
967 mode, strategy);
968}

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

815{
817 BufferTag tag;
819
820 Assert(BufferIsValid(recent_buffer));
821
824 InitBufferTag(&tag, &rlocator, forkNum, blockNum);
825
826 if (BufferIsLocal(recent_buffer))
827 {
828 int b = -recent_buffer - 1;
829
832
833 /* Is it still valid and holding the right tag? */
834 if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
835 {
836 PinLocalBuffer(bufHdr, true);
837
839
840 return true;
841 }
842 }
843 else
844 {
845 bufHdr = GetBufferDescriptor(recent_buffer - 1);
846
847 /*
848 * Is it still valid and holding the right tag? We do an unlocked tag
849 * comparison first, to make it unlikely that we'll increment the
850 * usage counter of the wrong buffer, if someone calls us with a very
851 * out of date recent_buffer. Then we'll check it again if we get the
852 * pin.
853 */
854 if (BufferTagsEqual(&tag, &bufHdr->tag) &&
855 PinBuffer(bufHdr, NULL, true))
856 {
857 if (BufferTagsEqual(&tag, &bufHdr->tag))
858 {
860 return true;
861 }
863 }
864 }
865
866 return false;
867}
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
static bool PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy, bool skip_if_not_valid)
Definition bufmgr.c:3188
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_rel_block(), and XLogReadBufferExtended().

◆ RelationGetNumberOfBlocksInFork()

BlockNumber RelationGetNumberOfBlocksInFork ( Relation  relation,
ForkNumber  forkNum 
)
extern

Definition at line 4564 of file bufmgr.c.

4565{
4566 if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
4567 {
4568 /*
4569 * Not every table AM uses BLCKSZ wide fixed size blocks. Therefore
4570 * tableam returns the size in bytes - but for the purpose of this
4571 * routine, we want the number of blocks. Therefore divide, rounding
4572 * up.
4573 */
4575
4576 szbytes = table_relation_size(relation, forkNum);
4577
4578 return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
4579 }
4580 else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
4581 {
4582 return smgrnblocks(RelationGetSmgr(relation), forkNum);
4583 }
4584 else
4585 Assert(false);
4586
4587 return 0; /* keep compiler quiet */
4588}
Form_pg_class rd_rel
Definition rel.h:111
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition tableam.h:1858

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

◆ ReleaseAndReadBuffer()

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

Definition at line 3128 of file bufmgr.c.

3131{
3132 ForkNumber forkNum = MAIN_FORKNUM;
3134
3135 if (BufferIsValid(buffer))
3136 {
3137 Assert(BufferIsPinned(buffer));
3138 if (BufferIsLocal(buffer))
3139 {
3140 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
3141 if (bufHdr->tag.blockNum == blockNum &&
3142 BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
3143 BufTagGetForkNum(&bufHdr->tag) == forkNum)
3144 return buffer;
3145 UnpinLocalBuffer(buffer);
3146 }
3147 else
3148 {
3149 bufHdr = GetBufferDescriptor(buffer - 1);
3150 /* we have pin, so it's ok to examine tag without spinlock */
3151 if (bufHdr->tag.blockNum == blockNum &&
3152 BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
3153 BufTagGetForkNum(&bufHdr->tag) == forkNum)
3154 return buffer;
3156 }
3157 }
3158
3159 return ReadBuffer(relation, blockNum);
3160}
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition bufmgr.c:874

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

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

◆ ReleaseBuffer()

void ReleaseBuffer ( Buffer  buffer)
extern

Definition at line 5505 of file bufmgr.c.

5506{
5507 if (!BufferIsValid(buffer))
5508 elog(ERROR, "bad buffer ID: %d", buffer);
5509
5510 if (BufferIsLocal(buffer))
5511 UnpinLocalBuffer(buffer);
5512 else
5513 UnpinBuffer(GetBufferDescriptor(buffer - 1));
5514}

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

Referenced by _bt_allocbuf(), _bt_pagedel(), _bt_relbuf(), _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(), fsm_vacuum_page(), get_actual_variable_endpoint(), get_raw_page_internal(), GetRecordedFreeSpace(), gin_check_parent_keys_consistency(), gin_check_posting_tree_parent_keys_consistency(), 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(), heap_xlog_visible(), heapam_index_fetch_reset(), heapam_scan_sample_next_block(), heapam_tuple_lock(), heapgettup(), heapgettup_pagemode(), invalidate_rel_block(), lazy_scan_heap(), lazy_vacuum_heap_rel(), modify_rel_block(), pg_prewarm(), pg_visibility(), pg_visibility_map(), pgstatindex_impl(), read_rel_block_ll(), read_stream_reset(), ReadBufferBI(), RelationAddBlocks(), RelationGetBufferForTuple(), 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(), UnlockReleaseBuffer(), 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 1618 of file bufmgr.c.

1622{
1623 int nblocks = 1;
1624 bool result;
1625
1626 result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags,
1627 false /* single block, no forwarding */ );
1628 Assert(nblocks == 1); /* single block can't be short */
1629
1630 return result;
1631}
static pg_attribute_always_inline bool StartReadBuffersImpl(ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, int flags, bool allow_forwarding)
Definition bufmgr.c:1372

References Assert, PrivateRefCountEntry::buffer, 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 1599 of file bufmgr.c.

1604{
1605 return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags,
1606 true /* expect forwarded buffers */ );
1607}

References StartReadBuffersImpl().

Referenced by read_stream_start_pending_read().

◆ UnlockBuffer()

void UnlockBuffer ( Buffer  buffer)
extern

Definition at line 6425 of file bufmgr.c.

6426{
6428
6429 Assert(BufferIsPinned(buffer));
6430 if (BufferIsLocal(buffer))
6431 return; /* local buffers need no lock */
6432
6433 buf_hdr = GetBufferDescriptor(buffer - 1);
6434 BufferLockUnlock(buffer, buf_hdr);
6435}
static void BufferLockUnlock(Buffer buffer, BufferDesc *buf_hdr)
Definition bufmgr.c:5881

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

Referenced by LockBuffer().

◆ UnlockBuffers()

void UnlockBuffers ( void  )
extern

Definition at line 5719 of file bufmgr.c.

5720{
5722
5723 if (buf)
5724 {
5726 uint64 unset_bits = 0;
5727
5729
5730 /*
5731 * Don't complain if flag bit not set; it could have been reset but we
5732 * got a cancel/die interrupt before getting the signal.
5733 */
5734 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5735 buf->wait_backend_pgprocno == MyProcNumber)
5737
5739 0, unset_bits,
5740 0);
5741
5743 }
5744}

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

5523{
5525 ReleaseBuffer(buffer);
5526}

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

Referenced by _bt_clear_incomplete_split(), _bt_restore_meta(), _hash_relbuf(), allocNewBuffer(), AlterSequence(), blbulkdelete(), blgetbitmap(), blinsert(), BloomInitMetapage(), blvacuumcleanup(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinbuild(), brinbuildempty(), brinGetStats(), brinRevmapDesummarizeRange(), bt_metap(), bt_multi_page_stats(), bt_page_items_internal(), bt_page_stats_internal(), bt_recheck_sibling_links(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), collect_corrupt_items(), collect_visibility_data(), count_nondeletable_pages(), createPostingTree(), doPickSplit(), entryLoadMoreItems(), fill_seq_fork_with_data(), flushCachedPage(), FreeSpaceMapPrepareTruncateRel(), fsm_search(), fsm_set_and_search(), generic_redo(), 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_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(), heap_xlog_visible(), heapam_scan_analyze_next_tuple(), initBloomState(), lazy_scan_heap(), lazy_scan_new_or_empty(), lazy_vacuum_heap_rel(), log_newpage_range(), moveLeafs(), nextval_internal(), palloc_btree_page(), pg_get_sequence_data(), pg_sequence_last_value(), pg_visibility(), pgstat_gist_page(), pgstat_heap(), pgstatginindex_internal(), pgstathashindex(), pgstatindex_impl(), 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()

void WaitReadBuffers ( ReadBuffersOperation operation)
extern

Definition at line 1742 of file bufmgr.c.

1743{
1744 PgAioReturn *aio_ret = &operation->io_return;
1747
1748 if (operation->persistence == RELPERSISTENCE_TEMP)
1749 {
1752 }
1753 else
1754 {
1757 }
1758
1759 /*
1760 * If we get here without an IO operation having been issued, the
1761 * io_method == IOMETHOD_SYNC path must have been used. Otherwise the
1762 * caller should not have called WaitReadBuffers().
1763 *
1764 * In the case of IOMETHOD_SYNC, we start - as we used to before the
1765 * introducing of AIO - the IO in WaitReadBuffers(). This is done as part
1766 * of the retry logic below, no extra code is required.
1767 *
1768 * This path is expected to eventually go away.
1769 */
1770 if (!pgaio_wref_valid(&operation->io_wref) && io_method != IOMETHOD_SYNC)
1771 elog(ERROR, "waiting for read operation that didn't read");
1772
1773 /*
1774 * To handle partial reads, and IOMETHOD_SYNC, we re-issue IO until we're
1775 * done. We may need multiple retries, not just because we could get
1776 * multiple partial reads, but also because some of the remaining
1777 * to-be-read buffers may have been read in by other backends, limiting
1778 * the IO size.
1779 */
1780 while (true)
1781 {
1783
1784 CheckReadBuffersOperation(operation, false);
1785
1786 /*
1787 * If there is an IO associated with the operation, we may need to
1788 * wait for it.
1789 */
1790 if (pgaio_wref_valid(&operation->io_wref))
1791 {
1792 /*
1793 * Track the time spent waiting for the IO to complete. As
1794 * tracking a wait even if we don't actually need to wait
1795 *
1796 * a) is not cheap, due to the timestamping overhead
1797 *
1798 * b) reports some time as waiting, even if we never waited
1799 *
1800 * we first check if we already know the IO is complete.
1801 */
1802 if (aio_ret->result.status == PGAIO_RS_UNKNOWN &&
1803 !pgaio_wref_check_done(&operation->io_wref))
1804 {
1806
1807 pgaio_wref_wait(&operation->io_wref);
1808
1809 /*
1810 * The IO operation itself was already counted earlier, in
1811 * AsyncReadBuffers(), this just accounts for the wait time.
1812 */
1814 io_start, 0, 0);
1815 }
1816 else
1817 {
1818 Assert(pgaio_wref_check_done(&operation->io_wref));
1819 }
1820
1821 /*
1822 * We now are sure the IO completed. Check the results. This
1823 * includes reporting on errors if there were any.
1824 */
1825 ProcessReadBuffersResult(operation);
1826 }
1827
1828 /*
1829 * Most of the time, the one IO we already started, will read in
1830 * everything. But we need to deal with partial reads and buffers not
1831 * needing IO anymore.
1832 */
1833 if (operation->nblocks_done == operation->nblocks)
1834 break;
1835
1837
1838 /*
1839 * This may only complete the IO partially, either because some
1840 * buffers were already valid, or because of a partial read.
1841 *
1842 * NB: In contrast to after the AsyncReadBuffers() call in
1843 * StartReadBuffers(), we do *not* reduce
1844 * ReadBuffersOperation->nblocks here, callers expect the full
1845 * operation to be completed at this point (as more operations may
1846 * have been queued).
1847 */
1849 }
1850
1851 CheckReadBuffersOperation(operation, true);
1852
1853 /* NB: READ_DONE tracepoint was already executed in completion callback */
1854}
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:1637
static void ProcessReadBuffersResult(ReadBuffersOperation *operation)
Definition bufmgr.c:1703
static bool AsyncReadBuffers(ReadBuffersOperation *operation, int *nblocks_progress)
Definition bufmgr.c:1874
IOContext IOContextForStrategy(BufferAccessStrategy strategy)
Definition freelist.c:747
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
PgAioWaitRef io_wref
Definition bufmgr.h:150
BufferAccessStrategy strategy
Definition bufmgr.h:138
PgAioReturn io_return
Definition bufmgr.h:151

References Assert, AsyncReadBuffers(), CHECK_FOR_INTERRUPTS, CheckReadBuffersOperation(), elog, ERROR, fb(), io_method, ReadBuffersOperation::io_return, ReadBuffersOperation::io_wref, IOCONTEXT_NORMAL, IOContextForStrategy(), IOMETHOD_SYNC, IOOBJECT_RELATION, IOOBJECT_TEMP_RELATION, IOOP_READ, ReadBuffersOperation::nblocks, ReadBuffersOperation::nblocks_done, ReadBuffersOperation::persistence, PGAIO_RS_UNKNOWN, pgaio_wref_check_done(), pgaio_wref_valid(), pgaio_wref_wait(), pgstat_count_io_op_time(), pgstat_prepare_io_time(), ProcessReadBuffersResult(), ReadBuffersOperation::strategy, and track_io_timing.

Referenced by 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 8723 of file bufmgr.c.

8723 {
8724 .stage = local_buffer_readv_stage,
8725
8726 /*
8727 * Note that this, in contrast to the shared_buffers case, uses
8728 * complete_local, as only the issuing backend has access to the required
8729 * datastructures. This is important in case the IO completion may be
8730 * consumed incidentally by another backend.
8731 */
8732 .complete_local = local_buffer_readv_complete,
8733 .report = buffer_readv_report,
8734};
static PgAioResult local_buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8707
static void local_buffer_readv_stage(PgAioHandle *ioh, uint8 cb_data)
Definition bufmgr.c:8701
static void buffer_readv_report(PgAioResult result, const PgAioTargetData *td, int elevel)
Definition bufmgr.c:8555

◆ aio_shared_buffer_readv_cb

PGDLLIMPORT const PgAioHandleCallbacks aio_shared_buffer_readv_cb
extern

Definition at line 8714 of file bufmgr.c.

8714 {
8716 .complete_shared = shared_buffer_readv_complete,
8717 /* need a local callback to report checksum failures */
8718 .complete_local = shared_buffer_readv_complete_local,
8719 .report = buffer_readv_report,
8720};
static PgAioResult shared_buffer_readv_complete_local(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8670
static void shared_buffer_readv_stage(PgAioHandle *ioh, uint8 cb_data)
Definition bufmgr.c:8650
static PgAioResult shared_buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8656

◆ backend_flush_after

PGDLLIMPORT int backend_flush_after
extern

Definition at line 225 of file bufmgr.c.

Referenced by 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 23 of file buf_init.c.

Referenced by BufferGetBlock(), and BufferManagerShmemInit().

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