PostgreSQL Source Code  git master
bufmgr.h File Reference
#include "storage/block.h"
#include "storage/buf.h"
#include "storage/bufpage.h"
#include "storage/relfilenode.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.

Macros

#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 BufferIsValid(bufnum)
 
#define BufferGetBlock(buffer)
 
#define BufferGetPageSize(buffer)
 
#define BufferGetPage(buffer)   ((Page)BufferGetBlock(buffer))
 
#define RelationGetNumberOfBlocks(reln)   RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)
 

Typedefs

typedef void * Block
 
typedef enum BufferAccessStrategyType BufferAccessStrategyType
 

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
}
 

Functions

bool ComputeIoConcurrency (int io_concurrency, double *target)
 
void PrefetchBuffer (Relation reln, ForkNumber forkNum, BlockNumber blockNum)
 
Buffer ReadBuffer (Relation reln, BlockNumber blockNum)
 
Buffer ReadBufferExtended (Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
 
Buffer ReadBufferWithoutRelcache (RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
 
void ReleaseBuffer (Buffer buffer)
 
void UnlockReleaseBuffer (Buffer buffer)
 
void MarkBufferDirty (Buffer buffer)
 
void IncrBufferRefCount (Buffer buffer)
 
Buffer ReleaseAndReadBuffer (Buffer buffer, Relation relation, BlockNumber blockNum)
 
void InitBufferPool (void)
 
void InitBufferPoolAccess (void)
 
void InitBufferPoolBackend (void)
 
void AtEOXact_Buffers (bool isCommit)
 
void PrintBufferLeakWarning (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 FlushDatabaseBuffers (Oid dbid)
 
void DropRelFileNodeBuffers (RelFileNodeBackend rnode, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
 
void DropRelFileNodesAllBuffers (RelFileNodeBackend *rnodes, int nnodes)
 
void DropDatabaseBuffers (Oid dbid)
 
bool BufferIsPermanent (Buffer buffer)
 
XLogRecPtr BufferGetLSNAtomic (Buffer buffer)
 
Size BufferShmemSize (void)
 
void BufferGetTag (Buffer buffer, RelFileNode *rnode, 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)
 
void AbortBufferIO (void)
 
void BufmgrCommit (void)
 
bool BgBufferSync (struct WritebackContext *wb_context)
 
void AtProcExit_LocalBuffers (void)
 
void TestForOldSnapshot_impl (Snapshot snapshot, Relation relation)
 
BufferAccessStrategy GetAccessStrategy (BufferAccessStrategyType btype)
 
void FreeAccessStrategy (BufferAccessStrategy strategy)
 
static void TestForOldSnapshot (Snapshot snapshot, Relation relation, Page page)
 

Variables

PGDLLIMPORT int NBuffers
 
bool zero_damaged_pages
 
int bgwriter_lru_maxpages
 
double bgwriter_lru_multiplier
 
bool track_io_timing
 
int target_prefetch_pages
 
int checkpoint_flush_after
 
int backend_flush_after
 
int bgwriter_flush_after
 
PGDLLIMPORT char * BufferBlocks
 
int effective_io_concurrency
 
PGDLLIMPORT int NLocBuffer
 
PGDLLIMPORT BlockLocalBufferBlockPointers
 
PGDLLIMPORT int32LocalRefCount
 

Macro Definition Documentation

◆ BUFFER_LOCK_EXCLUSIVE

◆ BUFFER_LOCK_SHARE

◆ BUFFER_LOCK_UNLOCK

#define BUFFER_LOCK_UNLOCK   0

Definition at line 86 of file bufmgr.h.

Referenced by _bt_drop_lock_and_maybe_pin(), _bt_endpoint(), _bt_first(), _bt_getroot(), _bt_killitems(), _bt_moveright(), _bt_pagedel(), _bt_relandgetbuf(), _bt_search(), _bt_unlink_halfdead_page(), _bt_update_meta_cleanup_info(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_finish_split(), _hash_first(), _hash_freeovflpage(), _hash_getcachedmetap(), _hash_init(), _hash_kill_items(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), blinsert(), BloomNewBuffer(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_page_cleanup(), bringetbitmap(), brinGetTupleForHeapBlock(), brininsert(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), brinsummarize(), btvacuumpage(), ConditionalLockBufferForCleanup(), fsm_readbuf(), fsm_search_avail(), fsm_vacuum_page(), get_raw_page_internal(), GetVisibilityMapPins(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_compute_xid_horizon_for_tuples(), heap_delete(), heap_fetch(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_page_prune_opt(), 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_bitmap_next_block(), heapam_scan_sample_next_tuple(), heapam_tuple_satisfies_snapshot(), heapgetpage(), heapgettup(), lazy_scan_heap(), LockBuffer(), LockBufferForCleanup(), pgrowlocks(), pgstat_heap(), pgstatindex_impl(), RelationGetBufferForTuple(), revmap_physical_extend(), SpGistNewBuffer(), summarize_range(), UnlockReleaseBuffer(), visibilitymap_clear(), visibilitymap_set(), vm_readbuf(), and XLogReadBufferExtended().

◆ BufferGetBlock

#define BufferGetBlock (   buffer)
Value:
( \
AssertMacro(BufferIsValid(buffer)), \
BufferIsLocal(buffer) ? \
LocalBufferBlockPointers[-(buffer) - 1] \
: \
(Block) (BufferBlocks + ((Size) ((buffer) - 1)) * BLCKSZ) \
)
PGDLLIMPORT char * BufferBlocks
Definition: buf_init.c:21
size_t Size
Definition: c.h:467
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
void * Block
Definition: bufmgr.h:24

Definition at line 126 of file bufmgr.h.

Referenced by XLogSaveBufferForHint().

◆ BufferGetPage

#define BufferGetPage (   buffer)    ((Page)BufferGetBlock(buffer))

Definition at line 159 of file bufmgr.h.

Referenced by _bt_binsrch(), _bt_binsrch_insert(), _bt_check_unique(), _bt_checkpage(), _bt_clear_incomplete_split(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_doinsert(), _bt_endpoint(), _bt_findinsertloc(), _bt_finish_split(), _bt_get_endpoint(), _bt_getbuf(), _bt_getmeta(), _bt_getroot(), _bt_getstackbuf(), _bt_gettrueroot(), _bt_insert_parent(), _bt_insertonpg(), _bt_is_page_halfdead(), _bt_killitems(), _bt_lock_branch_parent(), _bt_mark_page_halfdead(), _bt_moveright(), _bt_newroot(), _bt_pagedel(), _bt_readnextpage(), _bt_readpage(), _bt_restore_meta(), _bt_search(), _bt_split(), _bt_stepright(), _bt_unlink_halfdead_page(), _bt_update_meta_cleanup_info(), _bt_vacuum_needs_cleanup(), _bt_vacuum_one_page(), _bt_walk_left(), _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_next(), _hash_pgaddmultitup(), _hash_pgaddtup(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), allocNewBuffer(), 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(), bt_rootdescend(), 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(), checkXLogConsistency(), 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_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(), ginbulkdelete(), ginDeletePage(), ginEntryInsert(), ginFindLeafPage(), ginFindParents(), 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_compute_xid_horizon_for_tuples(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_get_latest_tid(), heap_hot_search_buffer(), heap_inplace_update(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_is_all_visible(), heap_page_prune(), heap_page_prune_execute(), heap_page_prune_opt(), heap_prune_chain(), heap_update(), heap_xlog_clean(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_freeze_page(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_update(), heap_xlog_visible(), heapam_index_build_range_scan(), heapam_index_validate_scan(), heapam_scan_analyze_next_tuple(), heapam_scan_bitmap_next_block(), heapam_scan_bitmap_next_tuple(), heapam_scan_sample_next_tuple(), heapgetpage(), heapgettup(), heapgettup_pagemode(), index_compute_xid_horizon_for_tuples(), initBloomState(), lazy_check_needs_freeze(), lazy_scan_heap(), lazy_vacuum_heap(), lazy_vacuum_page(), log_heap_update(), log_newpage_buffer(), log_newpage_range(), log_split_page(), MarkBufferDirtyHint(), 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(), RelationAddExtraBlocks(), RelationGetBufferForTuple(), RelationPutHeapTuple(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), scanPostingTree(), 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(), visibilitymap_clear(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_prepare_truncate(), visibilitymap_set(), vm_readbuf(), writeListPage(), XLogCheckBufferNeedsBackup(), XLogReadBufferExtended(), XLogReadBufferForRedoExtended(), XLogRecordPageWithFreeSpace(), XLogRegisterBuffer(), XLogSaveBufferForHint(), and xlogVacuumPage().

◆ BufferGetPageSize

◆ BufferIsValid

#define BufferIsValid (   bufnum)
Value:
( \
AssertMacro((bufnum) <= NBuffers && (bufnum) >= -NLocBuffer), \
(bufnum) != InvalidBuffer \
)
#define InvalidBuffer
Definition: buf.h:25
PGDLLIMPORT int NLocBuffer
Definition: localbuf.c:41
PGDLLIMPORT int NBuffers
Definition: globals.c:131

Definition at line 113 of file bufmgr.h.

Referenced by _bt_clear_incomplete_split(), _bt_endpoint(), _bt_first(), _bt_get_endpoint(), _bt_insertonpg(), _bt_killitems(), _bt_readpage(), _bt_relandgetbuf(), _bt_search(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_dropscanbuf(), _hash_freeovflpage(), _hash_getbucketbuf_from_hashkey(), _hash_getcachedmetap(), _hash_readnext(), _hash_readpage(), _hash_readprev(), autoprewarm_database_main(), 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_rootdescend(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), BufferGetLSNAtomic(), BufferIsPermanent(), CheckForSerializableConflictIn(), checkXLogConsistency(), ConditionalLockBuffer(), ConditionalLockBufferForCleanup(), doPickSplit(), entryGetItem(), entryLoadMoreItems(), 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(), 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_compute_xid_horizon_for_tuples(), heap_endscan(), heap_lock_tuple(), heap_rescan(), heap_update(), heap_xlog_clean(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_freeze_page(), heap_xlog_inplace(), 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(), heapam_tuple_satisfies_snapshot(), heapgetpage(), heapgettup(), heapgettup_pagemode(), IsBufferCleanupOK(), lazy_scan_heap(), lazy_vacuum_heap(), lazy_vacuum_page(), LockBuffer(), LockBufferForCleanup(), log_heap_visible(), MarkBufferDirty(), MarkBufferDirtyHint(), PrintBufferLeakWarning(), ReleaseAndReadBuffer(), ReleaseBuffer(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), statapprox_heap(), tts_buffer_heap_clear(), tts_buffer_heap_copyslot(), tts_buffer_heap_materialize(), tts_buffer_heap_store_tuple(), visibilitymap_clear(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_pin(), visibilitymap_pin_ok(), visibilitymap_prepare_truncate(), visibilitymap_set(), and XLogReadBufferForRedoExtended().

◆ MAX_IO_CONCURRENCY

#define MAX_IO_CONCURRENCY   1000

Definition at line 78 of file bufmgr.h.

Referenced by ComputeIoConcurrency(), and heap_compute_xid_horizon_for_tuples().

◆ P_NEW

◆ RelationGetNumberOfBlocks

Typedef Documentation

◆ Block

typedef void* Block

Definition at line 24 of file bufmgr.h.

◆ BufferAccessStrategyType

Enumeration Type Documentation

◆ BufferAccessStrategyType

Enumerator
BAS_NORMAL 
BAS_BULKREAD 
BAS_BULKWRITE 
BAS_VACUUM 

Definition at line 27 of file bufmgr.h.

28 {
29  BAS_NORMAL, /* Normal random access */
30  BAS_BULKREAD, /* Large read-only scan (hint bit updates are
31  * ok) */
32  BAS_BULKWRITE, /* Large multi-block write (e.g. COPY IN) */
33  BAS_VACUUM /* VACUUM */
BufferAccessStrategyType
Definition: bufmgr.h:27

◆ ReadBufferMode

Enumerator
RBM_NORMAL 
RBM_ZERO_AND_LOCK 
RBM_ZERO_AND_CLEANUP_LOCK 
RBM_ZERO_ON_ERROR 
RBM_NORMAL_NO_LOG 

Definition at line 37 of file bufmgr.h.

38 {
39  RBM_NORMAL, /* Normal read */
40  RBM_ZERO_AND_LOCK, /* Don't read from disk, caller will
41  * initialize. Also locks the page. */
42  RBM_ZERO_AND_CLEANUP_LOCK, /* Like RBM_ZERO_AND_LOCK, but locks the page
43  * in "cleanup" mode */
44  RBM_ZERO_ON_ERROR, /* Read, but return an all-zeros page on error */
45  RBM_NORMAL_NO_LOG /* Don't log page as invalid during WAL
46  * replay; otherwise same as RBM_NORMAL */
ReadBufferMode
Definition: bufmgr.h:37

Function Documentation

◆ AbortBufferIO()

void AbortBufferIO ( void  )

Definition at line 4040 of file bufmgr.c.

References Assert, buftag::blockNum, BM_DIRTY, BM_IO_ERROR, BM_IO_IN_PROGRESS, BM_VALID, buf, BufferDescriptorGetIOLock, ereport, errcode(), errdetail(), errmsg(), buftag::forkNum, InProgressBuf, IsForInput, LockBufHdr(), LW_EXCLUSIVE, LWLockAcquire(), pfree(), relpathperm, buftag::rnode, BufferDesc::tag, TerminateBufferIO(), UnlockBufHdr, and WARNING.

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

4041 {
4043 
4044  if (buf)
4045  {
4046  uint32 buf_state;
4047 
4048  /*
4049  * Since LWLockReleaseAll has already been called, we're not holding
4050  * the buffer's io_in_progress_lock. We have to re-acquire it so that
4051  * we can use TerminateBufferIO. Anyone who's executing WaitIO on the
4052  * buffer will be in a busy spin until we succeed in doing this.
4053  */
4055 
4056  buf_state = LockBufHdr(buf);
4057  Assert(buf_state & BM_IO_IN_PROGRESS);
4058  if (IsForInput)
4059  {
4060  Assert(!(buf_state & BM_DIRTY));
4061 
4062  /* We'd better not think buffer is valid yet */
4063  Assert(!(buf_state & BM_VALID));
4064  UnlockBufHdr(buf, buf_state);
4065  }
4066  else
4067  {
4068  Assert(buf_state & BM_DIRTY);
4069  UnlockBufHdr(buf, buf_state);
4070  /* Issue notice if this is not the first failure... */
4071  if (buf_state & BM_IO_ERROR)
4072  {
4073  /* Buffer is pinned, so we can read tag without spinlock */
4074  char *path;
4075 
4076  path = relpathperm(buf->tag.rnode, buf->tag.forkNum);
4077  ereport(WARNING,
4078  (errcode(ERRCODE_IO_ERROR),
4079  errmsg("could not write block %u of %s",
4080  buf->tag.blockNum, path),
4081  errdetail("Multiple failures --- write error might be permanent.")));
4082  pfree(path);
4083  }
4084  }
4085  TerminateBufferIO(buf, false, BM_IO_ERROR);
4086  }
4087 }
#define relpathperm(rnode, forknum)
Definition: relpath.h:83
ForkNumber forkNum
Definition: buf_internals.h:93
int errcode(int sqlerrcode)
Definition: elog.c:608
#define BM_DIRTY
Definition: buf_internals.h:58
#define BufferDescriptorGetIOLock(bdesc)
static BufferDesc * InProgressBuf
Definition: bufmgr.c:133
void pfree(void *pointer)
Definition: mcxt.c:1056
static char * buf
Definition: pg_test_fsync.c:67
int errdetail(const char *fmt,...)
Definition: elog.c:955
unsigned int uint32
Definition: c.h:359
static bool IsForInput
Definition: bufmgr.c:134
#define ereport(elevel, rest)
Definition: elog.h:141
#define WARNING
Definition: elog.h:40
static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits)
Definition: bufmgr.c:4008
#define BM_VALID
Definition: buf_internals.h:59
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
#define Assert(condition)
Definition: c.h:739
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
BlockNumber blockNum
Definition: buf_internals.h:94
RelFileNode rnode
Definition: buf_internals.h:92
#define BM_IO_ERROR
Definition: buf_internals.h:62
BufferTag tag
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define UnlockBufHdr(desc, s)
#define BM_IO_IN_PROGRESS
Definition: buf_internals.h:61

◆ AtEOXact_Buffers()

void AtEOXact_Buffers ( bool  isCommit)

Definition at line 2433 of file bufmgr.c.

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

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

2434 {
2436 
2437  AtEOXact_LocalBuffers(isCommit);
2438 
2440 }
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:171
#define Assert(condition)
Definition: c.h:739
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:2508
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:572

◆ AtProcExit_LocalBuffers()

void AtProcExit_LocalBuffers ( void  )

Definition at line 583 of file localbuf.c.

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

584 {
585  /*
586  * We shouldn't be holding any remaining pins; if we are, and assertions
587  * aren't enabled, we'll fail later in DropRelFileNodeBuffers while trying
588  * to drop the temp rels.
589  */
591 }
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:543

◆ BgBufferSync()

bool BgBufferSync ( struct WritebackContext wb_context)

Definition at line 2063 of file bufmgr.c.

References Assert, bgwriter_lru_maxpages, bgwriter_lru_multiplier, BgWriterDelay, BgWriterStats, BUF_REUSABLE, BUF_WRITTEN, CurrentResourceOwner, DEBUG1, DEBUG2, elog, PgStat_MsgBgWriter::m_buf_alloc, PgStat_MsgBgWriter::m_buf_written_clean, PgStat_MsgBgWriter::m_maxwritten_clean, NBuffers, ResourceOwnerEnlargeBuffers(), StrategySyncStart(), and SyncOneBuffer().

Referenced by BackgroundWriterMain().

2064 {
2065  /* info obtained from freelist.c */
2066  int strategy_buf_id;
2067  uint32 strategy_passes;
2068  uint32 recent_alloc;
2069 
2070  /*
2071  * Information saved between calls so we can determine the strategy
2072  * point's advance rate and avoid scanning already-cleaned buffers.
2073  */
2074  static bool saved_info_valid = false;
2075  static int prev_strategy_buf_id;
2076  static uint32 prev_strategy_passes;
2077  static int next_to_clean;
2078  static uint32 next_passes;
2079 
2080  /* Moving averages of allocation rate and clean-buffer density */
2081  static float smoothed_alloc = 0;
2082  static float smoothed_density = 10.0;
2083 
2084  /* Potentially these could be tunables, but for now, not */
2085  float smoothing_samples = 16;
2086  float scan_whole_pool_milliseconds = 120000.0;
2087 
2088  /* Used to compute how far we scan ahead */
2089  long strategy_delta;
2090  int bufs_to_lap;
2091  int bufs_ahead;
2092  float scans_per_alloc;
2093  int reusable_buffers_est;
2094  int upcoming_alloc_est;
2095  int min_scan_buffers;
2096 
2097  /* Variables for the scanning loop proper */
2098  int num_to_scan;
2099  int num_written;
2100  int reusable_buffers;
2101 
2102  /* Variables for final smoothed_density update */
2103  long new_strategy_delta;
2104  uint32 new_recent_alloc;
2105 
2106  /*
2107  * Find out where the freelist clock sweep currently is, and how many
2108  * buffer allocations have happened since our last call.
2109  */
2110  strategy_buf_id = StrategySyncStart(&strategy_passes, &recent_alloc);
2111 
2112  /* Report buffer alloc counts to pgstat */
2113  BgWriterStats.m_buf_alloc += recent_alloc;
2114 
2115  /*
2116  * If we're not running the LRU scan, just stop after doing the stats
2117  * stuff. We mark the saved state invalid so that we can recover sanely
2118  * if LRU scan is turned back on later.
2119  */
2120  if (bgwriter_lru_maxpages <= 0)
2121  {
2122  saved_info_valid = false;
2123  return true;
2124  }
2125 
2126  /*
2127  * Compute strategy_delta = how many buffers have been scanned by the
2128  * clock sweep since last time. If first time through, assume none. Then
2129  * see if we are still ahead of the clock sweep, and if so, how many
2130  * buffers we could scan before we'd catch up with it and "lap" it. Note:
2131  * weird-looking coding of xxx_passes comparisons are to avoid bogus
2132  * behavior when the passes counts wrap around.
2133  */
2134  if (saved_info_valid)
2135  {
2136  int32 passes_delta = strategy_passes - prev_strategy_passes;
2137 
2138  strategy_delta = strategy_buf_id - prev_strategy_buf_id;
2139  strategy_delta += (long) passes_delta * NBuffers;
2140 
2141  Assert(strategy_delta >= 0);
2142 
2143  if ((int32) (next_passes - strategy_passes) > 0)
2144  {
2145  /* we're one pass ahead of the strategy point */
2146  bufs_to_lap = strategy_buf_id - next_to_clean;
2147 #ifdef BGW_DEBUG
2148  elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
2149  next_passes, next_to_clean,
2150  strategy_passes, strategy_buf_id,
2151  strategy_delta, bufs_to_lap);
2152 #endif
2153  }
2154  else if (next_passes == strategy_passes &&
2155  next_to_clean >= strategy_buf_id)
2156  {
2157  /* on same pass, but ahead or at least not behind */
2158  bufs_to_lap = NBuffers - (next_to_clean - strategy_buf_id);
2159 #ifdef BGW_DEBUG
2160  elog(DEBUG2, "bgwriter ahead: bgw %u-%u strategy %u-%u delta=%ld lap=%d",
2161  next_passes, next_to_clean,
2162  strategy_passes, strategy_buf_id,
2163  strategy_delta, bufs_to_lap);
2164 #endif
2165  }
2166  else
2167  {
2168  /*
2169  * We're behind, so skip forward to the strategy point and start
2170  * cleaning from there.
2171  */
2172 #ifdef BGW_DEBUG
2173  elog(DEBUG2, "bgwriter behind: bgw %u-%u strategy %u-%u delta=%ld",
2174  next_passes, next_to_clean,
2175  strategy_passes, strategy_buf_id,
2176  strategy_delta);
2177 #endif
2178  next_to_clean = strategy_buf_id;
2179  next_passes = strategy_passes;
2180  bufs_to_lap = NBuffers;
2181  }
2182  }
2183  else
2184  {
2185  /*
2186  * Initializing at startup or after LRU scanning had been off. Always
2187  * start at the strategy point.
2188  */
2189 #ifdef BGW_DEBUG
2190  elog(DEBUG2, "bgwriter initializing: strategy %u-%u",
2191  strategy_passes, strategy_buf_id);
2192 #endif
2193  strategy_delta = 0;
2194  next_to_clean = strategy_buf_id;
2195  next_passes = strategy_passes;
2196  bufs_to_lap = NBuffers;
2197  }
2198 
2199  /* Update saved info for next time */
2200  prev_strategy_buf_id = strategy_buf_id;
2201  prev_strategy_passes = strategy_passes;
2202  saved_info_valid = true;
2203 
2204  /*
2205  * Compute how many buffers had to be scanned for each new allocation, ie,
2206  * 1/density of reusable buffers, and track a moving average of that.
2207  *
2208  * If the strategy point didn't move, we don't update the density estimate
2209  */
2210  if (strategy_delta > 0 && recent_alloc > 0)
2211  {
2212  scans_per_alloc = (float) strategy_delta / (float) recent_alloc;
2213  smoothed_density += (scans_per_alloc - smoothed_density) /
2214  smoothing_samples;
2215  }
2216 
2217  /*
2218  * Estimate how many reusable buffers there are between the current
2219  * strategy point and where we've scanned ahead to, based on the smoothed
2220  * density estimate.
2221  */
2222  bufs_ahead = NBuffers - bufs_to_lap;
2223  reusable_buffers_est = (float) bufs_ahead / smoothed_density;
2224 
2225  /*
2226  * Track a moving average of recent buffer allocations. Here, rather than
2227  * a true average we want a fast-attack, slow-decline behavior: we
2228  * immediately follow any increase.
2229  */
2230  if (smoothed_alloc <= (float) recent_alloc)
2231  smoothed_alloc = recent_alloc;
2232  else
2233  smoothed_alloc += ((float) recent_alloc - smoothed_alloc) /
2234  smoothing_samples;
2235 
2236  /* Scale the estimate by a GUC to allow more aggressive tuning. */
2237  upcoming_alloc_est = (int) (smoothed_alloc * bgwriter_lru_multiplier);
2238 
2239  /*
2240  * If recent_alloc remains at zero for many cycles, smoothed_alloc will
2241  * eventually underflow to zero, and the underflows produce annoying
2242  * kernel warnings on some platforms. Once upcoming_alloc_est has gone to
2243  * zero, there's no point in tracking smaller and smaller values of
2244  * smoothed_alloc, so just reset it to exactly zero to avoid this
2245  * syndrome. It will pop back up as soon as recent_alloc increases.
2246  */
2247  if (upcoming_alloc_est == 0)
2248  smoothed_alloc = 0;
2249 
2250  /*
2251  * Even in cases where there's been little or no buffer allocation
2252  * activity, we want to make a small amount of progress through the buffer
2253  * cache so that as many reusable buffers as possible are clean after an
2254  * idle period.
2255  *
2256  * (scan_whole_pool_milliseconds / BgWriterDelay) computes how many times
2257  * the BGW will be called during the scan_whole_pool time; slice the
2258  * buffer pool into that many sections.
2259  */
2260  min_scan_buffers = (int) (NBuffers / (scan_whole_pool_milliseconds / BgWriterDelay));
2261 
2262  if (upcoming_alloc_est < (min_scan_buffers + reusable_buffers_est))
2263  {
2264 #ifdef BGW_DEBUG
2265  elog(DEBUG2, "bgwriter: alloc_est=%d too small, using min=%d + reusable_est=%d",
2266  upcoming_alloc_est, min_scan_buffers, reusable_buffers_est);
2267 #endif
2268  upcoming_alloc_est = min_scan_buffers + reusable_buffers_est;
2269  }
2270 
2271  /*
2272  * Now write out dirty reusable buffers, working forward from the
2273  * next_to_clean point, until we have lapped the strategy scan, or cleaned
2274  * enough buffers to match our estimate of the next cycle's allocation
2275  * requirements, or hit the bgwriter_lru_maxpages limit.
2276  */
2277 
2278  /* Make sure we can handle the pin inside SyncOneBuffer */
2280 
2281  num_to_scan = bufs_to_lap;
2282  num_written = 0;
2283  reusable_buffers = reusable_buffers_est;
2284 
2285  /* Execute the LRU scan */
2286  while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
2287  {
2288  int sync_state = SyncOneBuffer(next_to_clean, true,
2289  wb_context);
2290 
2291  if (++next_to_clean >= NBuffers)
2292  {
2293  next_to_clean = 0;
2294  next_passes++;
2295  }
2296  num_to_scan--;
2297 
2298  if (sync_state & BUF_WRITTEN)
2299  {
2300  reusable_buffers++;
2301  if (++num_written >= bgwriter_lru_maxpages)
2302  {
2304  break;
2305  }
2306  }
2307  else if (sync_state & BUF_REUSABLE)
2308  reusable_buffers++;
2309  }
2310 
2311  BgWriterStats.m_buf_written_clean += num_written;
2312 
2313 #ifdef BGW_DEBUG
2314  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",
2315  recent_alloc, smoothed_alloc, strategy_delta, bufs_ahead,
2316  smoothed_density, reusable_buffers_est, upcoming_alloc_est,
2317  bufs_to_lap - num_to_scan,
2318  num_written,
2319  reusable_buffers - reusable_buffers_est);
2320 #endif
2321 
2322  /*
2323  * Consider the above scan as being like a new allocation scan.
2324  * Characterize its density and update the smoothed one based on it. This
2325  * effectively halves the moving average period in cases where both the
2326  * strategy and the background writer are doing some useful scanning,
2327  * which is helpful because a long memory isn't as desirable on the
2328  * density estimates.
2329  */
2330  new_strategy_delta = bufs_to_lap - num_to_scan;
2331  new_recent_alloc = reusable_buffers - reusable_buffers_est;
2332  if (new_strategy_delta > 0 && new_recent_alloc > 0)
2333  {
2334  scans_per_alloc = (float) new_strategy_delta / (float) new_recent_alloc;
2335  smoothed_density += (scans_per_alloc - smoothed_density) /
2336  smoothing_samples;
2337 
2338 #ifdef BGW_DEBUG
2339  elog(DEBUG2, "bgwriter: cleaner density alloc=%u scan=%ld density=%.2f new smoothed=%.2f",
2340  new_recent_alloc, new_strategy_delta,
2341  scans_per_alloc, smoothed_density);
2342 #endif
2343  }
2344 
2345  /* Return true if OK to hibernate */
2346  return (bufs_to_lap == 0 && recent_alloc == 0);
2347 }
PgStat_Counter m_buf_alloc
Definition: pgstat.h:420
int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc)
Definition: freelist.c:395
#define DEBUG1
Definition: elog.h:25
int BgWriterDelay
Definition: bgwriter.c:64
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
PgStat_Counter m_maxwritten_clean
Definition: pgstat.h:417
PgStat_Counter m_buf_written_clean
Definition: pgstat.h:416
PgStat_MsgBgWriter BgWriterStats
Definition: pgstat.c:142
double bgwriter_lru_multiplier
Definition: bufmgr.c:111
static int SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
Definition: bufmgr.c:2366
signed int int32
Definition: c.h:347
#define BUF_REUSABLE
Definition: bufmgr.c:67
int bgwriter_lru_maxpages
Definition: bufmgr.c:110
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:359
#define BUF_WRITTEN
Definition: bufmgr.c:66
void ResourceOwnerEnlargeBuffers(ResourceOwner owner)
Definition: resowner.c:893
#define Assert(condition)
Definition: c.h:739
#define elog(elevel,...)
Definition: elog.h:228
int NBuffers
Definition: globals.c:131

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)

Definition at line 2623 of file bufmgr.c.

References Assert, buftag::blockNum, BufferIsLocal, BufferIsPinned, GetBufferDescriptor, GetLocalBufferDescriptor, and BufferDesc::tag.

Referenced by _bt_checkpage(), _bt_endpoint(), _bt_finish_split(), _bt_first(), _bt_getroot(), _bt_insert_parent(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_moveright(), _bt_newroot(), _bt_pagedel(), _bt_readnextpage(), _bt_readpage(), _bt_restore_meta(), _bt_search(), _bt_split(), _bt_unlink_halfdead_page(), _bt_walk_left(), _hash_addovflpage(), _hash_checkpage(), _hash_first(), _hash_freeovflpage(), _hash_getnewbuf(), _hash_readnext(), _hash_readpage(), _hash_splitbucket(), allocNewBuffer(), blinsert(), BloomInitMetapage(), brin_doinsert(), brin_doupdate(), brin_getinsertbuffer(), brin_initialize_empty_new_buffer(), brin_page_cleanup(), brin_xlog_insert_update(), brinbuild(), brinGetTupleForHeapBlock(), CheckForSerializableConflictIn(), createPostingTree(), dataBeginPlaceToPageLeaf(), dataPrepareDownlink(), doPickSplit(), entryPrepareDownlink(), fill_seq_with_data(), ginFindParents(), ginFinishSplit(), ginPlaceToPage(), ginRedoDeleteListPages(), ginRedoUpdateMetapage(), ginScanToDelete(), gistbufferinginserttuples(), gistbuild(), gistcheckpage(), gistdeletepage(), gistformdownlink(), gistMemorizeAllDownlinks(), gistplacetopage(), gistRelocateBuildBuffersOnSplit(), gistScanPage(), hash_xlog_add_ovfl_page(), heap_delete(), heap_hot_search_buffer(), heap_insert(), heap_multi_insert(), heap_page_is_all_visible(), heap_prune_chain(), heap_update(), heap_xlog_confirm(), heap_xlog_lock(), makeSublist(), moveLeafs(), moveRightIfItNeeded(), pgstathashindex(), ReadBufferBI(), RelationAddExtraBlocks(), RelationGetBufferForTuple(), RelationPutHeapTuple(), revmap_get_buffer(), revmap_physical_extend(), spgAddNodeAction(), spgbuild(), spgdoinsert(), SpGistSetLastUsedPage(), spgSplitNodeAction(), spgWalk(), startScanEntry(), terminate_brin_buildstate(), vacuumLeafPage(), visibilitymap_clear(), visibilitymap_get_status(), visibilitymap_pin(), visibilitymap_pin_ok(), visibilitymap_set(), and XLogReadBufferExtended().

2624 {
2625  BufferDesc *bufHdr;
2626 
2627  Assert(BufferIsPinned(buffer));
2628 
2629  if (BufferIsLocal(buffer))
2630  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2631  else
2632  bufHdr = GetBufferDescriptor(buffer - 1);
2633 
2634  /* pinned, so OK to read tag without spinlock */
2635  return bufHdr->tag.blockNum;
2636 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:420
#define GetLocalBufferDescriptor(id)
#define GetBufferDescriptor(id)
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
BlockNumber blockNum
Definition: buf_internals.h:94
BufferTag tag

◆ BufferGetLSNAtomic()

XLogRecPtr BufferGetLSNAtomic ( Buffer  buffer)

Definition at line 2886 of file bufmgr.c.

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

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

2887 {
2888  BufferDesc *bufHdr = GetBufferDescriptor(buffer - 1);
2889  char *page = BufferGetPage(buffer);
2890  XLogRecPtr lsn;
2891  uint32 buf_state;
2892 
2893  /*
2894  * If we don't need locking for correctness, fastpath out.
2895  */
2896  if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
2897  return PageGetLSN(page);
2898 
2899  /* Make sure we've got a real buffer, and that we hold a pin on it. */
2900  Assert(BufferIsValid(buffer));
2901  Assert(BufferIsPinned(buffer));
2902 
2903  buf_state = LockBufHdr(bufHdr);
2904  lsn = PageGetLSN(page);
2905  UnlockBufHdr(bufHdr, buf_state);
2906 
2907  return lsn;
2908 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:420
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:359
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define PageGetLSN(page)
Definition: bufpage.h:366
#define UnlockBufHdr(desc, s)
#define XLogHintBitIsNeeded()
Definition: xlog.h:192

◆ BufferGetTag()

void BufferGetTag ( Buffer  buffer,
RelFileNode rnode,
ForkNumber forknum,
BlockNumber blknum 
)

Definition at line 2644 of file bufmgr.c.

References Assert, buftag::blockNum, BufferIsLocal, BufferIsPinned, buftag::forkNum, GetBufferDescriptor, GetLocalBufferDescriptor, buftag::rnode, and BufferDesc::tag.

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

2646 {
2647  BufferDesc *bufHdr;
2648 
2649  /* Do the same checks as BufferGetBlockNumber. */
2650  Assert(BufferIsPinned(buffer));
2651 
2652  if (BufferIsLocal(buffer))
2653  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2654  else
2655  bufHdr = GetBufferDescriptor(buffer - 1);
2656 
2657  /* pinned, so OK to read tag without spinlock */
2658  *rnode = bufHdr->tag.rnode;
2659  *forknum = bufHdr->tag.forkNum;
2660  *blknum = bufHdr->tag.blockNum;
2661 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:420
ForkNumber forkNum
Definition: buf_internals.h:93
#define GetLocalBufferDescriptor(id)
#define GetBufferDescriptor(id)
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
BlockNumber blockNum
Definition: buf_internals.h:94
RelFileNode rnode
Definition: buf_internals.h:92
BufferTag tag

◆ BufferIsPermanent()

bool BufferIsPermanent ( Buffer  buffer)

Definition at line 2856 of file bufmgr.c.

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

Referenced by SetHintBits().

2857 {
2858  BufferDesc *bufHdr;
2859 
2860  /* Local buffers are used only for temp relations. */
2861  if (BufferIsLocal(buffer))
2862  return false;
2863 
2864  /* Make sure we've got a real buffer, and that we hold a pin on it. */
2865  Assert(BufferIsValid(buffer));
2866  Assert(BufferIsPinned(buffer));
2867 
2868  /*
2869  * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
2870  * need not bother with the buffer header spinlock. Even if someone else
2871  * changes the buffer header state while we're doing this, the state is
2872  * changed atomically, so we'll read the old value or the new value, but
2873  * not random garbage.
2874  */
2875  bufHdr = GetBufferDescriptor(buffer - 1);
2876  return (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT) != 0;
2877 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:420
#define BM_PERMANENT
Definition: buf_internals.h:66
#define GetBufferDescriptor(id)
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
pg_atomic_uint32 state
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241

◆ BufferShmemSize()

Size BufferShmemSize ( void  )

Definition at line 160 of file buf_init.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

161 {
162  Size size = 0;
163 
164  /* size of buffer descriptors */
165  size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
166  /* to allow aligning buffer descriptors */
167  size = add_size(size, PG_CACHE_LINE_SIZE);
168 
169  /* size of data pages */
170  size = add_size(size, mul_size(NBuffers, BLCKSZ));
171 
172  /* size of stuff controlled by freelist.c */
173  size = add_size(size, StrategyShmemSize());
174 
175  /*
176  * It would be nice to include the I/O locks in the BufferDesc, but that
177  * would increase the size of a BufferDesc to more than one cache line,
178  * and benchmarking has shown that keeping every BufferDesc aligned on a
179  * cache line boundary is important for performance. So, instead, the
180  * array of I/O locks is allocated in a separate tranche. Because those
181  * locks are not highly contended, we lay out the array with minimal
182  * padding.
183  */
184  size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded)));
185  /* to allow aligning the above */
186  size = add_size(size, PG_CACHE_LINE_SIZE);
187 
188  /* size of checkpoint sort array in bufmgr.c */
189  size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
190 
191  return size;
192 }
#define PG_CACHE_LINE_SIZE
Size mul_size(Size s1, Size s2)
Definition: shmem.c:515
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
size_t Size
Definition: c.h:467
int NBuffers
Definition: globals.c:131
Size StrategyShmemSize(void)
Definition: freelist.c:454

◆ BufmgrCommit()

void BufmgrCommit ( void  )

Definition at line 2609 of file bufmgr.c.

Referenced by PrepareTransaction(), and RecordTransactionCommit().

2610 {
2611  /* Nothing to do in bufmgr anymore... */
2612 }

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)

Definition at line 2592 of file bufmgr.c.

References BufferSync(), CheckpointStats, CheckpointStatsData::ckpt_sync_end_t, CheckpointStatsData::ckpt_sync_t, CheckpointStatsData::ckpt_write_t, GetCurrentTimestamp(), and ProcessSyncRequests().

Referenced by CheckPointGuts().

2593 {
2594  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_START(flags);
2596  BufferSync(flags);
2598  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_SYNC_START();
2601  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_DONE();
2602 }
void ProcessSyncRequests(void)
Definition: sync.c:236
TimestampTz ckpt_sync_end_t
Definition: xlog.h:238
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1583
static void BufferSync(int flags)
Definition: bufmgr.c:1786
CheckpointStatsData CheckpointStats
Definition: xlog.c:181
TimestampTz ckpt_write_t
Definition: xlog.h:236
TimestampTz ckpt_sync_t
Definition: xlog.h:237

◆ ComputeIoConcurrency()

bool ComputeIoConcurrency ( int  io_concurrency,
double *  target 
)

Definition at line 469 of file bufmgr.c.

References i, Max, MAX_IO_CONCURRENCY, and Min.

Referenced by check_effective_io_concurrency(), and ExecInitBitmapHeapScan().

470 {
471  double new_prefetch_pages = 0.0;
472  int i;
473 
474  /*
475  * Make sure the io_concurrency value is within valid range; it may have
476  * been forced with a manual pg_tablespace update.
477  */
478  io_concurrency = Min(Max(io_concurrency, 0), MAX_IO_CONCURRENCY);
479 
480  /*----------
481  * The user-visible GUC parameter is the number of drives (spindles),
482  * which we need to translate to a number-of-pages-to-prefetch target.
483  * The target value is stashed in *extra and then assigned to the actual
484  * variable by assign_effective_io_concurrency.
485  *
486  * The expected number of prefetch pages needed to keep N drives busy is:
487  *
488  * drives | I/O requests
489  * -------+----------------
490  * 1 | 1
491  * 2 | 2/1 + 2/2 = 3
492  * 3 | 3/1 + 3/2 + 3/3 = 5 1/2
493  * 4 | 4/1 + 4/2 + 4/3 + 4/4 = 8 1/3
494  * n | n * H(n)
495  *
496  * This is called the "coupon collector problem" and H(n) is called the
497  * harmonic series. This could be approximated by n * ln(n), but for
498  * reasonable numbers of drives we might as well just compute the series.
499  *
500  * Alternatively we could set the target to the number of pages necessary
501  * so that the expected number of active spindles is some arbitrary
502  * percentage of the total. This sounds the same but is actually slightly
503  * different. The result ends up being ln(1-P)/ln((n-1)/n) where P is
504  * that desired fraction.
505  *
506  * Experimental results show that both of these formulas aren't aggressive
507  * enough, but we don't really have any better proposals.
508  *
509  * Note that if io_concurrency = 0 (disabled), we must set target = 0.
510  *----------
511  */
512 
513  for (i = 1; i <= io_concurrency; i++)
514  new_prefetch_pages += (double) io_concurrency / (double) i;
515 
516  *target = new_prefetch_pages;
517 
518  /* This range check shouldn't fail, but let's be paranoid */
519  return (new_prefetch_pages >= 0.0 && new_prefetch_pages < (double) INT_MAX);
520 }
#define MAX_IO_CONCURRENCY
Definition: bufmgr.h:78
#define Min(x, y)
Definition: c.h:911
#define Max(x, y)
Definition: c.h:905
int i

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

Definition at line 3638 of file bufmgr.c.

References Assert, buf, BufferDescriptorGetContentLock, BufferIsLocal, BufferIsValid, GetBufferDescriptor, LW_EXCLUSIVE, and LWLockConditionalAcquire().

Referenced by _bt_doinsert(), _bt_getbuf(), BloomNewBuffer(), ConditionalLockBufferForCleanup(), GinNewBuffer(), gistNewBuffer(), RelationGetBufferForTuple(), spgdoinsert(), SpGistGetBuffer(), SpGistNewBuffer(), and SpGistUpdateMetaPage().

3639 {
3640  BufferDesc *buf;
3641 
3642  Assert(BufferIsValid(buffer));
3643  if (BufferIsLocal(buffer))
3644  return true; /* act as though we got it */
3645 
3646  buf = GetBufferDescriptor(buffer - 1);
3647 
3649  LW_EXCLUSIVE);
3650 }
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1294
static char * buf
Definition: pg_test_fsync.c:67
#define GetBufferDescriptor(id)
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113

◆ ConditionalLockBufferForCleanup()

bool ConditionalLockBufferForCleanup ( Buffer  buffer)

Definition at line 3784 of file bufmgr.c.

References Assert, BUF_STATE_GET_REFCOUNT, 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(), lazy_scan_heap(), and lazy_vacuum_heap().

3785 {
3786  BufferDesc *bufHdr;
3787  uint32 buf_state,
3788  refcount;
3789 
3790  Assert(BufferIsValid(buffer));
3791 
3792  if (BufferIsLocal(buffer))
3793  {
3794  refcount = LocalRefCount[-buffer - 1];
3795  /* There should be exactly one pin */
3796  Assert(refcount > 0);
3797  if (refcount != 1)
3798  return false;
3799  /* Nobody else to wait for */
3800  return true;
3801  }
3802 
3803  /* There should be exactly one local pin */
3804  refcount = GetPrivateRefCount(buffer);
3805  Assert(refcount);
3806  if (refcount != 1)
3807  return false;
3808 
3809  /* Try to acquire lock */
3810  if (!ConditionalLockBuffer(buffer))
3811  return false;
3812 
3813  bufHdr = GetBufferDescriptor(buffer - 1);
3814  buf_state = LockBufHdr(bufHdr);
3815  refcount = BUF_STATE_GET_REFCOUNT(buf_state);
3816 
3817  Assert(refcount > 0);
3818  if (refcount == 1)
3819  {
3820  /* Successfully acquired exclusive lock with pincount 1 */
3821  UnlockBufHdr(bufHdr, buf_state);
3822  return true;
3823  }
3824 
3825  /* Failed, so release the lock */
3826  UnlockBufHdr(bufHdr, buf_state);
3827  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3828  return false;
3829 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:86
#define GetBufferDescriptor(id)
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:359
unsigned int uint32
Definition: c.h:359
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:3638
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3612
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define UnlockBufHdr(desc, s)
int32 * LocalRefCount
Definition: localbuf.c:45
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:48

◆ DropDatabaseBuffers()

void DropDatabaseBuffers ( Oid  dbid)

Definition at line 3109 of file bufmgr.c.

References buftag::blockNum, buf, BufferDescriptorGetBuffer, RelFileNode::dbNode, elog, buftag::forkNum, BufferDesc::freeNext, GetBufferDescriptor, GetPrivateRefCount(), i, InvalidateBuffer(), InvalidBackendId, LockBufHdr(), LOG, NBuffers, relpathbackend, relpathperm, buftag::rnode, BufferDesc::tag, and UnlockBufHdr.

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

3110 {
3111  int i;
3112 
3113  /*
3114  * We needn't consider local buffers, since by assumption the target
3115  * database isn't our own.
3116  */
3117 
3118  for (i = 0; i < NBuffers; i++)
3119  {
3120  BufferDesc *bufHdr = GetBufferDescriptor(i);
3121  uint32 buf_state;
3122 
3123  /*
3124  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3125  * and saves some cycles.
3126  */
3127  if (bufHdr->tag.rnode.dbNode != dbid)
3128  continue;
3129 
3130  buf_state = LockBufHdr(bufHdr);
3131  if (bufHdr->tag.rnode.dbNode == dbid)
3132  InvalidateBuffer(bufHdr); /* releases spinlock */
3133  else
3134  UnlockBufHdr(bufHdr, buf_state);
3135  }
3136 }
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1360
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:359
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
RelFileNode rnode
Definition: buf_internals.h:92
BufferTag tag
#define UnlockBufHdr(desc, s)
int i
int NBuffers
Definition: globals.c:131

◆ DropRelFileNodeBuffers()

void DropRelFileNodeBuffers ( RelFileNodeBackend  rnode,
ForkNumber forkNum,
int  nforks,
BlockNumber firstDelBlock 
)

Definition at line 2937 of file bufmgr.c.

References RelFileNodeBackend::backend, buftag::blockNum, DropRelFileNodeLocalBuffers(), buftag::forkNum, GetBufferDescriptor, i, InvalidateBuffer(), LockBufHdr(), MyBackendId, NBuffers, RelFileNodeBackend::node, RelFileNodeBackendIsTemp, RelFileNodeEquals, buftag::rnode, BufferDesc::tag, and UnlockBufHdr.

Referenced by smgrtruncate().

2939 {
2940  int i;
2941  int j;
2942 
2943  /* If it's a local relation, it's localbuf.c's problem. */
2944  if (RelFileNodeBackendIsTemp(rnode))
2945  {
2946  if (rnode.backend == MyBackendId)
2947  {
2948  for (j = 0; j < nforks; j++)
2949  DropRelFileNodeLocalBuffers(rnode.node, forkNum[j],
2950  firstDelBlock[j]);
2951  }
2952  return;
2953  }
2954 
2955  for (i = 0; i < NBuffers; i++)
2956  {
2957  BufferDesc *bufHdr = GetBufferDescriptor(i);
2958  uint32 buf_state;
2959 
2960  /*
2961  * We can make this a tad faster by prechecking the buffer tag before
2962  * we attempt to lock the buffer; this saves a lot of lock
2963  * acquisitions in typical cases. It should be safe because the
2964  * caller must have AccessExclusiveLock on the relation, or some other
2965  * reason to be certain that no one is loading new pages of the rel
2966  * into the buffer pool. (Otherwise we might well miss such pages
2967  * entirely.) Therefore, while the tag might be changing while we
2968  * look at it, it can't be changing *to* a value we care about, only
2969  * *away* from such a value. So false negatives are impossible, and
2970  * false positives are safe because we'll recheck after getting the
2971  * buffer lock.
2972  *
2973  * We could check forkNum and blockNum as well as the rnode, but the
2974  * incremental win from doing so seems small.
2975  */
2976  if (!RelFileNodeEquals(bufHdr->tag.rnode, rnode.node))
2977  continue;
2978 
2979  buf_state = LockBufHdr(bufHdr);
2980 
2981  for (j = 0; j < nforks; j++)
2982  {
2983  if (RelFileNodeEquals(bufHdr->tag.rnode, rnode.node) &&
2984  bufHdr->tag.forkNum == forkNum[j] &&
2985  bufHdr->tag.blockNum >= firstDelBlock[j])
2986  {
2987  InvalidateBuffer(bufHdr); /* releases spinlock */
2988  break;
2989  }
2990  }
2991  if (j >= nforks)
2992  UnlockBufHdr(bufHdr, buf_state);
2993  }
2994 }
BackendId MyBackendId
Definition: globals.c:81
#define RelFileNodeBackendIsTemp(rnode)
Definition: relfilenode.h:78
ForkNumber forkNum
Definition: buf_internals.h:93
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1360
void DropRelFileNodeLocalBuffers(RelFileNode rnode, ForkNumber forkNum, BlockNumber firstDelBlock)
Definition: localbuf.c:320
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:359
RelFileNode node
Definition: relfilenode.h:74
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
BackendId backend
Definition: relfilenode.h:75
BlockNumber blockNum
Definition: buf_internals.h:94
RelFileNode rnode
Definition: buf_internals.h:92
BufferTag tag
#define UnlockBufHdr(desc, s)
int i
int NBuffers
Definition: globals.c:131
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88

◆ DropRelFileNodesAllBuffers()

void DropRelFileNodesAllBuffers ( RelFileNodeBackend rnodes,
int  nnodes 
)

Definition at line 3006 of file bufmgr.c.

References DROP_RELS_BSEARCH_THRESHOLD, DropRelFileNodeAllLocalBuffers(), GetBufferDescriptor, i, InvalidateBuffer(), LockBufHdr(), MyBackendId, NBuffers, RelFileNodeBackend::node, palloc(), pfree(), pg_qsort(), RelFileNodeBackendIsTemp, RelFileNodeEquals, buftag::rnode, rnode_comparator(), BufferDesc::tag, and UnlockBufHdr.

Referenced by smgrdounlink(), and smgrdounlinkall().

3007 {
3008  int i,
3009  n = 0;
3010  RelFileNode *nodes;
3011  bool use_bsearch;
3012 
3013  if (nnodes == 0)
3014  return;
3015 
3016  nodes = palloc(sizeof(RelFileNode) * nnodes); /* non-local relations */
3017 
3018  /* If it's a local relation, it's localbuf.c's problem. */
3019  for (i = 0; i < nnodes; i++)
3020  {
3021  if (RelFileNodeBackendIsTemp(rnodes[i]))
3022  {
3023  if (rnodes[i].backend == MyBackendId)
3024  DropRelFileNodeAllLocalBuffers(rnodes[i].node);
3025  }
3026  else
3027  nodes[n++] = rnodes[i].node;
3028  }
3029 
3030  /*
3031  * If there are no non-local relations, then we're done. Release the
3032  * memory and return.
3033  */
3034  if (n == 0)
3035  {
3036  pfree(nodes);
3037  return;
3038  }
3039 
3040  /*
3041  * For low number of relations to drop just use a simple walk through, to
3042  * save the bsearch overhead. The threshold to use is rather a guess than
3043  * an exactly determined value, as it depends on many factors (CPU and RAM
3044  * speeds, amount of shared buffers etc.).
3045  */
3046  use_bsearch = n > DROP_RELS_BSEARCH_THRESHOLD;
3047 
3048  /* sort the list of rnodes if necessary */
3049  if (use_bsearch)
3050  pg_qsort(nodes, n, sizeof(RelFileNode), rnode_comparator);
3051 
3052  for (i = 0; i < NBuffers; i++)
3053  {
3054  RelFileNode *rnode = NULL;
3055  BufferDesc *bufHdr = GetBufferDescriptor(i);
3056  uint32 buf_state;
3057 
3058  /*
3059  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3060  * and saves some cycles.
3061  */
3062 
3063  if (!use_bsearch)
3064  {
3065  int j;
3066 
3067  for (j = 0; j < n; j++)
3068  {
3069  if (RelFileNodeEquals(bufHdr->tag.rnode, nodes[j]))
3070  {
3071  rnode = &nodes[j];
3072  break;
3073  }
3074  }
3075  }
3076  else
3077  {
3078  rnode = bsearch((const void *) &(bufHdr->tag.rnode),
3079  nodes, n, sizeof(RelFileNode),
3081  }
3082 
3083  /* buffer doesn't belong to any of the given relfilenodes; skip it */
3084  if (rnode == NULL)
3085  continue;
3086 
3087  buf_state = LockBufHdr(bufHdr);
3088  if (RelFileNodeEquals(bufHdr->tag.rnode, (*rnode)))
3089  InvalidateBuffer(bufHdr); /* releases spinlock */
3090  else
3091  UnlockBufHdr(bufHdr, buf_state);
3092  }
3093 
3094  pfree(nodes);
3095 }
BackendId MyBackendId
Definition: globals.c:81
#define RelFileNodeBackendIsTemp(rnode)
Definition: relfilenode.h:78
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1360
#define DROP_RELS_BSEARCH_THRESHOLD
Definition: bufmgr.c:69
void DropRelFileNodeAllLocalBuffers(RelFileNode rnode)
Definition: localbuf.c:367
void pfree(void *pointer)
Definition: mcxt.c:1056
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:359
static int rnode_comparator(const void *p1, const void *p2)
Definition: bufmgr.c:4131
RelFileNode node
Definition: relfilenode.h:74
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
void pg_qsort(void *base, size_t nel, size_t elsize, int(*cmp)(const void *, const void *))
Definition: qsort.c:113
RelFileNode rnode
Definition: buf_internals.h:92
BufferTag tag
void * palloc(Size size)
Definition: mcxt.c:949
#define UnlockBufHdr(desc, s)
int i
int NBuffers
Definition: globals.c:131
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88

◆ FlushDatabaseBuffers()

void FlushDatabaseBuffers ( Oid  dbid)

Definition at line 3312 of file bufmgr.c.

References BM_DIRTY, BM_VALID, BufferDescriptorGetContentLock, CurrentResourceOwner, RelFileNode::dbNode, FlushBuffer(), GetBufferDescriptor, i, LockBufHdr(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NBuffers, PinBuffer_Locked(), ReservePrivateRefCountEntry(), ResourceOwnerEnlargeBuffers(), buftag::rnode, BufferDesc::tag, UnlockBufHdr, and UnpinBuffer().

Referenced by dbase_redo().

3313 {
3314  int i;
3315  BufferDesc *bufHdr;
3316 
3317  /* Make sure we can handle the pin inside the loop */
3319 
3320  for (i = 0; i < NBuffers; i++)
3321  {
3322  uint32 buf_state;
3323 
3324  bufHdr = GetBufferDescriptor(i);
3325 
3326  /*
3327  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3328  * and saves some cycles.
3329  */
3330  if (bufHdr->tag.rnode.dbNode != dbid)
3331  continue;
3332 
3334 
3335  buf_state = LockBufHdr(bufHdr);
3336  if (bufHdr->tag.rnode.dbNode == dbid &&
3337  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3338  {
3339  PinBuffer_Locked(bufHdr);
3341  FlushBuffer(bufHdr, NULL);
3343  UnpinBuffer(bufHdr, true);
3344  }
3345  else
3346  UnlockBufHdr(bufHdr, buf_state);
3347  }
3348 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
#define BM_DIRTY
Definition: buf_internals.h:58
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln)
Definition: bufmgr.c:2683
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:359
static void UnpinBuffer(BufferDesc *buf, bool fixOwner)
Definition: bufmgr.c:1702
void ResourceOwnerEnlargeBuffers(ResourceOwner owner)
Definition: resowner.c:893
#define BM_VALID
Definition: buf_internals.h:59
#define BufferDescriptorGetContentLock(bdesc)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:1664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
RelFileNode rnode
Definition: buf_internals.h:92
BufferTag tag
#define UnlockBufHdr(desc, s)
int i
int NBuffers
Definition: globals.c:131
static void ReservePrivateRefCountEntry(void)
Definition: bufmgr.c:187

◆ FlushOneBuffer()

void FlushOneBuffer ( Buffer  buffer)

Definition at line 3355 of file bufmgr.c.

References Assert, BufferDescriptorGetContentLock, BufferIsLocal, BufferIsPinned, FlushBuffer(), GetBufferDescriptor, and LWLockHeldByMe().

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

3356 {
3357  BufferDesc *bufHdr;
3358 
3359  /* currently not needed, but no fundamental reason not to support */
3360  Assert(!BufferIsLocal(buffer));
3361 
3362  Assert(BufferIsPinned(buffer));
3363 
3364  bufHdr = GetBufferDescriptor(buffer - 1);
3365 
3367 
3368  FlushBuffer(bufHdr, NULL);
3369 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:420
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1842
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln)
Definition: bufmgr.c:2683
#define GetBufferDescriptor(id)
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37

◆ FlushRelationBuffers()

void FlushRelationBuffers ( Relation  rel)

Definition at line 3214 of file bufmgr.c.

References ErrorContextCallback::arg, buftag::blockNum, BM_DIRTY, BM_JUST_DIRTIED, BM_VALID, BufferDescriptorGetContentLock, ErrorContextCallback::callback, CurrentResourceOwner, error_context_stack, FlushBuffer(), buftag::forkNum, GetBufferDescriptor, GetLocalBufferDescriptor, i, local_buffer_write_error_callback(), LocalBufHdrGetBlock, LockBufHdr(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NBuffers, NLocBuffer, PageSetChecksumInplace(), pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), PinBuffer_Locked(), ErrorContextCallback::previous, RelationData::rd_node, RelationData::rd_smgr, RelationOpenSmgr, RelationUsesLocalBuffers, RelFileNodeEquals, ReservePrivateRefCountEntry(), ResourceOwnerEnlargeBuffers(), buftag::rnode, smgrwrite(), BufferDesc::state, BufferDesc::tag, UnlockBufHdr, and UnpinBuffer().

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

3215 {
3216  int i;
3217  BufferDesc *bufHdr;
3218 
3219  /* Open rel at the smgr level if not already done */
3220  RelationOpenSmgr(rel);
3221 
3222  if (RelationUsesLocalBuffers(rel))
3223  {
3224  for (i = 0; i < NLocBuffer; i++)
3225  {
3226  uint32 buf_state;
3227 
3228  bufHdr = GetLocalBufferDescriptor(i);
3229  if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
3230  ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
3231  (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3232  {
3233  ErrorContextCallback errcallback;
3234  Page localpage;
3235 
3236  localpage = (char *) LocalBufHdrGetBlock(bufHdr);
3237 
3238  /* Setup error traceback support for ereport() */
3240  errcallback.arg = (void *) bufHdr;
3241  errcallback.previous = error_context_stack;
3242  error_context_stack = &errcallback;
3243 
3244  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
3245 
3246  smgrwrite(rel->rd_smgr,
3247  bufHdr->tag.forkNum,
3248  bufHdr->tag.blockNum,
3249  localpage,
3250  false);
3251 
3252  buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED);
3253  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
3254 
3255  /* Pop the error context stack */
3256  error_context_stack = errcallback.previous;
3257  }
3258  }
3259 
3260  return;
3261  }
3262 
3263  /* Make sure we can handle the pin inside the loop */
3265 
3266  for (i = 0; i < NBuffers; i++)
3267  {
3268  uint32 buf_state;
3269 
3270  bufHdr = GetBufferDescriptor(i);
3271 
3272  /*
3273  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3274  * and saves some cycles.
3275  */
3276  if (!RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
3277  continue;
3278 
3280 
3281  buf_state = LockBufHdr(bufHdr);
3282  if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
3283  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3284  {
3285  PinBuffer_Locked(bufHdr);
3287  FlushBuffer(bufHdr, rel->rd_smgr);
3289  UnpinBuffer(bufHdr, true);
3290  }
3291  else
3292  UnlockBufHdr(bufHdr, buf_state);
3293  }
3294 }
#define LocalBufHdrGetBlock(bufHdr)
Definition: bufmgr.c:62
ForkNumber forkNum
Definition: buf_internals.h:93
static void local_buffer_write_error_callback(void *arg)
Definition: bufmgr.c:4112
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
#define GetLocalBufferDescriptor(id)
#define BM_DIRTY
Definition: buf_internals.h:58
void(* callback)(void *arg)
Definition: elog.h:256
struct ErrorContextCallback * previous
Definition: elog.h:255
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln)
Definition: bufmgr.c:2683
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
ErrorContextCallback * error_context_stack
Definition: elog.c:91
#define RelationOpenSmgr(relation)
Definition: rel.h:485
int NLocBuffer
Definition: localbuf.c:41
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:530
#define GetBufferDescriptor(id)
#define BM_JUST_DIRTIED
Definition: buf_internals.h:63
unsigned int uint32
Definition: c.h:359
static void UnpinBuffer(BufferDesc *buf, bool fixOwner)
Definition: bufmgr.c:1702
void ResourceOwnerEnlargeBuffers(ResourceOwner owner)
Definition: resowner.c:893
#define BM_VALID
Definition: buf_internals.h:59
RelFileNode rd_node
Definition: rel.h:55
#define BufferDescriptorGetContentLock(bdesc)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:1664
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1198
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
BlockNumber blockNum
Definition: buf_internals.h:94
RelFileNode rnode
Definition: buf_internals.h:92
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:537
BufferTag tag
#define UnlockBufHdr(desc, s)
int i
int NBuffers
Definition: globals.c:131
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:277
static void ReservePrivateRefCountEntry(void)
Definition: bufmgr.c:187
pg_atomic_uint32 state
Pointer Page
Definition: bufpage.h:78
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241

◆ FreeAccessStrategy()

void FreeAccessStrategy ( BufferAccessStrategy  strategy)

Definition at line 597 of file freelist.c.

References pfree().

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

598 {
599  /* don't crash if called on a "default" strategy */
600  if (strategy != NULL)
601  pfree(strategy);
602 }
void pfree(void *pointer)
Definition: mcxt.c:1056

◆ GetAccessStrategy()

BufferAccessStrategy GetAccessStrategy ( BufferAccessStrategyType  btype)

Definition at line 542 of file freelist.c.

References BAS_BULKREAD, BAS_BULKWRITE, BAS_NORMAL, BAS_VACUUM, BufferAccessStrategyData::btype, BufferAccessStrategyData::buffers, elog, ERROR, Min, NBuffers, offsetof, palloc0(), and BufferAccessStrategyData::ring_size.

Referenced by blgetbitmap(), bt_check_every_level(), collect_corrupt_items(), collect_visibility_data(), do_autovacuum(), GetBulkInsertState(), initscan(), pgstat_index(), pgstathashindex(), pgstatindex_impl(), statapprox_heap(), and vacuum().

543 {
544  BufferAccessStrategy strategy;
545  int ring_size;
546 
547  /*
548  * Select ring size to use. See buffer/README for rationales.
549  *
550  * Note: if you change the ring size for BAS_BULKREAD, see also
551  * SYNC_SCAN_REPORT_INTERVAL in access/heap/syncscan.c.
552  */
553  switch (btype)
554  {
555  case BAS_NORMAL:
556  /* if someone asks for NORMAL, just give 'em a "default" object */
557  return NULL;
558 
559  case BAS_BULKREAD:
560  ring_size = 256 * 1024 / BLCKSZ;
561  break;
562  case BAS_BULKWRITE:
563  ring_size = 16 * 1024 * 1024 / BLCKSZ;
564  break;
565  case BAS_VACUUM:
566  ring_size = 256 * 1024 / BLCKSZ;
567  break;
568 
569  default:
570  elog(ERROR, "unrecognized buffer access strategy: %d",
571  (int) btype);
572  return NULL; /* keep compiler quiet */
573  }
574 
575  /* Make sure ring isn't an undue fraction of shared buffers */
576  ring_size = Min(NBuffers / 8, ring_size);
577 
578  /* Allocate the object and initialize all elements to zeroes */
579  strategy = (BufferAccessStrategy)
581  ring_size * sizeof(Buffer));
582 
583  /* Set fields that don't start out zero */
584  strategy->btype = btype;
585  strategy->ring_size = ring_size;
586 
587  return strategy;
588 }
struct BufferAccessStrategyData * BufferAccessStrategy
Definition: buf.h:44
#define Min(x, y)
Definition: c.h:911
#define ERROR
Definition: elog.h:43
BufferAccessStrategyType btype
Definition: freelist.c:74
void * palloc0(Size size)
Definition: mcxt.c:980
#define elog(elevel,...)
Definition: elog.h:228
int NBuffers
Definition: globals.c:131
int Buffer
Definition: buf.h:23
#define offsetof(type, field)
Definition: c.h:662

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )

Definition at line 3758 of file bufmgr.c.

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and RecoveryConflictInterrupt().

3759 {
3760  int bufid = GetStartupBufferPinWaitBufId();
3761 
3762  /*
3763  * If we get woken slowly then it's possible that the Startup process was
3764  * already woken by other backends before we got here. Also possible that
3765  * we get here by multiple interrupts or interrupts at inappropriate
3766  * times, so make sure we do nothing if the bufid is not set.
3767  */
3768  if (bufid < 0)
3769  return false;
3770 
3771  if (GetPrivateRefCount(bufid + 1) > 0)
3772  return true;
3773 
3774  return false;
3775 }
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:359
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:657

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

Definition at line 3413 of file bufmgr.c.

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

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

3414 {
3415  Assert(BufferIsPinned(buffer));
3417  if (BufferIsLocal(buffer))
3418  LocalRefCount[-buffer - 1]++;
3419  else
3420  {
3421  PrivateRefCountEntry *ref;
3422 
3423  ref = GetPrivateRefCountEntry(buffer, true);
3424  Assert(ref != NULL);
3425  ref->refcount++;
3426  }
3428 }
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition: bufmgr.c:279
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:420
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:906
void ResourceOwnerEnlargeBuffers(ResourceOwner owner)
Definition: resowner.c:893
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
int32 * LocalRefCount
Definition: localbuf.c:45

◆ InitBufferPool()

void InitBufferPool ( void  )

Definition at line 67 of file buf_init.c.

References Assert, backend_flush_after, buf, BufferDesc::buf_id, BufferBlocks, BufferDescriptorGetContentLock, BufferDescriptorGetIOLock, CLEAR_BUFFERTAG, BufferDesc::freeNext, FREENEXT_END_OF_LIST, GetBufferDescriptor, i, LWLockInitialize(), LWLockRegisterTranche(), LWTRANCHE_BUFFER_CONTENT, LWTRANCHE_BUFFER_IO_IN_PROGRESS, NBuffers, pg_atomic_init_u32(), ShmemInitStruct(), BufferDesc::state, StrategyInitialize(), BufferDesc::tag, BufferDesc::wait_backend_pid, and WritebackContextInit().

Referenced by CreateSharedMemoryAndSemaphores().

68 {
69  bool foundBufs,
70  foundDescs,
71  foundIOLocks,
72  foundBufCkpt;
73 
74  /* Align descriptors to a cacheline boundary. */
76  ShmemInitStruct("Buffer Descriptors",
77  NBuffers * sizeof(BufferDescPadded),
78  &foundDescs);
79 
80  BufferBlocks = (char *)
81  ShmemInitStruct("Buffer Blocks",
82  NBuffers * (Size) BLCKSZ, &foundBufs);
83 
84  /* Align lwlocks to cacheline boundary */
86  ShmemInitStruct("Buffer IO Locks",
88  &foundIOLocks);
89 
92 
93  /*
94  * The array used to sort to-be-checkpointed buffer ids is located in
95  * shared memory, to avoid having to allocate significant amounts of
96  * memory at runtime. As that'd be in the middle of a checkpoint, or when
97  * the checkpointer is restarted, memory allocation failures would be
98  * painful.
99  */
101  ShmemInitStruct("Checkpoint BufferIds",
102  NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
103 
104  if (foundDescs || foundBufs || foundIOLocks || foundBufCkpt)
105  {
106  /* should find all of these, or none of them */
107  Assert(foundDescs && foundBufs && foundIOLocks && foundBufCkpt);
108  /* note: this path is only taken in EXEC_BACKEND case */
109  }
110  else
111  {
112  int i;
113 
114  /*
115  * Initialize all the buffer headers.
116  */
117  for (i = 0; i < NBuffers; i++)
118  {
120 
121  CLEAR_BUFFERTAG(buf->tag);
122 
123  pg_atomic_init_u32(&buf->state, 0);
124  buf->wait_backend_pid = 0;
125 
126  buf->buf_id = i;
127 
128  /*
129  * Initially link all the buffers together as unused. Subsequent
130  * management of this list is done by freelist.c.
131  */
132  buf->freeNext = i + 1;
133 
136 
139  }
140 
141  /* Correct last entry of linked list */
142  GetBufferDescriptor(NBuffers - 1)->freeNext = FREENEXT_END_OF_LIST;
143  }
144 
145  /* Init other shared buffer-management stuff */
146  StrategyInitialize(!foundDescs);
147 
148  /* Initialize per-backend file flush context */
151 }
#define FREENEXT_END_OF_LIST
LWLockMinimallyPadded * BufferIOLWLockArray
Definition: buf_init.c:22
int wait_backend_pid
int backend_flush_after
Definition: bufmgr.c:121
#define BufferDescriptorGetIOLock(bdesc)
void StrategyInitialize(bool init)
Definition: freelist.c:475
void WritebackContextInit(WritebackContext *context, int *max_pending)
Definition: bufmgr.c:4298
void LWLockRegisterTranche(int tranche_id, const char *tranche_name)
Definition: lwlock.c:603
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:392
WritebackContext BackendWritebackContext
Definition: buf_init.c:23
static char * buf
Definition: pg_test_fsync.c:67
BufferDescPadded * BufferDescriptors
Definition: buf_init.c:20
#define GetBufferDescriptor(id)
union LWLockMinimallyPadded LWLockMinimallyPadded
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:678
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:739
#define CLEAR_BUFFERTAG(a)
Definition: buf_internals.h:97
CkptSortItem * CkptBufferIds
Definition: buf_init.c:24
size_t Size
Definition: c.h:467
BufferTag tag
int i
int NBuffers
Definition: globals.c:131
pg_atomic_uint32 state
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:223
char * BufferBlocks
Definition: buf_init.c:21

◆ InitBufferPoolAccess()

void InitBufferPoolAccess ( void  )

Definition at line 2455 of file bufmgr.c.

References HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, HASHCTL::keysize, MemSet, and PrivateRefCountArray.

Referenced by BaseInit().

2456 {
2457  HASHCTL hash_ctl;
2458 
2459  memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
2460 
2461  MemSet(&hash_ctl, 0, sizeof(hash_ctl));
2462  hash_ctl.keysize = sizeof(int32);
2463  hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
2464 
2465  PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
2466  HASH_ELEM | HASH_BLOBS);
2467 }
struct PrivateRefCountEntry PrivateRefCountEntry
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:962
signed int int32
Definition: c.h:347
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition: bufmgr.c:169
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
static HTAB * PrivateRefCountHash
Definition: bufmgr.c:170

◆ InitBufferPoolBackend()

void InitBufferPoolBackend ( void  )

Definition at line 2479 of file bufmgr.c.

References AtProcExit_Buffers(), and on_shmem_exit().

Referenced by AuxiliaryProcessMain(), and InitPostgres().

2480 {
2482 }
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
static void AtProcExit_Buffers(int code, Datum arg)
Definition: bufmgr.c:2489

◆ IsBufferCleanupOK()

bool IsBufferCleanupOK ( Buffer  buffer)

Definition at line 3840 of file bufmgr.c.

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

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

3841 {
3842  BufferDesc *bufHdr;
3843  uint32 buf_state;
3844 
3845  Assert(BufferIsValid(buffer));
3846 
3847  if (BufferIsLocal(buffer))
3848  {
3849  /* There should be exactly one pin */
3850  if (LocalRefCount[-buffer - 1] != 1)
3851  return false;
3852  /* Nobody else to wait for */
3853  return true;
3854  }
3855 
3856  /* There should be exactly one local pin */
3857  if (GetPrivateRefCount(buffer) != 1)
3858  return false;
3859 
3860  bufHdr = GetBufferDescriptor(buffer - 1);
3861 
3862  /* caller must hold exclusive lock on buffer */
3864  LW_EXCLUSIVE));
3865 
3866  buf_state = LockBufHdr(bufHdr);
3867 
3868  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
3869  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
3870  {
3871  /* pincount is OK. */
3872  UnlockBufHdr(bufHdr, buf_state);
3873  return true;
3874  }
3875 
3876  UnlockBufHdr(bufHdr, buf_state);
3877  return false;
3878 }
bool LWLockHeldByMeInMode(LWLock *l, LWLockMode mode)
Definition: lwlock.c:1860
#define GetBufferDescriptor(id)
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:359
unsigned int uint32
Definition: c.h:359
#define BufferDescriptorGetContentLock(bdesc)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define UnlockBufHdr(desc, s)
int32 * LocalRefCount
Definition: localbuf.c:45
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:48

◆ LockBuffer()

void LockBuffer ( Buffer  buffer,
int  mode 
)

Definition at line 3612 of file bufmgr.c.

References Assert, buf, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferDescriptorGetContentLock, BufferIsLocal, BufferIsValid, elog, ERROR, GetBufferDescriptor, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), and LWLockRelease().

Referenced by _bt_drop_lock_and_maybe_pin(), _bt_endpoint(), _bt_first(), _bt_getbuf(), _bt_getroot(), _bt_killitems(), _bt_moveright(), _bt_pagedel(), _bt_readnextpage(), _bt_relandgetbuf(), _bt_search(), _bt_unlink_halfdead_page(), _bt_update_meta_cleanup_info(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_finish_split(), _hash_first(), _hash_freeovflpage(), _hash_getbuf(), _hash_getbuf_with_strategy(), _hash_getcachedmetap(), _hash_getnewbuf(), _hash_init(), _hash_kill_items(), _hash_readnext(), _hash_readpage(), _hash_readprev(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), blbulkdelete(), blgetbitmap(), blinsert(), BloomNewBuffer(), blvacuumcleanup(), brin_doinsert(), brin_doupdate(), brin_evacuate_page(), brin_getinsertbuffer(), brin_page_cleanup(), brinbuild(), brinbuildempty(), bringetbitmap(), brinGetStats(), brinGetTupleForHeapBlock(), brininsert(), brinLockRevmapPageForUpdate(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), brinsummarize(), bt_metap(), bt_page_items(), bt_page_stats(), btvacuumpage(), checkXLogConsistency(), collect_corrupt_items(), collect_visibility_data(), collectMatchBitmap(), ConditionalLockBufferForCleanup(), count_nondeletable_pages(), entryLoadMoreItems(), fill_seq_with_data(), FreeSpaceMapPrepareTruncateRel(), fsm_readbuf(), fsm_search(), fsm_search_avail(), fsm_set_and_search(), fsm_vacuum_page(), get_raw_page_internal(), GetVisibilityMapPins(), ginbuildempty(), ginbulkdelete(), ginEntryInsert(), ginFindLeafPage(), ginFindParents(), ginFinishSplit(), ginGetStats(), ginHeapTupleFastInsert(), ginInsertCleanup(), ginInsertValue(), GinNewBuffer(), ginScanToDelete(), ginStepRight(), ginTraverseLock(), ginUpdateStats(), ginvacuumcleanup(), ginVacuumPostingTreeLeaves(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistbuildempty(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistfinishsplit(), gistfixsplit(), gistformdownlink(), gistGetMaxLevel(), gistinserttuples(), gistkillitems(), gistNewBuffer(), gistProcessItup(), gistScanPage(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_compute_xid_horizon_for_tuples(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_get_latest_tid(), heap_inplace_update(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_page_prune_opt(), 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_bitmap_next_block(), heapam_scan_sample_next_tuple(), heapam_tuple_satisfies_snapshot(), heapgetpage(), heapgettup(), initBloomState(), lazy_scan_heap(), LockBufferForCleanup(), log_newpage_range(), palloc_btree_page(), pg_visibility(), pgrowlocks(), pgstat_btree_page(), pgstat_gist_page(), pgstat_heap(), pgstatginindex_internal(), pgstathashindex(), pgstatindex_impl(), read_seq_tuple(), RelationGetBufferForTuple(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), shiftList(), spgdoinsert(), spgGetCache(), SpGistNewBuffer(), spgprocesspending(), spgvacuumpage(), spgWalk(), startScanEntry(), statapprox_heap(), summarize_range(), UnlockReleaseBuffer(), visibilitymap_clear(), visibilitymap_prepare_truncate(), visibilitymap_set(), vm_readbuf(), XLogReadBufferExtended(), XLogReadBufferForRedoExtended(), and XLogRecordPageWithFreeSpace().

3613 {
3614  BufferDesc *buf;
3615 
3616  Assert(BufferIsValid(buffer));
3617  if (BufferIsLocal(buffer))
3618  return; /* local buffers need no lock */
3619 
3620  buf = GetBufferDescriptor(buffer - 1);
3621 
3622  if (mode == BUFFER_LOCK_UNLOCK)
3624  else if (mode == BUFFER_LOCK_SHARE)
3626  else if (mode == BUFFER_LOCK_EXCLUSIVE)
3628  else
3629  elog(ERROR, "unrecognized buffer lock mode: %d", mode);
3630 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:86
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:88
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define GetBufferDescriptor(id)
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define elog(elevel,...)
Definition: elog.h:228
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:87

◆ LockBufferForCleanup()

void LockBufferForCleanup ( Buffer  buffer)

Definition at line 3669 of file bufmgr.c.

References Assert, BM_PIN_COUNT_WAITER, BUF_STATE_GET_REFCOUNT, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferIsLocal, BufferIsValid, elog, ERROR, GetBufferDescriptor, GetPrivateRefCount(), InHotStandby, LocalRefCount, LockBuffer(), LockBufHdr(), MyProcPid, PG_WAIT_BUFFER_PIN, ProcWaitForSignal(), ResolveRecoveryConflictWithBufferPin(), SetStartupBufferPinWaitBufId(), UnlockBufHdr, and BufferDesc::wait_backend_pid.

Referenced by btvacuumpage(), ginVacuumPostingTree(), hashbulkdelete(), lazy_scan_heap(), ReadBuffer_common(), and XLogReadBufferForRedoExtended().

3670 {
3671  BufferDesc *bufHdr;
3672 
3673  Assert(BufferIsValid(buffer));
3674  Assert(PinCountWaitBuf == NULL);
3675 
3676  if (BufferIsLocal(buffer))
3677  {
3678  /* There should be exactly one pin */
3679  if (LocalRefCount[-buffer - 1] != 1)
3680  elog(ERROR, "incorrect local pin count: %d",
3681  LocalRefCount[-buffer - 1]);
3682  /* Nobody else to wait for */
3683  return;
3684  }
3685 
3686  /* There should be exactly one local pin */
3687  if (GetPrivateRefCount(buffer) != 1)
3688  elog(ERROR, "incorrect local pin count: %d",
3689  GetPrivateRefCount(buffer));
3690 
3691  bufHdr = GetBufferDescriptor(buffer - 1);
3692 
3693  for (;;)
3694  {
3695  uint32 buf_state;
3696 
3697  /* Try to acquire lock */
3699  buf_state = LockBufHdr(bufHdr);
3700 
3701  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
3702  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
3703  {
3704  /* Successfully acquired exclusive lock with pincount 1 */
3705  UnlockBufHdr(bufHdr, buf_state);
3706  return;
3707  }
3708  /* Failed, so mark myself as waiting for pincount 1 */
3709  if (buf_state & BM_PIN_COUNT_WAITER)
3710  {
3711  UnlockBufHdr(bufHdr, buf_state);
3712  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3713  elog(ERROR, "multiple backends attempting to wait for pincount 1");
3714  }
3715  bufHdr->wait_backend_pid = MyProcPid;
3716  PinCountWaitBuf = bufHdr;
3717  buf_state |= BM_PIN_COUNT_WAITER;
3718  UnlockBufHdr(bufHdr, buf_state);
3719  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3720 
3721  /* Wait to be signaled by UnpinBuffer() */
3722  if (InHotStandby)
3723  {
3724  /* Publish the bufid that Startup process waits on */
3725  SetStartupBufferPinWaitBufId(buffer - 1);
3726  /* Set alarm and then wait to be signaled by UnpinBuffer() */
3728  /* Reset the published bufid */
3730  }
3731  else
3733 
3734  /*
3735  * Remove flag marking us as waiter. Normally this will not be set
3736  * anymore, but ProcWaitForSignal() can return for other signals as
3737  * well. We take care to only reset the flag if we're the waiter, as
3738  * theoretically another backend could have started waiting. That's
3739  * impossible with the current usages due to table level locking, but
3740  * better be safe.
3741  */
3742  buf_state = LockBufHdr(bufHdr);
3743  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
3744  bufHdr->wait_backend_pid == MyProcPid)
3745  buf_state &= ~BM_PIN_COUNT_WAITER;
3746  UnlockBufHdr(bufHdr, buf_state);
3747 
3748  PinCountWaitBuf = NULL;
3749  /* Loop back and try again */
3750  }
3751 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:86
int MyProcPid
Definition: globals.c:40
int wait_backend_pid
#define InHotStandby
Definition: xlog.h:74
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:88
#define ERROR
Definition: elog.h:43
void ResolveRecoveryConflictWithBufferPin(void)
Definition: standby.c:461
void SetStartupBufferPinWaitBufId(int bufid)
Definition: proc.c:645
#define GetBufferDescriptor(id)
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:359
unsigned int uint32
Definition: c.h:359
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1794
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3612
#define PG_WAIT_BUFFER_PIN
Definition: pgstat.h:756
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define UnlockBufHdr(desc, s)
#define elog(elevel,...)
Definition: elog.h:228
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:137
int32 * LocalRefCount
Definition: localbuf.c:45
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:48
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:64

◆ MarkBufferDirty()

void MarkBufferDirty ( Buffer  buffer)

Definition at line 1458 of file bufmgr.c.

References Assert, BM_DIRTY, BM_JUST_DIRTIED, BM_LOCKED, BUF_STATE_GET_REFCOUNT, 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, VacuumPageDirty, and WaitBufHdrUnlocked().

Referenced by _bt_clear_incomplete_split(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_newroot(), _bt_restore_meta(), _bt_split(), _bt_unlink_halfdead_page(), _bt_update_meta_cleanup_info(), _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_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), createPostingTree(), do_setval(), doPickSplit(), fill_seq_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_inplace_update(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_prune(), heap_update(), heap_xlog_clean(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_freeze_page(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_update(), heap_xlog_visible(), lazy_scan_heap(), lazy_vacuum_page(), log_newpage_range(), moveLeafs(), nextval_internal(), 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().

1459 {
1460  BufferDesc *bufHdr;
1461  uint32 buf_state;
1462  uint32 old_buf_state;
1463 
1464  if (!BufferIsValid(buffer))
1465  elog(ERROR, "bad buffer ID: %d", buffer);
1466 
1467  if (BufferIsLocal(buffer))
1468  {
1469  MarkLocalBufferDirty(buffer);
1470  return;
1471  }
1472 
1473  bufHdr = GetBufferDescriptor(buffer - 1);
1474 
1475  Assert(BufferIsPinned(buffer));
1477  LW_EXCLUSIVE));
1478 
1479  old_buf_state = pg_atomic_read_u32(&bufHdr->state);
1480  for (;;)
1481  {
1482  if (old_buf_state & BM_LOCKED)
1483  old_buf_state = WaitBufHdrUnlocked(bufHdr);
1484 
1485  buf_state = old_buf_state;
1486 
1487  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
1488  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
1489 
1490  if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
1491  buf_state))
1492  break;
1493  }
1494 
1495  /*
1496  * If the buffer was not dirty already, do vacuum accounting.
1497  */
1498  if (!(old_buf_state & BM_DIRTY))
1499  {
1500  VacuumPageDirty++;
1502  if (VacuumCostActive)
1504  }
1505 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:420
bool LWLockHeldByMeInMode(LWLock *l, LWLockMode mode)
Definition: lwlock.c:1860
int VacuumCostBalance
Definition: globals.c:147
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:311
#define BM_DIRTY
Definition: buf_internals.h:58
int VacuumCostPageDirty
Definition: globals.c:139
#define ERROR
Definition: elog.h:43
#define GetBufferDescriptor(id)
#define BM_JUST_DIRTIED
Definition: buf_internals.h:63
long shared_blks_dirtied
Definition: instrument.h:23
unsigned int uint32
Definition: c.h:359
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:280
#define BM_LOCKED
Definition: buf_internals.h:57
int VacuumPageDirty
Definition: globals.c:145
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
static uint32 WaitBufHdrUnlocked(BufferDesc *buf)
Definition: bufmgr.c:4186
#define elog(elevel,...)
Definition: elog.h:228
pg_atomic_uint32 state
BufferUsage pgBufferUsage
Definition: instrument.c:20
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:48
bool VacuumCostActive
Definition: globals.c:148
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241

◆ MarkBufferDirtyHint()

void MarkBufferDirtyHint ( Buffer  buffer,
bool  buffer_std 
)

Definition at line 3445 of file bufmgr.c.

References Assert, BM_DIRTY, BM_JUST_DIRTIED, BM_PERMANENT, BUF_STATE_GET_REFCOUNT, BufferDescriptorGetContentLock, BufferGetPage, BufferIsLocal, BufferIsValid, PGXACT::delayChkpt, elog, ERROR, GetBufferDescriptor, GetPrivateRefCount(), InvalidXLogRecPtr, LockBufHdr(), LWLockHeldByMe(), MarkLocalBufferDirty(), MyPgXact, PageSetLSN, pg_atomic_read_u32(), pgBufferUsage, RecoveryInProgress(), BufferUsage::shared_blks_dirtied, BufferDesc::state, UnlockBufHdr, VacuumCostActive, VacuumCostBalance, VacuumCostPageDirty, VacuumPageDirty, XLogHintBitIsNeeded, XLogRecPtrIsInvalid, and XLogSaveBufferForHint().

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

3446 {
3447  BufferDesc *bufHdr;
3448  Page page = BufferGetPage(buffer);
3449 
3450  if (!BufferIsValid(buffer))
3451  elog(ERROR, "bad buffer ID: %d", buffer);
3452 
3453  if (BufferIsLocal(buffer))
3454  {
3455  MarkLocalBufferDirty(buffer);
3456  return;
3457  }
3458 
3459  bufHdr = GetBufferDescriptor(buffer - 1);
3460 
3461  Assert(GetPrivateRefCount(buffer) > 0);
3462  /* here, either share or exclusive lock is OK */
3464 
3465  /*
3466  * This routine might get called many times on the same page, if we are
3467  * making the first scan after commit of an xact that added/deleted many
3468  * tuples. So, be as quick as we can if the buffer is already dirty. We
3469  * do this by not acquiring spinlock if it looks like the status bits are
3470  * already set. Since we make this test unlocked, there's a chance we
3471  * might fail to notice that the flags have just been cleared, and failed
3472  * to reset them, due to memory-ordering issues. But since this function
3473  * is only intended to be used in cases where failing to write out the
3474  * data would be harmless anyway, it doesn't really matter.
3475  */
3476  if ((pg_atomic_read_u32(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
3478  {
3480  bool dirtied = false;
3481  bool delayChkpt = false;
3482  uint32 buf_state;
3483 
3484  /*
3485  * If we need to protect hint bit updates from torn writes, WAL-log a
3486  * full page image of the page. This full page image is only necessary
3487  * if the hint bit update is the first change to the page since the
3488  * last checkpoint.
3489  *
3490  * We don't check full_page_writes here because that logic is included
3491  * when we call XLogInsert() since the value changes dynamically.
3492  */
3493  if (XLogHintBitIsNeeded() &&
3494  (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT))
3495  {
3496  /*
3497  * If we're in recovery we cannot dirty a page because of a hint.
3498  * We can set the hint, just not dirty the page as a result so the
3499  * hint is lost when we evict the page or shutdown.
3500  *
3501  * See src/backend/storage/page/README for longer discussion.
3502  */
3503  if (RecoveryInProgress())
3504  return;
3505 
3506  /*
3507  * If the block is already dirty because we either made a change
3508  * or set a hint already, then we don't need to write a full page
3509  * image. Note that aggressive cleaning of blocks dirtied by hint
3510  * bit setting would increase the call rate. Bulk setting of hint
3511  * bits would reduce the call rate...
3512  *
3513  * We must issue the WAL record before we mark the buffer dirty.
3514  * Otherwise we might write the page before we write the WAL. That
3515  * causes a race condition, since a checkpoint might occur between
3516  * writing the WAL record and marking the buffer dirty. We solve
3517  * that with a kluge, but one that is already in use during
3518  * transaction commit to prevent race conditions. Basically, we
3519  * simply prevent the checkpoint WAL record from being written
3520  * until we have marked the buffer dirty. We don't start the
3521  * checkpoint flush until we have marked dirty, so our checkpoint
3522  * must flush the change to disk successfully or the checkpoint
3523  * never gets written, so crash recovery will fix.
3524  *
3525  * It's possible we may enter here without an xid, so it is
3526  * essential that CreateCheckpoint waits for virtual transactions
3527  * rather than full transactionids.
3528  */
3529  MyPgXact->delayChkpt = delayChkpt = true;
3530  lsn = XLogSaveBufferForHint(buffer, buffer_std);
3531  }
3532 
3533  buf_state = LockBufHdr(bufHdr);
3534 
3535  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
3536 
3537  if (!(buf_state & BM_DIRTY))
3538  {
3539  dirtied = true; /* Means "will be dirtied by this action" */
3540 
3541  /*
3542  * Set the page LSN if we wrote a backup block. We aren't supposed
3543  * to set this when only holding a share lock but as long as we
3544  * serialise it somehow we're OK. We choose to set LSN while
3545  * holding the buffer header lock, which causes any reader of an
3546  * LSN who holds only a share lock to also obtain a buffer header
3547  * lock before using PageGetLSN(), which is enforced in
3548  * BufferGetLSNAtomic().
3549  *
3550  * If checksums are enabled, you might think we should reset the
3551  * checksum here. That will happen when the page is written
3552  * sometime later in this checkpoint cycle.
3553  */
3554  if (!XLogRecPtrIsInvalid(lsn))
3555  PageSetLSN(page, lsn);
3556  }
3557 
3558  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
3559  UnlockBufHdr(bufHdr, buf_state);
3560 
3561  if (delayChkpt)
3562  MyPgXact->delayChkpt = false;
3563 
3564  if (dirtied)
3565  {
3566  VacuumPageDirty++;
3568  if (VacuumCostActive)
3570  }
3571  }
3572 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define BM_PERMANENT
Definition: buf_internals.h:66
int VacuumCostBalance
Definition: globals.c:147
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1842
XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
Definition: xloginsert.c:893
bool RecoveryInProgress(void)
Definition: xlog.c:7930
#define BM_DIRTY
Definition: buf_internals.h:58
int VacuumCostPageDirty
Definition: globals.c:139
PGXACT * MyPgXact
Definition: proc.c:68
#define ERROR
Definition: elog.h:43
#define GetBufferDescriptor(id)
#define BM_JUST_DIRTIED
Definition: buf_internals.h:63
long shared_blks_dirtied
Definition: instrument.h:23
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:359
unsigned int uint32
Definition: c.h:359
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
bool delayChkpt
Definition: proc.h:235
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:280
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
int VacuumPageDirty
Definition: globals.c:145
#define BufferDescriptorGetContentLock(bdesc)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define UnlockBufHdr(desc, s)
#define elog(elevel,...)
Definition: elog.h:228
pg_atomic_uint32 state
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
#define XLogHintBitIsNeeded()
Definition: xlog.h:192
Pointer Page
Definition: bufpage.h:78
BufferUsage pgBufferUsage
Definition: instrument.c:20
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:48
bool VacuumCostActive
Definition: globals.c:148
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241

◆ PrefetchBuffer()

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

Definition at line 531 of file bufmgr.c.

References Assert, BlockNumberIsValid, BufMappingPartitionLock, BufTableHashCode(), BufTableLookup(), ereport, errcode(), errmsg(), ERROR, INIT_BUFFERTAG, LocalPrefetchBuffer(), LW_SHARED, LWLockAcquire(), LWLockRelease(), RelFileNodeBackend::node, RelationData::rd_smgr, RELATION_IS_OTHER_TEMP, RelationIsValid, RelationOpenSmgr, RelationUsesLocalBuffers, SMgrRelationData::smgr_rnode, and smgrprefetch().

Referenced by BitmapPrefetch(), count_nondeletable_pages(), HeapTupleHeaderAdvanceLatestRemovedXid(), and pg_prewarm().

532 {
533 #ifdef USE_PREFETCH
534  Assert(RelationIsValid(reln));
535  Assert(BlockNumberIsValid(blockNum));
536 
537  /* Open it at the smgr level if not already done */
538  RelationOpenSmgr(reln);
539 
540  if (RelationUsesLocalBuffers(reln))
541  {
542  /* see comments in ReadBufferExtended */
543  if (RELATION_IS_OTHER_TEMP(reln))
544  ereport(ERROR,
545  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
546  errmsg("cannot access temporary tables of other sessions")));
547 
548  /* pass it off to localbuf.c */
549  LocalPrefetchBuffer(reln->rd_smgr, forkNum, blockNum);
550  }
551  else
552  {
553  BufferTag newTag; /* identity of requested block */
554  uint32 newHash; /* hash value for newTag */
555  LWLock *newPartitionLock; /* buffer partition lock for it */
556  int buf_id;
557 
558  /* create a tag so we can lookup the buffer */
559  INIT_BUFFERTAG(newTag, reln->rd_smgr->smgr_rnode.node,
560  forkNum, blockNum);
561 
562  /* determine its hash code and partition lock ID */
563  newHash = BufTableHashCode(&newTag);
564  newPartitionLock = BufMappingPartitionLock(newHash);
565 
566  /* see if the block is in the buffer pool already */
567  LWLockAcquire(newPartitionLock, LW_SHARED);
568  buf_id = BufTableLookup(&newTag, newHash);
569  LWLockRelease(newPartitionLock);
570 
571  /* If not in buffers, initiate prefetch */
572  if (buf_id < 0)
573  smgrprefetch(reln->rd_smgr, forkNum, blockNum);
574 
575  /*
576  * If the block *is* in buffers, we do nothing. This is not really
577  * ideal: the block might be just about to be evicted, which would be
578  * stupid since we know we are going to need it soon. But the only
579  * easy answer is to bump the usage_count, which does not seem like a
580  * great solution: when the caller does ultimately touch the block,
581  * usage_count would get bumped again, resulting in too much
582  * favoritism for blocks that are involved in a prefetch sequence. A
583  * real fix would involve some additional per-buffer state, and it's
584  * not clear that there's enough of a problem to justify that.
585  */
586  }
587 #endif /* USE_PREFETCH */
588 }
Definition: lwlock.h:32
#define BufMappingPartitionLock(hashcode)
void LocalPrefetchBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition: localbuf.c:64
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
uint32 BufTableHashCode(BufferTag *tagPtr)
Definition: buf_table.c:79
int errcode(int sqlerrcode)
Definition: elog.c:608
int BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
Definition: buf_table.c:91
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define RelationOpenSmgr(relation)
Definition: rel.h:485
#define ERROR
Definition: elog.h:43
#define RelationIsValid(relation)
Definition: rel.h:401
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
unsigned int uint32
Definition: c.h:359
#define ereport(elevel, rest)
Definition: elog.h:141
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:739
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:558
#define INIT_BUFFERTAG(a, xx_rnode, xx_forkNum, xx_blockNum)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:537
int errmsg(const char *fmt,...)
Definition: elog.c:822
void smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: smgr.c:494

◆ PrintBufferLeakWarning()

void PrintBufferLeakWarning ( Buffer  buffer)

Definition at line 2549 of file bufmgr.c.

References Assert, buftag::blockNum, buf, BUF_FLAG_MASK, BUF_STATE_GET_REFCOUNT, BufferIsLocal, BufferIsValid, elog, buftag::forkNum, GetBufferDescriptor, GetLocalBufferDescriptor, GetPrivateRefCount(), InvalidBackendId, LocalRefCount, MyBackendId, pfree(), pg_atomic_read_u32(), relpathbackend, buftag::rnode, BufferDesc::state, BufferDesc::tag, and WARNING.

Referenced by CheckForBufferLeaks(), CheckForLocalBufferLeaks(), and ResourceOwnerReleaseInternal().

2550 {
2551  BufferDesc *buf;
2552  int32 loccount;
2553  char *path;
2554  BackendId backend;
2555  uint32 buf_state;
2556 
2557  Assert(BufferIsValid(buffer));
2558  if (BufferIsLocal(buffer))
2559  {
2560  buf = GetLocalBufferDescriptor(-buffer - 1);
2561  loccount = LocalRefCount[-buffer - 1];
2562  backend = MyBackendId;
2563  }
2564  else
2565  {
2566  buf = GetBufferDescriptor(buffer - 1);
2567  loccount = GetPrivateRefCount(buffer);
2568  backend = InvalidBackendId;
2569  }
2570 
2571  /* theoretically we should lock the bufhdr here */
2572  path = relpathbackend(buf->tag.rnode, backend, buf->tag.forkNum);
2573  buf_state = pg_atomic_read_u32(&buf->state);
2574  elog(WARNING,
2575  "buffer refcount leak: [%03d] "
2576  "(rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
2577  buffer, path,
2578  buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
2579  BUF_STATE_GET_REFCOUNT(buf_state), loccount);
2580  pfree(path);
2581 }
BackendId MyBackendId
Definition: globals.c:81
ForkNumber forkNum
Definition: buf_internals.h:93
#define GetLocalBufferDescriptor(id)
signed int int32
Definition: c.h:347
void pfree(void *pointer)
Definition: mcxt.c:1056
#define BUF_FLAG_MASK
Definition: buf_internals.h:45
static char * buf
Definition: pg_test_fsync.c:67
#define GetBufferDescriptor(id)
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:359
unsigned int uint32
Definition: c.h:359
#define WARNING
Definition: elog.h:40
#define InvalidBackendId
Definition: backendid.h:23
int BackendId
Definition: backendid.h:21
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
BlockNumber blockNum
Definition: buf_internals.h:94
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
RelFileNode rnode
Definition: buf_internals.h:92
BufferTag tag
#define elog(elevel,...)
Definition: elog.h:228
pg_atomic_uint32 state
#define relpathbackend(rnode, backend, forknum)
Definition: relpath.h:78
int32 * LocalRefCount
Definition: localbuf.c:45
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:48
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241

◆ ReadBuffer()

Buffer ReadBuffer ( Relation  reln,
BlockNumber  blockNum 
)

Definition at line 596 of file bufmgr.c.

References MAIN_FORKNUM, RBM_NORMAL, and ReadBufferExtended().

Referenced by _bt_doinsert(), _bt_getbuf(), _hash_getbuf(), _hash_getbuf_with_condlock_cleanup(), blbulkdelete(), blinsert(), BloomNewBuffer(), brin_getinsertbuffer(), brinbuild(), brinGetStats(), brinGetTupleForHeapBlock(), brinRevmapDesummarizeRange(), brinRevmapInitialize(), bt_metap(), bt_page_items(), bt_page_stats(), fill_seq_with_data(), ginFindLeafPage(), ginFindParents(), ginGetStats(), ginHeapTupleFastInsert(), ginInsertCleanup(), GinNewBuffer(), ginStepRight(), ginUpdateStats(), gistBufferingFindCorrectParent(), gistbufferinginserttuples(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistfixsplit(), gistGetMaxLevel(), gistkillitems(), gistNewBuffer(), gistProcessItup(), gistScanPage(), heap_abort_speculative(), heap_compute_xid_horizon_for_tuples(), heap_delete(), heap_fetch(), heap_finish_speculative(), heap_get_latest_tid(), heap_inplace_update(), heap_lock_tuple(), heap_update(), initBloomState(), log_newpage_range(), 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().

597 {
598  return ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);
599 }
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:642

◆ ReadBufferExtended()

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

Definition at line 642 of file bufmgr.c.

References buf, ereport, errcode(), errmsg(), ERROR, pgstat_count_buffer_hit, pgstat_count_buffer_read, RelationData::rd_rel, RelationData::rd_smgr, ReadBuffer_common(), RELATION_IS_OTHER_TEMP, and RelationOpenSmgr.

Referenced by _hash_getbuf_with_strategy(), _hash_getinitbuf(), _hash_getnewbuf(), autoprewarm_database_main(), blbulkdelete(), blgetbitmap(), blvacuumcleanup(), brin_vacuum_scan(), brinbuildempty(), btvacuumpage(), collect_corrupt_items(), collect_visibility_data(), count_nondeletable_pages(), fsm_readbuf(), get_raw_page_internal(), ginbuildempty(), ginbulkdelete(), ginDeletePage(), ginScanToDelete(), ginvacuumcleanup(), ginVacuumPostingTree(), ginVacuumPostingTreeLeaves(), gistbuildempty(), gistvacuum_delete_empty_pages(), gistvacuumpage(), hashbulkdelete(), heapam_scan_analyze_next_block(), heapgetpage(), lazy_scan_heap(), lazy_vacuum_heap(), palloc_btree_page(), pg_prewarm(), pgstat_btree_page(), pgstat_gist_page(), pgstat_heap(), pgstathashindex(), pgstatindex_impl(), ReadBuffer(), ReadBufferBI(), spgprocesspending(), spgvacuumpage(), statapprox_heap(), and vm_readbuf().

644 {
645  bool hit;
646  Buffer buf;
647 
648  /* Open it at the smgr level if not already done */
649  RelationOpenSmgr(reln);
650 
651  /*
652  * Reject attempts to read non-local temporary relations; we would be
653  * likely to get wrong data since we have no visibility into the owning
654  * session's local buffers.
655  */
656  if (RELATION_IS_OTHER_TEMP(reln))
657  ereport(ERROR,
658  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
659  errmsg("cannot access temporary tables of other sessions")));
660 
661  /*
662  * Read the buffer, and update pgstat counters to reflect a cache hit or
663  * miss.
664  */
666  buf = ReadBuffer_common(reln->rd_smgr, reln->rd_rel->relpersistence,
667  forkNum, blockNum, mode, strategy, &hit);
668  if (hit)
670  return buf;
671 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
int errcode(int sqlerrcode)
Definition: elog.c:608
Form_pg_class rd_rel
Definition: rel.h:84
#define RelationOpenSmgr(relation)
Definition: rel.h:485
#define ERROR
Definition: elog.h:43
#define pgstat_count_buffer_read(rel)
Definition: pgstat.h:1385
static char * buf
Definition: pg_test_fsync.c:67
#define ereport(elevel, rest)
Definition: elog.h:141
#define pgstat_count_buffer_hit(rel)
Definition: pgstat.h:1390
static Buffer ReadBuffer_common(SMgrRelation reln, char relpersistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool *hit)
Definition: bufmgr.c:705
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:558
int errmsg(const char *fmt,...)
Definition: elog.c:822
int Buffer
Definition: buf.h:23

◆ ReadBufferWithoutRelcache()

Buffer ReadBufferWithoutRelcache ( RelFileNode  rnode,
ForkNumber  forkNum,
BlockNumber  blockNum,
ReadBufferMode  mode,
BufferAccessStrategy  strategy 
)

Definition at line 684 of file bufmgr.c.

References Assert, InRecovery, InvalidBackendId, ReadBuffer_common(), and smgropen().

Referenced by XLogReadBufferExtended().

687 {
688  bool hit;
689 
690  SMgrRelation smgr = smgropen(rnode, InvalidBackendId);
691 
693 
694  return ReadBuffer_common(smgr, RELPERSISTENCE_PERMANENT, forkNum, blockNum,
695  mode, strategy, &hit);
696 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
bool InRecovery
Definition: xlog.c:200
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:145
#define InvalidBackendId
Definition: backendid.h:23
static Buffer ReadBuffer_common(SMgrRelation reln, char relpersistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool *hit)
Definition: bufmgr.c:705
#define Assert(condition)
Definition: c.h:739

◆ RelationGetNumberOfBlocksInFork()

BlockNumber RelationGetNumberOfBlocksInFork ( Relation  relation,
ForkNumber  forkNum 
)

Definition at line 2810 of file bufmgr.c.

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

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

2811 {
2812  switch (relation->rd_rel->relkind)
2813  {
2814  case RELKIND_SEQUENCE:
2815  case RELKIND_INDEX:
2816  case RELKIND_PARTITIONED_INDEX:
2817  /* Open it at the smgr level if not already done */
2818  RelationOpenSmgr(relation);
2819 
2820  return smgrnblocks(relation->rd_smgr, forkNum);
2821 
2822  case RELKIND_RELATION:
2823  case RELKIND_TOASTVALUE:
2824  case RELKIND_MATVIEW:
2825  {
2826  /*
2827  * Not every table AM uses BLCKSZ wide fixed size blocks.
2828  * Therefore tableam returns the size in bytes - but for the
2829  * purpose of this routine, we want the number of blocks.
2830  * Therefore divide, rounding up.
2831  */
2832  uint64 szbytes;
2833 
2834  szbytes = table_relation_size(relation, forkNum);
2835 
2836  return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
2837  }
2838  case RELKIND_VIEW:
2839  case RELKIND_COMPOSITE_TYPE:
2840  case RELKIND_FOREIGN_TABLE:
2841  case RELKIND_PARTITIONED_TABLE:
2842  default:
2843  Assert(false);
2844  break;
2845  }
2846 
2847  return 0; /* keep compiler quiet */
2848 }
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
Form_pg_class rd_rel
Definition: rel.h:84
#define RelationOpenSmgr(relation)
Definition: rel.h:485
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition: tableam.h:1610
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:555
#define Assert(condition)
Definition: c.h:739

◆ ReleaseAndReadBuffer()

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

Definition at line 1521 of file bufmgr.c.

References Assert, buftag::blockNum, PrivateRefCountEntry::buffer, BufferIsLocal, BufferIsPinned, BufferIsValid, CurrentResourceOwner, buftag::forkNum, GetBufferDescriptor, GetLocalBufferDescriptor, LocalRefCount, MAIN_FORKNUM, RelationData::rd_node, ReadBuffer(), RelFileNodeEquals, ResourceOwnerForgetBuffer(), buftag::rnode, BufferDesc::tag, and UnpinBuffer().

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

1524 {
1525  ForkNumber forkNum = MAIN_FORKNUM;
1526  BufferDesc *bufHdr;
1527 
1528  if (BufferIsValid(buffer))
1529  {
1530  Assert(BufferIsPinned(buffer));
1531  if (BufferIsLocal(buffer))
1532  {
1533  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
1534  if (bufHdr->tag.blockNum == blockNum &&
1535  RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node) &&
1536  bufHdr->tag.forkNum == forkNum)
1537  return buffer;
1539  LocalRefCount[-buffer - 1]--;
1540  }
1541  else
1542  {
1543  bufHdr = GetBufferDescriptor(buffer - 1);
1544  /* we have pin, so it's ok to examine tag without spinlock */
1545  if (bufHdr->tag.blockNum == blockNum &&
1546  RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node) &&
1547  bufHdr->tag.forkNum == forkNum)
1548  return buffer;
1549  UnpinBuffer(bufHdr, true);
1550  }
1551  }
1552 
1553  return ReadBuffer(relation, blockNum);
1554 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:420
ForkNumber forkNum
Definition: buf_internals.h:93
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
#define GetLocalBufferDescriptor(id)
#define GetBufferDescriptor(id)
ForkNumber
Definition: relpath.h:40
static void UnpinBuffer(BufferDesc *buf, bool fixOwner)
Definition: bufmgr.c:1702
RelFileNode rd_node
Definition: rel.h:55
#define Assert(condition)
Definition: c.h:739
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:596
#define BufferIsLocal(buffer)
Definition: buf.h:37
BlockNumber blockNum
Definition: buf_internals.h:94
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
RelFileNode rnode
Definition: buf_internals.h:92
BufferTag tag
int32 * LocalRefCount
Definition: localbuf.c:45
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88
void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:915

◆ ReleaseBuffer()

void ReleaseBuffer ( Buffer  buffer)

Definition at line 3375 of file bufmgr.c.

References Assert, BufferIsLocal, BufferIsValid, CurrentResourceOwner, elog, ERROR, GetBufferDescriptor, LocalRefCount, ResourceOwnerForgetBuffer(), and UnpinBuffer().

Referenced by _bt_doinsert(), _bt_drop_lock_and_maybe_pin(), _bt_getbuf(), _bt_pagedel(), _bt_unlink_halfdead_page(), _hash_dropbuf(), _hash_getbuf_with_condlock_cleanup(), autoprewarm_database_main(), blinsert(), BloomNewBuffer(), brin_getinsertbuffer(), brin_vacuum_scan(), bringetbitmap(), brinGetTupleForHeapBlock(), brininsert(), brinRevmapTerminate(), brinsummarize(), collect_corrupt_items(), collect_visibility_data(), entryLoadMoreItems(), ExecEndBitmapHeapScan(), ExecEndIndexOnlyScan(), ExecReScanBitmapHeapScan(), FreeBulkInsertState(), freeGinBtreeStack(), fsm_vacuum_page(), get_actual_variable_endpoint(), get_raw_page_internal(), GetRecordedFreeSpace(), ginDeletePage(), ginFindParents(), ginFinishSplit(), ginFreeScanKeys(), ginInsertCleanup(), GinNewBuffer(), ginScanToDelete(), gistdoinsert(), gistFindCorrectParent(), gistNewBuffer(), gistvacuum_delete_empty_pages(), heap_abort_speculative(), heap_compute_xid_horizon_for_tuples(), heap_delete(), heap_endscan(), heap_fetch(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_rescan(), heap_update(), 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(), heapgetpage(), heapgettup(), heapgettup_pagemode(), lazy_scan_heap(), lazy_vacuum_heap(), pg_prewarm(), pg_visibility(), pg_visibility_map(), pg_visibility_map_summary(), pgstatindex_impl(), ReadBufferBI(), RelationGetBufferForTuple(), ReleaseBulkInsertStatePin(), ResourceOwnerReleaseInternal(), revmap_get_buffer(), revmap_physical_extend(), 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(), visibilitymap_count(), visibilitymap_get_status(), visibilitymap_pin(), and XLogReadBufferExtended().

3376 {
3377  if (!BufferIsValid(buffer))
3378  elog(ERROR, "bad buffer ID: %d", buffer);
3379 
3380  if (BufferIsLocal(buffer))
3381  {
3383 
3384  Assert(LocalRefCount[-buffer - 1] > 0);
3385  LocalRefCount[-buffer - 1]--;
3386  return;
3387  }
3388 
3389  UnpinBuffer(GetBufferDescriptor(buffer - 1), true);
3390 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
#define ERROR
Definition: elog.h:43
#define GetBufferDescriptor(id)
static void UnpinBuffer(BufferDesc *buf, bool fixOwner)
Definition: bufmgr.c:1702
#define Assert(condition)
Definition: c.h:739
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define elog(elevel,...)
Definition: elog.h:228
int32 * LocalRefCount
Definition: localbuf.c:45
void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:915

◆ TestForOldSnapshot()

static void TestForOldSnapshot ( Snapshot  snapshot,
Relation  relation,
Page  page 
)
inlinestatic

Definition at line 264 of file bufmgr.h.

References Assert, old_snapshot_threshold, PageGetLSN, SNAPSHOT_MVCC, SNAPSHOT_TOAST, TestForOldSnapshot_impl(), and XLogRecPtrIsInvalid.

Referenced by _bt_get_endpoint(), _bt_moveright(), _bt_readnextpage(), _bt_walk_left(), _hash_first(), _hash_next(), _hash_readnext(), _hash_readprev(), blgetbitmap(), brinGetTupleForHeapBlock(), brinRevmapInitialize(), collectMatchBitmap(), collectMatchesForHeapRow(), ginFindLeafPage(), gistScanPage(), heap_fetch(), heap_get_latest_tid(), heapgetpage(), heapgettup(), heapgettup_pagemode(), scanGetCandidate(), scanPendingInsert(), and spgWalk().

265 {
266  Assert(relation != NULL);
267 
268  if (old_snapshot_threshold >= 0
269  && (snapshot) != NULL
270  && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
271  || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
272  && !XLogRecPtrIsInvalid((snapshot)->lsn)
273  && PageGetLSN(page) > (snapshot)->lsn)
274  TestForOldSnapshot_impl(snapshot, relation);
275 }
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define Assert(condition)
Definition: c.h:739
#define PageGetLSN(page)
Definition: bufpage.h:366
int old_snapshot_threshold
Definition: snapmgr.c:75
void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation)
Definition: bufmgr.c:4418

◆ TestForOldSnapshot_impl()

void TestForOldSnapshot_impl ( Snapshot  snapshot,
Relation  relation 
)

Definition at line 4418 of file bufmgr.c.

References ereport, errcode(), errmsg(), ERROR, GetOldSnapshotThresholdTimestamp(), and RelationAllowsEarlyPruning.

Referenced by TestForOldSnapshot().

4419 {
4420  if (RelationAllowsEarlyPruning(relation)
4421  && (snapshot)->whenTaken < GetOldSnapshotThresholdTimestamp())
4422  ereport(ERROR,
4423  (errcode(ERRCODE_SNAPSHOT_TOO_OLD),
4424  errmsg("snapshot too old")));
4425 }
TimestampTz GetOldSnapshotThresholdTimestamp(void)
Definition: snapmgr.c:1745
#define RelationAllowsEarlyPruning(rel)
Definition: snapmgr.h:38
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ UnlockBuffers()

void UnlockBuffers ( void  )

Definition at line 3584 of file bufmgr.c.

References BM_PIN_COUNT_WAITER, buf, LockBufHdr(), MyProcPid, PinCountWaitBuf, UnlockBufHdr, and BufferDesc::wait_backend_pid.

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

3585 {
3587 
3588  if (buf)
3589  {
3590  uint32 buf_state;
3591 
3592  buf_state = LockBufHdr(buf);
3593 
3594  /*
3595  * Don't complain if flag bit not set; it could have been reset but we
3596  * got a cancel/die interrupt before getting the signal.
3597  */
3598  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
3599  buf->wait_backend_pid == MyProcPid)
3600  buf_state &= ~BM_PIN_COUNT_WAITER;
3601 
3602  UnlockBufHdr(buf, buf_state);
3603 
3604  PinCountWaitBuf = NULL;
3605  }
3606 }
int MyProcPid
Definition: globals.c:40
int wait_backend_pid
static char * buf
Definition: pg_test_fsync.c:67
unsigned int uint32
Definition: c.h:359
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4158
#define UnlockBufHdr(desc, s)
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:137
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:64

◆ UnlockReleaseBuffer()

void UnlockReleaseBuffer ( Buffer  buffer)

Definition at line 3398 of file bufmgr.c.

References BUFFER_LOCK_UNLOCK, LockBuffer(), and ReleaseBuffer().

Referenced by _bt_clear_incomplete_split(), _bt_relbuf(), _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_page_items(), bt_page_stats(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), checkXLogConsistency(), collect_corrupt_items(), collect_visibility_data(), count_nondeletable_pages(), createPostingTree(), do_setval(), doPickSplit(), entryLoadMoreItems(), fill_seq_with_data(), flushCachedPage(), FreeSpaceMapPrepareTruncateRel(), fsm_search(), fsm_set_and_search(), generic_redo(), ginbuild(), ginbuildempty(), ginbulkdelete(), ginFindParents(), 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_get_latest_tid(), heap_inplace_update(), heap_insert(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_update(), heap_xlog_clean(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_freeze_page(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_update(), heap_xlog_visible(), heapam_scan_analyze_next_tuple(), initBloomState(), lazy_scan_heap(), lazy_vacuum_heap(), log_newpage_range(), moveLeafs(), nextval_internal(), palloc_btree_page(), pg_sequence_last_value(), pg_visibility(), pgstat_gist_page(), pgstat_heap(), pgstatginindex_internal(), pgstathashindex(), RelationAddExtraBlocks(), RelationGetBufferForTuple(), ResetSequence(), revmap_physical_extend(), scanGetCandidate(), scanPendingInsert(), scanPostingTree(), seq_redo(), shiftList(), spgAddNodeAction(), spgbuild(), spgdoinsert(), spgGetCache(), SpGistGetBuffer(), SpGistUpdateMetaPage(), spgMatchNodeAction(), spgprocesspending(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), spgSplitNodeAction(), spgvacuumpage(), spgWalk(), statapprox_heap(), visibilitymap_prepare_truncate(), writeListPage(), xlog_redo(), and XLogRecordPageWithFreeSpace().

3399 {
3400  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3401  ReleaseBuffer(buffer);
3402 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:86
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3375
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3612

Variable Documentation

◆ backend_flush_after

int backend_flush_after

Definition at line 121 of file bufmgr.c.

Referenced by InitBufferPool().

◆ bgwriter_flush_after

int bgwriter_flush_after

Definition at line 120 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

int bgwriter_lru_maxpages

Definition at line 110 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

double bgwriter_lru_multiplier

Definition at line 111 of file bufmgr.c.

Referenced by BgBufferSync().

◆ BufferBlocks

PGDLLIMPORT char* BufferBlocks

Definition at line 21 of file buf_init.c.

Referenced by InitBufferPool().

◆ checkpoint_flush_after

int checkpoint_flush_after

Definition at line 119 of file bufmgr.c.

Referenced by BufferSync().

◆ effective_io_concurrency

int effective_io_concurrency

◆ LocalBufferBlockPointers

PGDLLIMPORT Block* LocalBufferBlockPointers

Definition at line 44 of file localbuf.c.

Referenced by InitLocalBuffers().

◆ LocalRefCount

◆ NBuffers

◆ NLocBuffer

◆ target_prefetch_pages

int target_prefetch_pages

Definition at line 130 of file bufmgr.c.

Referenced by assign_effective_io_concurrency(), and ExecInitBitmapHeapScan().

◆ track_io_timing

bool track_io_timing

Definition at line 112 of file bufmgr.c.

Referenced by FlushBuffer(), ReadBuffer_common(), and show_buffer_usage().

◆ zero_damaged_pages

bool zero_damaged_pages

Definition at line 109 of file bufmgr.c.

Referenced by mdread(), and ReadBuffer_common().