PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 280 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 3989 of file bufmgr.c.

3990{
3992
3993 AtEOXact_LocalBuffers(isCommit);
3994
3996}
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:4058
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:214
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 3618 of file bufmgr.c.

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

382{
383 Assert(BufferIsValid(buffer));
384
385 if (BufferIsLocal(buffer))
386 return LocalBufferBlockPointers[-buffer - 1];
387 else
388 return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
389}
#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:365
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 4161 of file bufmgr.c.

4162{
4163 BufferDesc *bufHdr;
4164
4165 Assert(BufferIsPinned(buffer));
4166
4167 if (BufferIsLocal(buffer))
4168 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
4169 else
4170 bufHdr = GetBufferDescriptor(buffer - 1);
4171
4172 /* pinned, so OK to read tag without spinlock */
4173 return bufHdr->tag.blockNum;
4174}
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:480
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 4423 of file bufmgr.c.

4424{
4425 char *page = BufferGetPage(buffer);
4426 BufferDesc *bufHdr;
4427 XLogRecPtr lsn;
4428 uint32 buf_state;
4429
4430 /*
4431 * If we don't need locking for correctness, fastpath out.
4432 */
4433 if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
4434 return PageGetLSN(page);
4435
4436 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4437 Assert(BufferIsValid(buffer));
4438 Assert(BufferIsPinned(buffer));
4439
4440 bufHdr = GetBufferDescriptor(buffer - 1);
4441 buf_state = LockBufHdr(bufHdr);
4442 lsn = PageGetLSN(page);
4443 UnlockBufHdr(bufHdr, buf_state);
4444
4445 return lsn;
4446}
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:6189
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:414
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 414 of file bufmgr.h.

415{
416 return (Page) BufferGetBlock(buffer);
417}
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:381
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 4182 of file bufmgr.c.

4184{
4185 BufferDesc *bufHdr;
4186
4187 /* Do the same checks as BufferGetBlockNumber. */
4188 Assert(BufferIsPinned(buffer));
4189
4190 if (BufferIsLocal(buffer))
4191 bufHdr = GetLocalBufferDescriptor(-buffer - 1);
4192 else
4193 bufHdr = GetBufferDescriptor(buffer - 1);
4194
4195 /* pinned, so OK to read tag without spinlock */
4196 *rlocator = BufTagGetRelFileLocator(&bufHdr->tag);
4197 *forknum = BufTagGetForkNum(&bufHdr->tag);
4198 *blknum = bufHdr->tag.blockNum;
4199}
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 2912 of file bufmgr.c.

2913{
2914 BufferDesc *bufHdr;
2915
2916 Assert(BufferIsPinned(buffer));
2917
2918 if (BufferIsLocal(buffer))
2919 {
2920 int bufid = -buffer - 1;
2921
2922 bufHdr = GetLocalBufferDescriptor(bufid);
2923 /* Content locks are not maintained for local buffers. */
2924 }
2925 else
2926 {
2927 bufHdr = GetBufferDescriptor(buffer - 1);
2929 LW_EXCLUSIVE));
2930 }
2931
2932 return pg_atomic_read_u32(&bufHdr->state) & BM_DIRTY;
2933}
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:2014
@ 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 2884 of file bufmgr.c.

2885{
2886 BufferDesc *bufHdr;
2887
2888 Assert(BufferIsPinned(buffer));
2889
2890 if (BufferIsLocal(buffer))
2891 {
2892 /* Content locks are not maintained for local buffers. */
2893 return true;
2894 }
2895 else
2896 {
2897 bufHdr = GetBufferDescriptor(buffer - 1);
2899 LW_EXCLUSIVE);
2900 }
2901}

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

Referenced by XLogRegisterBuffer().

◆ BufferIsPermanent()

bool BufferIsPermanent ( Buffer  buffer)

Definition at line 4393 of file bufmgr.c.

4394{
4395 BufferDesc *bufHdr;
4396
4397 /* Local buffers are used only for temp relations. */
4398 if (BufferIsLocal(buffer))
4399 return false;
4400
4401 /* Make sure we've got a real buffer, and that we hold a pin on it. */
4402 Assert(BufferIsValid(buffer));
4403 Assert(BufferIsPinned(buffer));
4404
4405 /*
4406 * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
4407 * need not bother with the buffer header spinlock. Even if someone else
4408 * changes the buffer header state while we're doing this, the state is
4409 * changed atomically, so we'll read the old value or the new value, but
4410 * not random garbage.
4411 */
4412 bufHdr = GetBufferDescriptor(buffer - 1);
4413 return (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT) != 0;
4414}
#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 365 of file bufmgr.h.

366{
367 Assert(bufnum <= NBuffers);
368 Assert(bufnum >= -NLocBuffer);
369
370 return bufnum != InvalidBuffer;
371}
#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:866
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:6331
int backend_flush_after
Definition: bufmgr.c:177
#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:189
#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 5584 of file bufmgr.c.

5585{
5586 if (BufferIsLocal(buffer))
5587 {
5588 if (LocalRefCount[-buffer - 1] != 1)
5589 elog(ERROR, "incorrect local pin count: %d",
5590 LocalRefCount[-buffer - 1]);
5591 }
5592 else
5593 {
5594 if (GetPrivateRefCount(buffer) != 1)
5595 elog(ERROR, "incorrect local pin count: %d",
5596 GetPrivateRefCount(buffer));
5597 }
5598}
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:422
#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 4147 of file bufmgr.c.

4148{
4149 BufferSync(flags);
4150}
static void BufferSync(int flags)
Definition: bufmgr.c:3342

References BufferSync().

Referenced by CheckPointGuts().

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

◆ ConditionalLockBufferForCleanup()

bool ConditionalLockBufferForCleanup ( Buffer  buffer)

Definition at line 5785 of file bufmgr.c.

5786{
5787 BufferDesc *bufHdr;
5788 uint32 buf_state,
5789 refcount;
5790
5791 Assert(BufferIsValid(buffer));
5792
5793 /* see AIO related comment in LockBufferForCleanup() */
5794
5795 if (BufferIsLocal(buffer))
5796 {
5797 refcount = LocalRefCount[-buffer - 1];
5798 /* There should be exactly one pin */
5799 Assert(refcount > 0);
5800 if (refcount != 1)
5801 return false;
5802 /* Nobody else to wait for */
5803 return true;
5804 }
5805
5806 /* There should be exactly one local pin */
5807 refcount = GetPrivateRefCount(buffer);
5808 Assert(refcount);
5809 if (refcount != 1)
5810 return false;
5811
5812 /* Try to acquire lock */
5813 if (!ConditionalLockBuffer(buffer))
5814 return false;
5815
5816 bufHdr = GetBufferDescriptor(buffer - 1);
5817 buf_state = LockBufHdr(bufHdr);
5818 refcount = BUF_STATE_GET_REFCOUNT(buf_state);
5819
5820 Assert(refcount > 0);
5821 if (refcount == 1)
5822 {
5823 /* Successfully acquired exclusive lock with pincount 1 */
5824 UnlockBufHdr(bufHdr, buf_state);
5825 return true;
5826 }
5827
5828 /* Failed, so release the lock */
5829 UnlockBufHdr(bufHdr, buf_state);
5831 return false;
5832}
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:59
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:5563
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5537
#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 5177 of file bufmgr.c.

5179{
5180 char relpersistence;
5181 SMgrRelation src_rel;
5182 SMgrRelation dst_rel;
5183
5184 /* Set the relpersistence. */
5185 relpersistence = permanent ?
5186 RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
5187
5188 src_rel = smgropen(src_rlocator, INVALID_PROC_NUMBER);
5189 dst_rel = smgropen(dst_rlocator, INVALID_PROC_NUMBER);
5190
5191 /*
5192 * Create and copy all forks of the relation. During create database we
5193 * have a separate cleanup mechanism which deletes complete database
5194 * directory. Therefore, each individual relation doesn't need to be
5195 * registered for cleanup.
5196 */
5197 RelationCreateStorage(dst_rlocator, relpersistence, false);
5198
5199 /* copy main fork. */
5200 RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, MAIN_FORKNUM,
5201 permanent);
5202
5203 /* copy those extra forks that exist */
5204 for (ForkNumber forkNum = MAIN_FORKNUM + 1;
5205 forkNum <= MAX_FORKNUM; forkNum++)
5206 {
5207 if (smgrexists(src_rel, forkNum))
5208 {
5209 smgrcreate(dst_rel, forkNum, false);
5210
5211 /*
5212 * WAL log creation if the relation is persistent, or this is the
5213 * init fork of an unlogged relation.
5214 */
5215 if (permanent || forkNum == INIT_FORKNUM)
5216 log_smgrcreate(&dst_rlocator, forkNum);
5217
5218 /* Copy a fork's data, block by block. */
5219 RelationCopyStorageUsingBuffer(src_rlocator, dst_rlocator, forkNum,
5220 permanent);
5221 }
5222 }
5223}
static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, RelFileLocator dstlocator, ForkNumber forkNum, bool permanent)
Definition: bufmgr.c:5063
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 4104 of file bufmgr.c.

4105{
4106 BufferDesc *buf;
4107 int32 loccount;
4108 char *result;
4109 ProcNumber backend;
4110 uint32 buf_state;
4111
4112 Assert(BufferIsValid(buffer));
4113 if (BufferIsLocal(buffer))
4114 {
4115 buf = GetLocalBufferDescriptor(-buffer - 1);
4116 loccount = LocalRefCount[-buffer - 1];
4117 backend = MyProcNumber;
4118 }
4119 else
4120 {
4121 buf = GetBufferDescriptor(buffer - 1);
4122 loccount = GetPrivateRefCount(buffer);
4123 backend = INVALID_PROC_NUMBER;
4124 }
4125
4126 /* theoretically we should lock the bufhdr here */
4127 buf_state = pg_atomic_read_u32(&buf->state);
4128
4129 result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
4130 buffer,
4132 BufTagGetForkNum(&buf->tag)).str,
4133 buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
4134 BUF_STATE_GET_REFCOUNT(buf_state), loccount);
4135 return result;
4136}
#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 4825 of file bufmgr.c.

4826{
4827 int i;
4828
4829 /*
4830 * We needn't consider local buffers, since by assumption the target
4831 * database isn't our own.
4832 */
4833
4834 for (i = 0; i < NBuffers; i++)
4835 {
4836 BufferDesc *bufHdr = GetBufferDescriptor(i);
4837 uint32 buf_state;
4838
4839 /*
4840 * As in DropRelationBuffers, an unlocked precheck should be safe and
4841 * saves some cycles.
4842 */
4843 if (bufHdr->tag.dbOid != dbid)
4844 continue;
4845
4846 buf_state = LockBufHdr(bufHdr);
4847 if (bufHdr->tag.dbOid == dbid)
4848 InvalidateBuffer(bufHdr); /* releases spinlock */
4849 else
4850 UnlockBufHdr(bufHdr, buf_state);
4851 }
4852}
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:2176

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

6612{
6613 *buffers_evicted = 0;
6614 *buffers_skipped = 0;
6615 *buffers_flushed = 0;
6616
6617 for (int buf = 1; buf <= NBuffers; buf++)
6618 {
6619 BufferDesc *desc = GetBufferDescriptor(buf - 1);
6620 uint32 buf_state;
6621 bool buffer_flushed;
6622
6623 buf_state = pg_atomic_read_u32(&desc->state);
6624 if (!(buf_state & BM_VALID))
6625 continue;
6626
6629
6630 LockBufHdr(desc);
6631
6632 if (EvictUnpinnedBufferInternal(desc, &buffer_flushed))
6633 (*buffers_evicted)++;
6634 else
6635 (*buffers_skipped)++;
6636
6637 if (buffer_flushed)
6638 (*buffers_flushed)++;
6639 }
6640}
#define BM_VALID
Definition: buf_internals.h:70
static bool EvictUnpinnedBufferInternal(BufferDesc *desc, bool *buffer_flushed)
Definition: bufmgr.c:6517
static void ReservePrivateRefCountEntry(void)
Definition: bufmgr.c:256
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 6658 of file bufmgr.c.

6660{
6662
6663 *buffers_skipped = 0;
6664 *buffers_evicted = 0;
6665 *buffers_flushed = 0;
6666
6667 for (int buf = 1; buf <= NBuffers; buf++)
6668 {
6669 BufferDesc *desc = GetBufferDescriptor(buf - 1);
6670 uint32 buf_state = pg_atomic_read_u32(&(desc->state));
6671 bool buffer_flushed;
6672
6673 /* An unlocked precheck should be safe and saves some cycles. */
6674 if ((buf_state & BM_VALID) == 0 ||
6676 continue;
6677
6678 /* Make sure we can pin the buffer. */
6681
6682 buf_state = LockBufHdr(desc);
6683
6684 /* recheck, could have changed without the lock */
6685 if ((buf_state & BM_VALID) == 0 ||
6687 {
6688 UnlockBufHdr(desc, buf_state);
6689 continue;
6690 }
6691
6692 if (EvictUnpinnedBufferInternal(desc, &buffer_flushed))
6693 (*buffers_evicted)++;
6694 else
6695 (*buffers_skipped)++;
6696
6697 if (buffer_flushed)
6698 (*buffers_flushed)++;
6699 }
6700}
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 6581 of file bufmgr.c.

6582{
6583 BufferDesc *desc;
6584
6586
6587 /* Make sure we can pin the buffer. */
6590
6591 desc = GetBufferDescriptor(buf - 1);
6592 LockBufHdr(desc);
6593
6594 return EvictUnpinnedBufferInternal(desc, buffer_flushed);
6595}

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

855{
856 Buffer buf;
857 uint32 extend_by = 1;
858
859 ExtendBufferedRelBy(bmr, forkNum, strategy, flags, extend_by,
860 &buf, &extend_by);
861
862 return buf;
863}
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:883

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

890{
891 Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
892 Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
893 Assert(extend_by > 0);
894
895 if (bmr.smgr == NULL)
896 {
897 bmr.smgr = RelationGetSmgr(bmr.rel);
898 bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
899 }
900
901 return ExtendBufferedRelCommon(bmr, fork, strategy, flags,
902 extend_by, InvalidBlockNumber,
903 buffers, extended_by);
904}
#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:2559
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 915 of file bufmgr.c.

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

5242{
5243 int i;
5244 BufferDesc *bufHdr;
5245
5246 for (i = 0; i < NBuffers; i++)
5247 {
5248 uint32 buf_state;
5249
5250 bufHdr = GetBufferDescriptor(i);
5251
5252 /*
5253 * As in DropRelationBuffers, an unlocked precheck should be safe and
5254 * saves some cycles.
5255 */
5256 if (bufHdr->tag.dbOid != dbid)
5257 continue;
5258
5259 /* Make sure we can handle the pin */
5262
5263 buf_state = LockBufHdr(bufHdr);
5264 if (bufHdr->tag.dbOid == dbid &&
5265 (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
5266 {
5267 PinBuffer_Locked(bufHdr);
5271 UnpinBuffer(bufHdr);
5272 }
5273 else
5274 UnlockBufHdr(bufHdr, buf_state);
5275 }
5276}
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context)
Definition: bufmgr.c:4221
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:3176
static void UnpinBuffer(BufferDesc *buf)
Definition: bufmgr.c:3257
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 5283 of file bufmgr.c.

5284{
5285 BufferDesc *bufHdr;
5286
5287 /* currently not needed, but no fundamental reason not to support */
5288 Assert(!BufferIsLocal(buffer));
5289
5290 Assert(BufferIsPinned(buffer));
5291
5292 bufHdr = GetBufferDescriptor(buffer - 1);
5293
5295
5297}
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1970

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

4874{
4875 int i;
4876 BufferDesc *bufHdr;
4877 SMgrRelation srel = RelationGetSmgr(rel);
4878
4879 if (RelationUsesLocalBuffers(rel))
4880 {
4881 for (i = 0; i < NLocBuffer; i++)
4882 {
4883 uint32 buf_state;
4884
4885 bufHdr = GetLocalBufferDescriptor(i);
4886 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
4887 ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
4888 (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4889 {
4890 ErrorContextCallback errcallback;
4891
4892 /* Setup error traceback support for ereport() */
4894 errcallback.arg = bufHdr;
4895 errcallback.previous = error_context_stack;
4896 error_context_stack = &errcallback;
4897
4898 /* Make sure we can handle the pin */
4901
4902 /*
4903 * Pin/upin mostly to make valgrind work, but it also seems
4904 * like the right thing to do.
4905 */
4906 PinLocalBuffer(bufHdr, false);
4907
4908
4909 FlushLocalBuffer(bufHdr, srel);
4910
4912
4913 /* Pop the error context stack */
4914 error_context_stack = errcallback.previous;
4915 }
4916 }
4917
4918 return;
4919 }
4920
4921 for (i = 0; i < NBuffers; i++)
4922 {
4923 uint32 buf_state;
4924
4925 bufHdr = GetBufferDescriptor(i);
4926
4927 /*
4928 * As in DropRelationBuffers, an unlocked precheck should be safe and
4929 * saves some cycles.
4930 */
4931 if (!BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator))
4932 continue;
4933
4934 /* Make sure we can handle the pin */
4937
4938 buf_state = LockBufHdr(bufHdr);
4939 if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
4940 (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
4941 {
4942 PinBuffer_Locked(bufHdr);
4946 UnpinBuffer(bufHdr);
4947 }
4948 else
4949 UnlockBufHdr(bufHdr, buf_state);
4950 }
4951}
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
static void local_buffer_write_error_callback(void *arg)
Definition: bufmgr.c:6146
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:297
void(* callback)(void *arg)
Definition: elog.h:298

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:2147

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 * the configured degree of IO concurrency. While being read
587 * in, 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:152
int io_combine_limit
Definition: bufmgr.c:167
uint32 GetPinLimit(void)
Definition: bufmgr.c:2503
#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:1970

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

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

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

2504{
2505 return MaxProportionalPins;
2506}

References MaxProportionalPins.

Referenced by GetAccessStrategy(), and read_stream_begin_impl().

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )

Definition at line 5759 of file bufmgr.c.

5760{
5761 int bufid = GetStartupBufferPinWaitBufId();
5762
5763 /*
5764 * If we get woken slowly then it's possible that the Startup process was
5765 * already woken by other backends before we got here. Also possible that
5766 * we get here by multiple interrupts or interrupts at inappropriate
5767 * times, so make sure we do nothing if the bufid is not set.
5768 */
5769 if (bufid < 0)
5770 return false;
5771
5772 if (GetPrivateRefCount(bufid + 1) > 0)
5773 return true;
5774
5775 return false;
5776}
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:767

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and ProcessRecoveryConflictInterrupt().

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

Definition at line 5335 of file bufmgr.c.

5336{
5337 Assert(BufferIsPinned(buffer));
5339 if (BufferIsLocal(buffer))
5340 LocalRefCount[-buffer - 1]++;
5341 else
5342 {
5344
5345 ref = GetPrivateRefCountEntry(buffer, true);
5346 Assert(ref != NULL);
5347 ref->refcount++;
5348 }
5350}
static void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition: bufmgr.c:348

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

4007{
4008 HASHCTL hash_ctl;
4009
4010 /*
4011 * An advisory limit on the number of pins each backend should hold, based
4012 * on shared_buffers and the maximum number of connections possible.
4013 * That's very pessimistic, but outside toy-sized shared_buffers it should
4014 * allow plenty of pins. LimitAdditionalPins() and
4015 * GetAdditionalPinLimit() can be used to check the remaining balance.
4016 */
4018
4019 memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
4020
4021 hash_ctl.keysize = sizeof(int32);
4022 hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
4023
4024 PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
4026
4027 /*
4028 * AtProcExit_Buffers needs LWLock access, and thereby has to be called at
4029 * the corresponding phase of backend shutdown.
4030 */
4031 Assert(MyProc != NULL);
4033}
static void AtProcExit_Buffers(int code, Datum arg)
Definition: bufmgr.c:4040
struct PrivateRefCountEntry PrivateRefCountEntry
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition: bufmgr.c:212
static HTAB * PrivateRefCountHash
Definition: bufmgr.c:213
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:447
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 5843 of file bufmgr.c.

5844{
5845 BufferDesc *bufHdr;
5846 uint32 buf_state;
5847
5848 Assert(BufferIsValid(buffer));
5849
5850 /* see AIO related comment in LockBufferForCleanup() */
5851
5852 if (BufferIsLocal(buffer))
5853 {
5854 /* There should be exactly one pin */
5855 if (LocalRefCount[-buffer - 1] != 1)
5856 return false;
5857 /* Nobody else to wait for */
5858 return true;
5859 }
5860
5861 /* There should be exactly one local pin */
5862 if (GetPrivateRefCount(buffer) != 1)
5863 return false;
5864
5865 bufHdr = GetBufferDescriptor(buffer - 1);
5866
5867 /* caller must hold exclusive lock on buffer */
5869 LW_EXCLUSIVE));
5870
5871 buf_state = LockBufHdr(bufHdr);
5872
5873 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5874 if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
5875 {
5876 /* pincount is OK. */
5877 UnlockBufHdr(bufHdr, buf_state);
5878 return true;
5879 }
5880
5881 UnlockBufHdr(bufHdr, buf_state);
5882 return false;
5883}

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

2542{
2543 uint32 limit;
2544
2545 if (*additional_pins <= 1)
2546 return;
2547
2548 limit = GetAdditionalPinLimit();
2549 limit = Max(limit, 1);
2550 if (limit < *additional_pins)
2551 *additional_pins = limit;
2552}
uint32 GetAdditionalPinLimit(void)
Definition: bufmgr.c:2515

References GetAdditionalPinLimit(), and Max.

Referenced by ExtendBufferedRelShared().

◆ LockBuffer()

void LockBuffer ( Buffer  buffer,
int  mode 
)

Definition at line 5537 of file bufmgr.c.

5538{
5539 BufferDesc *buf;
5540
5541 Assert(BufferIsPinned(buffer));
5542 if (BufferIsLocal(buffer))
5543 return; /* local buffers need no lock */
5544
5545 buf = GetBufferDescriptor(buffer - 1);
5546
5547 if (mode == BUFFER_LOCK_UNLOCK)
5549 else if (mode == BUFFER_LOCK_SHARE)
5551 else if (mode == BUFFER_LOCK_EXCLUSIVE)
5553 else
5554 elog(ERROR, "unrecognized buffer lock mode: %d", mode);
5555}
#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 5617 of file bufmgr.c.

5618{
5619 BufferDesc *bufHdr;
5620 TimestampTz waitStart = 0;
5621 bool waiting = false;
5622 bool logged_recovery_conflict = false;
5623
5624 Assert(BufferIsPinned(buffer));
5625 Assert(PinCountWaitBuf == NULL);
5626
5628
5629 /*
5630 * We do not yet need to be worried about in-progress AIOs holding a pin,
5631 * as we, so far, only support doing reads via AIO and this function can
5632 * only be called once the buffer is valid (i.e. no read can be in
5633 * flight).
5634 */
5635
5636 /* Nobody else to wait for */
5637 if (BufferIsLocal(buffer))
5638 return;
5639
5640 bufHdr = GetBufferDescriptor(buffer - 1);
5641
5642 for (;;)
5643 {
5644 uint32 buf_state;
5645
5646 /* Try to acquire lock */
5648 buf_state = LockBufHdr(bufHdr);
5649
5650 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5651 if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
5652 {
5653 /* Successfully acquired exclusive lock with pincount 1 */
5654 UnlockBufHdr(bufHdr, buf_state);
5655
5656 /*
5657 * Emit the log message if recovery conflict on buffer pin was
5658 * resolved but the startup process waited longer than
5659 * deadlock_timeout for it.
5660 */
5661 if (logged_recovery_conflict)
5663 waitStart, GetCurrentTimestamp(),
5664 NULL, false);
5665
5666 if (waiting)
5667 {
5668 /* reset ps display to remove the suffix if we added one */
5670 waiting = false;
5671 }
5672 return;
5673 }
5674 /* Failed, so mark myself as waiting for pincount 1 */
5675 if (buf_state & BM_PIN_COUNT_WAITER)
5676 {
5677 UnlockBufHdr(bufHdr, buf_state);
5679 elog(ERROR, "multiple backends attempting to wait for pincount 1");
5680 }
5682 PinCountWaitBuf = bufHdr;
5683 buf_state |= BM_PIN_COUNT_WAITER;
5684 UnlockBufHdr(bufHdr, buf_state);
5686
5687 /* Wait to be signaled by UnpinBuffer() */
5688 if (InHotStandby)
5689 {
5690 if (!waiting)
5691 {
5692 /* adjust the process title to indicate that it's waiting */
5693 set_ps_display_suffix("waiting");
5694 waiting = true;
5695 }
5696
5697 /*
5698 * Emit the log message if the startup process is waiting longer
5699 * than deadlock_timeout for recovery conflict on buffer pin.
5700 *
5701 * Skip this if first time through because the startup process has
5702 * not started waiting yet in this case. So, the wait start
5703 * timestamp is set after this logic.
5704 */
5705 if (waitStart != 0 && !logged_recovery_conflict)
5706 {
5708
5709 if (TimestampDifferenceExceeds(waitStart, now,
5711 {
5713 waitStart, now, NULL, true);
5714 logged_recovery_conflict = true;
5715 }
5716 }
5717
5718 /*
5719 * Set the wait start timestamp if logging is enabled and first
5720 * time through.
5721 */
5722 if (log_recovery_conflict_waits && waitStart == 0)
5723 waitStart = GetCurrentTimestamp();
5724
5725 /* Publish the bufid that Startup process waits on */
5726 SetStartupBufferPinWaitBufId(buffer - 1);
5727 /* Set alarm and then wait to be signaled by UnpinBuffer() */
5729 /* Reset the published bufid */
5731 }
5732 else
5733 ProcWaitForSignal(WAIT_EVENT_BUFFER_PIN);
5734
5735 /*
5736 * Remove flag marking us as waiter. Normally this will not be set
5737 * anymore, but ProcWaitForSignal() can return for other signals as
5738 * well. We take care to only reset the flag if we're the waiter, as
5739 * theoretically another backend could have started waiting. That's
5740 * impossible with the current usages due to table level locking, but
5741 * better be safe.
5742 */
5743 buf_state = LockBufHdr(bufHdr);
5744 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5746 buf_state &= ~BM_PIN_COUNT_WAITER;
5747 UnlockBufHdr(bufHdr, buf_state);
5748
5749 PinCountWaitBuf = NULL;
5750 /* Loop back and try again */
5751 }
5752}
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:5584
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:180
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 2945 of file bufmgr.c.

2946{
2947 BufferDesc *bufHdr;
2948 uint32 buf_state;
2949 uint32 old_buf_state;
2950
2951 if (!BufferIsValid(buffer))
2952 elog(ERROR, "bad buffer ID: %d", buffer);
2953
2954 if (BufferIsLocal(buffer))
2955 {
2956 MarkLocalBufferDirty(buffer);
2957 return;
2958 }
2959
2960 bufHdr = GetBufferDescriptor(buffer - 1);
2961
2962 Assert(BufferIsPinned(buffer));
2964 LW_EXCLUSIVE));
2965
2966 old_buf_state = pg_atomic_read_u32(&bufHdr->state);
2967 for (;;)
2968 {
2969 if (old_buf_state & BM_LOCKED)
2970 old_buf_state = WaitBufHdrUnlocked(bufHdr);
2971
2972 buf_state = old_buf_state;
2973
2974 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
2975 buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
2976
2977 if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
2978 buf_state))
2979 break;
2980 }
2981
2982 /*
2983 * If the buffer was not dirty already, do vacuum accounting.
2984 */
2985 if (!(old_buf_state & BM_DIRTY))
2986 {
2988 if (VacuumCostActive)
2990 }
2991}
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:6219
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 5367 of file bufmgr.c.

5368{
5369 BufferDesc *bufHdr;
5370 Page page = BufferGetPage(buffer);
5371
5372 if (!BufferIsValid(buffer))
5373 elog(ERROR, "bad buffer ID: %d", buffer);
5374
5375 if (BufferIsLocal(buffer))
5376 {
5377 MarkLocalBufferDirty(buffer);
5378 return;
5379 }
5380
5381 bufHdr = GetBufferDescriptor(buffer - 1);
5382
5383 Assert(GetPrivateRefCount(buffer) > 0);
5384 /* here, either share or exclusive lock is OK */
5386
5387 /*
5388 * This routine might get called many times on the same page, if we are
5389 * making the first scan after commit of an xact that added/deleted many
5390 * tuples. So, be as quick as we can if the buffer is already dirty. We
5391 * do this by not acquiring spinlock if it looks like the status bits are
5392 * already set. Since we make this test unlocked, there's a chance we
5393 * might fail to notice that the flags have just been cleared, and failed
5394 * to reset them, due to memory-ordering issues. But since this function
5395 * is only intended to be used in cases where failing to write out the
5396 * data would be harmless anyway, it doesn't really matter.
5397 */
5398 if ((pg_atomic_read_u32(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
5400 {
5402 bool dirtied = false;
5403 bool delayChkptFlags = false;
5404 uint32 buf_state;
5405
5406 /*
5407 * If we need to protect hint bit updates from torn writes, WAL-log a
5408 * full page image of the page. This full page image is only necessary
5409 * if the hint bit update is the first change to the page since the
5410 * last checkpoint.
5411 *
5412 * We don't check full_page_writes here because that logic is included
5413 * when we call XLogInsert() since the value changes dynamically.
5414 */
5415 if (XLogHintBitIsNeeded() &&
5417 {
5418 /*
5419 * If we must not write WAL, due to a relfilelocator-specific
5420 * condition or being in recovery, don't dirty the page. We can
5421 * set the hint, just not dirty the page as a result so the hint
5422 * is lost when we evict the page or shutdown.
5423 *
5424 * See src/backend/storage/page/README for longer discussion.
5425 */
5426 if (RecoveryInProgress() ||
5428 return;
5429
5430 /*
5431 * If the block is already dirty because we either made a change
5432 * or set a hint already, then we don't need to write a full page
5433 * image. Note that aggressive cleaning of blocks dirtied by hint
5434 * bit setting would increase the call rate. Bulk setting of hint
5435 * bits would reduce the call rate...
5436 *
5437 * We must issue the WAL record before we mark the buffer dirty.
5438 * Otherwise we might write the page before we write the WAL. That
5439 * causes a race condition, since a checkpoint might occur between
5440 * writing the WAL record and marking the buffer dirty. We solve
5441 * that with a kluge, but one that is already in use during
5442 * transaction commit to prevent race conditions. Basically, we
5443 * simply prevent the checkpoint WAL record from being written
5444 * until we have marked the buffer dirty. We don't start the
5445 * checkpoint flush until we have marked dirty, so our checkpoint
5446 * must flush the change to disk successfully or the checkpoint
5447 * never gets written, so crash recovery will fix.
5448 *
5449 * It's possible we may enter here without an xid, so it is
5450 * essential that CreateCheckPoint waits for virtual transactions
5451 * rather than full transactionids.
5452 */
5455 delayChkptFlags = true;
5456 lsn = XLogSaveBufferForHint(buffer, buffer_std);
5457 }
5458
5459 buf_state = LockBufHdr(bufHdr);
5460
5461 Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
5462
5463 if (!(buf_state & BM_DIRTY))
5464 {
5465 dirtied = true; /* Means "will be dirtied by this action" */
5466
5467 /*
5468 * Set the page LSN if we wrote a backup block. We aren't supposed
5469 * to set this when only holding a share lock but as long as we
5470 * serialise it somehow we're OK. We choose to set LSN while
5471 * holding the buffer header lock, which causes any reader of an
5472 * LSN who holds only a share lock to also obtain a buffer header
5473 * lock before using PageGetLSN(), which is enforced in
5474 * BufferGetLSNAtomic().
5475 *
5476 * If checksums are enabled, you might think we should reset the
5477 * checksum here. That will happen when the page is written
5478 * sometime later in this checkpoint cycle.
5479 */
5480 if (!XLogRecPtrIsInvalid(lsn))
5481 PageSetLSN(page, lsn);
5482 }
5483
5484 buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
5485 UnlockBufHdr(bufHdr, buf_state);
5486
5487 if (delayChkptFlags)
5488 MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
5489
5490 if (dirtied)
5491 {
5493 if (VacuumCostActive)
5495 }
5496 }
5497}
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:391
#define DELAY_CHKPT_START
Definition: proc.h:120
bool RelFileLocatorSkippingWAL(RelFileLocator rlocator)
Definition: storage.c:573
int delayChkptFlags
Definition: proc.h:241
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 644 of file bufmgr.c.

645{
646 Assert(RelationIsValid(reln));
647 Assert(BlockNumberIsValid(blockNum));
648
649 if (RelationUsesLocalBuffers(reln))
650 {
651 /* see comments in ReadBufferExtended */
652 if (RELATION_IS_OTHER_TEMP(reln))
654 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
655 errmsg("cannot access temporary tables of other sessions")));
656
657 /* pass it off to localbuf.c */
658 return PrefetchLocalBuffer(RelationGetSmgr(reln), forkNum, blockNum);
659 }
660 else
661 {
662 /* pass it to the shared buffer version */
663 return PrefetchSharedBuffer(RelationGetSmgr(reln), forkNum, blockNum);
664 }
665}
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:554
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 751 of file bufmgr.c.

752{
753 return ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);
754}
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:798

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

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

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

838{
839 SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
840
841 return ReadBuffer_common(NULL, smgr,
842 permanent ? RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED,
843 forkNum, blockNum,
844 mode, strategy);
845}

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

677{
678 BufferDesc *bufHdr;
679 BufferTag tag;
680 uint32 buf_state;
681 bool have_private_ref;
682
683 Assert(BufferIsValid(recent_buffer));
684
687 InitBufferTag(&tag, &rlocator, forkNum, blockNum);
688
689 if (BufferIsLocal(recent_buffer))
690 {
691 int b = -recent_buffer - 1;
692
693 bufHdr = GetLocalBufferDescriptor(b);
694 buf_state = pg_atomic_read_u32(&bufHdr->state);
695
696 /* Is it still valid and holding the right tag? */
697 if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
698 {
699 PinLocalBuffer(bufHdr, true);
700
702
703 return true;
704 }
705 }
706 else
707 {
708 bufHdr = GetBufferDescriptor(recent_buffer - 1);
709 have_private_ref = GetPrivateRefCount(recent_buffer) > 0;
710
711 /*
712 * Do we already have this buffer pinned with a private reference? If
713 * so, it must be valid and it is safe to check the tag without
714 * locking. If not, we have to lock the header first and then check.
715 */
716 if (have_private_ref)
717 buf_state = pg_atomic_read_u32(&bufHdr->state);
718 else
719 buf_state = LockBufHdr(bufHdr);
720
721 if ((buf_state & BM_VALID) && BufferTagsEqual(&tag, &bufHdr->tag))
722 {
723 /*
724 * It's now safe to pin the buffer. We can't pin first and ask
725 * questions later, because it might confuse code paths like
726 * InvalidateBuffer() if we pinned a random non-matching buffer.
727 */
728 if (have_private_ref)
729 PinBuffer(bufHdr, NULL); /* bump pin count */
730 else
731 PinBuffer_Locked(bufHdr); /* pin for first time */
732
734
735 return true;
736 }
737
738 /* If we locked the header above, now unlock. */
739 if (!have_private_ref)
740 UnlockBufHdr(bufHdr, buf_state);
741 }
742
743 return false;
744}
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:3065
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 4361 of file bufmgr.c.

4362{
4363 if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
4364 {
4365 /*
4366 * Not every table AM uses BLCKSZ wide fixed size blocks. Therefore
4367 * tableam returns the size in bytes - but for the purpose of this
4368 * routine, we want the number of blocks. Therefore divide, rounding
4369 * up.
4370 */
4371 uint64 szbytes;
4372
4373 szbytes = table_relation_size(relation, forkNum);
4374
4375 return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
4376 }
4377 else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
4378 {
4379 return smgrnblocks(RelationGetSmgr(relation), forkNum);
4380 }
4381 else
4382 Assert(false);
4383
4384 return 0; /* keep compiler quiet */
4385}
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 3007 of file bufmgr.c.

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

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

5304{
5305 if (!BufferIsValid(buffer))
5306 elog(ERROR, "bad buffer ID: %d", buffer);
5307
5308 if (BufferIsLocal(buffer))
5309 UnpinLocalBuffer(buffer);
5310 else
5311 UnpinBuffer(GetBufferDescriptor(buffer - 1));
5312}

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

1510{
1511 int nblocks = 1;
1512 bool result;
1513
1514 result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags,
1515 false /* single block, no forwarding */ );
1516 Assert(nblocks == 1); /* single block can't be short */
1517
1518 return result;
1519}
static pg_attribute_always_inline bool StartReadBuffersImpl(ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, int flags, bool allow_forwarding)
Definition: bufmgr.c:1255

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

1492{
1493 return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags,
1494 true /* expect forwarded buffers */ );
1495}

References StartReadBuffersImpl().

Referenced by read_stream_start_pending_read().

◆ UnlockBuffers()

void UnlockBuffers ( void  )

Definition at line 5509 of file bufmgr.c.

5510{
5512
5513 if (buf)
5514 {
5515 uint32 buf_state;
5516
5517 buf_state = LockBufHdr(buf);
5518
5519 /*
5520 * Don't complain if flag bit not set; it could have been reset but we
5521 * got a cancel/die interrupt before getting the signal.
5522 */
5523 if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
5524 buf->wait_backend_pgprocno == MyProcNumber)
5525 buf_state &= ~BM_PIN_COUNT_WAITER;
5526
5527 UnlockBufHdr(buf, buf_state);
5528
5529 PinCountWaitBuf = NULL;
5530 }
5531}

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

5321{
5323 ReleaseBuffer(buffer);
5324}

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

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

◆ aio_shared_buffer_readv_cb

PGDLLIMPORT const PgAioHandleCallbacks aio_shared_buffer_readv_cb
extern

Definition at line 7367 of file bufmgr.c.

◆ backend_flush_after

PGDLLIMPORT int backend_flush_after
extern

Definition at line 177 of file bufmgr.c.

Referenced by BufferManagerShmemInit().

◆ bgwriter_flush_after

PGDLLIMPORT int bgwriter_flush_after
extern

Definition at line 176 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

PGDLLIMPORT int bgwriter_lru_maxpages
extern

Definition at line 142 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

PGDLLIMPORT double bgwriter_lru_multiplier
extern

Definition at line 143 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 175 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 168 of file bufmgr.c.

Referenced by assign_io_combine_limit(), and assign_io_max_combine_limit().

◆ io_max_combine_limit

PGDLLIMPORT int io_max_combine_limit
extern

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

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