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

◆ SMgrRelation

Definition at line 97 of file bufmgr.h.

◆ WritebackContext

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

4104{
4106
4108
4110}
static void CheckForBufferLeaks(void)
Definition bufmgr.c:4173
static int32 PrivateRefCountOverflowed
Definition bufmgr.c:250
#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 3735 of file bufmgr.c.

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

4357{
4359
4360 Assert(BufferIsPinned(buffer));
4361
4362 if (BufferIsLocal(buffer))
4363 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
4364 else
4365 bufHdr = GetBufferDescriptor(buffer - 1);
4366
4367 /* pinned, so OK to read tag without spinlock */
4368 return bufHdr->tag.blockNum;
4369}
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
#define BufferIsPinned(bufnum)
Definition bufmgr.c:589

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

4635{
4636 char *page = BufferGetPage(buffer);
4638 XLogRecPtr lsn;
4639
4640 /*
4641 * If we don't need locking for correctness, fastpath out.
4642 */
4643 if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
4644 return PageGetLSN(page);
4645
4646 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4647 Assert(BufferIsValid(buffer));
4648 Assert(BufferIsPinned(buffer));
4649
4650 bufHdr = GetBufferDescriptor(buffer - 1);
4652 lsn = PageGetLSN(page);
4654
4655 return lsn;
4656}
static void UnlockBufHdr(BufferDesc *desc)
uint64 LockBufHdr(BufferDesc *desc)
Definition bufmgr.c:7097
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 4377 of file bufmgr.c.

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

3025{
3027
3028 Assert(BufferIsPinned(buffer));
3029
3030 if (BufferIsLocal(buffer))
3031 {
3032 int bufid = -buffer - 1;
3033
3035 /* Content locks are not maintained for local buffers. */
3036 }
3037 else
3038 {
3039 bufHdr = GetBufferDescriptor(buffer - 1);
3041 }
3042
3043 return pg_atomic_read_u64(&bufHdr->state) & BM_DIRTY;
3044}
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:2997

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

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

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

2998{
3000
3001 Assert(BufferIsPinned(buffer));
3002
3003 if (BufferIsLocal(buffer))
3004 {
3005 /* Content locks are not maintained for local buffers. */
3006 return true;
3007 }
3008 else
3009 {
3010 bufHdr = GetBufferDescriptor(buffer - 1);
3012 }
3013}
static bool BufferLockHeldByMeInMode(BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:6372
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 4604 of file bufmgr.c.

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

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

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

6485{
6486 if (BufferIsLocal(buffer))
6487 {
6488 if (LocalRefCount[-buffer - 1] != 1)
6489 elog(ERROR, "incorrect local pin count: %d",
6490 LocalRefCount[-buffer - 1]);
6491 }
6492 else
6493 {
6494 if (GetPrivateRefCount(buffer) != 1)
6495 elog(ERROR, "incorrect local pin count: %d",
6496 GetPrivateRefCount(buffer));
6497 }
6498}
static int32 GetPrivateRefCount(Buffer buffer)
Definition bufmgr.c:528
#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 4342 of file bufmgr.c.

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

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)
extern

Definition at line 6464 of file bufmgr.c.

6465{
6466 BufferDesc *buf;
6467
6468 Assert(BufferIsPinned(buffer));
6469 if (BufferIsLocal(buffer))
6470 return true; /* act as though we got it */
6471
6472 buf = GetBufferDescriptor(buffer - 1);
6473
6475}
static bool BufferLockConditional(Buffer buffer, BufferDesc *buf_hdr, BufferLockMode mode)
Definition bufmgr.c:5900

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

6691{
6694 refcount;
6695
6696 Assert(BufferIsValid(buffer));
6697
6698 /* see AIO related comment in LockBufferForCleanup() */
6699
6700 if (BufferIsLocal(buffer))
6701 {
6702 refcount = LocalRefCount[-buffer - 1];
6703 /* There should be exactly one pin */
6704 Assert(refcount > 0);
6705 if (refcount != 1)
6706 return false;
6707 /* Nobody else to wait for */
6708 return true;
6709 }
6710
6711 /* There should be exactly one local pin */
6712 refcount = GetPrivateRefCount(buffer);
6713 Assert(refcount);
6714 if (refcount != 1)
6715 return false;
6716
6717 /* Try to acquire lock */
6718 if (!ConditionalLockBuffer(buffer))
6719 return false;
6720
6721 bufHdr = GetBufferDescriptor(buffer - 1);
6724
6725 Assert(refcount > 0);
6726 if (refcount == 1)
6727 {
6728 /* Successfully acquired exclusive lock with pincount 1 */
6730 return true;
6731 }
6732
6733 /* Failed, so release the lock */
6736 return false;
6737}
#define BUF_STATE_GET_REFCOUNT(state)
bool ConditionalLockBuffer(Buffer buffer)
Definition bufmgr.c:6464
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 5377 of file bufmgr.c.

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

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

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

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

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

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

7563{
7564 *buffers_evicted = 0;
7565 *buffers_skipped = 0;
7566 *buffers_flushed = 0;
7567
7568 for (int buf = 1; buf <= NBuffers; buf++)
7569 {
7570 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7572 bool buffer_flushed;
7573
7575
7577 if (!(buf_state & BM_VALID))
7578 continue;
7579
7582
7583 LockBufHdr(desc);
7584
7586 (*buffers_evicted)++;
7587 else
7588 (*buffers_skipped)++;
7589
7590 if (buffer_flushed)
7591 (*buffers_flushed)++;
7592 }
7593}
#define BM_VALID
static bool EvictUnpinnedBufferInternal(BufferDesc *desc, bool *buffer_flushed)
Definition bufmgr.c:7470
static void ReservePrivateRefCountEntry(void)
Definition bufmgr.c:293
#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 7611 of file bufmgr.c.

7613{
7615
7616 *buffers_skipped = 0;
7617 *buffers_evicted = 0;
7618 *buffers_flushed = 0;
7619
7620 for (int buf = 1; buf <= NBuffers; buf++)
7621 {
7622 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7624 bool buffer_flushed;
7625
7627
7628 /* An unlocked precheck should be safe and saves some cycles. */
7629 if ((buf_state & BM_VALID) == 0 ||
7631 continue;
7632
7633 /* Make sure we can pin the buffer. */
7636
7637 buf_state = LockBufHdr(desc);
7638
7639 /* recheck, could have changed without the lock */
7640 if ((buf_state & BM_VALID) == 0 ||
7642 {
7643 UnlockBufHdr(desc);
7644 continue;
7645 }
7646
7648 (*buffers_evicted)++;
7649 else
7650 (*buffers_skipped)++;
7651
7652 if (buffer_flushed)
7653 (*buffers_flushed)++;
7654 }
7655}
#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 964 of file bufmgr.c.

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

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

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

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

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

5442{
5443 int i;
5445
5446 for (i = 0; i < NBuffers; i++)
5447 {
5449
5451
5452 /*
5453 * As in DropRelationBuffers, an unlocked precheck should be safe and
5454 * saves some cycles.
5455 */
5456 if (bufHdr->tag.dbOid != dbid)
5457 continue;
5458
5459 /* Make sure we can handle the pin */
5462
5464 if (bufHdr->tag.dbOid == dbid &&
5466 {
5470 }
5471 else
5473 }
5474}
static void FlushUnlockedBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition bufmgr.c:4553
static void PinBuffer_Locked(BufferDesc *buf)
Definition bufmgr.c:3292
static void UnpinBuffer(BufferDesc *buf)
Definition bufmgr.c:3360
@ 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 5481 of file bufmgr.c.

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

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

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

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

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:184
int io_combine_limit
Definition bufmgr.c:199
uint32 GetPinLimit(void)
Definition bufmgr.c:2603
#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:553
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 2615 of file bufmgr.c.

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

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

2604{
2605 return MaxProportionalPins;
2606}

References MaxProportionalPins.

Referenced by GetAccessStrategy(), and read_stream_begin_impl().

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )
extern

Definition at line 6664 of file bufmgr.c.

6665{
6667
6668 /*
6669 * If we get woken slowly then it's possible that the Startup process was
6670 * already woken by other backends before we got here. Also possible that
6671 * we get here by multiple interrupts or interrupts at inappropriate
6672 * times, so make sure we do nothing if the bufid is not set.
6673 */
6674 if (bufid < 0)
6675 return false;
6676
6677 if (GetPrivateRefCount(bufid + 1) > 0)
6678 return true;
6679
6680 return false;
6681}
int GetStartupBufferPinWaitBufId(void)
Definition proc.c:771

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

Referenced by CheckRecoveryConflictDeadlock(), and ProcessRecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)
extern

Definition at line 5533 of file bufmgr.c.

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

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

4121{
4123
4124 /*
4125 * An advisory limit on the number of pins each backend should hold, based
4126 * on shared_buffers and the maximum number of connections possible.
4127 * That's very pessimistic, but outside toy-sized shared_buffers it should
4128 * allow plenty of pins. LimitAdditionalPins() and
4129 * GetAdditionalPinLimit() can be used to check the remaining balance.
4130 */
4132
4135
4136 hash_ctl.keysize = sizeof(Buffer);
4137 hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
4138
4139 PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
4141
4142 /*
4143 * AtProcExit_Buffers needs LWLock access, and thereby has to be called at
4144 * the corresponding phase of backend shutdown.
4145 */
4146 Assert(MyProc != NULL);
4148}
static Buffer PrivateRefCountArrayKeys[REFCOUNT_ARRAY_ENTRIES]
Definition bufmgr.c:247
static void AtProcExit_Buffers(int code, Datum arg)
Definition bufmgr.c:4155
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition bufmgr.c:248
static HTAB * PrivateRefCountHash
Definition bufmgr.c:249
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:469
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 6748 of file bufmgr.c.

6749{
6752
6753 Assert(BufferIsValid(buffer));
6754
6755 /* see AIO related comment in LockBufferForCleanup() */
6756
6757 if (BufferIsLocal(buffer))
6758 {
6759 /* There should be exactly one pin */
6760 if (LocalRefCount[-buffer - 1] != 1)
6761 return false;
6762 /* Nobody else to wait for */
6763 return true;
6764 }
6765
6766 /* There should be exactly one local pin */
6767 if (GetPrivateRefCount(buffer) != 1)
6768 return false;
6769
6770 bufHdr = GetBufferDescriptor(buffer - 1);
6771
6772 /* caller must hold exclusive lock on buffer */
6774
6776
6779 {
6780 /* pincount is OK. */
6782 return true;
6783 }
6784
6786 return false;
6787}

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

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

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:6405
void LockBufferInternal(Buffer buffer, BufferLockMode mode)
Definition bufmgr.c:6421

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

6518{
6520 TimestampTz waitStart = 0;
6521 bool waiting = false;
6522 bool logged_recovery_conflict = false;
6523
6524 Assert(BufferIsPinned(buffer));
6526
6528
6529 /*
6530 * We do not yet need to be worried about in-progress AIOs holding a pin,
6531 * as we, so far, only support doing reads via AIO and this function can
6532 * only be called once the buffer is valid (i.e. no read can be in
6533 * flight).
6534 */
6535
6536 /* Nobody else to wait for */
6537 if (BufferIsLocal(buffer))
6538 return;
6539
6540 bufHdr = GetBufferDescriptor(buffer - 1);
6541
6542 for (;;)
6543 {
6545 uint64 unset_bits = 0;
6546
6547 /* Try to acquire lock */
6550
6553 {
6554 /* Successfully acquired exclusive lock with pincount 1 */
6556
6557 /*
6558 * Emit the log message if recovery conflict on buffer pin was
6559 * resolved but the startup process waited longer than
6560 * deadlock_timeout for it.
6561 */
6564 waitStart, GetCurrentTimestamp(),
6565 NULL, false);
6566
6567 if (waiting)
6568 {
6569 /* reset ps display to remove the suffix if we added one */
6571 waiting = false;
6572 }
6573 return;
6574 }
6575 /* Failed, so mark myself as waiting for pincount 1 */
6577 {
6580 elog(ERROR, "multiple backends attempting to wait for pincount 1");
6581 }
6582 bufHdr->wait_backend_pgprocno = MyProcNumber;
6586 0);
6588
6589 /* Wait to be signaled by UnpinBuffer() */
6590 if (InHotStandby)
6591 {
6592 if (!waiting)
6593 {
6594 /* adjust the process title to indicate that it's waiting */
6595 set_ps_display_suffix("waiting");
6596 waiting = true;
6597 }
6598
6599 /*
6600 * Emit the log message if the startup process is waiting longer
6601 * than deadlock_timeout for recovery conflict on buffer pin.
6602 *
6603 * Skip this if first time through because the startup process has
6604 * not started waiting yet in this case. So, the wait start
6605 * timestamp is set after this logic.
6606 */
6607 if (waitStart != 0 && !logged_recovery_conflict)
6608 {
6610
6611 if (TimestampDifferenceExceeds(waitStart, now,
6613 {
6615 waitStart, now, NULL, true);
6617 }
6618 }
6619
6620 /*
6621 * Set the wait start timestamp if logging is enabled and first
6622 * time through.
6623 */
6624 if (log_recovery_conflict_waits && waitStart == 0)
6625 waitStart = GetCurrentTimestamp();
6626
6627 /* Publish the bufid that Startup process waits on */
6628 SetStartupBufferPinWaitBufId(buffer - 1);
6629 /* Set alarm and then wait to be signaled by UnpinBuffer() */
6631 /* Reset the published bufid */
6633 }
6634 else
6636
6637 /*
6638 * Remove flag marking us as waiter. Normally this will not be set
6639 * anymore, but ProcWaitForSignal() can return for other signals as
6640 * well. We take care to only reset the flag if we're the waiter, as
6641 * theoretically another backend could have started waiting. That's
6642 * impossible with the current usages due to table level locking, but
6643 * better be safe.
6644 */
6646 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
6647 bufHdr->wait_backend_pgprocno == MyProcNumber)
6649
6651 0, unset_bits,
6652 0);
6653
6655 /* Loop back and try again */
6656 }
6657}
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:6484
static BufferDesc * PinCountWaitBuf
Definition bufmgr.c:212
int64 TimestampTz
Definition timestamp.h:39
@ PROCSIG_RECOVERY_CONFLICT_BUFFERPIN
Definition procsignal.h:47
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:759
void ProcWaitForSignal(uint32 wait_event_info)
Definition proc.c:1980
void ResolveRecoveryConflictWithBufferPin(void)
Definition standby.c:793
bool log_recovery_conflict_waits
Definition standby.c:42
void LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start, TimestampTz now, VirtualTransactionId *wait_list, bool still_waiting)
Definition standby.c:274
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, PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, ProcWaitForSignal(), 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 6421 of file bufmgr.c.

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

3057{
3061
3062 if (!BufferIsValid(buffer))
3063 elog(ERROR, "bad buffer ID: %d", buffer);
3064
3065 if (BufferIsLocal(buffer))
3066 {
3067 MarkLocalBufferDirty(buffer);
3068 return;
3069 }
3070
3071 bufHdr = GetBufferDescriptor(buffer - 1);
3072
3073 Assert(BufferIsPinned(buffer));
3075
3076 /*
3077 * NB: We have to wait for the buffer header spinlock to be not held, as
3078 * TerminateBufferIO() relies on the spinlock.
3079 */
3081 for (;;)
3082 {
3085
3087
3090
3092 buf_state))
3093 break;
3094 }
3095
3096 /*
3097 * If the buffer was not dirty already, do vacuum accounting.
3098 */
3099 if (!(old_buf_state & BM_DIRTY))
3100 {
3102 if (VacuumCostActive)
3104 }
3105}
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:7145
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 5565 of file bufmgr.c.

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

7814{
7815 *buffers_dirtied = 0;
7817 *buffers_skipped = 0;
7818
7819 for (int buf = 1; buf <= NBuffers; buf++)
7820 {
7821 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7824
7826
7828 if (!(buf_state & BM_VALID))
7829 continue;
7830
7833
7834 LockBufHdr(desc);
7835
7837 (*buffers_dirtied)++;
7838 else if (buffer_already_dirty)
7839 (*buffers_already_dirty)++;
7840 else
7841 (*buffers_skipped)++;
7842 }
7843}
static bool MarkDirtyUnpinnedBufferInternal(Buffer buf, BufferDesc *desc, bool *buffer_already_dirty)
Definition bufmgr.c:7662

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

7758{
7760
7761 *buffers_dirtied = 0;
7763 *buffers_skipped = 0;
7764
7765 for (int buf = 1; buf <= NBuffers; buf++)
7766 {
7767 BufferDesc *desc = GetBufferDescriptor(buf - 1);
7770
7772
7773 /* An unlocked precheck should be safe and saves some cycles. */
7774 if ((buf_state & BM_VALID) == 0 ||
7776 continue;
7777
7778 /* Make sure we can pin the buffer. */
7781
7782 buf_state = LockBufHdr(desc);
7783
7784 /* recheck, could have changed without the lock */
7785 if ((buf_state & BM_VALID) == 0 ||
7787 {
7788 UnlockBufHdr(desc);
7789 continue;
7790 }
7791
7793 (*buffers_dirtied)++;
7794 else if (buffer_already_dirty)
7795 (*buffers_already_dirty)++;
7796 else
7797 (*buffers_skipped)++;
7798 }
7799}

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

7719{
7720 BufferDesc *desc;
7721 bool buffer_dirtied = false;
7722
7724
7725 /* Make sure we can pin the buffer. */
7728
7729 desc = GetBufferDescriptor(buf - 1);
7730 LockBufHdr(desc);
7731
7733 /* Both can not be true at the same time */
7735
7736 return buffer_dirtied;
7737}

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

773{
775 Assert(BlockNumberIsValid(blockNum));
776
778 {
779 /* see comments in ReadBufferExtended */
783 errmsg("cannot access temporary tables of other sessions")));
784
785 /* pass it off to localbuf.c */
786 return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
787 }
788 else
789 {
790 /* pass it to the shared buffer version */
791 return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
792 }
793}
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition bufmgr.c:682
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#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 682 of file bufmgr.c.

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

865{
867}
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition bufmgr.c:911

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

References StartReadBuffersImpl().

Referenced by read_stream_start_pending_read().

◆ UnlockBuffer()

void UnlockBuffer ( Buffer  buffer)
extern

Definition at line 6405 of file bufmgr.c.

6406{
6408
6409 Assert(BufferIsPinned(buffer));
6410 if (BufferIsLocal(buffer))
6411 return; /* local buffers need no lock */
6412
6413 buf_hdr = GetBufferDescriptor(buffer - 1);
6414 BufferLockUnlock(buffer, buf_hdr);
6415}
static void BufferLockUnlock(Buffer buffer, BufferDesc *buf_hdr)
Definition bufmgr.c:5871

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

Referenced by LockBuffer().

◆ UnlockBuffers()

void UnlockBuffers ( void  )
extern

Definition at line 5709 of file bufmgr.c.

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

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

5519{
5521 ReleaseBuffer(buffer);
5522}

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

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

8519 {
8520 .stage = local_buffer_readv_stage,
8521
8522 /*
8523 * Note that this, in contrast to the shared_buffers case, uses
8524 * complete_local, as only the issuing backend has access to the required
8525 * datastructures. This is important in case the IO completion may be
8526 * consumed incidentally by another backend.
8527 */
8528 .complete_local = local_buffer_readv_complete,
8529 .report = buffer_readv_report,
8530};
static PgAioResult local_buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8503
static void local_buffer_readv_stage(PgAioHandle *ioh, uint8 cb_data)
Definition bufmgr.c:8497
static void buffer_readv_report(PgAioResult result, const PgAioTargetData *td, int elevel)
Definition bufmgr.c:8351

◆ aio_shared_buffer_readv_cb

PGDLLIMPORT const PgAioHandleCallbacks aio_shared_buffer_readv_cb
extern

Definition at line 8510 of file bufmgr.c.

8510 {
8512 .complete_shared = shared_buffer_readv_complete,
8513 /* need a local callback to report checksum failures */
8514 .complete_local = shared_buffer_readv_complete_local,
8515 .report = buffer_readv_report,
8516};
static PgAioResult shared_buffer_readv_complete_local(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8466
static void shared_buffer_readv_stage(PgAioHandle *ioh, uint8 cb_data)
Definition bufmgr.c:8446
static PgAioResult shared_buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
Definition bufmgr.c:8452

◆ backend_flush_after

PGDLLIMPORT int backend_flush_after
extern

Definition at line 209 of file bufmgr.c.

Referenced by BufferManagerShmemInit().

◆ bgwriter_flush_after

PGDLLIMPORT int bgwriter_flush_after
extern

Definition at line 208 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

PGDLLIMPORT int bgwriter_lru_maxpages
extern

Definition at line 174 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

PGDLLIMPORT double bgwriter_lru_multiplier
extern

Definition at line 175 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 207 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 200 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 173 of file bufmgr.c.

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