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

4105{
4107
4109
4111}
static void CheckForBufferLeaks(void)
Definition bufmgr.c:4174
static int32 PrivateRefCountOverflowed
Definition bufmgr.c:251
#define Assert(condition)
Definition c.h:873
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 3736 of file bufmgr.c.

3737{
3738 /* info obtained from freelist.c */
3739 int strategy_buf_id;
3742
3743 /*
3744 * Information saved between calls so we can determine the strategy
3745 * point's advance rate and avoid scanning already-cleaned buffers.
3746 */
3747 static bool saved_info_valid = false;
3748 static int prev_strategy_buf_id;
3750 static int next_to_clean;
3751 static uint32 next_passes;
3752
3753 /* Moving averages of allocation rate and clean-buffer density */
3754 static float smoothed_alloc = 0;
3755 static float smoothed_density = 10.0;
3756
3757 /* Potentially these could be tunables, but for now, not */
3758 float smoothing_samples = 16;
3759 float scan_whole_pool_milliseconds = 120000.0;
3760
3761 /* Used to compute how far we scan ahead */
3762 long strategy_delta;
3763 int bufs_to_lap;
3764 int bufs_ahead;
3765 float scans_per_alloc;
3768 int min_scan_buffers;
3769
3770 /* Variables for the scanning loop proper */
3771 int num_to_scan;
3772 int num_written;
3773 int reusable_buffers;
3774
3775 /* Variables for final smoothed_density update */
3776 long new_strategy_delta;
3778
3779 /*
3780 * Find out where the clock-sweep currently is, and how many buffer
3781 * allocations have happened since our last call.
3782 */
3784
3785 /* Report buffer alloc counts to pgstat */
3787
3788 /*
3789 * If we're not running the LRU scan, just stop after doing the stats
3790 * stuff. We mark the saved state invalid so that we can recover sanely
3791 * if LRU scan is turned back on later.
3792 */
3793 if (bgwriter_lru_maxpages <= 0)
3794 {
3795 saved_info_valid = false;
3796 return true;
3797 }
3798
3799 /*
3800 * Compute strategy_delta = how many buffers have been scanned by the
3801 * clock-sweep since last time. If first time through, assume none. Then
3802 * see if we are still ahead of the clock-sweep, and if so, how many
3803 * buffers we could scan before we'd catch up with it and "lap" it. Note:
3804 * weird-looking coding of xxx_passes comparisons are to avoid bogus
3805 * behavior when the passes counts wrap around.
3806 */
3807 if (saved_info_valid)
3808 {
3810
3813
3814 Assert(strategy_delta >= 0);
3815
3816 if ((int32) (next_passes - strategy_passes) > 0)
3817 {
3818 /* we're one pass ahead of the strategy point */
3820#ifdef BGW_DEBUG
3821 elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3825#endif
3826 }
3827 else if (next_passes == strategy_passes &&
3829 {
3830 /* on same pass, but ahead or at least not behind */
3832#ifdef BGW_DEBUG
3833 elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3837#endif
3838 }
3839 else
3840 {
3841 /*
3842 * We're behind, so skip forward to the strategy point and start
3843 * cleaning from there.
3844 */
3845#ifdef BGW_DEBUG
3846 elog(DEBUG2, "bgwriter behind: bgw %u-%u strategy %u-%u delta=%ld",
3850#endif
3854 }
3855 }
3856 else
3857 {
3858 /*
3859 * Initializing at startup or after LRU scanning had been off. Always
3860 * start at the strategy point.
3861 */
3862#ifdef BGW_DEBUG
3863 elog(DEBUG2, "bgwriter initializing: strategy %u-%u",
3865#endif
3866 strategy_delta = 0;
3870 }
3871
3872 /* Update saved info for next time */
3875 saved_info_valid = true;
3876
3877 /*
3878 * Compute how many buffers had to be scanned for each new allocation, ie,
3879 * 1/density of reusable buffers, and track a moving average of that.
3880 *
3881 * If the strategy point didn't move, we don't update the density estimate
3882 */
3883 if (strategy_delta > 0 && recent_alloc > 0)
3884 {
3888 }
3889
3890 /*
3891 * Estimate how many reusable buffers there are between the current
3892 * strategy point and where we've scanned ahead to, based on the smoothed
3893 * density estimate.
3894 */
3897
3898 /*
3899 * Track a moving average of recent buffer allocations. Here, rather than
3900 * a true average we want a fast-attack, slow-decline behavior: we
3901 * immediately follow any increase.
3902 */
3903 if (smoothed_alloc <= (float) recent_alloc)
3905 else
3908
3909 /* Scale the estimate by a GUC to allow more aggressive tuning. */
3911
3912 /*
3913 * If recent_alloc remains at zero for many cycles, smoothed_alloc will
3914 * eventually underflow to zero, and the underflows produce annoying
3915 * kernel warnings on some platforms. Once upcoming_alloc_est has gone to
3916 * zero, there's no point in tracking smaller and smaller values of
3917 * smoothed_alloc, so just reset it to exactly zero to avoid this
3918 * syndrome. It will pop back up as soon as recent_alloc increases.
3919 */
3920 if (upcoming_alloc_est == 0)
3921 smoothed_alloc = 0;
3922
3923 /*
3924 * Even in cases where there's been little or no buffer allocation
3925 * activity, we want to make a small amount of progress through the buffer
3926 * cache so that as many reusable buffers as possible are clean after an
3927 * idle period.
3928 *
3929 * (scan_whole_pool_milliseconds / BgWriterDelay) computes how many times
3930 * the BGW will be called during the scan_whole_pool time; slice the
3931 * buffer pool into that many sections.
3932 */
3934
3936 {
3937#ifdef BGW_DEBUG
3938 elog(DEBUG2, "bgwriter: alloc_est=%d too small, using min=%d + reusable_est=%d",
3940#endif
3942 }
3943
3944 /*
3945 * Now write out dirty reusable buffers, working forward from the
3946 * next_to_clean point, until we have lapped the strategy scan, or cleaned
3947 * enough buffers to match our estimate of the next cycle's allocation
3948 * requirements, or hit the bgwriter_lru_maxpages limit.
3949 */
3950
3951 num_to_scan = bufs_to_lap;
3952 num_written = 0;
3954
3955 /* Execute the LRU scan */
3956 while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
3957 {
3959 wb_context);
3960
3961 if (++next_to_clean >= NBuffers)
3962 {
3963 next_to_clean = 0;
3964 next_passes++;
3965 }
3966 num_to_scan--;
3967
3968 if (sync_state & BUF_WRITTEN)
3969 {
3972 {
3974 break;
3975 }
3976 }
3977 else if (sync_state & BUF_REUSABLE)
3979 }
3980
3982
3983#ifdef BGW_DEBUG
3984 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",
3987 bufs_to_lap - num_to_scan,
3990#endif
3991
3992 /*
3993 * Consider the above scan as being like a new allocation scan.
3994 * Characterize its density and update the smoothed one based on it. This
3995 * effectively halves the moving average period in cases where both the
3996 * strategy and the background writer are doing some useful scanning,
3997 * which is helpful because a long memory isn't as desirable on the
3998 * density estimates.
3999 */
4000 new_strategy_delta = bufs_to_lap - num_to_scan;
4002 if (new_strategy_delta > 0 && new_recent_alloc > 0)
4003 {
4007
4008#ifdef BGW_DEBUG
4009 elog(DEBUG2, "bgwriter: cleaner density alloc=%u scan=%ld density=%.2f new smoothed=%.2f",
4012#endif
4013 }
4014
4015 /* Return true if OK to hibernate */
4016 return (bufs_to_lap == 0 && recent_alloc == 0);
4017}
int BgWriterDelay
Definition bgwriter.c:58
#define BUF_REUSABLE
Definition bufmgr.c:83
double bgwriter_lru_multiplier
Definition bufmgr.c:176
static int SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
Definition bufmgr.c:4034
int bgwriter_lru_maxpages
Definition bufmgr.c:175
#define BUF_WRITTEN
Definition bufmgr.c:82
int32_t int32
Definition c.h:542
uint32_t uint32
Definition c.h:546
#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:242
PgStat_Counter maxwritten_clean
Definition pgstat.h:243
PgStat_Counter buf_alloc
Definition pgstat.h:244

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

◆ BufferGetBlock()

static Block BufferGetBlock ( Buffer  buffer)
inlinestatic

Definition at line 433 of file bufmgr.h.

434{
435 Assert(BufferIsValid(buffer));
436
437 if (BufferIsLocal(buffer))
438 return LocalBufferBlockPointers[-buffer - 1];
439 else
440 return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
441}
#define BufferIsLocal(buffer)
Definition buf.h:37
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:417
size_t Size
Definition c.h:619

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)
static BufferDesc * GetBufferDescriptor(uint32 id)
#define BufferIsPinned(bufnum)
Definition bufmgr.c:590

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(), ginEntryInsert(), ginFindParents(), ginFinishSplit(), ginPlaceToPage(), ginRedoDeleteListPages(), ginRedoUpdateMetapage(), ginScanToDelete(), 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_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_plan(), 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(), 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 4635 of file bufmgr.c.

4636{
4637 char *page = BufferGetPage(buffer);
4639 XLogRecPtr lsn;
4640
4641 /*
4642 * If we don't need locking for correctness, fastpath out.
4643 */
4644 if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
4645 return PageGetLSN(page);
4646
4647 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4648 Assert(BufferIsValid(buffer));
4649 Assert(BufferIsPinned(buffer));
4650
4651 bufHdr = GetBufferDescriptor(buffer - 1);
4653 lsn = PageGetLSN(page);
4655
4656 return lsn;
4657}
static void UnlockBufHdr(BufferDesc *desc)
uint64 LockBufHdr(BufferDesc *desc)
Definition bufmgr.c:7108
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:466
static XLogRecPtr PageGetLSN(const PageData *page)
Definition bufpage.h:385
#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(), SetHintBits(), and XLogSaveBufferForHint().

◆ BufferGetPage()

static Page BufferGetPage ( Buffer  buffer)
inlinestatic

Definition at line 466 of file bufmgr.h.

467{
468 return (Page) BufferGetBlock(buffer);
469}
static Block BufferGetBlock(Buffer buffer)
Definition bufmgr.h:433
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(), 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(), ginDeletePage(), ginEntryInsert(), ginFindLeafPage(), ginFindParents(), ginFinishOldSplit(), ginFinishSplit(), ginGetStats(), ginHeapTupleFastInsert(), GinInitBuffer(), GinInitMetabuffer(), ginInsertCleanup(), ginInsertValue(), GinNewBuffer(), ginPlaceToPage(), ginRedoClearIncompleteSplit(), ginRedoCreatePTree(), ginRedoDeleteListPages(), ginRedoDeletePage(), ginRedoInsert(), ginRedoInsertData(), ginRedoInsertEntry(), ginRedoInsertListPage(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginScanToDelete(), ginStepRight(), ginTraverseLock(), ginUpdateStats(), ginvacuumcleanup(), ginVacuumEntryPage(), ginVacuumPostingTreeLeaf(), ginVacuumPostingTreeLeaves(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistbuild(), gistcheckpage(), gistdeletepage(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistfixsplit(), gistformdownlink(), gistGetMaxLevel(), GISTInitBuffer(), gistkillitems(), gistMemorizeAllDownlinks(), gistNewBuffer(), gistplacetopage(), gistProcessItup(), gistRedoClearFollowRight(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), gistScanPage(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hash_bitmap_info(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_force_common(), heap_freeze_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_and_freeze(), 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(), MarkBufferDirtyHint(), 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_plan(), 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 3025 of file bufmgr.c.

3026{
3028
3029 Assert(BufferIsPinned(buffer));
3030
3031 if (BufferIsLocal(buffer))
3032 {
3033 int bufid = -buffer - 1;
3034
3036 /* Content locks are not maintained for local buffers. */
3037 }
3038 else
3039 {
3040 bufHdr = GetBufferDescriptor(buffer - 1);
3042 }
3043
3044 return pg_atomic_read_u64(&bufHdr->state) & BM_DIRTY;
3045}
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition atomics.h:467
#define BM_DIRTY
bool BufferIsLockedByMeInMode(Buffer buffer, BufferLockMode mode)
Definition bufmgr.c:2998

References Assert, BM_DIRTY, PrivateRefCountEntry::buffer, BUFFER_LOCK_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(), and XLogRegisterBuffer().

◆ BufferIsLockedByMe()

bool BufferIsLockedByMe ( Buffer  buffer)
extern

Definition at line 2972 of file bufmgr.c.

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

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

Referenced by FlushOneBuffer(), and MarkBufferDirtyHint().

◆ BufferIsLockedByMeInMode()

bool BufferIsLockedByMeInMode ( Buffer  buffer,
BufferLockMode  mode 
)
extern

Definition at line 2998 of file bufmgr.c.

2999{
3001
3002 Assert(BufferIsPinned(buffer));
3003
3004 if (BufferIsLocal(buffer))
3005 {
3006 /* Content locks are not maintained for local buffers. */
3007 return true;
3008 }
3009 else
3010 {
3011 bufHdr = GetBufferDescriptor(buffer - 1);
3013 }
3014}
static bool BufferLockHeldByMeInMode(BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:6383
static PgChecksumMode mode

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

Referenced by BufferIsDirty(), HeapTupleSetHintBits(), identify_and_fix_vm_corruption(), IsBufferCleanupOK(), MarkBufferDirty(), visibilitymap_set(), visibilitymap_set_vmbits(), and XLogRegisterBuffer().

◆ BufferIsPermanent()

bool BufferIsPermanent ( Buffer  buffer)
extern

Definition at line 4605 of file bufmgr.c.

4606{
4608
4609 /* Local buffers are used only for temp relations. */
4610 if (BufferIsLocal(buffer))
4611 return false;
4612
4613 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4614 Assert(BufferIsValid(buffer));
4615 Assert(BufferIsPinned(buffer));
4616
4617 /*
4618 * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
4619 * need not bother with the buffer header spinlock. Even if someone else
4620 * changes the buffer header state while we're doing this, the state is
4621 * changed atomically, so we'll read the old value or the new value, but
4622 * not random garbage.
4623 */
4624 bufHdr = GetBufferDescriptor(buffer - 1);
4625 return (pg_atomic_read_u64(&bufHdr->state) & BM_PERMANENT) != 0;
4626}
#define BM_PERMANENT

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

Referenced by SetHintBits().

◆ BufferIsValid()

static bool BufferIsValid ( Buffer  bufnum)
inlinestatic

Definition at line 417 of file bufmgr.h.

418{
421
422 return bufnum != InvalidBuffer;
423}
#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(), ginScanToDelete(), 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(), 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(), 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:7268
int backend_flush_after
Definition bufmgr.c:210
#define TYPEALIGN(ALIGNVAL, LEN)
Definition c.h:819
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:378

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:482
Size mul_size(Size s1, Size s2)
Definition shmem.c:497

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

Referenced by CalculateShmemSize().

◆ CheckBufferIsPinnedOnce()

void CheckBufferIsPinnedOnce ( Buffer  buffer)
extern

Definition at line 6495 of file bufmgr.c.

6496{
6497 if (BufferIsLocal(buffer))
6498 {
6499 if (LocalRefCount[-buffer - 1] != 1)
6500 elog(ERROR, "incorrect local pin count: %d",
6501 LocalRefCount[-buffer - 1]);
6502 }
6503 else
6504 {
6505 if (GetPrivateRefCount(buffer) != 1)
6506 elog(ERROR, "incorrect local pin count: %d",
6507 GetPrivateRefCount(buffer));
6508 }
6509}
static int32 GetPrivateRefCount(Buffer buffer)
Definition bufmgr.c:529
#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:3457

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)
extern

Definition at line 6475 of file bufmgr.c.

6476{
6477 BufferDesc *buf;
6478
6479 Assert(BufferIsPinned(buffer));
6480 if (BufferIsLocal(buffer))
6481 return true; /* act as though we got it */
6482
6483 buf = GetBufferDescriptor(buffer - 1);
6484
6486}
static bool BufferLockConditional(Buffer buffer, BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:5908

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

6702{
6705 refcount;
6706
6707 Assert(BufferIsValid(buffer));
6708
6709 /* see AIO related comment in LockBufferForCleanup() */
6710
6711 if (BufferIsLocal(buffer))
6712 {
6713 refcount = LocalRefCount[-buffer - 1];
6714 /* There should be exactly one pin */
6715 Assert(refcount > 0);
6716 if (refcount != 1)
6717 return false;
6718 /* Nobody else to wait for */
6719 return true;
6720 }
6721
6722 /* There should be exactly one local pin */
6723 refcount = GetPrivateRefCount(buffer);
6724 Assert(refcount);
6725 if (refcount != 1)
6726 return false;
6727
6728 /* Try to acquire lock */
6729 if (!ConditionalLockBuffer(buffer))
6730 return false;
6731
6732 bufHdr = GetBufferDescriptor(buffer - 1);
6735
6736 Assert(refcount > 0);
6737 if (refcount == 1)
6738 {
6739 /* Successfully acquired exclusive lock with pincount 1 */
6741 return true;
6742 }
6743
6744 /* Failed, so release the lock */
6747 return false;
6748}
#define BUF_STATE_GET_REFCOUNT(state)
bool ConditionalLockBuffer(Buffer buffer)
Definition bufmgr.c:6475
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:328
uint64_t uint64
Definition c.h:547

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

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

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

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

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

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

7574{
7575 *buffers_evicted = 0;
7576 *buffers_skipped = 0;
7577 *buffers_flushed = 0;
7578
7579 for (int buf = 1; buf <= NBuffers; buf++)
7580 {
7581 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7583 bool buffer_flushed;
7584
7586
7588 if (!(buf_state & BM_VALID))
7589 continue;
7590
7593
7594 LockBufHdr(desc);
7595
7597 (*buffers_evicted)++;
7598 else
7599 (*buffers_skipped)++;
7600
7601 if (buffer_flushed)
7602 (*buffers_flushed)++;
7603 }
7604}
#define BM_VALID
static bool EvictUnpinnedBufferInternal(BufferDesc *desc, bool *buffer_flushed)
Definition bufmgr.c:7481
static void ReservePrivateRefCountEntry(void)
Definition bufmgr.c:294
#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 7622 of file bufmgr.c.

7624{
7626
7627 *buffers_skipped = 0;
7628 *buffers_evicted = 0;
7629 *buffers_flushed = 0;
7630
7631 for (int buf = 1; buf <= NBuffers; buf++)
7632 {
7633 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7635 bool buffer_flushed;
7636
7638
7639 /* An unlocked precheck should be safe and saves some cycles. */
7640 if ((buf_state & BM_VALID) == 0 ||
7642 continue;
7643
7644 /* Make sure we can pin the buffer. */
7647
7648 buf_state = LockBufHdr(desc);
7649
7650 /* recheck, could have changed without the lock */
7651 if ((buf_state & BM_VALID) == 0 ||
7653 {
7654 UnlockBufHdr(desc);
7655 continue;
7656 }
7657
7659 (*buffers_evicted)++;
7660 else
7661 (*buffers_skipped)++;
7662
7663 if (buffer_flushed)
7664 (*buffers_flushed)++;
7665 }
7666}
#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 965 of file bufmgr.c.

969{
970 Buffer buf;
971 uint32 extend_by = 1;
972
973 ExtendBufferedRelBy(bmr, forkNum, strategy, flags, extend_by,
974 &buf, &extend_by);
975
976 return buf;
977}
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:997

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

1004{
1005 Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
1006 Assert(bmr.smgr == NULL || bmr.relpersistence != '\0');
1007 Assert(extend_by > 0);
1008
1009 if (bmr.relpersistence == '\0')
1010 bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
1011
1012 return ExtendBufferedRelCommon(bmr, fork, strategy, flags,
1014 buffers, extended_by);
1015}
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:2660

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

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

5443{
5444 int i;
5446
5447 for (i = 0; i < NBuffers; i++)
5448 {
5450
5452
5453 /*
5454 * As in DropRelationBuffers, an unlocked precheck should be safe and
5455 * saves some cycles.
5456 */
5457 if (bufHdr->tag.dbOid != dbid)
5458 continue;
5459
5460 /* Make sure we can handle the pin */
5463
5465 if (bufHdr->tag.dbOid == dbid &&
5467 {
5471 }
5472 else
5474 }
5475}
static void FlushUnlockedBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition bufmgr.c:4554
static void PinBuffer_Locked(BufferDesc *buf)
Definition bufmgr.c:3293
static void UnpinBuffer(BufferDesc *buf)
Definition bufmgr.c:3361
@ IOOBJECT_RELATION
Definition pgstat.h:277
@ IOCONTEXT_NORMAL
Definition pgstat.h:289

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

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

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

5079{
5080 int i;
5082 SMgrRelation srel = RelationGetSmgr(rel);
5083
5084 if (RelationUsesLocalBuffers(rel))
5085 {
5086 for (i = 0; i < NLocBuffer; i++)
5087 {
5089
5091 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
5092 ((buf_state = pg_atomic_read_u64(&bufHdr->state)) &
5093 (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
5094 {
5095 ErrorContextCallback errcallback;
5096
5097 /* Setup error traceback support for ereport() */
5099 errcallback.arg = bufHdr;
5100 errcallback.previous = error_context_stack;
5101 error_context_stack = &errcallback;
5102
5103 /* Make sure we can handle the pin */
5106
5107 /*
5108 * Pin/unpin mostly to make valgrind work, but it also seems
5109 * like the right thing to do.
5110 */
5111 PinLocalBuffer(bufHdr, false);
5112
5113
5114 FlushLocalBuffer(bufHdr, srel);
5115
5117
5118 /* Pop the error context stack */
5119 error_context_stack = errcallback.previous;
5120 }
5121 }
5122
5123 return;
5124 }
5125
5126 for (i = 0; i < NBuffers; i++)
5127 {
5129
5131
5132 /*
5133 * As in DropRelationBuffers, an unlocked precheck should be safe and
5134 * saves some cycles.
5135 */
5137 continue;
5138
5139 /* Make sure we can handle the pin */
5142
5144 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
5146 {
5150 }
5151 else
5153 }
5154}
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
static void local_buffer_write_error_callback(void *arg)
Definition bufmgr.c:7065
ErrorContextCallback * error_context_stack
Definition elog.c:95
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 5166 of file bufmgr.c.

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

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:185
int io_combine_limit
Definition bufmgr.c:200
uint32 GetPinLimit(void)
Definition bufmgr.c:2604
#define Max(x, y)
Definition c.h:991
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:997
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:561
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 2616 of file bufmgr.c.

2617{
2619
2620 /*
2621 * We get the number of "overflowed" pins for free, but don't know the
2622 * number of pins in PrivateRefCountArray. The cost of calculating that
2623 * exactly doesn't seem worth it, so just assume the max.
2624 */
2626
2627 /* Is this backend already holding more than its fair share? */
2629 return 0;
2630
2632}
static uint32 MaxProportionalPins
Definition bufmgr.c:256
#define REFCOUNT_ARRAY_ENTRIES
Definition bufmgr.c:130

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

2605{
2606 return MaxProportionalPins;
2607}

References MaxProportionalPins.

Referenced by GetAccessStrategy(), and read_stream_begin_impl().

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )
extern

Definition at line 6675 of file bufmgr.c.

6676{
6678
6679 /*
6680 * If we get woken slowly then it's possible that the Startup process was
6681 * already woken by other backends before we got here. Also possible that
6682 * we get here by multiple interrupts or interrupts at inappropriate
6683 * times, so make sure we do nothing if the bufid is not set.
6684 */
6685 if (bufid < 0)
6686 return false;
6687
6688 if (GetPrivateRefCount(bufid + 1) > 0)
6689 return true;
6690
6691 return false;
6692}
int GetStartupBufferPinWaitBufId(void)
Definition proc.c:769

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

Referenced by CheckRecoveryConflictDeadlock(), and ProcessRecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)
extern

Definition at line 5534 of file bufmgr.c.

5535{
5536 Assert(BufferIsPinned(buffer));
5538 if (BufferIsLocal(buffer))
5539 LocalRefCount[-buffer - 1]++;
5540 else
5541 {
5543
5544 ref = GetPrivateRefCountEntry(buffer, true);
5545 Assert(ref != NULL);
5546 ref->data.refcount++;
5547 }
5549}
static void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition bufmgr.c:494

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

4122{
4124
4125 /*
4126 * An advisory limit on the number of pins each backend should hold, based
4127 * on shared_buffers and the maximum number of connections possible.
4128 * That's very pessimistic, but outside toy-sized shared_buffers it should
4129 * allow plenty of pins. LimitAdditionalPins() and
4130 * GetAdditionalPinLimit() can be used to check the remaining balance.
4131 */
4133
4136
4137 hash_ctl.keysize = sizeof(Buffer);
4138 hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
4139
4140 PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
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:248
static void AtProcExit_Buffers(int code, Datum arg)
Definition bufmgr.c:4156
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition bufmgr.c:249
static HTAB * PrivateRefCountHash
Definition bufmgr.c:250
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:358
int MaxBackends
Definition globals.c:146
#define HASH_ELEM
Definition hsearch.h:95
#define HASH_BLOBS
Definition hsearch.h:97
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition ipc.c:372
#define NUM_AUXILIARY_PROCS
Definition proc.h:473
PGPROC * MyProc
Definition proc.c:67

References Assert, AtProcExit_Buffers(), fb(), HASH_BLOBS, hash_create(), HASH_ELEM, 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 6759 of file bufmgr.c.

6760{
6763
6764 Assert(BufferIsValid(buffer));
6765
6766 /* see AIO related comment in LockBufferForCleanup() */
6767
6768 if (BufferIsLocal(buffer))
6769 {
6770 /* There should be exactly one pin */
6771 if (LocalRefCount[-buffer - 1] != 1)
6772 return false;
6773 /* Nobody else to wait for */
6774 return true;
6775 }
6776
6777 /* There should be exactly one local pin */
6778 if (GetPrivateRefCount(buffer) != 1)
6779 return false;
6780
6781 bufHdr = GetBufferDescriptor(buffer - 1);
6782
6783 /* caller must hold exclusive lock on buffer */
6785
6787
6790 {
6791 /* pincount is OK. */
6793 return true;
6794 }
6795
6797 return false;
6798}

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

2643{
2644 uint32 limit;
2645
2646 if (*additional_pins <= 1)
2647 return;
2648
2649 limit = GetAdditionalPinLimit();
2650 limit = Max(limit, 1);
2651 if (limit < *additional_pins)
2652 *additional_pins = limit;
2653}
uint32 GetAdditionalPinLimit(void)
Definition bufmgr.c:2616

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

Referenced by ExtendBufferedRelShared().

◆ LockBuffer()

static void LockBuffer ( Buffer  buffer,
BufferLockMode  mode 
)
inlinestatic

Definition at line 328 of file bufmgr.h.

329{
331 UnlockBuffer(buffer);
332 else
333 LockBufferInternal(buffer, mode);
334}
void UnlockBuffer(Buffer buffer)
Definition bufmgr.c:6416
void LockBufferInternal(Buffer buffer, BufferLockMode mode)
Definition bufmgr.c:6432

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

6529{
6531 TimestampTz waitStart = 0;
6532 bool waiting = false;
6533 bool logged_recovery_conflict = false;
6534
6535 Assert(BufferIsPinned(buffer));
6537
6539
6540 /*
6541 * We do not yet need to be worried about in-progress AIOs holding a pin,
6542 * as we, so far, only support doing reads via AIO and this function can
6543 * only be called once the buffer is valid (i.e. no read can be in
6544 * flight).
6545 */
6546
6547 /* Nobody else to wait for */
6548 if (BufferIsLocal(buffer))
6549 return;
6550
6551 bufHdr = GetBufferDescriptor(buffer - 1);
6552
6553 for (;;)
6554 {
6556 uint64 unset_bits = 0;
6557
6558 /* Try to acquire lock */
6561
6564 {
6565 /* Successfully acquired exclusive lock with pincount 1 */
6567
6568 /*
6569 * Emit the log message if recovery conflict on buffer pin was
6570 * resolved but the startup process waited longer than
6571 * deadlock_timeout for it.
6572 */
6575 waitStart, GetCurrentTimestamp(),
6576 NULL, false);
6577
6578 if (waiting)
6579 {
6580 /* reset ps display to remove the suffix if we added one */
6582 waiting = false;
6583 }
6584 return;
6585 }
6586 /* Failed, so mark myself as waiting for pincount 1 */
6588 {
6591 elog(ERROR, "multiple backends attempting to wait for pincount 1");
6592 }
6593 bufHdr->wait_backend_pgprocno = MyProcNumber;
6597 0);
6599
6600 /* Wait to be signaled by UnpinBuffer() */
6601 if (InHotStandby)
6602 {
6603 if (!waiting)
6604 {
6605 /* adjust the process title to indicate that it's waiting */
6606 set_ps_display_suffix("waiting");
6607 waiting = true;
6608 }
6609
6610 /*
6611 * Emit the log message if the startup process is waiting longer
6612 * than deadlock_timeout for recovery conflict on buffer pin.
6613 *
6614 * Skip this if first time through because the startup process has
6615 * not started waiting yet in this case. So, the wait start
6616 * timestamp is set after this logic.
6617 */
6618 if (waitStart != 0 && !logged_recovery_conflict)
6619 {
6621
6622 if (TimestampDifferenceExceeds(waitStart, now,
6624 {
6626 waitStart, now, NULL, true);
6628 }
6629 }
6630
6631 /*
6632 * Set the wait start timestamp if logging is enabled and first
6633 * time through.
6634 */
6635 if (log_recovery_conflict_waits && waitStart == 0)
6636 waitStart = GetCurrentTimestamp();
6637
6638 /* Publish the bufid that Startup process waits on */
6639 SetStartupBufferPinWaitBufId(buffer - 1);
6640 /* Set alarm and then wait to be signaled by UnpinBuffer() */
6642 /* Reset the published bufid */
6644 }
6645 else
6647
6648 /*
6649 * Remove flag marking us as waiter. Normally this will not be set
6650 * anymore, but ProcWaitForSignal() can return for other signals as
6651 * well. We take care to only reset the flag if we're the waiter, as
6652 * theoretically another backend could have started waiting. That's
6653 * impossible with the current usages due to table level locking, but
6654 * better be safe.
6655 */
6657 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
6658 bufHdr->wait_backend_pgprocno == MyProcNumber)
6660
6662 0, unset_bits,
6663 0);
6664
6666 /* Loop back and try again */
6667 }
6668}
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition timestamp.c:1781
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1645
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1609
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:6495
static BufferDesc * PinCountWaitBuf
Definition bufmgr.c:213
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:58
void SetStartupBufferPinWaitBufId(int bufid)
Definition proc.c:757
void ProcWaitForSignal(uint32 wait_event_info)
Definition proc.c:1984
void ResolveRecoveryConflictWithBufferPin(void)
Definition standby.c:793
bool log_recovery_conflict_waits
Definition standby.c:42
void LogRecoveryConflict(RecoveryConflictReason reason, TimestampTz wait_start, TimestampTz now, VirtualTransactionId *wait_list, bool still_waiting)
Definition standby.c:274
@ 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 6432 of file bufmgr.c.

6433{
6435
6436 /*
6437 * We can't wait if we haven't got a PGPROC. This should only occur
6438 * during bootstrap or shared memory initialization. Put an Assert here
6439 * to catch unsafe coding practices.
6440 */
6442
6443 /* handled in LockBuffer() wrapper */
6445
6446 Assert(BufferIsPinned(buffer));
6447 if (BufferIsLocal(buffer))
6448 return; /* local buffers need no lock */
6449
6450 buf_hdr = GetBufferDescriptor(buffer - 1);
6451
6452 /*
6453 * Test the most frequent lock modes first. While a switch (mode) would be
6454 * nice, at least gcc generates considerably worse code for it.
6455 *
6456 * Call BufferLockAcquire() with a constant argument for mode, to generate
6457 * more efficient code for the different lock modes.
6458 */
6459 if (mode == BUFFER_LOCK_SHARE)
6461 else if (mode == BUFFER_LOCK_EXCLUSIVE)
6465 else
6466 elog(ERROR, "unrecognized buffer lock mode: %d", mode);
6467}
static void BufferLockAcquire(Buffer buffer, BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:5756
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 3057 of file bufmgr.c.

3058{
3062
3063 if (!BufferIsValid(buffer))
3064 elog(ERROR, "bad buffer ID: %d", buffer);
3065
3066 if (BufferIsLocal(buffer))
3067 {
3068 MarkLocalBufferDirty(buffer);
3069 return;
3070 }
3071
3072 bufHdr = GetBufferDescriptor(buffer - 1);
3073
3074 Assert(BufferIsPinned(buffer));
3076
3077 /*
3078 * NB: We have to wait for the buffer header spinlock to be not held, as
3079 * TerminateBufferIO() relies on the spinlock.
3080 */
3082 for (;;)
3083 {
3086
3088
3091
3093 buf_state))
3094 break;
3095 }
3096
3097 /*
3098 * If the buffer was not dirty already, do vacuum accounting.
3099 */
3100 if (!(old_buf_state & BM_DIRTY))
3101 {
3103 if (VacuumCostActive)
3105 }
3106}
static bool pg_atomic_compare_exchange_u64(volatile pg_atomic_uint64 *ptr, uint64 *expected, uint64 newval)
Definition atomics.h:522
#define BM_LOCKED
#define BM_JUST_DIRTIED
pg_noinline uint64 WaitBufHdrUnlocked(BufferDesc *buf)
Definition bufmgr.c:7156
bool VacuumCostActive
Definition globals.c:158
int VacuumCostBalance
Definition globals.c:157
int VacuumCostPageDirty
Definition globals.c:153
BufferUsage pgBufferUsage
Definition instrument.c:20
void MarkLocalBufferDirty(Buffer buffer)
Definition localbuf.c:491
int64 shared_blks_dirtied
Definition instrument.h:28

References Assert, BM_DIRTY, BM_JUST_DIRTIED, 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(), ginDeletePage(), ginHeapTupleFastInsert(), ginPlaceToPage(), ginRedoClearIncompleteSplit(), ginRedoCreatePTree(), ginRedoDeleteListPages(), ginRedoDeletePage(), ginRedoInsert(), ginRedoInsertListPage(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginUpdateStats(), ginVacuumPostingTreeLeaf(), gistbuild(), gistbuildempty(), gistdeletepage(), gistplacetopage(), gistprunepage(), gistRedoClearFollowRight(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), gistvacuumpage(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_finish_speculative(), heap_force_common(), heap_inplace_update_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(), identify_and_fix_vm_corruption(), 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()

void MarkBufferDirtyHint ( Buffer  buffer,
bool  buffer_std 
)
extern

Definition at line 5566 of file bufmgr.c.

5567{
5569 Page page = BufferGetPage(buffer);
5570
5571 if (!BufferIsValid(buffer))
5572 elog(ERROR, "bad buffer ID: %d", buffer);
5573
5574 if (BufferIsLocal(buffer))
5575 {
5576 MarkLocalBufferDirty(buffer);
5577 return;
5578 }
5579
5580 bufHdr = GetBufferDescriptor(buffer - 1);
5581
5582 Assert(GetPrivateRefCount(buffer) > 0);
5583 /* here, either share or exclusive lock is OK */
5584 Assert(BufferIsLockedByMe(buffer));
5585
5586 /*
5587 * This routine might get called many times on the same page, if we are
5588 * making the first scan after commit of an xact that added/deleted many
5589 * tuples. So, be as quick as we can if the buffer is already dirty. We
5590 * do this by not acquiring spinlock if it looks like the status bits are
5591 * already set. Since we make this test unlocked, there's a chance we
5592 * might fail to notice that the flags have just been cleared, and failed
5593 * to reset them, due to memory-ordering issues. But since this function
5594 * is only intended to be used in cases where failing to write out the
5595 * data would be harmless anyway, it doesn't really matter.
5596 */
5597 if ((pg_atomic_read_u64(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
5599 {
5601 bool dirtied = false;
5602 bool delayChkptFlags = false;
5604
5605 /*
5606 * If we need to protect hint bit updates from torn writes, WAL-log a
5607 * full page image of the page. This full page image is only necessary
5608 * if the hint bit update is the first change to the page since the
5609 * last checkpoint.
5610 *
5611 * We don't check full_page_writes here because that logic is included
5612 * when we call XLogInsert() since the value changes dynamically.
5613 */
5614 if (XLogHintBitIsNeeded() &&
5616 {
5617 /*
5618 * If we must not write WAL, due to a relfilelocator-specific
5619 * condition or being in recovery, don't dirty the page. We can
5620 * set the hint, just not dirty the page as a result so the hint
5621 * is lost when we evict the page or shutdown.
5622 *
5623 * See src/backend/storage/page/README for longer discussion.
5624 */
5625 if (RecoveryInProgress() ||
5627 return;
5628
5629 /*
5630 * If the block is already dirty because we either made a change
5631 * or set a hint already, then we don't need to write a full page
5632 * image. Note that aggressive cleaning of blocks dirtied by hint
5633 * bit setting would increase the call rate. Bulk setting of hint
5634 * bits would reduce the call rate...
5635 *
5636 * We must issue the WAL record before we mark the buffer dirty.
5637 * Otherwise we might write the page before we write the WAL. That
5638 * causes a race condition, since a checkpoint might occur between
5639 * writing the WAL record and marking the buffer dirty. We solve
5640 * that with a kluge, but one that is already in use during
5641 * transaction commit to prevent race conditions. Basically, we
5642 * simply prevent the checkpoint WAL record from being written
5643 * until we have marked the buffer dirty. We don't start the
5644 * checkpoint flush until we have marked dirty, so our checkpoint
5645 * must flush the change to disk successfully or the checkpoint
5646 * never gets written, so crash recovery will fix.
5647 *
5648 * It's possible we may enter here without an xid, so it is
5649 * essential that CreateCheckPoint waits for virtual transactions
5650 * rather than full transactionids.
5651 */
5654 delayChkptFlags = true;
5655 lsn = XLogSaveBufferForHint(buffer, buffer_std);
5656 }
5657
5659
5661
5662 if (!(buf_state & BM_DIRTY))
5663 {
5664 dirtied = true; /* Means "will be dirtied by this action" */
5665
5666 /*
5667 * Set the page LSN if we wrote a backup block. We aren't supposed
5668 * to set this when only holding a share lock but as long as we
5669 * serialise it somehow we're OK. We choose to set LSN while
5670 * holding the buffer header lock, which causes any reader of an
5671 * LSN who holds only a share lock to also obtain a buffer header
5672 * lock before using PageGetLSN(), which is enforced in
5673 * BufferGetLSNAtomic().
5674 *
5675 * If checksums are enabled, you might think we should reset the
5676 * checksum here. That will happen when the page is written
5677 * sometime later in this checkpoint cycle.
5678 */
5679 if (XLogRecPtrIsValid(lsn))
5680 PageSetLSN(page, lsn);
5681 }
5682
5685 0, 0);
5686
5687 if (delayChkptFlags)
5689
5690 if (dirtied)
5691 {
5693 if (VacuumCostActive)
5695 }
5696 }
5697}
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition bufpage.h:390
#define DELAY_CHKPT_START
Definition proc.h:136
bool RelFileLocatorSkippingWAL(RelFileLocator rlocator)
Definition storage.c:573
int delayChkptFlags
Definition proc.h:267
bool RecoveryInProgress(void)
Definition xlog.c:6460
#define XLogRecPtrIsValid(r)
Definition xlogdefs.h:29
#define InvalidXLogRecPtr
Definition xlogdefs.h:28
XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std)

References Assert, BM_DIRTY, BM_JUST_DIRTIED, BM_PERMANENT, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferGetPage(), BufferIsLocal, BufferIsLockedByMe(), BufferIsValid(), BufTagGetRelFileLocator(), DELAY_CHKPT_START, PGPROC::delayChkptFlags, elog, ERROR, fb(), GetBufferDescriptor(), GetPrivateRefCount(), InvalidXLogRecPtr, LockBufHdr(), MarkLocalBufferDirty(), MyProc, PageSetLSN(), pg_atomic_read_u64(), pgBufferUsage, RecoveryInProgress(), RelFileLocatorSkippingWAL(), BufferUsage::shared_blks_dirtied, UnlockBufHdrExt(), VacuumCostActive, VacuumCostBalance, VacuumCostPageDirty, XLogHintBitIsNeeded, XLogRecPtrIsValid, and XLogSaveBufferForHint().

Referenced by _bt_check_unique(), _bt_killitems(), _hash_kill_items(), brin_start_evacuating_page(), btvacuumpage(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), gistkillitems(), heap_page_prune_and_freeze(), read_seq_tuple(), SetHintBits(), and XLogRecordPageWithFreeSpace().

◆ MarkDirtyAllUnpinnedBuffers()

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

Definition at line 7822 of file bufmgr.c.

7825{
7826 *buffers_dirtied = 0;
7828 *buffers_skipped = 0;
7829
7830 for (int buf = 1; buf <= NBuffers; buf++)
7831 {
7832 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7835
7837
7839 if (!(buf_state & BM_VALID))
7840 continue;
7841
7844
7845 LockBufHdr(desc);
7846
7848 (*buffers_dirtied)++;
7849 else if (buffer_already_dirty)
7850 (*buffers_already_dirty)++;
7851 else
7852 (*buffers_skipped)++;
7853 }
7854}
static bool MarkDirtyUnpinnedBufferInternal(Buffer buf, BufferDesc *desc, bool *buffer_already_dirty)
Definition bufmgr.c:7673

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

7769{
7771
7772 *buffers_dirtied = 0;
7774 *buffers_skipped = 0;
7775
7776 for (int buf = 1; buf <= NBuffers; buf++)
7777 {
7778 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7781
7783
7784 /* An unlocked precheck should be safe and saves some cycles. */
7785 if ((buf_state & BM_VALID) == 0 ||
7787 continue;
7788
7789 /* Make sure we can pin the buffer. */
7792
7793 buf_state = LockBufHdr(desc);
7794
7795 /* recheck, could have changed without the lock */
7796 if ((buf_state & BM_VALID) == 0 ||
7798 {
7799 UnlockBufHdr(desc);
7800 continue;
7801 }
7802
7804 (*buffers_dirtied)++;
7805 else if (buffer_already_dirty)
7806 (*buffers_already_dirty)++;
7807 else
7808 (*buffers_skipped)++;
7809 }
7810}

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

7730{
7731 BufferDesc *desc;
7732 bool buffer_dirtied = false;
7733
7735
7736 /* Make sure we can pin the buffer. */
7739
7740 desc = GetBufferDescriptor(buf - 1);
7741 LockBufHdr(desc);
7742
7744 /* Both can not be true at the same time */
7746
7747 return buffer_dirtied;
7748}

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

774{
776 Assert(BlockNumberIsValid(blockNum));
777
779 {
780 /* see comments in ReadBufferExtended */
784 errmsg("cannot access temporary tables of other sessions")));
785
786 /* pass it off to localbuf.c */
787 return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
788 }
789 else
790 {
791 /* pass it to the shared buffer version */
792 return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
793 }
794}
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition bufmgr.c:683
int errcode(int sqlerrcode)
Definition elog.c:864
int errmsg(const char *fmt,...)
Definition elog.c:1081
#define ereport(elevel,...)
Definition elog.h:150
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition localbuf.c:72
#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 683 of file bufmgr.c.

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

866{
868}
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition bufmgr.c:912

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

914{
915 Buffer buf;
916
917 /*
918 * Reject attempts to read non-local temporary relations; we would be
919 * likely to get wrong data since we have no visibility into the owning
920 * session's local buffers.
921 */
925 errmsg("cannot access temporary tables of other sessions")));
926
927 /*
928 * Read the buffer, and update pgstat counters to reflect a cache hit or
929 * miss.
930 */
932 forkNum, blockNum, mode, strategy);
933
934 return buf;
935}

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(), blbulkdelete(), blgetbitmap(), BloomInitMetapage(), blvacuumcleanup(), 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(), ginDeletePage(), ginScanToDelete(), ginvacuumcleanup(), ginVacuumPostingTree(), ginVacuumPostingTreeLeaves(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hashbulkdelete(), 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(), pgstathashindex(), pgstatindex_impl(), ReadBuffer(), ReadBufferBI(), spgprocesspending(), statapprox_heap(), and vm_readbuf().

◆ ReadBufferWithoutRelcache()

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

Definition at line 949 of file bufmgr.c.

952{
953 SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
954
955 return ReadBuffer_common(NULL, smgr,
957 forkNum, blockNum,
958 mode, strategy);
959}

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

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

4574{
4575 if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
4576 {
4577 /*
4578 * Not every table AM uses BLCKSZ wide fixed size blocks. Therefore
4579 * tableam returns the size in bytes - but for the purpose of this
4580 * routine, we want the number of blocks. Therefore divide, rounding
4581 * up.
4582 */
4584
4585 szbytes = table_relation_size(relation, forkNum);
4586
4587 return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
4588 }
4589 else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
4590 {
4591 return smgrnblocks(RelationGetSmgr(relation), forkNum);
4592 }
4593 else
4594 Assert(false);
4595
4596 return 0; /* keep compiler quiet */
4597}
Form_pg_class rd_rel
Definition rel.h:111
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition tableam.h:1859

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

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

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

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

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(), ginDeletePage(), ginFindParents(), ginFinishSplit(), ginFreeScanKeys(), ginInsertCleanup(), GinNewBuffer(), ginScanToDelete(), 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 1609 of file bufmgr.c.

1613{
1614 int nblocks = 1;
1615 bool result;
1616
1617 result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags,
1618 false /* single block, no forwarding */ );
1619 Assert(nblocks == 1); /* single block can't be short */
1620
1621 return result;
1622}
static pg_attribute_always_inline bool StartReadBuffersImpl(ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, int flags, bool allow_forwarding)
Definition bufmgr.c:1363

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

1595{
1596 return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags,
1597 true /* expect forwarded buffers */ );
1598}

References StartReadBuffersImpl().

Referenced by read_stream_start_pending_read().

◆ UnlockBuffer()

void UnlockBuffer ( Buffer  buffer)
extern

Definition at line 6416 of file bufmgr.c.

6417{
6419
6420 Assert(BufferIsPinned(buffer));
6421 if (BufferIsLocal(buffer))
6422 return; /* local buffers need no lock */
6423
6424 buf_hdr = GetBufferDescriptor(buffer - 1);
6425 BufferLockUnlock(buffer, buf_hdr);
6426}
static void BufferLockUnlock(Buffer buffer, BufferDesc *buf_hdr)
Definition bufmgr.c:5872

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

Referenced by LockBuffer().

◆ UnlockBuffers()

void UnlockBuffers ( void  )
extern

Definition at line 5710 of file bufmgr.c.

5711{
5713
5714 if (buf)
5715 {
5717 uint64 unset_bits = 0;
5718
5720
5721 /*
5722 * Don't complain if flag bit not set; it could have been reset but we
5723 * got a cancel/die interrupt before getting the signal.
5724 */
5725 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5726 buf->wait_backend_pgprocno == MyProcNumber)
5728
5730 0, unset_bits,
5731 0);
5732
5734 }
5735}

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

5520{
5522 ReleaseBuffer(buffer);
5523}

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(), ginScanToDelete(), ginStepRight(), ginUpdateStats(), ginvacuumcleanup(), ginVacuumPostingTree(), ginVacuumPostingTreeLeaves(), gistbufferinginserttuples(), gistbuild(), gistbuildempty(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistGetMaxLevel(), gistinserttuples(), gistkillitems(), gistplacetopage(), gistProcessItup(), gistRedoClearFollowRight(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), gistScanPage(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_split_page(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), heap_delete(), heap_finish_speculative(), heap_force_common(), heap_get_latest_tid(), heap_index_delete_tuples(), heap_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(), 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 1733 of file bufmgr.c.

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

8530 {
8531 .stage = local_buffer_readv_stage,
8532
8533 /*
8534 * Note that this, in contrast to the shared_buffers case, uses
8535 * complete_local, as only the issuing backend has access to the required
8536 * datastructures. This is important in case the IO completion may be
8537 * consumed incidentally by another backend.
8538 */
8539 .complete_local = local_buffer_readv_complete,
8540 .report = buffer_readv_report,
8541};
static PgAioResult local_buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8514
static void local_buffer_readv_stage(PgAioHandle *ioh, uint8 cb_data)
Definition bufmgr.c:8508
static void buffer_readv_report(PgAioResult result, const PgAioTargetData *td, int elevel)
Definition bufmgr.c:8362

◆ aio_shared_buffer_readv_cb

PGDLLIMPORT const PgAioHandleCallbacks aio_shared_buffer_readv_cb
extern

Definition at line 8521 of file bufmgr.c.

8521 {
8523 .complete_shared = shared_buffer_readv_complete,
8524 /* need a local callback to report checksum failures */
8525 .complete_local = shared_buffer_readv_complete_local,
8526 .report = buffer_readv_report,
8527};
static PgAioResult shared_buffer_readv_complete_local(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8477
static void shared_buffer_readv_stage(PgAioHandle *ioh, uint8 cb_data)
Definition bufmgr.c:8457
static PgAioResult shared_buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8463

◆ backend_flush_after

PGDLLIMPORT int backend_flush_after
extern

Definition at line 210 of file bufmgr.c.

Referenced by BufferManagerShmemInit().

◆ bgwriter_flush_after

PGDLLIMPORT int bgwriter_flush_after
extern

Definition at line 209 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

PGDLLIMPORT int bgwriter_lru_maxpages
extern

Definition at line 175 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

PGDLLIMPORT double bgwriter_lru_multiplier
extern

Definition at line 176 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 208 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 201 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 174 of file bufmgr.c.

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