PostgreSQL Source Code git master
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 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 BUFFER_LOCK_UNLOCK   0
 
#define BUFFER_LOCK_SHARE   1
 
#define BUFFER_LOCK_EXCLUSIVE   2
 
#define RelationGetNumberOfBlocks(reln)    RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)
 

Typedefs

typedef void * Block
 
typedef enum BufferAccessStrategyType BufferAccessStrategyType
 
typedef struct PrefetchBufferResult PrefetchBufferResult
 
typedef enum ExtendBufferedFlags ExtendBufferedFlags
 
typedef struct BufferManagerRelation BufferManagerRelation
 
typedef struct ReadBuffersOperation ReadBuffersOperation
 

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)
}
 

Functions

PrefetchBufferResult PrefetchSharedBuffer (struct SMgrRelationData *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 BufferIsExclusiveLocked (Buffer buffer)
 
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)
 
char * DebugPrintBufferRefcount (Buffer buffer)
 
void CheckPointBuffers (int flags)
 
BlockNumber BufferGetBlockNumber (Buffer buffer)
 
BlockNumber RelationGetNumberOfBlocksInFork (Relation relation, ForkNumber forkNum)
 
void FlushOneBuffer (Buffer buffer)
 
void FlushRelationBuffers (Relation rel)
 
void FlushRelationsAllBuffers (struct SMgrRelationData **smgrs, int nrels)
 
void CreateAndCopyRelationData (RelFileLocator src_rlocator, RelFileLocator dst_rlocator, bool permanent)
 
void FlushDatabaseBuffers (Oid dbid)
 
void DropRelationBuffers (struct SMgrRelationData *smgr_reln, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
 
void DropRelationsAllBuffers (struct SMgrRelationData **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 LockBuffer (Buffer buffer, int mode)
 
bool ConditionalLockBuffer (Buffer buffer)
 
void LockBufferForCleanup (Buffer buffer)
 
bool ConditionalLockBufferForCleanup (Buffer buffer)
 
bool IsBufferCleanupOK (Buffer buffer)
 
bool HoldingBufferPinThatDelaysRecovery (void)
 
bool BgBufferSync (struct 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)
 
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 char * BufferBlocks
 
PGDLLIMPORT int NLocBuffer
 
PGDLLIMPORT BlockLocalBufferBlockPointers
 
PGDLLIMPORT int32LocalRefCount
 

Macro Definition Documentation

◆ BMR_REL

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

Definition at line 108 of file bufmgr.h.

◆ BMR_SMGR

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

Definition at line 109 of file bufmgr.h.

◆ BUFFER_LOCK_EXCLUSIVE

#define BUFFER_LOCK_EXCLUSIVE   2

Definition at line 198 of file bufmgr.h.

◆ BUFFER_LOCK_SHARE

#define BUFFER_LOCK_SHARE   1

Definition at line 197 of file bufmgr.h.

◆ BUFFER_LOCK_UNLOCK

#define BUFFER_LOCK_UNLOCK   0

Definition at line 196 of file bufmgr.h.

◆ DEFAULT_EFFECTIVE_IO_CONCURRENCY

#define DEFAULT_EFFECTIVE_IO_CONCURRENCY   16

Definition at line 161 of file bufmgr.h.

◆ DEFAULT_IO_COMBINE_LIMIT

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

Definition at line 167 of file bufmgr.h.

◆ DEFAULT_MAINTENANCE_IO_CONCURRENCY

#define DEFAULT_MAINTENANCE_IO_CONCURRENCY   16

Definition at line 162 of file bufmgr.h.

◆ MAX_IO_COMBINE_LIMIT

#define MAX_IO_COMBINE_LIMIT   PG_IOV_MAX

Definition at line 166 of file bufmgr.h.

◆ MAX_IO_CONCURRENCY

#define MAX_IO_CONCURRENCY   1000

Definition at line 188 of file bufmgr.h.

◆ P_NEW

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

Definition at line 191 of file bufmgr.h.

◆ READ_BUFFERS_IGNORE_CHECKSUM_FAILURES

#define READ_BUFFERS_IGNORE_CHECKSUM_FAILURES   (1 << 2)

Definition at line 116 of file bufmgr.h.

◆ READ_BUFFERS_ISSUE_ADVICE

#define READ_BUFFERS_ISSUE_ADVICE   (1 << 1)

Definition at line 114 of file bufmgr.h.

◆ READ_BUFFERS_SYNCHRONOUSLY

#define READ_BUFFERS_SYNCHRONOUSLY   (1 << 3)

Definition at line 118 of file bufmgr.h.

◆ READ_BUFFERS_ZERO_ON_ERROR

#define READ_BUFFERS_ZERO_ON_ERROR   (1 << 0)

Definition at line 112 of file bufmgr.h.

◆ RelationGetNumberOfBlocks

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

Definition at line 283 of file bufmgr.h.

Typedef Documentation

◆ Block

typedef void* Block

Definition at line 26 of file bufmgr.h.

◆ BufferAccessStrategyType

◆ BufferManagerRelation

◆ ExtendBufferedFlags

◆ PrefetchBufferResult

◆ ReadBuffersOperation

Definition at line 144 of file bufmgr.h.

Enumeration Type Documentation

◆ BufferAccessStrategyType

Enumerator
BAS_NORMAL 
BAS_BULKREAD 
BAS_BULKWRITE 
BAS_VACUUM 

Definition at line 34 of file bufmgr.h.

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

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

Definition at line 3996 of file bufmgr.c.

3997{
3999
4000 AtEOXact_LocalBuffers(isCommit);
4001
4003}
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:4065
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:217
Assert(PointerIsAligned(start, uint64))
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:993

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

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

◆ AtProcExit_LocalBuffers()

void AtProcExit_LocalBuffers ( void  )

Definition at line 1004 of file localbuf.c.

1005{
1006 /*
1007 * We shouldn't be holding any remaining pins; if we are, and assertions
1008 * aren't enabled, we'll fail later in DropRelationBuffers while trying to
1009 * drop the temp rels.
1010 */
1012}
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:960

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

◆ BgBufferSync()

bool BgBufferSync ( struct WritebackContext wb_context)

Definition at line 3625 of file bufmgr.c.

3626{
3627 /* info obtained from freelist.c */
3628 int strategy_buf_id;
3629 uint32 strategy_passes;
3630 uint32 recent_alloc;
3631
3632 /*
3633 * Information saved between calls so we can determine the strategy
3634 * point's advance rate and avoid scanning already-cleaned buffers.
3635 */
3636 static bool saved_info_valid = false;
3637 static int prev_strategy_buf_id;
3638 static uint32 prev_strategy_passes;
3639 static int next_to_clean;
3640 static uint32 next_passes;
3641
3642 /* Moving averages of allocation rate and clean-buffer density */
3643 static float smoothed_alloc = 0;
3644 static float smoothed_density = 10.0;
3645
3646 /* Potentially these could be tunables, but for now, not */
3647 float smoothing_samples = 16;
3648 float scan_whole_pool_milliseconds = 120000.0;
3649
3650 /* Used to compute how far we scan ahead */
3651 long strategy_delta;
3652 int bufs_to_lap;
3653 int bufs_ahead;
3654 float scans_per_alloc;
3655 int reusable_buffers_est;
3656 int upcoming_alloc_est;
3657 int min_scan_buffers;
3658
3659 /* Variables for the scanning loop proper */
3660 int num_to_scan;
3661 int num_written;
3662 int reusable_buffers;
3663
3664 /* Variables for final smoothed_density update */
3665 long new_strategy_delta;
3666 uint32 new_recent_alloc;
3667
3668 /*
3669 * Find out where the freelist clock sweep currently is, and how many
3670 * buffer allocations have happened since our last call.
3671 */
3672 strategy_buf_id = StrategySyncStart(&strategy_passes, &recent_alloc);
3673
3674 /* Report buffer alloc counts to pgstat */
3675 PendingBgWriterStats.buf_alloc += recent_alloc;
3676
3677 /*
3678 * If we're not running the LRU scan, just stop after doing the stats
3679 * stuff. We mark the saved state invalid so that we can recover sanely
3680 * if LRU scan is turned back on later.
3681 */
3682 if (bgwriter_lru_maxpages <= 0)
3683 {
3684 saved_info_valid = false;
3685 return true;
3686 }
3687
3688 /*
3689 * Compute strategy_delta = how many buffers have been scanned by the
3690 * clock sweep since last time. If first time through, assume none. Then
3691 * see if we are still ahead of the clock sweep, and if so, how many
3692 * buffers we could scan before we'd catch up with it and "lap" it. Note:
3693 * weird-looking coding of xxx_passes comparisons are to avoid bogus
3694 * behavior when the passes counts wrap around.
3695 */
3696 if (saved_info_valid)
3697 {
3698 int32 passes_delta = strategy_passes - prev_strategy_passes;
3699
3700 strategy_delta = strategy_buf_id - prev_strategy_buf_id;
3701 strategy_delta += (long) passes_delta * NBuffers;
3702
3703 Assert(strategy_delta >= 0);
3704
3705 if ((int32) (next_passes - strategy_passes) > 0)
3706 {
3707 /* we're one pass ahead of the strategy point */
3708 bufs_to_lap = strategy_buf_id - next_to_clean;
3709#ifdef BGW_DEBUG
3710 elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3711 next_passes, next_to_clean,
3712 strategy_passes, strategy_buf_id,
3713 strategy_delta, bufs_to_lap);
3714#endif
3715 }
3716 else if (next_passes == strategy_passes &&
3717 next_to_clean >= strategy_buf_id)
3718 {
3719 /* on same pass, but ahead or at least not behind */
3720 bufs_to_lap = NBuffers - (next_to_clean - strategy_buf_id);
3721#ifdef BGW_DEBUG
3722 elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
3723 next_passes, next_to_clean,
3724 strategy_passes, strategy_buf_id,
3725 strategy_delta, bufs_to_lap);
3726#endif
3727 }
3728 else
3729 {
3730 /*
3731 * We're behind, so skip forward to the strategy point and start
3732 * cleaning from there.
3733 */
3734#ifdef BGW_DEBUG
3735 elog(DEBUG2, "bgwriter behind: bgw %u-%u strategy %u-%u delta=%ld",
3736 next_passes, next_to_clean,
3737 strategy_passes, strategy_buf_id,
3738 strategy_delta);
3739#endif
3740 next_to_clean = strategy_buf_id;
3741 next_passes = strategy_passes;
3742 bufs_to_lap = NBuffers;
3743 }
3744 }
3745 else
3746 {
3747 /*
3748 * Initializing at startup or after LRU scanning had been off. Always
3749 * start at the strategy point.
3750 */
3751#ifdef BGW_DEBUG
3752 elog(DEBUG2, "bgwriter initializing: strategy %u-%u",
3753 strategy_passes, strategy_buf_id);
3754#endif
3755 strategy_delta = 0;
3756 next_to_clean = strategy_buf_id;
3757 next_passes = strategy_passes;
3758 bufs_to_lap = NBuffers;
3759 }
3760
3761 /* Update saved info for next time */
3762 prev_strategy_buf_id = strategy_buf_id;
3763 prev_strategy_passes = strategy_passes;
3764 saved_info_valid = true;
3765
3766 /*
3767 * Compute how many buffers had to be scanned for each new allocation, ie,
3768 * 1/density of reusable buffers, and track a moving average of that.
3769 *
3770 * If the strategy point didn't move, we don't update the density estimate
3771 */
3772 if (strategy_delta > 0 && recent_alloc > 0)
3773 {
3774 scans_per_alloc = (float) strategy_delta / (float) recent_alloc;
3775 smoothed_density += (scans_per_alloc - smoothed_density) /
3776 smoothing_samples;
3777 }
3778
3779 /*
3780 * Estimate how many reusable buffers there are between the current
3781 * strategy point and where we've scanned ahead to, based on the smoothed
3782 * density estimate.
3783 */
3784 bufs_ahead = NBuffers - bufs_to_lap;
3785 reusable_buffers_est = (float) bufs_ahead / smoothed_density;
3786
3787 /*
3788 * Track a moving average of recent buffer allocations. Here, rather than
3789 * a true average we want a fast-attack, slow-decline behavior: we
3790 * immediately follow any increase.
3791 */
3792 if (smoothed_alloc <= (float) recent_alloc)
3793 smoothed_alloc = recent_alloc;
3794 else
3795 smoothed_alloc += ((float) recent_alloc - smoothed_alloc) /
3796 smoothing_samples;
3797
3798 /* Scale the estimate by a GUC to allow more aggressive tuning. */
3799 upcoming_alloc_est = (int) (smoothed_alloc * bgwriter_lru_multiplier);
3800
3801 /*
3802 * If recent_alloc remains at zero for many cycles, smoothed_alloc will
3803 * eventually underflow to zero, and the underflows produce annoying
3804 * kernel warnings on some platforms. Once upcoming_alloc_est has gone to
3805 * zero, there's no point in tracking smaller and smaller values of
3806 * smoothed_alloc, so just reset it to exactly zero to avoid this
3807 * syndrome. It will pop back up as soon as recent_alloc increases.
3808 */
3809 if (upcoming_alloc_est == 0)
3810 smoothed_alloc = 0;
3811
3812 /*
3813 * Even in cases where there's been little or no buffer allocation
3814 * activity, we want to make a small amount of progress through the buffer
3815 * cache so that as many reusable buffers as possible are clean after an
3816 * idle period.
3817 *
3818 * (scan_whole_pool_milliseconds / BgWriterDelay) computes how many times
3819 * the BGW will be called during the scan_whole_pool time; slice the
3820 * buffer pool into that many sections.
3821 */
3822 min_scan_buffers = (int) (NBuffers / (scan_whole_pool_milliseconds / BgWriterDelay));
3823
3824 if (upcoming_alloc_est < (min_scan_buffers + reusable_buffers_est))
3825 {
3826#ifdef BGW_DEBUG
3827 elog(DEBUG2, "bgwriter: alloc_est=%d too small, using min=%d + reusable_est=%d",
3828 upcoming_alloc_est, min_scan_buffers, reusable_buffers_est);
3829#endif
3830 upcoming_alloc_est = min_scan_buffers + reusable_buffers_est;
3831 }
3832
3833 /*
3834 * Now write out dirty reusable buffers, working forward from the
3835 * next_to_clean point, until we have lapped the strategy scan, or cleaned
3836 * enough buffers to match our estimate of the next cycle's allocation
3837 * requirements, or hit the bgwriter_lru_maxpages limit.
3838 */
3839
3840 num_to_scan = bufs_to_lap;
3841 num_written = 0;
3842 reusable_buffers = reusable_buffers_est;
3843
3844 /* Execute the LRU scan */
3845 while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
3846 {
3847 int sync_state = SyncOneBuffer(next_to_clean, true,
3848 wb_context);
3849
3850 if (++next_to_clean >= NBuffers)
3851 {
3852 next_to_clean = 0;
3853 next_passes++;
3854 }
3855 num_to_scan--;
3856
3857 if (sync_state & BUF_WRITTEN)
3858 {
3859 reusable_buffers++;
3860 if (++num_written >= bgwriter_lru_maxpages)
3861 {
3863 break;
3864 }
3865 }
3866 else if (sync_state & BUF_REUSABLE)
3867 reusable_buffers++;
3868 }
3869
3871
3872#ifdef BGW_DEBUG
3873 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",
3874 recent_alloc, smoothed_alloc, strategy_delta, bufs_ahead,
3875 smoothed_density, reusable_buffers_est, upcoming_alloc_est,
3876 bufs_to_lap - num_to_scan,
3877 num_written,
3878 reusable_buffers - reusable_buffers_est);
3879#endif
3880
3881 /*
3882 * Consider the above scan as being like a new allocation scan.
3883 * Characterize its density and update the smoothed one based on it. This
3884 * effectively halves the moving average period in cases where both the
3885 * strategy and the background writer are doing some useful scanning,
3886 * which is helpful because a long memory isn't as desirable on the
3887 * density estimates.
3888 */
3889 new_strategy_delta = bufs_to_lap - num_to_scan;
3890 new_recent_alloc = reusable_buffers - reusable_buffers_est;
3891 if (new_strategy_delta > 0 && new_recent_alloc > 0)
3892 {
3893 scans_per_alloc = (float) new_strategy_delta / (float) new_recent_alloc;
3894 smoothed_density += (scans_per_alloc - smoothed_density) /
3895 smoothing_samples;
3896
3897#ifdef BGW_DEBUG
3898 elog(DEBUG2, "bgwriter: cleaner density alloc=%u scan=%ld density=%.2f new smoothed=%.2f",
3899 new_recent_alloc, new_strategy_delta,
3900 scans_per_alloc, smoothed_density);
3901#endif
3902 }
3903
3904 /* Return true if OK to hibernate */
3905 return (bufs_to_lap == 0 && recent_alloc == 0);
3906}
int BgWriterDelay
Definition: bgwriter.c:58
#define BUF_REUSABLE
Definition: bufmgr.c:81
double bgwriter_lru_multiplier
Definition: bufmgr.c:146
static int SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
Definition: bufmgr.c:3923
int bgwriter_lru_maxpages
Definition: bufmgr.c:145
#define BUF_WRITTEN
Definition: bufmgr.c:80
int32_t int32
Definition: c.h:498
uint32_t uint32
Definition: c.h:502
#define DEBUG2
Definition: elog.h:29
#define DEBUG1
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:225
int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc)
Definition: freelist.c:394
int NBuffers
Definition: globals.c:143
PgStat_BgWriterStats PendingBgWriterStats
PgStat_Counter buf_written_clean
Definition: pgstat.h:239
PgStat_Counter maxwritten_clean
Definition: pgstat.h:240
PgStat_Counter buf_alloc
Definition: pgstat.h:241

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, PgStat_BgWriterStats::maxwritten_clean, NBuffers, PendingBgWriterStats, StrategySyncStart(), and SyncOneBuffer().

Referenced by BackgroundWriterMain().

◆ BufferGetBlock()

static Block BufferGetBlock ( Buffer  buffer)
inlinestatic

Definition at line 384 of file bufmgr.h.

385{
386 Assert(BufferIsValid(buffer));
387
388 if (BufferIsLocal(buffer))
389 return LocalBufferBlockPointers[-buffer - 1];
390 else
391 return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
392}
#define BufferIsLocal(buffer)
Definition: buf.h:37
PGDLLIMPORT Block * LocalBufferBlockPointers
Definition: localbuf.c:47
void * Block
Definition: bufmgr.h:26
PGDLLIMPORT char * BufferBlocks
Definition: buf_init.c:22
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:368
size_t Size
Definition: c.h:576

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

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

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)

Definition at line 4231 of file bufmgr.c.

4232{
4233 BufferDesc *bufHdr;
4234
4235 Assert(BufferIsPinned(buffer));
4236
4237 if (BufferIsLocal(buffer))
4238 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
4239 else
4240 bufHdr = GetBufferDescriptor(buffer - 1);
4241
4242 /* pinned, so OK to read tag without spinlock */
4243 return bufHdr->tag.blockNum;
4244}
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:483
BufferTag tag
BlockNumber blockNum

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

Referenced by _bt_binsrch_insert(), _bt_bottomupdel_pass(), _bt_check_unique(), _bt_checkpage(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_doinsert(), _bt_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_is_all_visible(), heap_page_prune_and_freeze(), 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(), 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(), and visibilitymap_set().

◆ BufferGetLSNAtomic()

XLogRecPtr BufferGetLSNAtomic ( Buffer  buffer)

Definition at line 4493 of file bufmgr.c.

4494{
4495 char *page = BufferGetPage(buffer);
4496 BufferDesc *bufHdr;
4497 XLogRecPtr lsn;
4498 uint32 buf_state;
4499
4500 /*
4501 * If we don't need locking for correctness, fastpath out.
4502 */
4503 if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
4504 return PageGetLSN(page);
4505
4506 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4507 Assert(BufferIsValid(buffer));
4508 Assert(BufferIsPinned(buffer));
4509
4510 bufHdr = GetBufferDescriptor(buffer - 1);
4511 buf_state = LockBufHdr(bufHdr);
4512 lsn = PageGetLSN(page);
4513 UnlockBufHdr(bufHdr, buf_state);
4514
4515 return lsn;
4516}
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:6259
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:417
static XLogRecPtr PageGetLSN(const PageData *page)
Definition: bufpage.h:386
#define XLogHintBitIsNeeded()
Definition: xlog.h:120
uint64 XLogRecPtr
Definition: xlogdefs.h:21

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

Referenced by _bt_killitems(), _bt_readpage(), gin_check_parent_keys_consistency(), gistdoinsert(), gistFindPath(), gistkillitems(), gistScanPage(), SetHintBits(), and XLogSaveBufferForHint().

◆ BufferGetPage()

static Page BufferGetPage ( Buffer  buffer)
inlinestatic

Definition at line 417 of file bufmgr.h.

418{
419 return (Page) BufferGetBlock(buffer);
420}
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:384
PageData * Page
Definition: bufpage.h:82

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(), do_setval(), 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_is_all_visible(), heap_page_prune_and_freeze(), heap_page_prune_execute(), heap_page_prune_opt(), 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_visibility(), pgstat_btree_page(), pgstat_gist_page(), pgstat_hash_page(), pgstat_heap(), pgstatginindex_internal(), pgstathashindex(), pgstatindex_impl(), read_seq_tuple(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), RelationPutHeapTuple(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), scanPostingTree(), ScanSourceDatabasePgClass(), seq_redo(), shiftList(), spgAddNodeAction(), spgbuild(), spgdoinsert(), spgGetCache(), SpGistGetBuffer(), SpGistInitBuffer(), SpGistNewBuffer(), SpGistSetLastUsedPage(), SpGistUpdateMetaPage(), spgprocesspending(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), spgvacuumpage(), spgWalk(), startScanEntry(), statapprox_heap(), terminate_brin_buildstate(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_prepare_truncate(), visibilitymap_set(), vm_readbuf(), writeListPage(), XLogCheckBufferNeedsBackup(), XLogReadBufferExtended(), XLogReadBufferForRedoExtended(), XLogRecordPageWithFreeSpace(), XLogRegisterBuffer(), XLogSaveBufferForHint(), xlogVacuumPage(), and ZeroAndLockBuffer().

◆ BufferGetPageSize()

◆ BufferGetTag()

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

Definition at line 4252 of file bufmgr.c.

4254{
4255 BufferDesc *bufHdr;
4256
4257 /* Do the same checks as BufferGetBlockNumber. */
4258 Assert(BufferIsPinned(buffer));
4259
4260 if (BufferIsLocal(buffer))
4261 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
4262 else
4263 bufHdr = GetBufferDescriptor(buffer - 1);
4264
4265 /* pinned, so OK to read tag without spinlock */
4266 *rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
4267 *forknum = BufTagGetForkNum(&bufHdr->tag);
4268 *blknum = bufHdr->tag.blockNum;
4269}
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)

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

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

◆ BufferIsDirty()

bool BufferIsDirty ( Buffer  buffer)

Definition at line 2919 of file bufmgr.c.

2920{
2921 BufferDesc *bufHdr;
2922
2923 Assert(BufferIsPinned(buffer));
2924
2925 if (BufferIsLocal(buffer))
2926 {
2927 int bufid = -buffer - 1;
2928
2929 bufHdr = GetLocalBufferDescriptor(bufid);
2930 /* Content locks are not maintained for local buffers. */
2931 }
2932 else
2933 {
2934 bufHdr = GetBufferDescriptor(buffer - 1);
2936 LW_EXCLUSIVE));
2937 }
2938
2939 return pg_atomic_read_u32(&bufHdr->state) & BM_DIRTY;
2940}
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:239
static LWLock * BufferDescriptorGetContentLock(const BufferDesc *bdesc)
#define BM_DIRTY
Definition: buf_internals.h:69
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:2029
@ LW_EXCLUSIVE
Definition: lwlock.h:114
pg_atomic_uint32 state

References Assert(), BM_DIRTY, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsPinned, GetBufferDescriptor(), GetLocalBufferDescriptor(), LW_EXCLUSIVE, LWLockHeldByMeInMode(), pg_atomic_read_u32(), and BufferDesc::state.

Referenced by XLogRegisterBuffer().

◆ BufferIsExclusiveLocked()

bool BufferIsExclusiveLocked ( Buffer  buffer)

Definition at line 2891 of file bufmgr.c.

2892{
2893 BufferDesc *bufHdr;
2894
2895 Assert(BufferIsPinned(buffer));
2896
2897 if (BufferIsLocal(buffer))
2898 {
2899 /* Content locks are not maintained for local buffers. */
2900 return true;
2901 }
2902 else
2903 {
2904 bufHdr = GetBufferDescriptor(buffer - 1);
2906 LW_EXCLUSIVE);
2907 }
2908}

References Assert(), PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsPinned, GetBufferDescriptor(), LW_EXCLUSIVE, and LWLockHeldByMeInMode().

Referenced by XLogRegisterBuffer().

◆ BufferIsPermanent()

bool BufferIsPermanent ( Buffer  buffer)

Definition at line 4463 of file bufmgr.c.

4464{
4465 BufferDesc *bufHdr;
4466
4467 /* Local buffers are used only for temp relations. */
4468 if (BufferIsLocal(buffer))
4469 return false;
4470
4471 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4472 Assert(BufferIsValid(buffer));
4473 Assert(BufferIsPinned(buffer));
4474
4475 /*
4476 * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
4477 * need not bother with the buffer header spinlock. Even if someone else
4478 * changes the buffer header state while we're doing this, the state is
4479 * changed atomically, so we'll read the old value or the new value, but
4480 * not random garbage.
4481 */
4482 bufHdr = GetBufferDescriptor(buffer - 1);
4483 return (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT) != 0;
4484}
#define BM_PERMANENT
Definition: buf_internals.h:77

References Assert(), BM_PERMANENT, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferIsValid(), GetBufferDescriptor(), pg_atomic_read_u32(), and BufferDesc::state.

Referenced by SetHintBits().

◆ BufferIsValid()

static bool BufferIsValid ( Buffer  bufnum)
inlinestatic

Definition at line 368 of file bufmgr.h.

369{
370 Assert(bufnum <= NBuffers);
371 Assert(bufnum >= -NLocBuffer);
372
373 return bufnum != InvalidBuffer;
374}
#define InvalidBuffer
Definition: buf.h:25
PGDLLIMPORT int NBuffers
Definition: globals.c:143
PGDLLIMPORT int NLocBuffer
Definition: localbuf.c:44

References Assert(), 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(), ResOwnerReleaseBufferPin(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgvacuumscan(), statapprox_heap(), tts_buffer_heap_clear(), tts_buffer_heap_copyslot(), tts_buffer_heap_materialize(), tts_buffer_heap_store_tuple(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_pin(), visibilitymap_pin_ok(), visibilitymap_prepare_truncate(), visibilitymap_set(), XLogPrefetcherNextBlock(), XLogReadBufferExtended(), and XLogReadBufferForRedoExtended().

◆ BufferManagerShmemInit()

void BufferManagerShmemInit ( void  )

Definition at line 68 of file buf_init.c.

69{
70 bool foundBufs,
71 foundDescs,
72 foundIOCV,
73 foundBufCkpt;
74
75 /* Align descriptors to a cacheline boundary. */
77 ShmemInitStruct("Buffer Descriptors",
78 NBuffers * sizeof(BufferDescPadded),
79 &foundDescs);
80
81 /* Align buffer pool on IO page size boundary. */
82 BufferBlocks = (char *)
84 ShmemInitStruct("Buffer Blocks",
85 NBuffers * (Size) BLCKSZ + PG_IO_ALIGN_SIZE,
86 &foundBufs));
87
88 /* Align condition variables to cacheline boundary. */
90 ShmemInitStruct("Buffer IO Condition Variables",
92 &foundIOCV);
93
94 /*
95 * The array used to sort to-be-checkpointed buffer ids is located in
96 * shared memory, to avoid having to allocate significant amounts of
97 * memory at runtime. As that'd be in the middle of a checkpoint, or when
98 * the checkpointer is restarted, memory allocation failures would be
99 * painful.
100 */
102 ShmemInitStruct("Checkpoint BufferIds",
103 NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
104
105 if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
106 {
107 /* should find all of these, or none of them */
108 Assert(foundDescs && foundBufs && foundIOCV && foundBufCkpt);
109 /* note: this path is only taken in EXEC_BACKEND case */
110 }
111 else
112 {
113 int i;
114
115 /*
116 * Initialize all the buffer headers.
117 */
118 for (i = 0; i < NBuffers; i++)
119 {
121
122 ClearBufferTag(&buf->tag);
123
124 pg_atomic_init_u32(&buf->state, 0);
125 buf->wait_backend_pgprocno = INVALID_PROC_NUMBER;
126
127 buf->buf_id = i;
128
129 pgaio_wref_clear(&buf->io_wref);
130
131 /*
132 * Initially link all the buffers together as unused. Subsequent
133 * management of this list is done by freelist.c.
134 */
135 buf->freeNext = i + 1;
136
139
141 }
142
143 /* Correct last entry of linked list */
145 }
146
147 /* Init other shared buffer-management stuff */
148 StrategyInitialize(!foundDescs);
149
150 /* Initialize per-backend file flush context */
153}
void pgaio_wref_clear(PgAioWaitRef *iow)
Definition: aio.c:882
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:221
CkptSortItem * CkptBufferIds
Definition: buf_init.c:25
char * BufferBlocks
Definition: buf_init.c:22
WritebackContext BackendWritebackContext
Definition: buf_init.c:24
ConditionVariableMinimallyPadded * BufferIOCVArray
Definition: buf_init.c:23
BufferDescPadded * BufferDescriptors
Definition: buf_init.c:21
static ConditionVariable * BufferDescriptorGetIOCV(const BufferDesc *bdesc)
#define FREENEXT_END_OF_LIST
static void ClearBufferTag(BufferTag *tag)
void WritebackContextInit(WritebackContext *context, int *max_pending)
Definition: bufmgr.c:6401
int backend_flush_after
Definition: bufmgr.c:180
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:775
void ConditionVariableInit(ConditionVariable *cv)
void StrategyInitialize(bool init)
Definition: freelist.c:474
int i
Definition: isn.c:77
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:721
@ LWTRANCHE_BUFFER_CONTENT
Definition: lwlock.h:191
#define PG_IO_ALIGN_SIZE
static char * buf
Definition: pg_test_fsync.c:72
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387

References Assert(), backend_flush_after, BackendWritebackContext, buf, BufferBlocks, BufferDescriptorGetContentLock(), BufferDescriptorGetIOCV(), BufferDescriptors, BufferIOCVArray, CkptBufferIds, ClearBufferTag(), ConditionVariableInit(), BufferDesc::freeNext, FREENEXT_END_OF_LIST, GetBufferDescriptor(), i, INVALID_PROC_NUMBER, LWLockInitialize(), LWTRANCHE_BUFFER_CONTENT, NBuffers, pg_atomic_init_u32(), PG_IO_ALIGN_SIZE, pgaio_wref_clear(), ShmemInitStruct(), StrategyInitialize(), TYPEALIGN, and WritebackContextInit().

Referenced by CreateOrAttachShmemStructs().

◆ BufferManagerShmemSize()

Size BufferManagerShmemSize ( void  )

Definition at line 162 of file buf_init.c.

163{
164 Size size = 0;
165
166 /* size of buffer descriptors */
167 size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
168 /* to allow aligning buffer descriptors */
169 size = add_size(size, PG_CACHE_LINE_SIZE);
170
171 /* size of data pages, plus alignment padding */
172 size = add_size(size, PG_IO_ALIGN_SIZE);
173 size = add_size(size, mul_size(NBuffers, BLCKSZ));
174
175 /* size of stuff controlled by freelist.c */
176 size = add_size(size, StrategyShmemSize());
177
178 /* size of I/O condition variables */
179 size = add_size(size, mul_size(NBuffers,
181 /* to allow aligning the above */
182 size = add_size(size, PG_CACHE_LINE_SIZE);
183
184 /* size of checkpoint sort array in bufmgr.c */
185 size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
186
187 return size;
188}
Size StrategyShmemSize(void)
Definition: freelist.c:453
#define PG_CACHE_LINE_SIZE
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510

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

Referenced by CalculateShmemSize().

◆ CheckBufferIsPinnedOnce()

void CheckBufferIsPinnedOnce ( Buffer  buffer)

Definition at line 5654 of file bufmgr.c.

5655{
5656 if (BufferIsLocal(buffer))
5657 {
5658 if (LocalRefCount[-buffer - 1] != 1)
5659 elog(ERROR, "incorrect local pin count: %d",
5660 LocalRefCount[-buffer - 1]);
5661 }
5662 else
5663 {
5664 if (GetPrivateRefCount(buffer) != 1)
5665 elog(ERROR, "incorrect local pin count: %d",
5666 GetPrivateRefCount(buffer));
5667 }
5668}
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:425
#define ERROR
Definition: elog.h:39
int32 * LocalRefCount
Definition: localbuf.c:48

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

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

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)

Definition at line 4217 of file bufmgr.c.

4218{
4219 BufferSync(flags);
4220}
static void BufferSync(int flags)
Definition: bufmgr.c:3349

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

◆ ConditionalLockBufferForCleanup()

bool ConditionalLockBufferForCleanup ( Buffer  buffer)

Definition at line 5855 of file bufmgr.c.

5856{
5857 BufferDesc *bufHdr;
5858 uint32 buf_state,
5859 refcount;
5860
5861 Assert(BufferIsValid(buffer));
5862
5863 /* see AIO related comment in LockBufferForCleanup() */
5864
5865 if (BufferIsLocal(buffer))
5866 {
5867 refcount = LocalRefCount[-buffer - 1];
5868 /* There should be exactly one pin */
5869 Assert(refcount > 0);
5870 if (refcount != 1)
5871 return false;
5872 /* Nobody else to wait for */
5873 return true;
5874 }
5875
5876 /* There should be exactly one local pin */
5877 refcount = GetPrivateRefCount(buffer);
5878 Assert(refcount);
5879 if (refcount != 1)
5880 return false;
5881
5882 /* Try to acquire lock */
5883 if (!ConditionalLockBuffer(buffer))
5884 return false;
5885
5886 bufHdr = GetBufferDescriptor(buffer - 1);
5887 buf_state = LockBufHdr(bufHdr);
5888 refcount = BUF_STATE_GET_REFCOUNT(buf_state);
5889
5890 Assert(refcount > 0);
5891 if (refcount == 1)
5892 {
5893 /* Successfully acquired exclusive lock with pincount 1 */
5894 UnlockBufHdr(bufHdr, buf_state);
5895 return true;
5896 }
5897
5898 /* Failed, so release the lock */
5899 UnlockBufHdr(bufHdr, buf_state);
5901 return false;
5902}
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:59
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:5633
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5607
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:196

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

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

◆ CreateAndCopyRelationData()

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

Definition at line 5247 of file bufmgr.c.

5249{
5250 char relpersistence;
5251 SMgrRelation src_rel;
5252 SMgrRelation dst_rel;
5253
5254 /* Set the relpersistence. */
5255 relpersistence = permanent ?
5256 RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
5257
5258 src_rel = smgropen(src_rlocator, INVALID_PROC_NUMBER);
5259 dst_rel = smgropen(dst_rlocator, INVALID_PROC_NUMBER);
5260
5261 /*
5262 * Create and copy all forks of the relation. During create database we
5263 * have a separate cleanup mechanism which deletes complete database
5264 * directory. Therefore, each individual relation doesn't need to be
5265 * registered for cleanup.
5266 */
5267 RelationCreateStorage(dst_rlocator, relpersistence, false);
5268
5269 /* copy main fork. */
5270 RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, MAIN_FORKNUM,
5271 permanent);
5272
5273 /* copy those extra forks that exist */
5274 for (ForkNumber forkNum = MAIN_FORKNUM + 1;
5275 forkNum <= MAX_FORKNUM; forkNum++)
5276 {
5277 if (smgrexists(src_rel, forkNum))
5278 {
5279 smgrcreate(dst_rel, forkNum, false);
5280
5281 /*
5282 * WAL log creation if the relation is persistent, or this is the
5283 * init fork of an unlogged relation.
5284 */
5285 if (permanent || forkNum == INIT_FORKNUM)
5286 log_smgrcreate(&dst_rlocator, forkNum);
5287
5288 /* Copy a fork's data, block by block. */
5289 RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, forkNum,
5290 permanent);
5291 }
5292 }
5293}
static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, RelFileLocator dstlocator, ForkNumber forkNum, bool permanent)
Definition: bufmgr.c:5133
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 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)

Definition at line 4174 of file bufmgr.c.

4175{
4176 BufferDesc *buf;
4177 int32 loccount;
4178 char *result;
4179 ProcNumber backend;
4180 uint32 buf_state;
4181
4182 Assert(BufferIsValid(buffer));
4183 if (BufferIsLocal(buffer))
4184 {
4185 buf = GetLocalBufferDescriptor(-buffer - 1);
4186 loccount = LocalRefCount[-buffer - 1];
4187 backend = MyProcNumber;
4188 }
4189 else
4190 {
4191 buf = GetBufferDescriptor(buffer - 1);
4192 loccount = GetPrivateRefCount(buffer);
4193 backend = INVALID_PROC_NUMBER;
4194 }
4195
4196 /* theoretically we should lock the bufhdr here */
4197 buf_state = pg_atomic_read_u32(&buf->state);
4198
4199 result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
4200 buffer,
4202 BufTagGetForkNum(&buf->tag)).str,
4203 buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
4204 BUF_STATE_GET_REFCOUNT(buf_state), loccount);
4205 return result;
4206}
#define BUF_FLAG_MASK
Definition: buf_internals.h:56
ProcNumber MyProcNumber
Definition: globals.c:91
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(), GetBufferDescriptor(), GetLocalBufferDescriptor(), GetPrivateRefCount(), INVALID_PROC_NUMBER, LocalRefCount, MyProcNumber, pg_atomic_read_u32(), psprintf(), and relpathbackend.

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

◆ DropDatabaseBuffers()

void DropDatabaseBuffers ( Oid  dbid)

Definition at line 4895 of file bufmgr.c.

4896{
4897 int i;
4898
4899 /*
4900 * We needn't consider local buffers, since by assumption the target
4901 * database isn't our own.
4902 */
4903
4904 for (i = 0; i < NBuffers; i++)
4905 {
4906 BufferDesc *bufHdr = GetBufferDescriptor(i);
4907 uint32 buf_state;
4908
4909 /*
4910 * As in DropRelationBuffers, an unlocked precheck should be safe and
4911 * saves some cycles.
4912 */
4913 if (bufHdr->tag.dbOid != dbid)
4914 continue;
4915
4916 buf_state = LockBufHdr(bufHdr);
4917 if (bufHdr->tag.dbOid == dbid)
4918 InvalidateBuffer(bufHdr); /* releases spinlock */
4919 else
4920 UnlockBufHdr(bufHdr, buf_state);
4921 }
4922}
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:2183

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

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

◆ DropRelationBuffers()

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

◆ DropRelationsAllBuffers()

void DropRelationsAllBuffers ( struct SMgrRelationData **  smgr_reln,
int  nlocators 
)

◆ EvictAllUnpinnedBuffers()

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

Definition at line 6680 of file bufmgr.c.

6682{
6683 *buffers_evicted = 0;
6684 *buffers_skipped = 0;
6685 *buffers_flushed = 0;
6686
6687 for (int buf = 1; buf <= NBuffers; buf++)
6688 {
6689 BufferDesc *desc = GetBufferDescriptor(buf - 1);
6690 uint32 buf_state;
6691 bool buffer_flushed;
6692
6693 buf_state = pg_atomic_read_u32(&desc->state);
6694 if (!(buf_state & BM_VALID))
6695 continue;
6696
6699
6700 LockBufHdr(desc);
6701
6702 if (EvictUnpinnedBufferInternal(desc, &buffer_flushed))
6703 (*buffers_evicted)++;
6704 else
6705 (*buffers_skipped)++;
6706
6707 if (buffer_flushed)
6708 (*buffers_flushed)++;
6709 }
6710}
#define BM_VALID
Definition: buf_internals.h:70
static bool EvictUnpinnedBufferInternal(BufferDesc *desc, bool *buffer_flushed)
Definition: bufmgr.c:6587
static void ReservePrivateRefCountEntry(void)
Definition: bufmgr.c:259
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:452

References BM_VALID, buf, CurrentResourceOwner, EvictUnpinnedBufferInternal(), GetBufferDescriptor(), LockBufHdr(), NBuffers, pg_atomic_read_u32(), 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 
)

Definition at line 6728 of file bufmgr.c.

6730{
6732
6733 *buffers_skipped = 0;
6734 *buffers_evicted = 0;
6735 *buffers_flushed = 0;
6736
6737 for (int buf = 1; buf <= NBuffers; buf++)
6738 {
6739 BufferDesc *desc = GetBufferDescriptor(buf - 1);
6740 uint32 buf_state = pg_atomic_read_u32(&(desc->state));
6741 bool buffer_flushed;
6742
6743 /* An unlocked precheck should be safe and saves some cycles. */
6744 if ((buf_state & BM_VALID) == 0 ||
6746 continue;
6747
6748 /* Make sure we can pin the buffer. */
6751
6752 buf_state = LockBufHdr(desc);
6753
6754 /* recheck, could have changed without the lock */
6755 if ((buf_state & BM_VALID) == 0 ||
6757 {
6758 UnlockBufHdr(desc, buf_state);
6759 continue;
6760 }
6761
6762 if (EvictUnpinnedBufferInternal(desc, &buffer_flushed))
6763 (*buffers_evicted)++;
6764 else
6765 (*buffers_skipped)++;
6766
6767 if (buffer_flushed)
6768 (*buffers_flushed)++;
6769 }
6770}
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:648
RelFileLocator rd_locator
Definition: rel.h:57

References Assert(), BM_VALID, buf, BufTagMatchesRelFileLocator(), CurrentResourceOwner, EvictUnpinnedBufferInternal(), GetBufferDescriptor(), LockBufHdr(), NBuffers, pg_atomic_read_u32(), 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 
)

Definition at line 6651 of file bufmgr.c.

6652{
6653 BufferDesc *desc;
6654
6656
6657 /* Make sure we can pin the buffer. */
6660
6661 desc = GetBufferDescriptor(buf - 1);
6662 LockBufHdr(desc);
6663
6664 return EvictUnpinnedBufferInternal(desc, buffer_flushed);
6665}

References Assert(), buf, BufferIsLocal, BufferIsValid(), CurrentResourceOwner, EvictUnpinnedBufferInternal(), GetBufferDescriptor(), LockBufHdr(), ReservePrivateRefCountEntry(), and ResourceOwnerEnlarge().

Referenced by invalidate_rel_block(), modify_rel_block(), and pg_buffercache_evict().

◆ ExtendBufferedRel()

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

Definition at line 858 of file bufmgr.c.

862{
863 Buffer buf;
864 uint32 extend_by = 1;
865
866 ExtendBufferedRelBy(bmr, forkNum, strategy, flags, extend_by,
867 &buf, &extend_by);
868
869 return buf;
870}
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:890

References buf, and ExtendBufferedRelBy().

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 
)

Definition at line 890 of file bufmgr.c.

897{
898 Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
899 Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
900 Assert(extend_by > 0);
901
902 if (bmr.smgr == NULL)
903 {
904 bmr.smgr = RelationGetSmgr(bmr.rel);
905 bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
906 }
907
908 return ExtendBufferedRelCommon(bmr, fork, strategy, flags,
909 extend_by, InvalidBlockNumber,
910 buffers, extended_by);
911}
#define InvalidBlockNumber
Definition: block.h:33
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:2566
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:578
struct SMgrRelationData * smgr
Definition: bufmgr.h:104
Form_pg_class rd_rel
Definition: rel.h:111

References Assert(), ExtendBufferedRelCommon(), InvalidBlockNumber, RelationData::rd_rel, BufferManagerRelation::rel, RelationGetSmgr(), BufferManagerRelation::relpersistence, and BufferManagerRelation::smgr.

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

◆ ExtendBufferedRelTo()

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

Definition at line 922 of file bufmgr.c.

928{
930 uint32 extended_by = 0;
931 Buffer buffer = InvalidBuffer;
932 Buffer buffers[64];
933
934 Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
935 Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
936 Assert(extend_to != InvalidBlockNumber && extend_to > 0);
937
938 if (bmr.smgr == NULL)
939 {
940 bmr.smgr = RelationGetSmgr(bmr.rel);
941 bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
942 }
943
944 /*
945 * If desired, create the file if it doesn't exist. If
946 * smgr_cached_nblocks[fork] is positive then it must exist, no need for
947 * an smgrexists call.
948 */
949 if ((flags & EB_CREATE_FORK_IF_NEEDED) &&
950 (bmr.smgr->smgr_cached_nblocks[fork] == 0 ||
952 !smgrexists(bmr.smgr, fork))
953 {
955
956 /* recheck, fork might have been created concurrently */
957 if (!smgrexists(bmr.smgr, fork))
958 smgrcreate(bmr.smgr, fork, flags & EB_PERFORMING_RECOVERY);
959
961 }
962
963 /*
964 * If requested, invalidate size cache, so that smgrnblocks asks the
965 * kernel.
966 */
967 if (flags & EB_CLEAR_SIZE_CACHE)
969
970 /*
971 * Estimate how many pages we'll need to extend by. This avoids acquiring
972 * unnecessarily many victim buffers.
973 */
974 current_size = smgrnblocks(bmr.smgr, fork);
975
976 /*
977 * Since no-one else can be looking at the page contents yet, there is no
978 * difference between an exclusive lock and a cleanup-strength lock. Note
979 * that we pass the original mode to ReadBuffer_common() below, when
980 * falling back to reading the buffer to a concurrent relation extension.
981 */
983 flags |= EB_LOCK_TARGET;
984
985 while (current_size < extend_to)
986 {
987 uint32 num_pages = lengthof(buffers);
988 BlockNumber first_block;
989
990 if ((uint64) current_size + num_pages > extend_to)
991 num_pages = extend_to - current_size;
992
993 first_block = ExtendBufferedRelCommon(bmr, fork, strategy, flags,
994 num_pages, extend_to,
995 buffers, &extended_by);
996
997 current_size = first_block + extended_by;
998 Assert(num_pages != 0 || current_size >= extend_to);
999
1000 for (uint32 i = 0; i < extended_by; i++)
1001 {
1002 if (first_block + i != extend_to - 1)
1003 ReleaseBuffer(buffers[i]);
1004 else
1005 buffer = buffers[i];
1006 }
1007 }
1008
1009 /*
1010 * It's possible that another backend concurrently extended the relation.
1011 * In that case read the buffer.
1012 *
1013 * XXX: Should we control this via a flag?
1014 */
1015 if (buffer == InvalidBuffer)
1016 {
1017 Assert(extended_by == 0);
1018 buffer = ReadBuffer_common(bmr.rel, bmr.smgr, bmr.relpersistence,
1019 fork, extend_to - 1, mode, strategy);
1020 }
1021
1022 return buffer;
1023}
uint32 BlockNumber
Definition: block.h:31
static Buffer ReadBuffer_common(Relation rel, SMgrRelation smgr, char smgr_persistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:1193
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5373
uint64_t uint64
Definition: c.h:503
#define lengthof(array)
Definition: c.h:759
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 PgChecksumMode mode
Definition: pg_checksums.c:55
static int64 current_size
Definition: pg_checksums.c:63
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:819
BlockNumber smgr_cached_nblocks[MAX_FORKNUM+1]
Definition: smgr.h:47

References Assert(), PrivateRefCountEntry::buffer, current_size, EB_CLEAR_SIZE_CACHE, EB_CREATE_FORK_IF_NEEDED, EB_LOCK_TARGET, EB_PERFORMING_RECOVERY, ExclusiveLock, ExtendBufferedRelCommon(), i, InvalidBlockNumber, InvalidBuffer, lengthof, LockRelationForExtension(), mode, RBM_ZERO_AND_CLEANUP_LOCK, RBM_ZERO_AND_LOCK, RelationData::rd_rel, ReadBuffer_common(), BufferManagerRelation::rel, RelationGetSmgr(), ReleaseBuffer(), BufferManagerRelation::relpersistence, BufferManagerRelation::smgr, SMgrRelationData::smgr_cached_nblocks, smgrcreate(), smgrexists(), smgrnblocks(), and UnlockRelationForExtension().

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

◆ FlushDatabaseBuffers()

void FlushDatabaseBuffers ( Oid  dbid)

Definition at line 5311 of file bufmgr.c.

5312{
5313 int i;
5314 BufferDesc *bufHdr;
5315
5316 for (i = 0; i < NBuffers; i++)
5317 {
5318 uint32 buf_state;
5319
5320 bufHdr = GetBufferDescriptor(i);
5321
5322 /*
5323 * As in DropRelationBuffers, an unlocked precheck should be safe and
5324 * saves some cycles.
5325 */
5326 if (bufHdr->tag.dbOid != dbid)
5327 continue;
5328
5329 /* Make sure we can handle the pin */
5332
5333 buf_state = LockBufHdr(bufHdr);
5334 if (bufHdr->tag.dbOid == dbid &&
5335 (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
5336 {
5337 PinBuffer_Locked(bufHdr);
5341 UnpinBuffer(bufHdr);
5342 }
5343 else
5344 UnlockBufHdr(bufHdr, buf_state);
5345 }
5346}
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition: bufmgr.c:4291
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:3183
static void UnpinBuffer(BufferDesc *buf)
Definition: bufmgr.c:3264
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1182
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1902
@ LW_SHARED
Definition: lwlock.h:115
@ IOOBJECT_RELATION
Definition: pgstat.h:274
@ IOCONTEXT_NORMAL
Definition: pgstat.h:286

References BM_DIRTY, BM_VALID, BufferDescriptorGetContentLock(), CurrentResourceOwner, buftag::dbOid, FlushBuffer(), GetBufferDescriptor(), i, IOCONTEXT_NORMAL, IOOBJECT_RELATION, LockBufHdr(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NBuffers, PinBuffer_Locked(), ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), BufferDesc::tag, UnlockBufHdr(), and UnpinBuffer().

Referenced by dbase_redo().

◆ FlushOneBuffer()

void FlushOneBuffer ( Buffer  buffer)

Definition at line 5353 of file bufmgr.c.

5354{
5355 BufferDesc *bufHdr;
5356
5357 /* currently not needed, but no fundamental reason not to support */
5358 Assert(!BufferIsLocal(buffer));
5359
5360 Assert(BufferIsPinned(buffer));
5361
5362 bufHdr = GetBufferDescriptor(buffer - 1);
5363
5365
5367}
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1985

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

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

◆ FlushRelationBuffers()

void FlushRelationBuffers ( Relation  rel)

Definition at line 4943 of file bufmgr.c.

4944{
4945 int i;
4946 BufferDesc *bufHdr;
4947 SMgrRelation srel = RelationGetSmgr(rel);
4948
4949 if (RelationUsesLocalBuffers(rel))
4950 {
4951 for (i = 0; i < NLocBuffer; i++)
4952 {
4953 uint32 buf_state;
4954
4955 bufHdr = GetLocalBufferDescriptor(i);
4956 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
4957 ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
4958 (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4959 {
4960 ErrorContextCallback errcallback;
4961
4962 /* Setup error traceback support for ereport() */
4964 errcallback.arg = bufHdr;
4965 errcallback.previous = error_context_stack;
4966 error_context_stack = &errcallback;
4967
4968 /* Make sure we can handle the pin */
4971
4972 /*
4973 * Pin/unpin mostly to make valgrind work, but it also seems
4974 * like the right thing to do.
4975 */
4976 PinLocalBuffer(bufHdr, false);
4977
4978
4979 FlushLocalBuffer(bufHdr, srel);
4980
4982
4983 /* Pop the error context stack */
4984 error_context_stack = errcallback.previous;
4985 }
4986 }
4987
4988 return;
4989 }
4990
4991 for (i = 0; i < NBuffers; i++)
4992 {
4993 uint32 buf_state;
4994
4995 bufHdr = GetBufferDescriptor(i);
4996
4997 /*
4998 * As in DropRelationBuffers, an unlocked precheck should be safe and
4999 * saves some cycles.
5000 */
5001 if (!BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator))
5002 continue;
5003
5004 /* Make sure we can handle the pin */
5007
5008 buf_state = LockBufHdr(bufHdr);
5009 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
5010 (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
5011 {
5012 PinBuffer_Locked(bufHdr);
5016 UnpinBuffer(bufHdr);
5017 }
5018 else
5019 UnlockBufHdr(bufHdr, buf_state);
5020 }
5021}
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
static void local_buffer_write_error_callback(void *arg)
Definition: bufmgr.c:6216
ErrorContextCallback * error_context_stack
Definition: elog.c:95
void FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln)
Definition: localbuf.c:182
void UnpinLocalBuffer(Buffer buffer)
Definition: localbuf.c:832
bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
Definition: localbuf.c:796
int NLocBuffer
Definition: localbuf.c:44
struct ErrorContextCallback * previous
Definition: elog.h:296
void(* callback)(void *arg)
Definition: elog.h:297

References ErrorContextCallback::arg, BM_DIRTY, BM_VALID, BufferDescriptorGetBuffer(), BufferDescriptorGetContentLock(), BufTagMatchesRelFileLocator(), ErrorContextCallback::callback, CurrentResourceOwner, error_context_stack, FlushBuffer(), FlushLocalBuffer(), GetBufferDescriptor(), GetLocalBufferDescriptor(), i, IOCONTEXT_NORMAL, IOOBJECT_RELATION, local_buffer_write_error_callback(), LockBufHdr(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NBuffers, NLocBuffer, pg_atomic_read_u32(), PinBuffer_Locked(), PinLocalBuffer(), ErrorContextCallback::previous, RelationData::rd_locator, RelationGetSmgr(), RelationUsesLocalBuffers, ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), BufferDesc::state, BufferDesc::tag, UnlockBufHdr(), UnpinBuffer(), and UnpinLocalBuffer().

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

◆ FlushRelationsAllBuffers()

void FlushRelationsAllBuffers ( struct SMgrRelationData **  smgrs,
int  nrels 
)

◆ FreeAccessStrategy()

void FreeAccessStrategy ( BufferAccessStrategy  strategy)

Definition at line 723 of file freelist.c.

724{
725 /* don't crash if called on a "default" strategy */
726 if (strategy != NULL)
727 pfree(strategy);
728}
void pfree(void *pointer)
Definition: mcxt.c:2152

References pfree().

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

◆ GetAccessStrategy()

BufferAccessStrategy GetAccessStrategy ( BufferAccessStrategyType  btype)

Definition at line 541 of file freelist.c.

542{
543 int ring_size_kb;
544
545 /*
546 * Select ring size to use. See buffer/README for rationales.
547 *
548 * Note: if you change the ring size for BAS_BULKREAD, see also
549 * SYNC_SCAN_REPORT_INTERVAL in access/heap/syncscan.c.
550 */
551 switch (btype)
552 {
553 case BAS_NORMAL:
554 /* if someone asks for NORMAL, just give 'em a "default" object */
555 return NULL;
556
557 case BAS_BULKREAD:
558 {
559 int ring_max_kb;
560
561 /*
562 * The ring always needs to be large enough to allow some
563 * separation in time between providing a buffer to the user
564 * of the strategy and that buffer being reused. Otherwise the
565 * user's pin will prevent reuse of the buffer, even without
566 * concurrent activity.
567 *
568 * We also need to ensure the ring always is large enough for
569 * SYNC_SCAN_REPORT_INTERVAL, as noted above.
570 *
571 * Thus we start out a minimal size and increase the size
572 * further if appropriate.
573 */
574 ring_size_kb = 256;
575
576 /*
577 * There's no point in a larger ring if we won't be allowed to
578 * pin sufficiently many buffers. But we never limit to less
579 * than the minimal size above.
580 */
581 ring_max_kb = GetPinLimit() * (BLCKSZ / 1024);
582 ring_max_kb = Max(ring_size_kb, ring_max_kb);
583
584 /*
585 * We would like the ring to additionally have space for the
586 * configured degree of IO concurrency. While being read in,
587 * buffers can obviously not yet be reused.
588 *
589 * Each IO can be up to io_combine_limit blocks large, and we
590 * want to start up to effective_io_concurrency IOs.
591 *
592 * Note that effective_io_concurrency may be 0, which disables
593 * AIO.
594 */
595 ring_size_kb += (BLCKSZ / 1024) *
597
598 if (ring_size_kb > ring_max_kb)
599 ring_size_kb = ring_max_kb;
600 break;
601 }
602 case BAS_BULKWRITE:
603 ring_size_kb = 16 * 1024;
604 break;
605 case BAS_VACUUM:
606 ring_size_kb = 2048;
607 break;
608
609 default:
610 elog(ERROR, "unrecognized buffer access strategy: %d",
611 (int) btype);
612 return NULL; /* keep compiler quiet */
613 }
614
615 return GetAccessStrategyWithSize(btype, ring_size_kb);
616}
int effective_io_concurrency
Definition: bufmgr.c:155
int io_combine_limit
Definition: bufmgr.c:170
uint32 GetPinLimit(void)
Definition: bufmgr.c:2510
#define Max(x, y)
Definition: c.h:969
BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype, int ring_size_kb)
Definition: freelist.c:626

References BAS_BULKREAD, BAS_BULKWRITE, BAS_NORMAL, BAS_VACUUM, effective_io_concurrency, elog, ERROR, 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)

Definition at line 666 of file freelist.c.

667{
668 if (strategy == NULL)
669 return 0;
670
671 return strategy->nbuffers;
672}

References BufferAccessStrategyData::nbuffers.

Referenced by parallel_vacuum_init().

◆ GetAccessStrategyPinLimit()

int GetAccessStrategyPinLimit ( BufferAccessStrategy  strategy)

Definition at line 689 of file freelist.c.

690{
691 if (strategy == NULL)
692 return NBuffers;
693
694 switch (strategy->btype)
695 {
696 case BAS_BULKREAD:
697
698 /*
699 * Since BAS_BULKREAD uses StrategyRejectBuffer(), dirty buffers
700 * shouldn't be a problem and the caller is free to pin up to the
701 * entire ring at once.
702 */
703 return strategy->nbuffers;
704
705 default:
706
707 /*
708 * Tell caller not to pin more than half the buffers in the ring.
709 * This is a trade-off between look ahead distance and deferring
710 * writeback and associated WAL traffic.
711 */
712 return strategy->nbuffers / 2;
713 }
714}
BufferAccessStrategyType btype
Definition: freelist.c:75

References BAS_BULKREAD, BufferAccessStrategyData::btype, BufferAccessStrategyData::nbuffers, and NBuffers.

Referenced by read_stream_begin_impl().

◆ GetAccessStrategyWithSize()

BufferAccessStrategy GetAccessStrategyWithSize ( BufferAccessStrategyType  btype,
int  ring_size_kb 
)

Definition at line 626 of file freelist.c.

627{
628 int ring_buffers;
629 BufferAccessStrategy strategy;
630
631 Assert(ring_size_kb >= 0);
632
633 /* Figure out how many buffers ring_size_kb is */
634 ring_buffers = ring_size_kb / (BLCKSZ / 1024);
635
636 /* 0 means unlimited, so no BufferAccessStrategy required */
637 if (ring_buffers == 0)
638 return NULL;
639
640 /* Cap to 1/8th of shared_buffers */
641 ring_buffers = Min(NBuffers / 8, ring_buffers);
642
643 /* NBuffers should never be less than 16, so this shouldn't happen */
644 Assert(ring_buffers > 0);
645
646 /* Allocate the object and initialize all elements to zeroes */
647 strategy = (BufferAccessStrategy)
648 palloc0(offsetof(BufferAccessStrategyData, buffers) +
649 ring_buffers * sizeof(Buffer));
650
651 /* Set fields that don't start out zero */
652 strategy->btype = btype;
653 strategy->nbuffers = ring_buffers;
654
655 return strategy;
656}
struct BufferAccessStrategyData * BufferAccessStrategy
Definition: buf.h:44
#define Min(x, y)
Definition: c.h:975
void * palloc0(Size size)
Definition: mcxt.c:1975

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

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

◆ GetAdditionalLocalPinLimit()

uint32 GetAdditionalLocalPinLimit ( void  )

Definition at line 314 of file localbuf.c.

315{
318}
int num_temp_buffers
Definition: guc_tables.c:552
static int NLocalPinnedBuffers
Definition: localbuf.c:55

References Assert(), NLocalPinnedBuffers, and num_temp_buffers.

Referenced by read_stream_start_pending_read().

◆ GetAdditionalPinLimit()

uint32 GetAdditionalPinLimit ( void  )

Definition at line 2522 of file bufmgr.c.

2523{
2524 uint32 estimated_pins_held;
2525
2526 /*
2527 * We get the number of "overflowed" pins for free, but don't know the
2528 * number of pins in PrivateRefCountArray. The cost of calculating that
2529 * exactly doesn't seem worth it, so just assume the max.
2530 */
2531 estimated_pins_held = PrivateRefCountOverflowed + REFCOUNT_ARRAY_ENTRIES;
2532
2533 /* Is this backend already holding more than its fair share? */
2534 if (estimated_pins_held > MaxProportionalPins)
2535 return 0;
2536
2537 return MaxProportionalPins - estimated_pins_held;
2538}
static uint32 MaxProportionalPins
Definition: bufmgr.c:221
#define REFCOUNT_ARRAY_ENTRIES
Definition: bufmgr.c:100

References MaxProportionalPins, PrivateRefCountOverflowed, and REFCOUNT_ARRAY_ENTRIES.

Referenced by LimitAdditionalPins(), and read_stream_start_pending_read().

◆ GetLocalPinLimit()

uint32 GetLocalPinLimit ( void  )

Definition at line 306 of file localbuf.c.

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

References num_temp_buffers.

Referenced by read_stream_begin_impl().

◆ GetPinLimit()

uint32 GetPinLimit ( void  )

Definition at line 2510 of file bufmgr.c.

2511{
2512 return MaxProportionalPins;
2513}

References MaxProportionalPins.

Referenced by GetAccessStrategy(), and read_stream_begin_impl().

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )

Definition at line 5829 of file bufmgr.c.

5830{
5831 int bufid = GetStartupBufferPinWaitBufId();
5832
5833 /*
5834 * If we get woken slowly then it's possible that the Startup process was
5835 * already woken by other backends before we got here. Also possible that
5836 * we get here by multiple interrupts or interrupts at inappropriate
5837 * times, so make sure we do nothing if the bufid is not set.
5838 */
5839 if (bufid < 0)
5840 return false;
5841
5842 if (GetPrivateRefCount(bufid + 1) > 0)
5843 return true;
5844
5845 return false;
5846}
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:767

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and ProcessRecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

Definition at line 5405 of file bufmgr.c.

5406{
5407 Assert(BufferIsPinned(buffer));
5409 if (BufferIsLocal(buffer))
5410 LocalRefCount[-buffer - 1]++;
5411 else
5412 {
5414
5415 ref = GetPrivateRefCountEntry(buffer, true);
5416 Assert(ref != NULL);
5417 ref->refcount++;
5418 }
5420}
static void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition: bufmgr.c:351

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

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

◆ InitBufferManagerAccess()

void InitBufferManagerAccess ( void  )

Definition at line 4013 of file bufmgr.c.

4014{
4015 HASHCTL hash_ctl;
4016
4017 /*
4018 * An advisory limit on the number of pins each backend should hold, based
4019 * on shared_buffers and the maximum number of connections possible.
4020 * That's very pessimistic, but outside toy-sized shared_buffers it should
4021 * allow plenty of pins. LimitAdditionalPins() and
4022 * GetAdditionalPinLimit() can be used to check the remaining balance.
4023 */
4025
4026 memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
4027
4028 hash_ctl.keysize = sizeof(int32);
4029 hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
4030
4031 PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
4033
4034 /*
4035 * AtProcExit_Buffers needs LWLock access, and thereby has to be called at
4036 * the corresponding phase of backend shutdown.
4037 */
4038 Assert(MyProc != NULL);
4040}
static void AtProcExit_Buffers(int code, Datum arg)
Definition: bufmgr.c:4047
struct PrivateRefCountEntry PrivateRefCountEntry
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition: bufmgr.c:215
static HTAB * PrivateRefCountHash
Definition: bufmgr.c:216
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
int MaxBackends
Definition: globals.c:147
#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:365
#define NUM_AUXILIARY_PROCS
Definition: proc.h:455
PGPROC * MyProc
Definition: proc.c:67
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76

References Assert(), AtProcExit_Buffers(), HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, HASHCTL::keysize, MaxBackends, MaxProportionalPins, MyProc, NBuffers, NUM_AUXILIARY_PROCS, on_shmem_exit(), PrivateRefCountArray, and PrivateRefCountHash.

Referenced by BaseInit().

◆ IsBufferCleanupOK()

bool IsBufferCleanupOK ( Buffer  buffer)

Definition at line 5913 of file bufmgr.c.

5914{
5915 BufferDesc *bufHdr;
5916 uint32 buf_state;
5917
5918 Assert(BufferIsValid(buffer));
5919
5920 /* see AIO related comment in LockBufferForCleanup() */
5921
5922 if (BufferIsLocal(buffer))
5923 {
5924 /* There should be exactly one pin */
5925 if (LocalRefCount[-buffer - 1] != 1)
5926 return false;
5927 /* Nobody else to wait for */
5928 return true;
5929 }
5930
5931 /* There should be exactly one local pin */
5932 if (GetPrivateRefCount(buffer) != 1)
5933 return false;
5934
5935 bufHdr = GetBufferDescriptor(buffer - 1);
5936
5937 /* caller must hold exclusive lock on buffer */
5939 LW_EXCLUSIVE));
5940
5941 buf_state = LockBufHdr(bufHdr);
5942
5943 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5944 if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
5945 {
5946 /* pincount is OK. */
5947 UnlockBufHdr(bufHdr, buf_state);
5948 return true;
5949 }
5950
5951 UnlockBufHdr(bufHdr, buf_state);
5952 return false;
5953}

References Assert(), BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsValid(), GetBufferDescriptor(), GetPrivateRefCount(), LocalRefCount, LockBufHdr(), LW_EXCLUSIVE, LWLockHeldByMeInMode(), and UnlockBufHdr().

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

◆ LimitAdditionalLocalPins()

void LimitAdditionalLocalPins ( uint32 additional_pins)

Definition at line 322 of file localbuf.c.

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

References NLocalPinnedBuffers, and num_temp_buffers.

Referenced by ExtendBufferedRelLocal().

◆ LimitAdditionalPins()

void LimitAdditionalPins ( uint32 additional_pins)

Definition at line 2548 of file bufmgr.c.

2549{
2550 uint32 limit;
2551
2552 if (*additional_pins <= 1)
2553 return;
2554
2555 limit = GetAdditionalPinLimit();
2556 limit = Max(limit, 1);
2557 if (limit < *additional_pins)
2558 *additional_pins = limit;
2559}
uint32 GetAdditionalPinLimit(void)
Definition: bufmgr.c:2522

References GetAdditionalPinLimit(), and Max.

Referenced by ExtendBufferedRelShared().

◆ LockBuffer()

void LockBuffer ( Buffer  buffer,
int  mode 
)

Definition at line 5607 of file bufmgr.c.

5608{
5609 BufferDesc *buf;
5610
5611 Assert(BufferIsPinned(buffer));
5612 if (BufferIsLocal(buffer))
5613 return; /* local buffers need no lock */
5614
5615 buf = GetBufferDescriptor(buffer - 1);
5616
5617 if (mode == BUFFER_LOCK_UNLOCK)
5619 else if (mode == BUFFER_LOCK_SHARE)
5621 else if (mode == BUFFER_LOCK_EXCLUSIVE)
5623 else
5624 elog(ERROR, "unrecognized buffer lock mode: %d", mode);
5625}
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:197
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:198

References Assert(), buf, PrivateRefCountEntry::buffer, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsPinned, elog, ERROR, GetBufferDescriptor(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), and mode.

Referenced by _bt_lockbuf(), _bt_unlockbuf(), _bt_upgradelockbufcleanup(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_finish_split(), _hash_first(), _hash_freeovflpage(), _hash_getbuf(), _hash_getbuf_with_strategy(), _hash_getcachedmetap(), _hash_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(), FreeSpaceMapPrepareTruncateRel(), fsm_readbuf(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), get_raw_page_internal(), 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_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_rel(), LockBufferForCleanup(), log_newpage_range(), modify_rel_block(), palloc_btree_page(), pg_visibility(), pgrowlocks(), pgstat_btree_page(), pgstat_gist_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(), verify_heapam(), verifyBackupPageConsistency(), visibilitymap_clear(), visibilitymap_prepare_truncate(), visibilitymap_set(), vm_readbuf(), XLogReadBufferForRedoExtended(), XLogRecordPageWithFreeSpace(), and ZeroAndLockBuffer().

◆ LockBufferForCleanup()

void LockBufferForCleanup ( Buffer  buffer)

Definition at line 5687 of file bufmgr.c.

5688{
5689 BufferDesc *bufHdr;
5690 TimestampTz waitStart = 0;
5691 bool waiting = false;
5692 bool logged_recovery_conflict = false;
5693
5694 Assert(BufferIsPinned(buffer));
5695 Assert(PinCountWaitBuf == NULL);
5696
5698
5699 /*
5700 * We do not yet need to be worried about in-progress AIOs holding a pin,
5701 * as we, so far, only support doing reads via AIO and this function can
5702 * only be called once the buffer is valid (i.e. no read can be in
5703 * flight).
5704 */
5705
5706 /* Nobody else to wait for */
5707 if (BufferIsLocal(buffer))
5708 return;
5709
5710 bufHdr = GetBufferDescriptor(buffer - 1);
5711
5712 for (;;)
5713 {
5714 uint32 buf_state;
5715
5716 /* Try to acquire lock */
5718 buf_state = LockBufHdr(bufHdr);
5719
5720 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5721 if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
5722 {
5723 /* Successfully acquired exclusive lock with pincount 1 */
5724 UnlockBufHdr(bufHdr, buf_state);
5725
5726 /*
5727 * Emit the log message if recovery conflict on buffer pin was
5728 * resolved but the startup process waited longer than
5729 * deadlock_timeout for it.
5730 */
5731 if (logged_recovery_conflict)
5733 waitStart, GetCurrentTimestamp(),
5734 NULL, false);
5735
5736 if (waiting)
5737 {
5738 /* reset ps display to remove the suffix if we added one */
5740 waiting = false;
5741 }
5742 return;
5743 }
5744 /* Failed, so mark myself as waiting for pincount 1 */
5745 if (buf_state & BM_PIN_COUNT_WAITER)
5746 {
5747 UnlockBufHdr(bufHdr, buf_state);
5749 elog(ERROR, "multiple backends attempting to wait for pincount 1");
5750 }
5752 PinCountWaitBuf = bufHdr;
5753 buf_state |= BM_PIN_COUNT_WAITER;
5754 UnlockBufHdr(bufHdr, buf_state);
5756
5757 /* Wait to be signaled by UnpinBuffer() */
5758 if (InHotStandby)
5759 {
5760 if (!waiting)
5761 {
5762 /* adjust the process title to indicate that it's waiting */
5763 set_ps_display_suffix("waiting");
5764 waiting = true;
5765 }
5766
5767 /*
5768 * Emit the log message if the startup process is waiting longer
5769 * than deadlock_timeout for recovery conflict on buffer pin.
5770 *
5771 * Skip this if first time through because the startup process has
5772 * not started waiting yet in this case. So, the wait start
5773 * timestamp is set after this logic.
5774 */
5775 if (waitStart != 0 && !logged_recovery_conflict)
5776 {
5778
5779 if (TimestampDifferenceExceeds(waitStart, now,
5781 {
5783 waitStart, now, NULL, true);
5784 logged_recovery_conflict = true;
5785 }
5786 }
5787
5788 /*
5789 * Set the wait start timestamp if logging is enabled and first
5790 * time through.
5791 */
5792 if (log_recovery_conflict_waits && waitStart == 0)
5793 waitStart = GetCurrentTimestamp();
5794
5795 /* Publish the bufid that Startup process waits on */
5796 SetStartupBufferPinWaitBufId(buffer - 1);
5797 /* Set alarm and then wait to be signaled by UnpinBuffer() */
5799 /* Reset the published bufid */
5801 }
5802 else
5803 ProcWaitForSignal(WAIT_EVENT_BUFFER_PIN);
5804
5805 /*
5806 * Remove flag marking us as waiter. Normally this will not be set
5807 * anymore, but ProcWaitForSignal() can return for other signals as
5808 * well. We take care to only reset the flag if we're the waiter, as
5809 * theoretically another backend could have started waiting. That's
5810 * impossible with the current usages due to table level locking, but
5811 * better be safe.
5812 */
5813 buf_state = LockBufHdr(bufHdr);
5814 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5816 buf_state &= ~BM_PIN_COUNT_WAITER;
5817 UnlockBufHdr(bufHdr, buf_state);
5818
5819 PinCountWaitBuf = NULL;
5820 /* Loop back and try again */
5821 }
5822}
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
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:75
void CheckBufferIsPinnedOnce(Buffer buffer)
Definition: bufmgr.c:5654
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:183
int64 TimestampTz
Definition: timestamp.h:39
@ PROCSIG_RECOVERY_CONFLICT_BUFFERPIN
Definition: procsignal.h:48
void set_ps_display_remove_suffix(void)
Definition: ps_status.c:423
void set_ps_display_suffix(const char *suffix)
Definition: ps_status.c:371
int DeadlockTimeout
Definition: proc.c:58
void SetStartupBufferPinWaitBufId(int bufid)
Definition: proc.c:755
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1975
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
int wait_backend_pgprocno
static volatile sig_atomic_t waiting
Definition: waiteventset.c:170
#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, 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(), BufferDesc::wait_backend_pgprocno, and waiting.

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

◆ MarkBufferDirty()

void MarkBufferDirty ( Buffer  buffer)

Definition at line 2952 of file bufmgr.c.

2953{
2954 BufferDesc *bufHdr;
2955 uint32 buf_state;
2956 uint32 old_buf_state;
2957
2958 if (!BufferIsValid(buffer))
2959 elog(ERROR, "bad buffer ID: %d", buffer);
2960
2961 if (BufferIsLocal(buffer))
2962 {
2963 MarkLocalBufferDirty(buffer);
2964 return;
2965 }
2966
2967 bufHdr = GetBufferDescriptor(buffer - 1);
2968
2969 Assert(BufferIsPinned(buffer));
2971 LW_EXCLUSIVE));
2972
2973 old_buf_state = pg_atomic_read_u32(&bufHdr->state);
2974 for (;;)
2975 {
2976 if (old_buf_state & BM_LOCKED)
2977 old_buf_state = WaitBufHdrUnlocked(bufHdr);
2978
2979 buf_state = old_buf_state;
2980
2981 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
2982 buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
2983
2984 if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
2985 buf_state))
2986 break;
2987 }
2988
2989 /*
2990 * If the buffer was not dirty already, do vacuum accounting.
2991 */
2992 if (!(old_buf_state & BM_DIRTY))
2993 {
2995 if (VacuumCostActive)
2997 }
2998}
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:349
#define BM_LOCKED
Definition: buf_internals.h:68
#define BM_JUST_DIRTIED
Definition: buf_internals.h:74
static uint32 WaitBufHdrUnlocked(BufferDesc *buf)
Definition: bufmgr.c:6289
bool VacuumCostActive
Definition: globals.c:159
int VacuumCostBalance
Definition: globals.c:158
int VacuumCostPageDirty
Definition: globals.c:154
BufferUsage pgBufferUsage
Definition: instrument.c:20
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:489
int64 shared_blks_dirtied
Definition: instrument.h:28

References Assert(), BM_DIRTY, BM_JUST_DIRTIED, BM_LOCKED, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferIsLocal, BufferIsPinned, BufferIsValid(), elog, ERROR, GetBufferDescriptor(), LW_EXCLUSIVE, LWLockHeldByMeInMode(), MarkLocalBufferDirty(), pg_atomic_compare_exchange_u32(), pg_atomic_read_u32(), pgBufferUsage, BufferUsage::shared_blks_dirtied, BufferDesc::state, VacuumCostActive, VacuumCostBalance, VacuumCostPageDirty, 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(), do_setval(), 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(), lazy_scan_new_or_empty(), lazy_scan_prune(), lazy_vacuum_heap_page(), log_newpage_range(), moveLeafs(), nextval_internal(), RelationAddBlocks(), RelationCopyStorageUsingBuffer(), RelationGetBufferForTuple(), revmap_physical_extend(), saveNodeLink(), seq_redo(), shiftList(), spgAddNodeAction(), spgbuild(), SpGistUpdateMetaPage(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), visibilitymap_clear(), visibilitymap_prepare_truncate(), visibilitymap_set(), writeListPage(), and XLogReadBufferForRedoExtended().

◆ MarkBufferDirtyHint()

void MarkBufferDirtyHint ( Buffer  buffer,
bool  buffer_std 
)

Definition at line 5437 of file bufmgr.c.

5438{
5439 BufferDesc *bufHdr;
5440 Page page = BufferGetPage(buffer);
5441
5442 if (!BufferIsValid(buffer))
5443 elog(ERROR, "bad buffer ID: %d", buffer);
5444
5445 if (BufferIsLocal(buffer))
5446 {
5447 MarkLocalBufferDirty(buffer);
5448 return;
5449 }
5450
5451 bufHdr = GetBufferDescriptor(buffer - 1);
5452
5453 Assert(GetPrivateRefCount(buffer) > 0);
5454 /* here, either share or exclusive lock is OK */
5456
5457 /*
5458 * This routine might get called many times on the same page, if we are
5459 * making the first scan after commit of an xact that added/deleted many
5460 * tuples. So, be as quick as we can if the buffer is already dirty. We
5461 * do this by not acquiring spinlock if it looks like the status bits are
5462 * already set. Since we make this test unlocked, there's a chance we
5463 * might fail to notice that the flags have just been cleared, and failed
5464 * to reset them, due to memory-ordering issues. But since this function
5465 * is only intended to be used in cases where failing to write out the
5466 * data would be harmless anyway, it doesn't really matter.
5467 */
5468 if ((pg_atomic_read_u32(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
5470 {
5472 bool dirtied = false;
5473 bool delayChkptFlags = false;
5474 uint32 buf_state;
5475
5476 /*
5477 * If we need to protect hint bit updates from torn writes, WAL-log a
5478 * full page image of the page. This full page image is only necessary
5479 * if the hint bit update is the first change to the page since the
5480 * last checkpoint.
5481 *
5482 * We don't check full_page_writes here because that logic is included
5483 * when we call XLogInsert() since the value changes dynamically.
5484 */
5485 if (XLogHintBitIsNeeded() &&
5487 {
5488 /*
5489 * If we must not write WAL, due to a relfilelocator-specific
5490 * condition or being in recovery, don't dirty the page. We can
5491 * set the hint, just not dirty the page as a result so the hint
5492 * is lost when we evict the page or shutdown.
5493 *
5494 * See src/backend/storage/page/README for longer discussion.
5495 */
5496 if (RecoveryInProgress() ||
5498 return;
5499
5500 /*
5501 * If the block is already dirty because we either made a change
5502 * or set a hint already, then we don't need to write a full page
5503 * image. Note that aggressive cleaning of blocks dirtied by hint
5504 * bit setting would increase the call rate. Bulk setting of hint
5505 * bits would reduce the call rate...
5506 *
5507 * We must issue the WAL record before we mark the buffer dirty.
5508 * Otherwise we might write the page before we write the WAL. That
5509 * causes a race condition, since a checkpoint might occur between
5510 * writing the WAL record and marking the buffer dirty. We solve
5511 * that with a kluge, but one that is already in use during
5512 * transaction commit to prevent race conditions. Basically, we
5513 * simply prevent the checkpoint WAL record from being written
5514 * until we have marked the buffer dirty. We don't start the
5515 * checkpoint flush until we have marked dirty, so our checkpoint
5516 * must flush the change to disk successfully or the checkpoint
5517 * never gets written, so crash recovery will fix.
5518 *
5519 * It's possible we may enter here without an xid, so it is
5520 * essential that CreateCheckPoint waits for virtual transactions
5521 * rather than full transactionids.
5522 */
5525 delayChkptFlags = true;
5526 lsn = XLogSaveBufferForHint(buffer, buffer_std);
5527 }
5528
5529 buf_state = LockBufHdr(bufHdr);
5530
5531 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5532
5533 if (!(buf_state & BM_DIRTY))
5534 {
5535 dirtied = true; /* Means "will be dirtied by this action" */
5536
5537 /*
5538 * Set the page LSN if we wrote a backup block. We aren't supposed
5539 * to set this when only holding a share lock but as long as we
5540 * serialise it somehow we're OK. We choose to set LSN while
5541 * holding the buffer header lock, which causes any reader of an
5542 * LSN who holds only a share lock to also obtain a buffer header
5543 * lock before using PageGetLSN(), which is enforced in
5544 * BufferGetLSNAtomic().
5545 *
5546 * If checksums are enabled, you might think we should reset the
5547 * checksum here. That will happen when the page is written
5548 * sometime later in this checkpoint cycle.
5549 */
5550 if (!XLogRecPtrIsInvalid(lsn))
5551 PageSetLSN(page, lsn);
5552 }
5553
5554 buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
5555 UnlockBufHdr(bufHdr, buf_state);
5556
5557 if (delayChkptFlags)
5558 MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
5559
5560 if (dirtied)
5561 {
5563 if (VacuumCostActive)
5565 }
5566 }
5567}
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:391
#define DELAY_CHKPT_START
Definition: proc.h:128
bool RelFileLocatorSkippingWAL(RelFileLocator rlocator)
Definition: storage.c:573
int delayChkptFlags
Definition: proc.h:249
bool RecoveryInProgress(void)
Definition: xlog.c:6522
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
Definition: xloginsert.c:1065

References Assert(), BM_DIRTY, BM_JUST_DIRTIED, BM_PERMANENT, BUF_STATE_GET_REFCOUNT, PrivateRefCountEntry::buffer, BufferDescriptorGetContentLock(), BufferGetPage(), BufferIsLocal, BufferIsValid(), BufTagGetRelFileLocator(), DELAY_CHKPT_START, PGPROC::delayChkptFlags, elog, ERROR, GetBufferDescriptor(), GetPrivateRefCount(), InvalidXLogRecPtr, LockBufHdr(), LWLockHeldByMe(), MarkLocalBufferDirty(), MyProc, PageSetLSN(), pg_atomic_read_u32(), pgBufferUsage, RecoveryInProgress(), RelFileLocatorSkippingWAL(), BufferUsage::shared_blks_dirtied, BufferDesc::state, BufferDesc::tag, UnlockBufHdr(), VacuumCostActive, VacuumCostBalance, VacuumCostPageDirty, XLogHintBitIsNeeded, XLogRecPtrIsInvalid, 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().

◆ PrefetchBuffer()

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

Definition at line 651 of file bufmgr.c.

652{
653 Assert(RelationIsValid(reln));
654 Assert(BlockNumberIsValid(blockNum));
655
656 if (RelationUsesLocalBuffers(reln))
657 {
658 /* see comments in ReadBufferExtended */
659 if (RELATION_IS_OTHER_TEMP(reln))
661 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
662 errmsg("cannot access temporary tables of other sessions")));
663
664 /* pass it off to localbuf.c */
665 return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
666 }
667 else
668 {
669 /* pass it to the shared buffer version */
670 return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
671 }
672}
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:561
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ereport(elevel,...)
Definition: elog.h:149
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition: localbuf.c:71
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:669
#define RelationIsValid(relation)
Definition: rel.h:489

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

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

◆ PrefetchSharedBuffer()

PrefetchBufferResult PrefetchSharedBuffer ( struct SMgrRelationData smgr_reln,
ForkNumber  forkNum,
BlockNumber  blockNum 
)

◆ ReadBuffer()

Buffer ReadBuffer ( Relation  reln,
BlockNumber  blockNum 
)

Definition at line 758 of file bufmgr.c.

759{
760 return ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);
761}
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:805

References 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 
)
inline

Definition at line 805 of file bufmgr.c.

807{
808 Buffer buf;
809
810 /*
811 * Reject attempts to read non-local temporary relations; we would be
812 * likely to get wrong data since we have no visibility into the owning
813 * session's local buffers.
814 */
815 if (RELATION_IS_OTHER_TEMP(reln))
817 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
818 errmsg("cannot access temporary tables of other sessions")));
819
820 /*
821 * Read the buffer, and update pgstat counters to reflect a cache hit or
822 * miss.
823 */
824 buf = ReadBuffer_common(reln, RelationGetSmgr(reln), 0,
825 forkNum, blockNum, mode, strategy);
826
827 return buf;
828}

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

Referenced by _hash_getbuf_with_strategy(), _hash_getinitbuf(), _hash_getnewbuf(), blbulkdelete(), blgetbitmap(), BloomInitMetapage(), blvacuumcleanup(), brin_vacuum_scan(), 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_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 
)

Definition at line 842 of file bufmgr.c.

845{
846 SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
847
848 return ReadBuffer_common(NULL, smgr,
849 permanent ? RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED,
850 forkNum, blockNum,
851 mode, strategy);
852}

References 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 
)

Definition at line 682 of file bufmgr.c.

684{
685 BufferDesc *bufHdr;
686 BufferTag tag;
687 uint32 buf_state;
688 bool have_private_ref;
689
690 Assert(BufferIsValid(recent_buffer));
691
694 InitBufferTag(&tag, &rlocator, forkNum, blockNum);
695
696 if (BufferIsLocal(recent_buffer))
697 {
698 int b = -recent_buffer - 1;
699
700 bufHdr = GetLocalBufferDescriptor(b);
701 buf_state = pg_atomic_read_u32(&bufHdr->state);
702
703 /* Is it still valid and holding the right tag? */
704 if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
705 {
706 PinLocalBuffer(bufHdr, true);
707
709
710 return true;
711 }
712 }
713 else
714 {
715 bufHdr = GetBufferDescriptor(recent_buffer - 1);
716 have_private_ref = GetPrivateRefCount(recent_buffer) > 0;
717
718 /*
719 * Do we already have this buffer pinned with a private reference? If
720 * so, it must be valid and it is safe to check the tag without
721 * locking. If not, we have to lock the header first and then check.
722 */
723 if (have_private_ref)
724 buf_state = pg_atomic_read_u32(&bufHdr->state);
725 else
726 buf_state = LockBufHdr(bufHdr);
727
728 if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
729 {
730 /*
731 * It's now safe to pin the buffer. We can't pin first and ask
732 * questions later, because it might confuse code paths like
733 * InvalidateBuffer() if we pinned a random non-matching buffer.
734 */
735 if (have_private_ref)
736 PinBuffer(bufHdr, NULL); /* bump pin count */
737 else
738 PinBuffer_Locked(bufHdr); /* pin for first time */
739
741
742 return true;
743 }
744
745 /* If we locked the header above, now unlock. */
746 if (!have_private_ref)
747 UnlockBufHdr(bufHdr, buf_state);
748 }
749
750 return false;
751}
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
static bool PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
Definition: bufmgr.c:3072
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, GetBufferDescriptor(), GetLocalBufferDescriptor(), GetPrivateRefCount(), InitBufferTag(), BufferUsage::local_blks_hit, LockBufHdr(), pg_atomic_read_u32(), pgBufferUsage, PinBuffer(), PinBuffer_Locked(), PinLocalBuffer(), ReservePrivateRefCountEntry(), ResourceOwnerEnlarge(), BufferUsage::shared_blks_hit, BufferDesc::state, BufferDesc::tag, and UnlockBufHdr().

Referenced by invalidate_rel_block(), and XLogReadBufferExtended().

◆ RelationGetNumberOfBlocksInFork()

BlockNumber RelationGetNumberOfBlocksInFork ( Relation  relation,
ForkNumber  forkNum 
)

Definition at line 4431 of file bufmgr.c.

4432{
4433 if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
4434 {
4435 /*
4436 * Not every table AM uses BLCKSZ wide fixed size blocks. Therefore
4437 * tableam returns the size in bytes - but for the purpose of this
4438 * routine, we want the number of blocks. Therefore divide, rounding
4439 * up.
4440 */
4441 uint64 szbytes;
4442
4443 szbytes = table_relation_size(relation, forkNum);
4444
4445 return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
4446 }
4447 else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
4448 {
4449 return smgrnblocks(RelationGetSmgr(relation), forkNum);
4450 }
4451 else
4452 Assert(false);
4453
4454 return 0; /* keep compiler quiet */
4455}
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition: tableam.h:1828

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

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

◆ ReleaseAndReadBuffer()

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

Definition at line 3014 of file bufmgr.c.

3017{
3018 ForkNumber forkNum = MAIN_FORKNUM;
3019 BufferDesc *bufHdr;
3020
3021 if (BufferIsValid(buffer))
3022 {
3023 Assert(BufferIsPinned(buffer));
3024 if (BufferIsLocal(buffer))
3025 {
3026 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
3027 if (bufHdr->tag.blockNum == blockNum &&
3028 BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
3029 BufTagGetForkNum(&bufHdr->tag) == forkNum)
3030 return buffer;
3031 UnpinLocalBuffer(buffer);
3032 }
3033 else
3034 {
3035 bufHdr = GetBufferDescriptor(buffer - 1);
3036 /* we have pin, so it's ok to examine tag without spinlock */
3037 if (bufHdr->tag.blockNum == blockNum &&
3038 BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
3039 BufTagGetForkNum(&bufHdr->tag) == forkNum)
3040 return buffer;
3041 UnpinBuffer(bufHdr);
3042 }
3043 }
3044
3045 return ReadBuffer(relation, blockNum);
3046}
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:758

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

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

◆ ReleaseBuffer()

void ReleaseBuffer ( Buffer  buffer)

Definition at line 5373 of file bufmgr.c.

5374{
5375 if (!BufferIsValid(buffer))
5376 elog(ERROR, "bad buffer ID: %d", buffer);
5377
5378 if (BufferIsLocal(buffer))
5379 UnpinLocalBuffer(buffer);
5380 else
5381 UnpinBuffer(GetBufferDescriptor(buffer - 1));
5382}

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

Referenced by _bt_allocbuf(), _bt_drop_lock_and_maybe_pin(), _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(), pg_visibility_map_summary(), 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 
)

Definition at line 1513 of file bufmgr.c.

1517{
1518 int nblocks = 1;
1519 bool result;
1520
1521 result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags,
1522 false /* single block, no forwarding */ );
1523 Assert(nblocks == 1); /* single block can't be short */
1524
1525 return result;
1526}
static pg_attribute_always_inline bool StartReadBuffersImpl(ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, int flags, bool allow_forwarding)
Definition: bufmgr.c:1262

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 
)

Definition at line 1494 of file bufmgr.c.

1499{
1500 return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags,
1501 true /* expect forwarded buffers */ );
1502}

References StartReadBuffersImpl().

Referenced by read_stream_start_pending_read().

◆ UnlockBuffers()

void UnlockBuffers ( void  )

Definition at line 5579 of file bufmgr.c.

5580{
5582
5583 if (buf)
5584 {
5585 uint32 buf_state;
5586
5587 buf_state = LockBufHdr(buf);
5588
5589 /*
5590 * Don't complain if flag bit not set; it could have been reset but we
5591 * got a cancel/die interrupt before getting the signal.
5592 */
5593 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5594 buf->wait_backend_pgprocno == MyProcNumber)
5595 buf_state &= ~BM_PIN_COUNT_WAITER;
5596
5597 UnlockBufHdr(buf, buf_state);
5598
5599 PinCountWaitBuf = NULL;
5600 }
5601}

References BM_PIN_COUNT_WAITER, buf, LockBufHdr(), MyProcNumber, PinCountWaitBuf, and UnlockBufHdr().

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

◆ UnlockReleaseBuffer()

void UnlockReleaseBuffer ( Buffer  buffer)

Definition at line 5390 of file bufmgr.c.

5391{
5393 ReleaseBuffer(buffer);
5394}

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(), do_setval(), 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(), 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)

Definition at line 1637 of file bufmgr.c.

1638{
1639 PgAioReturn *aio_ret = &operation->io_return;
1640 IOContext io_context;
1641 IOObject io_object;
1642
1643 if (operation->persistence == RELPERSISTENCE_TEMP)
1644 {
1645 io_context = IOCONTEXT_NORMAL;
1646 io_object = IOOBJECT_TEMP_RELATION;
1647 }
1648 else
1649 {
1650 io_context = IOContextForStrategy(operation->strategy);
1651 io_object = IOOBJECT_RELATION;
1652 }
1653
1654 /*
1655 * If we get here without an IO operation having been issued, the
1656 * io_method == IOMETHOD_SYNC path must have been used. Otherwise the
1657 * caller should not have called WaitReadBuffers().
1658 *
1659 * In the case of IOMETHOD_SYNC, we start - as we used to before the
1660 * introducing of AIO - the IO in WaitReadBuffers(). This is done as part
1661 * of the retry logic below, no extra code is required.
1662 *
1663 * This path is expected to eventually go away.
1664 */
1665 if (!pgaio_wref_valid(&operation->io_wref) && io_method != IOMETHOD_SYNC)
1666 elog(ERROR, "waiting for read operation that didn't read");
1667
1668 /*
1669 * To handle partial reads, and IOMETHOD_SYNC, we re-issue IO until we're
1670 * done. We may need multiple retries, not just because we could get
1671 * multiple partial reads, but also because some of the remaining
1672 * to-be-read buffers may have been read in by other backends, limiting
1673 * the IO size.
1674 */
1675 while (true)
1676 {
1677 int ignored_nblocks_progress;
1678
1679 CheckReadBuffersOperation(operation, false);
1680
1681 /*
1682 * If there is an IO associated with the operation, we may need to
1683 * wait for it.
1684 */
1685 if (pgaio_wref_valid(&operation->io_wref))
1686 {
1687 /*
1688 * Track the time spent waiting for the IO to complete. As
1689 * tracking a wait even if we don't actually need to wait
1690 *
1691 * a) is not cheap, due to the timestamping overhead
1692 *
1693 * b) reports some time as waiting, even if we never waited
1694 *
1695 * we first check if we already know the IO is complete.
1696 */
1697 if (aio_ret->result.status == PGAIO_RS_UNKNOWN &&
1698 !pgaio_wref_check_done(&operation->io_wref))
1699 {
1701
1702 pgaio_wref_wait(&operation->io_wref);
1703
1704 /*
1705 * The IO operation itself was already counted earlier, in
1706 * AsyncReadBuffers(), this just accounts for the wait time.
1707 */
1708 pgstat_count_io_op_time(io_object, io_context, IOOP_READ,
1709 io_start, 0, 0);
1710 }
1711 else
1712 {
1713 Assert(pgaio_wref_check_done(&operation->io_wref));
1714 }
1715
1716 /*
1717 * We now are sure the IO completed. Check the results. This
1718 * includes reporting on errors if there were any.
1719 */
1720 ProcessReadBuffersResult(operation);
1721 }
1722
1723 /*
1724 * Most of the time, the one IO we already started, will read in
1725 * everything. But we need to deal with partial reads and buffers not
1726 * needing IO anymore.
1727 */
1728 if (operation->nblocks_done == operation->nblocks)
1729 break;
1730
1732
1733 /*
1734 * This may only complete the IO partially, either because some
1735 * buffers were already valid, or because of a partial read.
1736 *
1737 * NB: In contrast to after the AsyncReadBuffers() call in
1738 * StartReadBuffers(), we do *not* reduce
1739 * ReadBuffersOperation->nblocks here, callers expect the full
1740 * operation to be completed at this point (as more operations may
1741 * have been queued).
1742 */
1743 AsyncReadBuffers(operation, &ignored_nblocks_progress);
1744 }
1745
1746 CheckReadBuffersOperation(operation, true);
1747
1748 /* NB: READ_DONE tracepoint was already executed in completion callback */
1749}
int io_method
Definition: aio.c:77
bool pgaio_wref_valid(PgAioWaitRef *iow)
Definition: aio.c:889
bool pgaio_wref_check_done(PgAioWaitRef *iow)
Definition: aio.c:923
void pgaio_wref_wait(PgAioWaitRef *iow)
Definition: aio.c:909
@ IOMETHOD_SYNC
Definition: aio.h:34
@ PGAIO_RS_UNKNOWN
Definition: aio_types.h:80
bool track_io_timing
Definition: bufmgr.c:147
static void CheckReadBuffersOperation(ReadBuffersOperation *operation, bool is_complete)
Definition: bufmgr.c:1532
static void ProcessReadBuffersResult(ReadBuffersOperation *operation)
Definition: bufmgr.c:1598
static bool AsyncReadBuffers(ReadBuffersOperation *operation, int *nblocks_progress)
Definition: bufmgr.c:1769
IOContext IOContextForStrategy(BufferAccessStrategy strategy)
Definition: freelist.c:800
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
IOObject
Definition: pgstat.h:273
@ IOOBJECT_TEMP_RELATION
Definition: pgstat.h:275
IOContext
Definition: pgstat.h:282
@ IOOP_READ
Definition: pgstat.h:312
instr_time pgstat_prepare_io_time(bool track_io_guc)
Definition: pgstat_io.c:90
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:121
uint32 status
Definition: aio_types.h:108
PgAioResult result
Definition: aio_types.h:132
PgAioWaitRef io_wref
Definition: bufmgr.h:140
BufferAccessStrategy strategy
Definition: bufmgr.h:128
PgAioReturn io_return
Definition: bufmgr.h:141

References Assert(), AsyncReadBuffers(), CHECK_FOR_INTERRUPTS, CheckReadBuffersOperation(), elog, ERROR, 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(), PgAioReturn::result, PgAioResult::status, 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 7446 of file bufmgr.c.

◆ aio_shared_buffer_readv_cb

PGDLLIMPORT const PgAioHandleCallbacks aio_shared_buffer_readv_cb
extern

Definition at line 7437 of file bufmgr.c.

◆ backend_flush_after

PGDLLIMPORT int backend_flush_after
extern

Definition at line 180 of file bufmgr.c.

Referenced by BufferManagerShmemInit().

◆ bgwriter_flush_after

PGDLLIMPORT int bgwriter_flush_after
extern

Definition at line 179 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

PGDLLIMPORT int bgwriter_lru_maxpages
extern

Definition at line 145 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

PGDLLIMPORT double bgwriter_lru_multiplier
extern

Definition at line 146 of file bufmgr.c.

Referenced by BgBufferSync().

◆ BufferBlocks

PGDLLIMPORT char* BufferBlocks
extern

Definition at line 22 of file buf_init.c.

Referenced by BufferGetBlock(), and BufferManagerShmemInit().

◆ checkpoint_flush_after

PGDLLIMPORT int checkpoint_flush_after
extern

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

Referenced by assign_io_max_combine_limit().

◆ io_max_combine_limit

◆ LocalBufferBlockPointers

PGDLLIMPORT Block* LocalBufferBlockPointers
extern

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

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