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.

Data Structures

struct  PrefetchBufferResult
 

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
 
typedef struct PrefetchBufferResult PrefetchBufferResult
 

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

PrefetchBufferResult PrefetchSharedBuffer (struct SMgrRelationData *smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
 
PrefetchBufferResult 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 FlushRelationsAllBuffers (struct SMgrRelationData **smgrs, int nrels)
 
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 effective_io_concurrency
 
int maintenance_io_concurrency
 
int checkpoint_flush_after
 
int backend_flush_after
 
int bgwriter_flush_after
 
PGDLLIMPORT char * BufferBlocks
 
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 96 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:473
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
void * Block
Definition: bufmgr.h:24

Definition at line 136 of file bufmgr.h.

Referenced by XLogSaveBufferForHint().

◆ BufferGetPage

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

Definition at line 169 of file bufmgr.h.

Referenced by _bt_binsrch(), _bt_binsrch_insert(), _bt_check_unique(), _bt_checkpage(), _bt_clear_incomplete_split(), _bt_dedup_one_page(), _bt_delitems_delete(), _bt_delitems_vacuum(), _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_killitems(), _bt_leftsib_splitflag(), _bt_lock_subtree_parent(), _bt_mark_page_halfdead(), _bt_moveright(), _bt_newroot(), _bt_pagedel(), _bt_readnextpage(), _bt_readpage(), _bt_restore_meta(), _bt_rightsib_halfdeadflag(), _bt_search(), _bt_search_insert(), _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_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), btvacuumpage(), BufferGetLSNAtomic(), 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 123 of file bufmgr.h.

Referenced by _bt_clear_incomplete_split(), _bt_endpoint(), _bt_first(), _bt_get_endpoint(), _bt_insertonpg(), _bt_readpage(), _bt_relandgetbuf(), _bt_search(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_dropscanbuf(), _hash_freeovflpage(), _hash_getbucketbuf_from_hashkey(), _hash_getcachedmetap(), _hash_readnext(), _hash_readpage(), _hash_readprev(), 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_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), BufferGetLSNAtomic(), BufferIsPermanent(), 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 88 of file bufmgr.h.

◆ P_NEW

◆ RelationGetNumberOfBlocks

Typedef Documentation

◆ Block

typedef void* Block

Definition at line 24 of file bufmgr.h.

◆ BufferAccessStrategyType

◆ PrefetchBufferResult

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

4173 {
4175 
4176  if (buf)
4177  {
4178  uint32 buf_state;
4179 
4180  /*
4181  * Since LWLockReleaseAll has already been called, we're not holding
4182  * the buffer's io_in_progress_lock. We have to re-acquire it so that
4183  * we can use TerminateBufferIO. Anyone who's executing WaitIO on the
4184  * buffer will be in a busy spin until we succeed in doing this.
4185  */
4187 
4188  buf_state = LockBufHdr(buf);
4189  Assert(buf_state & BM_IO_IN_PROGRESS);
4190  if (IsForInput)
4191  {
4192  Assert(!(buf_state & BM_DIRTY));
4193 
4194  /* We'd better not think buffer is valid yet */
4195  Assert(!(buf_state & BM_VALID));
4196  UnlockBufHdr(buf, buf_state);
4197  }
4198  else
4199  {
4200  Assert(buf_state & BM_DIRTY);
4201  UnlockBufHdr(buf, buf_state);
4202  /* Issue notice if this is not the first failure... */
4203  if (buf_state & BM_IO_ERROR)
4204  {
4205  /* Buffer is pinned, so we can read tag without spinlock */
4206  char *path;
4207 
4208  path = relpathperm(buf->tag.rnode, buf->tag.forkNum);
4209  ereport(WARNING,
4210  (errcode(ERRCODE_IO_ERROR),
4211  errmsg("could not write block %u of %s",
4212  buf->tag.blockNum, path),
4213  errdetail("Multiple failures --- write error might be permanent.")));
4214  pfree(path);
4215  }
4216  }
4217  TerminateBufferIO(buf, false, BM_IO_ERROR);
4218  }
4219 }
#define relpathperm(rnode, forknum)
Definition: relpath.h:83
ForkNumber forkNum
Definition: buf_internals.h:93
int errcode(int sqlerrcode)
Definition: elog.c:610
#define BM_DIRTY
Definition: buf_internals.h:58
#define BufferDescriptorGetIOLock(bdesc)
static BufferDesc * InProgressBuf
Definition: bufmgr.c:152
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:957
unsigned int uint32
Definition: c.h:374
static bool IsForInput
Definition: bufmgr.c:153
#define WARNING
Definition: elog.h:40
static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits)
Definition: bufmgr.c:4140
#define BM_VALID
Definition: buf_internals.h:59
#define ereport(elevel,...)
Definition: elog.h:144
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4290
#define Assert(condition)
Definition: c.h:745
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
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:824
#define UnlockBufHdr(desc, s)
#define BM_IO_IN_PROGRESS
Definition: buf_internals.h:61

◆ AtEOXact_Buffers()

void AtEOXact_Buffers ( bool  isCommit)

Definition at line 2443 of file bufmgr.c.

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

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

2444 {
2446 
2447  AtEOXact_LocalBuffers(isCommit);
2448 
2450 }
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:190
#define Assert(condition)
Definition: c.h:745
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:2518
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:578

◆ AtProcExit_LocalBuffers()

void AtProcExit_LocalBuffers ( void  )

Definition at line 589 of file localbuf.c.

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

590 {
591  /*
592  * We shouldn't be holding any remaining pins; if we are, and assertions
593  * aren't enabled, we'll fail later in DropRelFileNodeBuffers while trying
594  * to drop the temp rels.
595  */
597 }
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:549

◆ BgBufferSync()

bool BgBufferSync ( struct WritebackContext wb_context)

Definition at line 2073 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().

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

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)

Definition at line 2633 of file bufmgr.c.

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

Referenced by _bt_check_unique(), _bt_checkpage(), _bt_delitems_vacuum(), _bt_doinsert(), _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_doinsert(), _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(), createPostingTree(), dataBeginPlaceToPageLeaf(), dataPrepareDownlink(), doPickSplit(), entryPrepareDownlink(), fill_seq_with_data(), ginEntryInsert(), ginFindParents(), ginFinishSplit(), ginPlaceToPage(), ginRedoDeleteListPages(), ginRedoUpdateMetapage(), ginScanToDelete(), gistbufferinginserttuples(), gistbuild(), gistcheckpage(), gistdeletepage(), gistformdownlink(), gistinserttuples(), 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().

2634 {
2635  BufferDesc *bufHdr;
2636 
2637  Assert(BufferIsPinned(buffer));
2638 
2639  if (BufferIsLocal(buffer))
2640  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2641  else
2642  bufHdr = GetBufferDescriptor(buffer - 1);
2643 
2644  /* pinned, so OK to read tag without spinlock */
2645  return bufHdr->tag.blockNum;
2646 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:439
#define GetLocalBufferDescriptor(id)
#define GetBufferDescriptor(id)
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
BlockNumber blockNum
Definition: buf_internals.h:94
BufferTag tag

◆ BufferGetLSNAtomic()

XLogRecPtr BufferGetLSNAtomic ( Buffer  buffer)

Definition at line 2896 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().

2897 {
2898  BufferDesc *bufHdr = GetBufferDescriptor(buffer - 1);
2899  char *page = BufferGetPage(buffer);
2900  XLogRecPtr lsn;
2901  uint32 buf_state;
2902 
2903  /*
2904  * If we don't need locking for correctness, fastpath out.
2905  */
2906  if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
2907  return PageGetLSN(page);
2908 
2909  /* Make sure we've got a real buffer, and that we hold a pin on it. */
2910  Assert(BufferIsValid(buffer));
2911  Assert(BufferIsPinned(buffer));
2912 
2913  buf_state = LockBufHdr(bufHdr);
2914  lsn = PageGetLSN(page);
2915  UnlockBufHdr(bufHdr, buf_state);
2916 
2917  return lsn;
2918 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:439
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:374
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4290
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define PageGetLSN(page)
Definition: bufpage.h:366
#define UnlockBufHdr(desc, s)
#define XLogHintBitIsNeeded()
Definition: xlog.h:202

◆ BufferGetTag()

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

Definition at line 2654 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().

2656 {
2657  BufferDesc *bufHdr;
2658 
2659  /* Do the same checks as BufferGetBlockNumber. */
2660  Assert(BufferIsPinned(buffer));
2661 
2662  if (BufferIsLocal(buffer))
2663  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2664  else
2665  bufHdr = GetBufferDescriptor(buffer - 1);
2666 
2667  /* pinned, so OK to read tag without spinlock */
2668  *rnode = bufHdr->tag.rnode;
2669  *forknum = bufHdr->tag.forkNum;
2670  *blknum = bufHdr->tag.blockNum;
2671 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:439
ForkNumber forkNum
Definition: buf_internals.h:93
#define GetLocalBufferDescriptor(id)
#define GetBufferDescriptor(id)
#define Assert(condition)
Definition: c.h:745
#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 2866 of file bufmgr.c.

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

Referenced by SetHintBits().

2867 {
2868  BufferDesc *bufHdr;
2869 
2870  /* Local buffers are used only for temp relations. */
2871  if (BufferIsLocal(buffer))
2872  return false;
2873 
2874  /* Make sure we've got a real buffer, and that we hold a pin on it. */
2875  Assert(BufferIsValid(buffer));
2876  Assert(BufferIsPinned(buffer));
2877 
2878  /*
2879  * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
2880  * need not bother with the buffer header spinlock. Even if someone else
2881  * changes the buffer header state while we're doing this, the state is
2882  * changed atomically, so we'll read the old value or the new value, but
2883  * not random garbage.
2884  */
2885  bufHdr = GetBufferDescriptor(buffer - 1);
2886  return (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT) != 0;
2887 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:439
#define BM_PERMANENT
Definition: buf_internals.h:66
#define GetBufferDescriptor(id)
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
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 157 of file buf_init.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ BufmgrCommit()

void BufmgrCommit ( void  )

Definition at line 2619 of file bufmgr.c.

Referenced by PrepareTransaction(), and RecordTransactionCommit().

2620 {
2621  /* Nothing to do in bufmgr anymore... */
2622 }

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)

Definition at line 2602 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().

2603 {
2604  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_START(flags);
2606  BufferSync(flags);
2608  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_SYNC_START();
2611  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_DONE();
2612 }
void ProcessSyncRequests(void)
Definition: sync.c:236
TimestampTz ckpt_sync_end_t
Definition: xlog.h:248
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
static void BufferSync(int flags)
Definition: bufmgr.c:1796
CheckpointStatsData CheckpointStats
Definition: xlog.c:185
TimestampTz ckpt_write_t
Definition: xlog.h:246
TimestampTz ckpt_sync_t
Definition: xlog.h:247

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

Definition at line 3748 of file bufmgr.c.

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

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

3749 {
3750  BufferDesc *buf;
3751 
3752  Assert(BufferIsValid(buffer));
3753  if (BufferIsLocal(buffer))
3754  return true; /* act as though we got it */
3755 
3756  buf = GetBufferDescriptor(buffer - 1);
3757 
3759  LW_EXCLUSIVE);
3760 }
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1380
static char * buf
Definition: pg_test_fsync.c:67
#define GetBufferDescriptor(id)
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123

◆ ConditionalLockBufferForCleanup()

bool ConditionalLockBufferForCleanup ( Buffer  buffer)

Definition at line 3916 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().

3917 {
3918  BufferDesc *bufHdr;
3919  uint32 buf_state,
3920  refcount;
3921 
3922  Assert(BufferIsValid(buffer));
3923 
3924  if (BufferIsLocal(buffer))
3925  {
3926  refcount = LocalRefCount[-buffer - 1];
3927  /* There should be exactly one pin */
3928  Assert(refcount > 0);
3929  if (refcount != 1)
3930  return false;
3931  /* Nobody else to wait for */
3932  return true;
3933  }
3934 
3935  /* There should be exactly one local pin */
3936  refcount = GetPrivateRefCount(buffer);
3937  Assert(refcount);
3938  if (refcount != 1)
3939  return false;
3940 
3941  /* Try to acquire lock */
3942  if (!ConditionalLockBuffer(buffer))
3943  return false;
3944 
3945  bufHdr = GetBufferDescriptor(buffer - 1);
3946  buf_state = LockBufHdr(bufHdr);
3947  refcount = BUF_STATE_GET_REFCOUNT(buf_state);
3948 
3949  Assert(refcount > 0);
3950  if (refcount == 1)
3951  {
3952  /* Successfully acquired exclusive lock with pincount 1 */
3953  UnlockBufHdr(bufHdr, buf_state);
3954  return true;
3955  }
3956 
3957  /* Failed, so release the lock */
3958  UnlockBufHdr(bufHdr, buf_state);
3959  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3960  return false;
3961 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:96
#define GetBufferDescriptor(id)
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:378
unsigned int uint32
Definition: c.h:374
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:3748
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3722
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4290
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#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 3119 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().

3120 {
3121  int i;
3122 
3123  /*
3124  * We needn't consider local buffers, since by assumption the target
3125  * database isn't our own.
3126  */
3127 
3128  for (i = 0; i < NBuffers; i++)
3129  {
3130  BufferDesc *bufHdr = GetBufferDescriptor(i);
3131  uint32 buf_state;
3132 
3133  /*
3134  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3135  * and saves some cycles.
3136  */
3137  if (bufHdr->tag.rnode.dbNode != dbid)
3138  continue;
3139 
3140  buf_state = LockBufHdr(bufHdr);
3141  if (bufHdr->tag.rnode.dbNode == dbid)
3142  InvalidateBuffer(bufHdr); /* releases spinlock */
3143  else
3144  UnlockBufHdr(bufHdr, buf_state);
3145  }
3146 }
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1370
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:374
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4290
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 2947 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().

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

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

Referenced by smgrdounlinkall().

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

3421 {
3422  int i;
3423  BufferDesc *bufHdr;
3424 
3425  /* Make sure we can handle the pin inside the loop */
3427 
3428  for (i = 0; i < NBuffers; i++)
3429  {
3430  uint32 buf_state;
3431 
3432  bufHdr = GetBufferDescriptor(i);
3433 
3434  /*
3435  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3436  * and saves some cycles.
3437  */
3438  if (bufHdr->tag.rnode.dbNode != dbid)
3439  continue;
3440 
3442 
3443  buf_state = LockBufHdr(bufHdr);
3444  if (bufHdr->tag.rnode.dbNode == dbid &&
3445  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3446  {
3447  PinBuffer_Locked(bufHdr);
3449  FlushBuffer(bufHdr, NULL);
3451  UnpinBuffer(bufHdr, true);
3452  }
3453  else
3454  UnlockBufHdr(bufHdr, buf_state);
3455  }
3456 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
#define BM_DIRTY
Definition: buf_internals.h:58
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln)
Definition: bufmgr.c:2693
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:374
static void UnpinBuffer(BufferDesc *buf, bool fixOwner)
Definition: bufmgr.c:1712
void ResourceOwnerEnlargeBuffers(ResourceOwner owner)
Definition: resowner.c:917
#define BM_VALID
Definition: buf_internals.h:59
#define BufferDescriptorGetContentLock(bdesc)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4290
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:1674
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
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:206

◆ FlushOneBuffer()

void FlushOneBuffer ( Buffer  buffer)

Definition at line 3463 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().

3464 {
3465  BufferDesc *bufHdr;
3466 
3467  /* currently not needed, but no fundamental reason not to support */
3468  Assert(!BufferIsLocal(buffer));
3469 
3470  Assert(BufferIsPinned(buffer));
3471 
3472  bufHdr = GetBufferDescriptor(buffer - 1);
3473 
3475 
3476  FlushBuffer(bufHdr, NULL);
3477 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:439
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln)
Definition: bufmgr.c:2693
#define GetBufferDescriptor(id)
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37

◆ FlushRelationBuffers()

void FlushRelationBuffers ( Relation  rel)

Definition at line 3224 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 heapam_relation_copy_data(), and index_copy_data().

3225 {
3226  int i;
3227  BufferDesc *bufHdr;
3228 
3229  /* Open rel at the smgr level if not already done */
3230  RelationOpenSmgr(rel);
3231 
3232  if (RelationUsesLocalBuffers(rel))
3233  {
3234  for (i = 0; i < NLocBuffer; i++)
3235  {
3236  uint32 buf_state;
3237 
3238  bufHdr = GetLocalBufferDescriptor(i);
3239  if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
3240  ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
3241  (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3242  {
3243  ErrorContextCallback errcallback;
3244  Page localpage;
3245 
3246  localpage = (char *) LocalBufHdrGetBlock(bufHdr);
3247 
3248  /* Setup error traceback support for ereport() */
3250  errcallback.arg = (void *) bufHdr;
3251  errcallback.previous = error_context_stack;
3252  error_context_stack = &errcallback;
3253 
3254  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
3255 
3256  smgrwrite(rel->rd_smgr,
3257  bufHdr->tag.forkNum,
3258  bufHdr->tag.blockNum,
3259  localpage,
3260  false);
3261 
3262  buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED);
3263  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
3264 
3265  /* Pop the error context stack */
3266  error_context_stack = errcallback.previous;
3267  }
3268  }
3269 
3270  return;
3271  }
3272 
3273  /* Make sure we can handle the pin inside the loop */
3275 
3276  for (i = 0; i < NBuffers; i++)
3277  {
3278  uint32 buf_state;
3279 
3280  bufHdr = GetBufferDescriptor(i);
3281 
3282  /*
3283  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3284  * and saves some cycles.
3285  */
3286  if (!RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
3287  continue;
3288 
3290 
3291  buf_state = LockBufHdr(bufHdr);
3292  if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
3293  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3294  {
3295  PinBuffer_Locked(bufHdr);
3297  FlushBuffer(bufHdr, rel->rd_smgr);
3299  UnpinBuffer(bufHdr, true);
3300  }
3301  else
3302  UnlockBufHdr(bufHdr, buf_state);
3303  }
3304 }
#define LocalBufHdrGetBlock(bufHdr)
Definition: bufmgr.c:63
ForkNumber forkNum
Definition: buf_internals.h:93
static void local_buffer_write_error_callback(void *arg)
Definition: bufmgr.c:4244
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:229
struct ErrorContextCallback * previous
Definition: elog.h:228
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln)
Definition: bufmgr.c:2693
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
ErrorContextCallback * error_context_stack
Definition: elog.c:92
#define RelationOpenSmgr(relation)
Definition: rel.h:513
int NLocBuffer
Definition: localbuf.c:41
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:513
#define GetBufferDescriptor(id)
#define BM_JUST_DIRTIED
Definition: buf_internals.h:63
unsigned int uint32
Definition: c.h:374
static void UnpinBuffer(BufferDesc *buf, bool fixOwner)
Definition: bufmgr.c:1712
void ResourceOwnerEnlargeBuffers(ResourceOwner owner)
Definition: resowner.c:917
#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:4290
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:1674
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1194
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
BlockNumber blockNum
Definition: buf_internals.h:94
RelFileNode rnode
Definition: buf_internals.h:92
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:572
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:206
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

◆ FlushRelationsAllBuffers()

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

◆ 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:927
#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:214
int NBuffers
Definition: globals.c:131
int Buffer
Definition: buf.h:23
#define offsetof(type, field)
Definition: c.h:668

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )

Definition at line 3890 of file bufmgr.c.

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and RecoveryConflictInterrupt().

3891 {
3892  int bufid = GetStartupBufferPinWaitBufId();
3893 
3894  /*
3895  * If we get woken slowly then it's possible that the Startup process was
3896  * already woken by other backends before we got here. Also possible that
3897  * we get here by multiple interrupts or interrupts at inappropriate
3898  * times, so make sure we do nothing if the bufid is not set.
3899  */
3900  if (bufid < 0)
3901  return false;
3902 
3903  if (GetPrivateRefCount(bufid + 1) > 0)
3904  return true;
3905 
3906  return false;
3907 }
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:378
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:657

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

Definition at line 3521 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().

3522 {
3523  Assert(BufferIsPinned(buffer));
3525  if (BufferIsLocal(buffer))
3526  LocalRefCount[-buffer - 1]++;
3527  else
3528  {
3529  PrivateRefCountEntry *ref;
3530 
3531  ref = GetPrivateRefCountEntry(buffer, true);
3532  Assert(ref != NULL);
3533  ref->refcount++;
3534  }
3536 }
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition: bufmgr.c:298
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:439
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:930
void ResourceOwnerEnlargeBuffers(ResourceOwner owner)
Definition: resowner.c:917
#define Assert(condition)
Definition: c.h:745
#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(), LWTRANCHE_BUFFER_CONTENT, LWTRANCHE_BUFFER_IO, 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 
90  /*
91  * The array used to sort to-be-checkpointed buffer ids is located in
92  * shared memory, to avoid having to allocate significant amounts of
93  * memory at runtime. As that'd be in the middle of a checkpoint, or when
94  * the checkpointer is restarted, memory allocation failures would be
95  * painful.
96  */
98  ShmemInitStruct("Checkpoint BufferIds",
99  NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
100 
101  if (foundDescs || foundBufs || foundIOLocks || foundBufCkpt)
102  {
103  /* should find all of these, or none of them */
104  Assert(foundDescs && foundBufs && foundIOLocks && foundBufCkpt);
105  /* note: this path is only taken in EXEC_BACKEND case */
106  }
107  else
108  {
109  int i;
110 
111  /*
112  * Initialize all the buffer headers.
113  */
114  for (i = 0; i < NBuffers; i++)
115  {
117 
118  CLEAR_BUFFERTAG(buf->tag);
119 
120  pg_atomic_init_u32(&buf->state, 0);
121  buf->wait_backend_pid = 0;
122 
123  buf->buf_id = i;
124 
125  /*
126  * Initially link all the buffers together as unused. Subsequent
127  * management of this list is done by freelist.c.
128  */
129  buf->freeNext = i + 1;
130 
133 
136  }
137 
138  /* Correct last entry of linked list */
139  GetBufferDescriptor(NBuffers - 1)->freeNext = FREENEXT_END_OF_LIST;
140  }
141 
142  /* Init other shared buffer-management stuff */
143  StrategyInitialize(!foundDescs);
144 
145  /* Initialize per-backend file flush context */
148 }
#define FREENEXT_END_OF_LIST
LWLockMinimallyPadded * BufferIOLWLockArray
Definition: buf_init.c:22
int wait_backend_pid
int backend_flush_after
Definition: bufmgr.c:149
#define BufferDescriptorGetIOLock(bdesc)
void StrategyInitialize(bool init)
Definition: freelist.c:475
void WritebackContextInit(WritebackContext *context, int *max_pending)
Definition: bufmgr.c:4430
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:745
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:745
#define CLEAR_BUFFERTAG(a)
Definition: buf_internals.h:97
CkptSortItem * CkptBufferIds
Definition: buf_init.c:24
size_t Size
Definition: c.h:473
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 2465 of file bufmgr.c.

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

Referenced by BaseInit().

2466 {
2467  HASHCTL hash_ctl;
2468 
2469  memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
2470 
2471  MemSet(&hash_ctl, 0, sizeof(hash_ctl));
2472  hash_ctl.keysize = sizeof(int32);
2473  hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
2474 
2475  PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
2476  HASH_ELEM | HASH_BLOBS);
2477 }
struct PrivateRefCountEntry PrivateRefCountEntry
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:978
signed int int32
Definition: c.h:362
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition: bufmgr.c:188
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:318
Size keysize
Definition: hsearch.h:72
static HTAB * PrivateRefCountHash
Definition: bufmgr.c:189

◆ InitBufferPoolBackend()

void InitBufferPoolBackend ( void  )

Definition at line 2489 of file bufmgr.c.

References AtProcExit_Buffers(), and on_shmem_exit().

Referenced by AuxiliaryProcessMain(), and InitPostgres().

2490 {
2492 }
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:2499

◆ IsBufferCleanupOK()

bool IsBufferCleanupOK ( Buffer  buffer)

Definition at line 3972 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().

3973 {
3974  BufferDesc *bufHdr;
3975  uint32 buf_state;
3976 
3977  Assert(BufferIsValid(buffer));
3978 
3979  if (BufferIsLocal(buffer))
3980  {
3981  /* There should be exactly one pin */
3982  if (LocalRefCount[-buffer - 1] != 1)
3983  return false;
3984  /* Nobody else to wait for */
3985  return true;
3986  }
3987 
3988  /* There should be exactly one local pin */
3989  if (GetPrivateRefCount(buffer) != 1)
3990  return false;
3991 
3992  bufHdr = GetBufferDescriptor(buffer - 1);
3993 
3994  /* caller must hold exclusive lock on buffer */
3996  LW_EXCLUSIVE));
3997 
3998  buf_state = LockBufHdr(bufHdr);
3999 
4000  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
4001  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
4002  {
4003  /* pincount is OK. */
4004  UnlockBufHdr(bufHdr, buf_state);
4005  return true;
4006  }
4007 
4008  UnlockBufHdr(bufHdr, buf_state);
4009  return false;
4010 }
bool LWLockHeldByMeInMode(LWLock *l, LWLockMode mode)
Definition: lwlock.c:1946
#define GetBufferDescriptor(id)
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:378
unsigned int uint32
Definition: c.h:374
#define BufferDescriptorGetContentLock(bdesc)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4290
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#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 3722 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().

3723 {
3724  BufferDesc *buf;
3725 
3726  Assert(BufferIsValid(buffer));
3727  if (BufferIsLocal(buffer))
3728  return; /* local buffers need no lock */
3729 
3730  buf = GetBufferDescriptor(buffer - 1);
3731 
3732  if (mode == BUFFER_LOCK_UNLOCK)
3734  else if (mode == BUFFER_LOCK_SHARE)
3736  else if (mode == BUFFER_LOCK_EXCLUSIVE)
3738  else
3739  elog(ERROR, "unrecognized buffer lock mode: %d", mode);
3740 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:96
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#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:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define elog(elevel,...)
Definition: elog.h:214
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:97

◆ LockBufferForCleanup()

void LockBufferForCleanup ( Buffer  buffer)

Definition at line 3779 of file bufmgr.c.

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

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

3780 {
3781  BufferDesc *bufHdr;
3782  char *new_status = NULL;
3783 
3784  Assert(BufferIsValid(buffer));
3785  Assert(PinCountWaitBuf == NULL);
3786 
3787  if (BufferIsLocal(buffer))
3788  {
3789  /* There should be exactly one pin */
3790  if (LocalRefCount[-buffer - 1] != 1)
3791  elog(ERROR, "incorrect local pin count: %d",
3792  LocalRefCount[-buffer - 1]);
3793  /* Nobody else to wait for */
3794  return;
3795  }
3796 
3797  /* There should be exactly one local pin */
3798  if (GetPrivateRefCount(buffer) != 1)
3799  elog(ERROR, "incorrect local pin count: %d",
3800  GetPrivateRefCount(buffer));
3801 
3802  bufHdr = GetBufferDescriptor(buffer - 1);
3803 
3804  for (;;)
3805  {
3806  uint32 buf_state;
3807 
3808  /* Try to acquire lock */
3810  buf_state = LockBufHdr(bufHdr);
3811 
3812  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
3813  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
3814  {
3815  /* Successfully acquired exclusive lock with pincount 1 */
3816  UnlockBufHdr(bufHdr, buf_state);
3817 
3818  /* Report change to non-waiting status */
3819  if (new_status)
3820  {
3821  set_ps_display(new_status);
3822  pfree(new_status);
3823  }
3824  return;
3825  }
3826  /* Failed, so mark myself as waiting for pincount 1 */
3827  if (buf_state & BM_PIN_COUNT_WAITER)
3828  {
3829  UnlockBufHdr(bufHdr, buf_state);
3830  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3831  elog(ERROR, "multiple backends attempting to wait for pincount 1");
3832  }
3833  bufHdr->wait_backend_pid = MyProcPid;
3834  PinCountWaitBuf = bufHdr;
3835  buf_state |= BM_PIN_COUNT_WAITER;
3836  UnlockBufHdr(bufHdr, buf_state);
3837  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3838 
3839  /* Wait to be signaled by UnpinBuffer() */
3840  if (InHotStandby)
3841  {
3842  /* Report change to waiting status */
3843  if (update_process_title && new_status == NULL)
3844  {
3845  const char *old_status;
3846  int len;
3847 
3848  old_status = get_ps_display(&len);
3849  new_status = (char *) palloc(len + 8 + 1);
3850  memcpy(new_status, old_status, len);
3851  strcpy(new_status + len, " waiting");
3852  set_ps_display(new_status);
3853  new_status[len] = '\0'; /* truncate off " waiting" */
3854  }
3855 
3856  /* Publish the bufid that Startup process waits on */
3857  SetStartupBufferPinWaitBufId(buffer - 1);
3858  /* Set alarm and then wait to be signaled by UnpinBuffer() */
3860  /* Reset the published bufid */
3862  }
3863  else
3865 
3866  /*
3867  * Remove flag marking us as waiter. Normally this will not be set
3868  * anymore, but ProcWaitForSignal() can return for other signals as
3869  * well. We take care to only reset the flag if we're the waiter, as
3870  * theoretically another backend could have started waiting. That's
3871  * impossible with the current usages due to table level locking, but
3872  * better be safe.
3873  */
3874  buf_state = LockBufHdr(bufHdr);
3875  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
3876  bufHdr->wait_backend_pid == MyProcPid)
3877  buf_state &= ~BM_PIN_COUNT_WAITER;
3878  UnlockBufHdr(bufHdr, buf_state);
3879 
3880  PinCountWaitBuf = NULL;
3881  /* Loop back and try again */
3882  }
3883 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:96
int MyProcPid
Definition: globals.c:40
int wait_backend_pid
bool update_process_title
Definition: ps_status.c:36
#define InHotStandby
Definition: xlog.h:74
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:98
void set_ps_display(const char *activity)
Definition: ps_status.c:349
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
void ResolveRecoveryConflictWithBufferPin(void)
Definition: standby.c:483
const char * get_ps_display(int *displen)
Definition: ps_status.c:430
void SetStartupBufferPinWaitBufId(int bufid)
Definition: proc.c:645
#define GetBufferDescriptor(id)
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:378
unsigned int uint32
Definition: c.h:374
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1800
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3722
#define PG_WAIT_BUFFER_PIN
Definition: pgstat.h:786
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4290
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
void * palloc(Size size)
Definition: mcxt.c:949
#define UnlockBufHdr(desc, s)
#define elog(elevel,...)
Definition: elog.h:214
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:156
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 1468 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_dedup_one_page(), _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_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), createPostingTree(), 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().

1469 {
1470  BufferDesc *bufHdr;
1471  uint32 buf_state;
1472  uint32 old_buf_state;
1473 
1474  if (!BufferIsValid(buffer))
1475  elog(ERROR, "bad buffer ID: %d", buffer);
1476 
1477  if (BufferIsLocal(buffer))
1478  {
1479  MarkLocalBufferDirty(buffer);
1480  return;
1481  }
1482 
1483  bufHdr = GetBufferDescriptor(buffer - 1);
1484 
1485  Assert(BufferIsPinned(buffer));
1487  LW_EXCLUSIVE));
1488 
1489  old_buf_state = pg_atomic_read_u32(&bufHdr->state);
1490  for (;;)
1491  {
1492  if (old_buf_state & BM_LOCKED)
1493  old_buf_state = WaitBufHdrUnlocked(bufHdr);
1494 
1495  buf_state = old_buf_state;
1496 
1497  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
1498  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
1499 
1500  if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
1501  buf_state))
1502  break;
1503  }
1504 
1505  /*
1506  * If the buffer was not dirty already, do vacuum accounting.
1507  */
1508  if (!(old_buf_state & BM_DIRTY))
1509  {
1510  VacuumPageDirty++;
1512  if (VacuumCostActive)
1514  }
1515 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:439
bool LWLockHeldByMeInMode(LWLock *l, LWLockMode mode)
Definition: lwlock.c:1946
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
int64 VacuumPageDirty
Definition: globals.c:145
#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:374
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:286
#define BM_LOCKED
Definition: buf_internals.h:57
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
static uint32 WaitBufHdrUnlocked(BufferDesc *buf)
Definition: bufmgr.c:4318
#define elog(elevel,...)
Definition: elog.h:214
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 3553 of file bufmgr.c.

References Assert, BM_DIRTY, BM_JUST_DIRTIED, BM_PERMANENT, BUF_STATE_GET_REFCOUNT, BufferDescriptorGetContentLock, BufferGetPage, BufferIsLocal, BufferIsValid, PGPROC::delayChkpt, elog, ERROR, GetBufferDescriptor, GetPrivateRefCount(), InvalidXLogRecPtr, LockBufHdr(), LWLockHeldByMe(), MarkLocalBufferDirty(), MyProc, PageSetLSN, pg_atomic_read_u32(), pgBufferUsage, RecoveryInProgress(), RelFileNodeSkippingWAL(), buftag::rnode, BufferUsage::shared_blks_dirtied, BufferDesc::state, BufferDesc::tag, 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().

3554 {
3555  BufferDesc *bufHdr;
3556  Page page = BufferGetPage(buffer);
3557 
3558  if (!BufferIsValid(buffer))
3559  elog(ERROR, "bad buffer ID: %d", buffer);
3560 
3561  if (BufferIsLocal(buffer))
3562  {
3563  MarkLocalBufferDirty(buffer);
3564  return;
3565  }
3566 
3567  bufHdr = GetBufferDescriptor(buffer - 1);
3568 
3569  Assert(GetPrivateRefCount(buffer) > 0);
3570  /* here, either share or exclusive lock is OK */
3572 
3573  /*
3574  * This routine might get called many times on the same page, if we are
3575  * making the first scan after commit of an xact that added/deleted many
3576  * tuples. So, be as quick as we can if the buffer is already dirty. We
3577  * do this by not acquiring spinlock if it looks like the status bits are
3578  * already set. Since we make this test unlocked, there's a chance we
3579  * might fail to notice that the flags have just been cleared, and failed
3580  * to reset them, due to memory-ordering issues. But since this function
3581  * is only intended to be used in cases where failing to write out the
3582  * data would be harmless anyway, it doesn't really matter.
3583  */
3584  if ((pg_atomic_read_u32(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
3586  {
3588  bool dirtied = false;
3589  bool delayChkpt = false;
3590  uint32 buf_state;
3591 
3592  /*
3593  * If we need to protect hint bit updates from torn writes, WAL-log a
3594  * full page image of the page. This full page image is only necessary
3595  * if the hint bit update is the first change to the page since the
3596  * last checkpoint.
3597  *
3598  * We don't check full_page_writes here because that logic is included
3599  * when we call XLogInsert() since the value changes dynamically.
3600  */
3601  if (XLogHintBitIsNeeded() &&
3602  (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT))
3603  {
3604  /*
3605  * If we must not write WAL, due to a relfilenode-specific
3606  * condition or being in recovery, don't dirty the page. We can
3607  * set the hint, just not dirty the page as a result so the hint
3608  * is lost when we evict the page or shutdown.
3609  *
3610  * See src/backend/storage/page/README for longer discussion.
3611  */
3612  if (RecoveryInProgress() ||
3613  RelFileNodeSkippingWAL(bufHdr->tag.rnode))
3614  return;
3615 
3616  /*
3617  * If the block is already dirty because we either made a change
3618  * or set a hint already, then we don't need to write a full page
3619  * image. Note that aggressive cleaning of blocks dirtied by hint
3620  * bit setting would increase the call rate. Bulk setting of hint
3621  * bits would reduce the call rate...
3622  *
3623  * We must issue the WAL record before we mark the buffer dirty.
3624  * Otherwise we might write the page before we write the WAL. That
3625  * causes a race condition, since a checkpoint might occur between
3626  * writing the WAL record and marking the buffer dirty. We solve
3627  * that with a kluge, but one that is already in use during
3628  * transaction commit to prevent race conditions. Basically, we
3629  * simply prevent the checkpoint WAL record from being written
3630  * until we have marked the buffer dirty. We don't start the
3631  * checkpoint flush until we have marked dirty, so our checkpoint
3632  * must flush the change to disk successfully or the checkpoint
3633  * never gets written, so crash recovery will fix.
3634  *
3635  * It's possible we may enter here without an xid, so it is
3636  * essential that CreateCheckpoint waits for virtual transactions
3637  * rather than full transactionids.
3638  */
3639  MyProc->delayChkpt = delayChkpt = true;
3640  lsn = XLogSaveBufferForHint(buffer, buffer_std);
3641  }
3642 
3643  buf_state = LockBufHdr(bufHdr);
3644 
3645  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
3646 
3647  if (!(buf_state & BM_DIRTY))
3648  {
3649  dirtied = true; /* Means "will be dirtied by this action" */
3650 
3651  /*
3652  * Set the page LSN if we wrote a backup block. We aren't supposed
3653  * to set this when only holding a share lock but as long as we
3654  * serialise it somehow we're OK. We choose to set LSN while
3655  * holding the buffer header lock, which causes any reader of an
3656  * LSN who holds only a share lock to also obtain a buffer header
3657  * lock before using PageGetLSN(), which is enforced in
3658  * BufferGetLSNAtomic().
3659  *
3660  * If checksums are enabled, you might think we should reset the
3661  * checksum here. That will happen when the page is written
3662  * sometime later in this checkpoint cycle.
3663  */
3664  if (!XLogRecPtrIsInvalid(lsn))
3665  PageSetLSN(page, lsn);
3666  }
3667 
3668  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
3669  UnlockBufHdr(bufHdr, buf_state);
3670 
3671  if (delayChkpt)
3672  MyProc->delayChkpt = false;
3673 
3674  if (dirtied)
3675  {
3676  VacuumPageDirty++;
3678  if (VacuumCostActive)
3680  }
3681  }
3682 }
#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:1928
PGPROC * MyProc
Definition: proc.c:67
XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
Definition: xloginsert.c:898
int64 VacuumPageDirty
Definition: globals.c:145
bool RecoveryInProgress(void)
Definition: xlog.c:8072
#define BM_DIRTY
Definition: buf_internals.h:58
int VacuumCostPageDirty
Definition: globals.c:139
#define ERROR
Definition: elog.h:43
bool delayChkpt
Definition: proc.h:152
#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:378
unsigned int uint32
Definition: c.h:374
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:286
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define BufferDescriptorGetContentLock(bdesc)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4290
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
RelFileNode rnode
Definition: buf_internals.h:92
bool RelFileNodeSkippingWAL(RelFileNode rnode)
Definition: storage.c:496
BufferTag tag
#define UnlockBufHdr(desc, s)
#define elog(elevel,...)
Definition: elog.h:214
pg_atomic_uint32 state
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
#define XLogHintBitIsNeeded()
Definition: xlog.h:202
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()

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

Definition at line 574 of file bufmgr.c.

References Assert, BlockNumberIsValid, ereport, errcode(), errmsg(), ERROR, PrefetchLocalBuffer(), PrefetchSharedBuffer(), RelationData::rd_smgr, RELATION_IS_OTHER_TEMP, RelationIsValid, RelationOpenSmgr, and RelationUsesLocalBuffers.

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

575 {
576  Assert(RelationIsValid(reln));
577  Assert(BlockNumberIsValid(blockNum));
578 
579  /* Open it at the smgr level if not already done */
580  RelationOpenSmgr(reln);
581 
582  if (RelationUsesLocalBuffers(reln))
583  {
584  /* see comments in ReadBufferExtended */
585  if (RELATION_IS_OTHER_TEMP(reln))
586  ereport(ERROR,
587  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
588  errmsg("cannot access temporary tables of other sessions")));
589 
590  /* pass it off to localbuf.c */
591  return PrefetchLocalBuffer(reln->rd_smgr, forkNum, blockNum);
592  }
593  else
594  {
595  /* pass it to the shared buffer version */
596  return PrefetchSharedBuffer(reln->rd_smgr, forkNum, blockNum);
597  }
598 }
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition: localbuf.c:64
int errcode(int sqlerrcode)
Definition: elog.c:610
#define RelationOpenSmgr(relation)
Definition: rel.h:513
#define ERROR
Definition: elog.h:43
#define RelationIsValid(relation)
Definition: rel.h:429
PrefetchBufferResult PrefetchSharedBuffer(SMgrRelation smgr_reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:487
#define ereport(elevel,...)
Definition: elog.h:144
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
#define Assert(condition)
Definition: c.h:745
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:593
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:572
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ PrefetchSharedBuffer()

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

◆ PrintBufferLeakWarning()

void PrintBufferLeakWarning ( Buffer  buffer)

Definition at line 2559 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().

2560 {
2561  BufferDesc *buf;
2562  int32 loccount;
2563  char *path;
2564  BackendId backend;
2565  uint32 buf_state;
2566 
2567  Assert(BufferIsValid(buffer));
2568  if (BufferIsLocal(buffer))
2569  {
2570  buf = GetLocalBufferDescriptor(-buffer - 1);
2571  loccount = LocalRefCount[-buffer - 1];
2572  backend = MyBackendId;
2573  }
2574  else
2575  {
2576  buf = GetBufferDescriptor(buffer - 1);
2577  loccount = GetPrivateRefCount(buffer);
2578  backend = InvalidBackendId;
2579  }
2580 
2581  /* theoretically we should lock the bufhdr here */
2582  path = relpathbackend(buf->tag.rnode, backend, buf->tag.forkNum);
2583  buf_state = pg_atomic_read_u32(&buf->state);
2584  elog(WARNING,
2585  "buffer refcount leak: [%03d] "
2586  "(rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
2587  buffer, path,
2588  buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
2589  BUF_STATE_GET_REFCOUNT(buf_state), loccount);
2590  pfree(path);
2591 }
BackendId MyBackendId
Definition: globals.c:81
ForkNumber forkNum
Definition: buf_internals.h:93
#define GetLocalBufferDescriptor(id)
signed int int32
Definition: c.h:362
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:378
unsigned int uint32
Definition: c.h:374
#define WARNING
Definition: elog.h:40
#define InvalidBackendId
Definition: backendid.h:23
int BackendId
Definition: backendid.h:21
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
BlockNumber blockNum
Definition: buf_internals.h:94
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
RelFileNode rnode
Definition: buf_internals.h:92
BufferTag tag
#define elog(elevel,...)
Definition: elog.h:214
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 606 of file bufmgr.c.

References MAIN_FORKNUM, RBM_NORMAL, and ReadBufferExtended().

Referenced by _bt_getbuf(), _bt_search_insert(), _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(), 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().

607 {
608  return ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);
609 }
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:652

◆ ReadBufferExtended()

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

Definition at line 652 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(), log_newpage_range(), 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().

654 {
655  bool hit;
656  Buffer buf;
657 
658  /* Open it at the smgr level if not already done */
659  RelationOpenSmgr(reln);
660 
661  /*
662  * Reject attempts to read non-local temporary relations; we would be
663  * likely to get wrong data since we have no visibility into the owning
664  * session's local buffers.
665  */
666  if (RELATION_IS_OTHER_TEMP(reln))
667  ereport(ERROR,
668  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
669  errmsg("cannot access temporary tables of other sessions")));
670 
671  /*
672  * Read the buffer, and update pgstat counters to reflect a cache hit or
673  * miss.
674  */
676  buf = ReadBuffer_common(reln->rd_smgr, reln->rd_rel->relpersistence,
677  forkNum, blockNum, mode, strategy, &hit);
678  if (hit)
680  return buf;
681 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
int errcode(int sqlerrcode)
Definition: elog.c:610
Form_pg_class rd_rel
Definition: rel.h:109
#define RelationOpenSmgr(relation)
Definition: rel.h:513
#define ERROR
Definition: elog.h:43
#define pgstat_count_buffer_read(rel)
Definition: pgstat.h:1422
static char * buf
Definition: pg_test_fsync.c:67
#define pgstat_count_buffer_hit(rel)
Definition: pgstat.h:1427
static Buffer ReadBuffer_common(SMgrRelation reln, char relpersistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool *hit)
Definition: bufmgr.c:715
#define ereport(elevel,...)
Definition: elog.h:144
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:593
int errmsg(const char *fmt,...)
Definition: elog.c:824
int Buffer
Definition: buf.h:23

◆ ReadBufferWithoutRelcache()

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

Definition at line 694 of file bufmgr.c.

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

Referenced by XLogReadBufferExtended().

697 {
698  bool hit;
699 
700  SMgrRelation smgr = smgropen(rnode, InvalidBackendId);
701 
703 
704  return ReadBuffer_common(smgr, RELPERSISTENCE_PERMANENT, forkNum, blockNum,
705  mode, strategy, &hit);
706 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
bool InRecovery
Definition: xlog.c:204
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:715
#define Assert(condition)
Definition: c.h:745

◆ RelationGetNumberOfBlocksInFork()

BlockNumber RelationGetNumberOfBlocksInFork ( Relation  relation,
ForkNumber  forkNum 
)

Definition at line 2820 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().

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

◆ ReleaseAndReadBuffer()

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

Definition at line 1531 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().

1534 {
1535  ForkNumber forkNum = MAIN_FORKNUM;
1536  BufferDesc *bufHdr;
1537 
1538  if (BufferIsValid(buffer))
1539  {
1540  Assert(BufferIsPinned(buffer));
1541  if (BufferIsLocal(buffer))
1542  {
1543  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
1544  if (bufHdr->tag.blockNum == blockNum &&
1545  RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node) &&
1546  bufHdr->tag.forkNum == forkNum)
1547  return buffer;
1549  LocalRefCount[-buffer - 1]--;
1550  }
1551  else
1552  {
1553  bufHdr = GetBufferDescriptor(buffer - 1);
1554  /* we have pin, so it's ok to examine tag without spinlock */
1555  if (bufHdr->tag.blockNum == blockNum &&
1556  RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node) &&
1557  bufHdr->tag.forkNum == forkNum)
1558  return buffer;
1559  UnpinBuffer(bufHdr, true);
1560  }
1561  }
1562 
1563  return ReadBuffer(relation, blockNum);
1564 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:439
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:1712
RelFileNode rd_node
Definition: rel.h:55
#define Assert(condition)
Definition: c.h:745
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:606
#define BufferIsLocal(buffer)
Definition: buf.h:37
BlockNumber blockNum
Definition: buf_internals.h:94
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
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:939

◆ ReleaseBuffer()

void ReleaseBuffer ( Buffer  buffer)

Definition at line 3483 of file bufmgr.c.

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

Referenced by _bt_drop_lock_and_maybe_pin(), _bt_getbuf(), _bt_pagedel(), _bt_search_insert(), _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().

3484 {
3485  if (!BufferIsValid(buffer))
3486  elog(ERROR, "bad buffer ID: %d", buffer);
3487 
3488  if (BufferIsLocal(buffer))
3489  {
3491 
3492  Assert(LocalRefCount[-buffer - 1] > 0);
3493  LocalRefCount[-buffer - 1]--;
3494  return;
3495  }
3496 
3497  UnpinBuffer(GetBufferDescriptor(buffer - 1), true);
3498 }
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:1712
#define Assert(condition)
Definition: c.h:745
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define elog(elevel,...)
Definition: elog.h:214
int32 * LocalRefCount
Definition: localbuf.c:45
void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:939

◆ TestForOldSnapshot()

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

Definition at line 277 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().

278 {
279  Assert(relation != NULL);
280 
281  if (old_snapshot_threshold >= 0
282  && (snapshot) != NULL
283  && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
284  || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
285  && !XLogRecPtrIsInvalid((snapshot)->lsn)
286  && PageGetLSN(page) > (snapshot)->lsn)
287  TestForOldSnapshot_impl(snapshot, relation);
288 }
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define Assert(condition)
Definition: c.h:745
#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:4550

◆ TestForOldSnapshot_impl()

void TestForOldSnapshot_impl ( Snapshot  snapshot,
Relation  relation 
)

Definition at line 4550 of file bufmgr.c.

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

Referenced by TestForOldSnapshot().

4551 {
4552  if (RelationAllowsEarlyPruning(relation)
4553  && (snapshot)->whenTaken < GetOldSnapshotThresholdTimestamp())
4554  ereport(ERROR,
4555  (errcode(ERRCODE_SNAPSHOT_TOO_OLD),
4556  errmsg("snapshot too old")));
4557 }
TimestampTz GetOldSnapshotThresholdTimestamp(void)
Definition: snapmgr.c:1745
#define RelationAllowsEarlyPruning(rel)
Definition: snapmgr.h:38
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ UnlockBuffers()

void UnlockBuffers ( void  )

Definition at line 3694 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().

3695 {
3697 
3698  if (buf)
3699  {
3700  uint32 buf_state;
3701 
3702  buf_state = LockBufHdr(buf);
3703 
3704  /*
3705  * Don't complain if flag bit not set; it could have been reset but we
3706  * got a cancel/die interrupt before getting the signal.
3707  */
3708  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
3709  buf->wait_backend_pid == MyProcPid)
3710  buf_state &= ~BM_PIN_COUNT_WAITER;
3711 
3712  UnlockBufHdr(buf, buf_state);
3713 
3714  PinCountWaitBuf = NULL;
3715  }
3716 }
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:374
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4290
#define UnlockBufHdr(desc, s)
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:156
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:64

◆ UnlockReleaseBuffer()

void UnlockReleaseBuffer ( Buffer  buffer)

Definition at line 3506 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_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), 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().

3507 {
3508  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3509  ReleaseBuffer(buffer);
3510 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:96
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3483
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3722

Variable Documentation

◆ backend_flush_after

int backend_flush_after

Definition at line 149 of file bufmgr.c.

Referenced by InitBufferPool().

◆ bgwriter_flush_after

int bgwriter_flush_after

Definition at line 148 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

int bgwriter_lru_maxpages

Definition at line 124 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

double bgwriter_lru_multiplier

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

Referenced by BufferSync().

◆ effective_io_concurrency

int effective_io_concurrency

Definition at line 134 of file bufmgr.c.

Referenced by get_tablespace_io_concurrency(), and tablespace_reloptions().

◆ LocalBufferBlockPointers

PGDLLIMPORT Block* LocalBufferBlockPointers

Definition at line 44 of file localbuf.c.

Referenced by InitLocalBuffers().

◆ LocalRefCount

◆ maintenance_io_concurrency

int maintenance_io_concurrency

◆ NBuffers

◆ NLocBuffer

◆ track_io_timing

bool track_io_timing

Definition at line 126 of file bufmgr.c.

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

◆ zero_damaged_pages

bool zero_damaged_pages

Definition at line 123 of file bufmgr.c.

Referenced by mdread(), and ReadBuffer_common().