PostgreSQL Source Code  git master
bufmgr.h File Reference
#include "storage/block.h"
#include "storage/buf.h"
#include "storage/bufpage.h"
#include "storage/relfilenode.h"
#include "utils/relcache.h"
#include "utils/snapmgr.h"
Include dependency graph for bufmgr.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MAX_IO_CONCURRENCY   1000
 
#define P_NEW   InvalidBlockNumber /* grow the file to get a new page */
 
#define BUFFER_LOCK_UNLOCK   0
 
#define BUFFER_LOCK_SHARE   1
 
#define BUFFER_LOCK_EXCLUSIVE   2
 
#define BufferIsValid(bufnum)
 
#define BufferGetBlock(buffer)
 
#define BufferGetPageSize(buffer)
 
#define BufferGetPage(buffer)   ((Page)BufferGetBlock(buffer))
 
#define RelationGetNumberOfBlocks(reln)   RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)
 

Typedefs

typedef void * Block
 
typedef enum BufferAccessStrategyType BufferAccessStrategyType
 

Enumerations

enum  BufferAccessStrategyType { BAS_NORMAL, BAS_BULKREAD, BAS_BULKWRITE, BAS_VACUUM }
 
enum  ReadBufferMode {
  RBM_NORMAL, RBM_ZERO_AND_LOCK, RBM_ZERO_AND_CLEANUP_LOCK, RBM_ZERO_ON_ERROR,
  RBM_NORMAL_NO_LOG
}
 

Functions

void PrefetchBuffer (Relation reln, ForkNumber forkNum, BlockNumber blockNum)
 
Buffer ReadBuffer (Relation reln, BlockNumber blockNum)
 
Buffer ReadBufferExtended (Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
 
Buffer ReadBufferWithoutRelcache (RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
 
void ReleaseBuffer (Buffer buffer)
 
void UnlockReleaseBuffer (Buffer buffer)
 
void MarkBufferDirty (Buffer buffer)
 
void IncrBufferRefCount (Buffer buffer)
 
Buffer ReleaseAndReadBuffer (Buffer buffer, Relation relation, BlockNumber blockNum)
 
void InitBufferPool (void)
 
void InitBufferPoolAccess (void)
 
void InitBufferPoolBackend (void)
 
void AtEOXact_Buffers (bool isCommit)
 
void PrintBufferLeakWarning (Buffer buffer)
 
void CheckPointBuffers (int flags)
 
BlockNumber BufferGetBlockNumber (Buffer buffer)
 
BlockNumber RelationGetNumberOfBlocksInFork (Relation relation, ForkNumber forkNum)
 
void FlushOneBuffer (Buffer buffer)
 
void FlushRelationBuffers (Relation rel)
 
void FlushDatabaseBuffers (Oid dbid)
 
void DropRelFileNodeBuffers (RelFileNodeBackend rnode, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
 
void DropRelFileNodesAllBuffers (RelFileNodeBackend *rnodes, int nnodes)
 
void DropDatabaseBuffers (Oid dbid)
 
bool BufferIsPermanent (Buffer buffer)
 
XLogRecPtr BufferGetLSNAtomic (Buffer buffer)
 
Size BufferShmemSize (void)
 
void BufferGetTag (Buffer buffer, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
 
void MarkBufferDirtyHint (Buffer buffer, bool buffer_std)
 
void UnlockBuffers (void)
 
void LockBuffer (Buffer buffer, int mode)
 
bool ConditionalLockBuffer (Buffer buffer)
 
void LockBufferForCleanup (Buffer buffer)
 
bool ConditionalLockBufferForCleanup (Buffer buffer)
 
bool IsBufferCleanupOK (Buffer buffer)
 
bool HoldingBufferPinThatDelaysRecovery (void)
 
void AbortBufferIO (void)
 
void BufmgrCommit (void)
 
bool BgBufferSync (struct WritebackContext *wb_context)
 
void AtProcExit_LocalBuffers (void)
 
void TestForOldSnapshot_impl (Snapshot snapshot, Relation relation)
 
BufferAccessStrategy GetAccessStrategy (BufferAccessStrategyType btype)
 
void FreeAccessStrategy (BufferAccessStrategy strategy)
 
static void TestForOldSnapshot (Snapshot snapshot, Relation relation, Page page)
 

Variables

PGDLLIMPORT int NBuffers
 
bool zero_damaged_pages
 
int bgwriter_lru_maxpages
 
double bgwriter_lru_multiplier
 
bool track_io_timing
 
int 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 84 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:466
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
void * Block
Definition: bufmgr.h:24

Definition at line 124 of file bufmgr.h.

Referenced by XLogSaveBufferForHint().

◆ BufferGetPage

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

Definition at line 157 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_is_page_halfdead(), _bt_killitems(), _bt_lock_branch_parent(), _bt_mark_page_halfdead(), _bt_moveright(), _bt_newroot(), _bt_pagedel(), _bt_readnextpage(), _bt_readpage(), _bt_restore_meta(), _bt_search(), _bt_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 111 of file bufmgr.h.

Referenced by _bt_clear_incomplete_split(), _bt_endpoint(), _bt_first(), _bt_get_endpoint(), _bt_insertonpg(), _bt_killitems(), _bt_readpage(), _bt_relandgetbuf(), _bt_search(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_dropscanbuf(), _hash_freeovflpage(), _hash_getbucketbuf_from_hashkey(), _hash_getcachedmetap(), _hash_readnext(), _hash_readpage(), _hash_readprev(), autoprewarm_database_main(), brin_doinsert(), brin_doupdate(), brin_getinsertbuffer(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), brinGetTupleForHeapBlock(), brininsert(), brinsummarize(), bt_rootdescend(), btree_xlog_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 76 of file bufmgr.h.

◆ P_NEW

◆ RelationGetNumberOfBlocks

Typedef Documentation

◆ Block

typedef void* Block

Definition at line 24 of file bufmgr.h.

◆ BufferAccessStrategyType

Enumeration Type Documentation

◆ BufferAccessStrategyType

Enumerator
BAS_NORMAL 
BAS_BULKREAD 
BAS_BULKWRITE 
BAS_VACUUM 

Definition at line 27 of file bufmgr.h.

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

◆ ReadBufferMode

Enumerator
RBM_NORMAL 
RBM_ZERO_AND_LOCK 
RBM_ZERO_AND_CLEANUP_LOCK 
RBM_ZERO_ON_ERROR 
RBM_NORMAL_NO_LOG 

Definition at line 37 of file bufmgr.h.

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

Function Documentation

◆ AbortBufferIO()

void AbortBufferIO ( void  )

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

4011 {
4013 
4014  if (buf)
4015  {
4016  uint32 buf_state;
4017 
4018  /*
4019  * Since LWLockReleaseAll has already been called, we're not holding
4020  * the buffer's io_in_progress_lock. We have to re-acquire it so that
4021  * we can use TerminateBufferIO. Anyone who's executing WaitIO on the
4022  * buffer will be in a busy spin until we succeed in doing this.
4023  */
4025 
4026  buf_state = LockBufHdr(buf);
4027  Assert(buf_state & BM_IO_IN_PROGRESS);
4028  if (IsForInput)
4029  {
4030  Assert(!(buf_state & BM_DIRTY));
4031 
4032  /* We'd better not think buffer is valid yet */
4033  Assert(!(buf_state & BM_VALID));
4034  UnlockBufHdr(buf, buf_state);
4035  }
4036  else
4037  {
4038  Assert(buf_state & BM_DIRTY);
4039  UnlockBufHdr(buf, buf_state);
4040  /* Issue notice if this is not the first failure... */
4041  if (buf_state & BM_IO_ERROR)
4042  {
4043  /* Buffer is pinned, so we can read tag without spinlock */
4044  char *path;
4045 
4046  path = relpathperm(buf->tag.rnode, buf->tag.forkNum);
4047  ereport(WARNING,
4048  (errcode(ERRCODE_IO_ERROR),
4049  errmsg("could not write block %u of %s",
4050  buf->tag.blockNum, path),
4051  errdetail("Multiple failures --- write error might be permanent.")));
4052  pfree(path);
4053  }
4054  }
4055  TerminateBufferIO(buf, false, BM_IO_ERROR);
4056  }
4057 }
#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:139
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:367
static bool IsForInput
Definition: bufmgr.c:140
#define WARNING
Definition: elog.h:40
static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits)
Definition: bufmgr.c:3978
#define BM_VALID
Definition: buf_internals.h:59
#define ereport(elevel,...)
Definition: elog.h:144
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4128
#define Assert(condition)
Definition: c.h:738
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1123
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 2381 of file bufmgr.c.

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

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

2382 {
2384 
2385  AtEOXact_LocalBuffers(isCommit);
2386 
2388 }
static int32 PrivateRefCountOverflowed
Definition: bufmgr.c:177
#define Assert(condition)
Definition: c.h:738
static void CheckForBufferLeaks(void)
Definition: bufmgr.c:2456
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:572

◆ AtProcExit_LocalBuffers()

void AtProcExit_LocalBuffers ( void  )

Definition at line 583 of file localbuf.c.

References CheckForLocalBufferLeaks().

Referenced by AtProcExit_Buffers().

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

◆ BgBufferSync()

bool BgBufferSync ( struct WritebackContext wb_context)

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

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

◆ BufferGetBlockNumber()

BlockNumber BufferGetBlockNumber ( Buffer  buffer)

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

2572 {
2573  BufferDesc *bufHdr;
2574 
2575  Assert(BufferIsPinned(buffer));
2576 
2577  if (BufferIsLocal(buffer))
2578  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2579  else
2580  bufHdr = GetBufferDescriptor(buffer - 1);
2581 
2582  /* pinned, so OK to read tag without spinlock */
2583  return bufHdr->tag.blockNum;
2584 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:426
#define GetLocalBufferDescriptor(id)
#define GetBufferDescriptor(id)
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
BlockNumber blockNum
Definition: buf_internals.h:94
BufferTag tag

◆ BufferGetLSNAtomic()

XLogRecPtr BufferGetLSNAtomic ( Buffer  buffer)

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

2835 {
2836  BufferDesc *bufHdr = GetBufferDescriptor(buffer - 1);
2837  char *page = BufferGetPage(buffer);
2838  XLogRecPtr lsn;
2839  uint32 buf_state;
2840 
2841  /*
2842  * If we don't need locking for correctness, fastpath out.
2843  */
2844  if (!XLogHintBitIsNeeded() || BufferIsLocal(buffer))
2845  return PageGetLSN(page);
2846 
2847  /* Make sure we've got a real buffer, and that we hold a pin on it. */
2848  Assert(BufferIsValid(buffer));
2849  Assert(BufferIsPinned(buffer));
2850 
2851  buf_state = LockBufHdr(bufHdr);
2852  lsn = PageGetLSN(page);
2853  UnlockBufHdr(bufHdr, buf_state);
2854 
2855  return lsn;
2856 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:426
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:367
#define BufferGetPage(buffer)
Definition: bufmgr.h:157
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4128
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
#define PageGetLSN(page)
Definition: bufpage.h:366
#define UnlockBufHdr(desc, s)
#define XLogHintBitIsNeeded()
Definition: xlog.h:193

◆ BufferGetTag()

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

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

2594 {
2595  BufferDesc *bufHdr;
2596 
2597  /* Do the same checks as BufferGetBlockNumber. */
2598  Assert(BufferIsPinned(buffer));
2599 
2600  if (BufferIsLocal(buffer))
2601  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
2602  else
2603  bufHdr = GetBufferDescriptor(buffer - 1);
2604 
2605  /* pinned, so OK to read tag without spinlock */
2606  *rnode = bufHdr->tag.rnode;
2607  *forknum = bufHdr->tag.forkNum;
2608  *blknum = bufHdr->tag.blockNum;
2609 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:426
ForkNumber forkNum
Definition: buf_internals.h:93
#define GetLocalBufferDescriptor(id)
#define GetBufferDescriptor(id)
#define Assert(condition)
Definition: c.h:738
#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 2804 of file bufmgr.c.

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

Referenced by SetHintBits().

2805 {
2806  BufferDesc *bufHdr;
2807 
2808  /* Local buffers are used only for temp relations. */
2809  if (BufferIsLocal(buffer))
2810  return false;
2811 
2812  /* Make sure we've got a real buffer, and that we hold a pin on it. */
2813  Assert(BufferIsValid(buffer));
2814  Assert(BufferIsPinned(buffer));
2815 
2816  /*
2817  * BM_PERMANENT can't be changed while we hold a pin on the buffer, so we
2818  * need not bother with the buffer header spinlock. Even if someone else
2819  * changes the buffer header state while we're doing this, the state is
2820  * changed atomically, so we'll read the old value or the new value, but
2821  * not random garbage.
2822  */
2823  bufHdr = GetBufferDescriptor(buffer - 1);
2824  return (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT) != 0;
2825 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:426
#define BM_PERMANENT
Definition: buf_internals.h:66
#define GetBufferDescriptor(id)
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
pg_atomic_uint32 state
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241

◆ BufferShmemSize()

Size BufferShmemSize ( void  )

Definition at line 160 of file buf_init.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ BufmgrCommit()

void BufmgrCommit ( void  )

Definition at line 2557 of file bufmgr.c.

Referenced by PrepareTransaction(), and RecordTransactionCommit().

2558 {
2559  /* Nothing to do in bufmgr anymore... */
2560 }

◆ CheckPointBuffers()

void CheckPointBuffers ( int  flags)

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

2541 {
2542  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_START(flags);
2544  BufferSync(flags);
2546  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_SYNC_START();
2549  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_DONE();
2550 }
void ProcessSyncRequests(void)
Definition: sync.c:236
TimestampTz ckpt_sync_end_t
Definition: xlog.h:239
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1583
static void BufferSync(int flags)
Definition: bufmgr.c:1734
CheckpointStatsData CheckpointStats
Definition: xlog.c:183
TimestampTz ckpt_write_t
Definition: xlog.h:237
TimestampTz ckpt_sync_t
Definition: xlog.h:238

◆ ConditionalLockBuffer()

bool ConditionalLockBuffer ( Buffer  buffer)

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

3587 {
3588  BufferDesc *buf;
3589 
3590  Assert(BufferIsValid(buffer));
3591  if (BufferIsLocal(buffer))
3592  return true; /* act as though we got it */
3593 
3594  buf = GetBufferDescriptor(buffer - 1);
3595 
3597  LW_EXCLUSIVE);
3598 }
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1295
static char * buf
Definition: pg_test_fsync.c:67
#define GetBufferDescriptor(id)
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111

◆ ConditionalLockBufferForCleanup()

bool ConditionalLockBufferForCleanup ( Buffer  buffer)

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

3755 {
3756  BufferDesc *bufHdr;
3757  uint32 buf_state,
3758  refcount;
3759 
3760  Assert(BufferIsValid(buffer));
3761 
3762  if (BufferIsLocal(buffer))
3763  {
3764  refcount = LocalRefCount[-buffer - 1];
3765  /* There should be exactly one pin */
3766  Assert(refcount > 0);
3767  if (refcount != 1)
3768  return false;
3769  /* Nobody else to wait for */
3770  return true;
3771  }
3772 
3773  /* There should be exactly one local pin */
3774  refcount = GetPrivateRefCount(buffer);
3775  Assert(refcount);
3776  if (refcount != 1)
3777  return false;
3778 
3779  /* Try to acquire lock */
3780  if (!ConditionalLockBuffer(buffer))
3781  return false;
3782 
3783  bufHdr = GetBufferDescriptor(buffer - 1);
3784  buf_state = LockBufHdr(bufHdr);
3785  refcount = BUF_STATE_GET_REFCOUNT(buf_state);
3786 
3787  Assert(refcount > 0);
3788  if (refcount == 1)
3789  {
3790  /* Successfully acquired exclusive lock with pincount 1 */
3791  UnlockBufHdr(bufHdr, buf_state);
3792  return true;
3793  }
3794 
3795  /* Failed, so release the lock */
3796  UnlockBufHdr(bufHdr, buf_state);
3797  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3798  return false;
3799 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:84
#define GetBufferDescriptor(id)
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:365
unsigned int uint32
Definition: c.h:367
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:3586
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3560
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4128
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
#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 3057 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().

3058 {
3059  int i;
3060 
3061  /*
3062  * We needn't consider local buffers, since by assumption the target
3063  * database isn't our own.
3064  */
3065 
3066  for (i = 0; i < NBuffers; i++)
3067  {
3068  BufferDesc *bufHdr = GetBufferDescriptor(i);
3069  uint32 buf_state;
3070 
3071  /*
3072  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3073  * and saves some cycles.
3074  */
3075  if (bufHdr->tag.rnode.dbNode != dbid)
3076  continue;
3077 
3078  buf_state = LockBufHdr(bufHdr);
3079  if (bufHdr->tag.rnode.dbNode == dbid)
3080  InvalidateBuffer(bufHdr); /* releases spinlock */
3081  else
3082  UnlockBufHdr(bufHdr, buf_state);
3083  }
3084 }
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1308
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:367
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4128
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 2885 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().

2887 {
2888  int i;
2889  int j;
2890 
2891  /* If it's a local relation, it's localbuf.c's problem. */
2892  if (RelFileNodeBackendIsTemp(rnode))
2893  {
2894  if (rnode.backend == MyBackendId)
2895  {
2896  for (j = 0; j < nforks; j++)
2897  DropRelFileNodeLocalBuffers(rnode.node, forkNum[j],
2898  firstDelBlock[j]);
2899  }
2900  return;
2901  }
2902 
2903  for (i = 0; i < NBuffers; i++)
2904  {
2905  BufferDesc *bufHdr = GetBufferDescriptor(i);
2906  uint32 buf_state;
2907 
2908  /*
2909  * We can make this a tad faster by prechecking the buffer tag before
2910  * we attempt to lock the buffer; this saves a lot of lock
2911  * acquisitions in typical cases. It should be safe because the
2912  * caller must have AccessExclusiveLock on the relation, or some other
2913  * reason to be certain that no one is loading new pages of the rel
2914  * into the buffer pool. (Otherwise we might well miss such pages
2915  * entirely.) Therefore, while the tag might be changing while we
2916  * look at it, it can't be changing *to* a value we care about, only
2917  * *away* from such a value. So false negatives are impossible, and
2918  * false positives are safe because we'll recheck after getting the
2919  * buffer lock.
2920  *
2921  * We could check forkNum and blockNum as well as the rnode, but the
2922  * incremental win from doing so seems small.
2923  */
2924  if (!RelFileNodeEquals(bufHdr->tag.rnode, rnode.node))
2925  continue;
2926 
2927  buf_state = LockBufHdr(bufHdr);
2928 
2929  for (j = 0; j < nforks; j++)
2930  {
2931  if (RelFileNodeEquals(bufHdr->tag.rnode, rnode.node) &&
2932  bufHdr->tag.forkNum == forkNum[j] &&
2933  bufHdr->tag.blockNum >= firstDelBlock[j])
2934  {
2935  InvalidateBuffer(bufHdr); /* releases spinlock */
2936  break;
2937  }
2938  }
2939  if (j >= nforks)
2940  UnlockBufHdr(bufHdr, buf_state);
2941  }
2942 }
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:1308
void DropRelFileNodeLocalBuffers(RelFileNode rnode, ForkNumber forkNum, BlockNumber firstDelBlock)
Definition: localbuf.c:320
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:367
RelFileNode node
Definition: relfilenode.h:74
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4128
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 2954 of file bufmgr.c.

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

Referenced by smgrdounlink(), and smgrdounlinkall().

2955 {
2956  int i,
2957  n = 0;
2958  RelFileNode *nodes;
2959  bool use_bsearch;
2960 
2961  if (nnodes == 0)
2962  return;
2963 
2964  nodes = palloc(sizeof(RelFileNode) * nnodes); /* non-local relations */
2965 
2966  /* If it's a local relation, it's localbuf.c's problem. */
2967  for (i = 0; i < nnodes; i++)
2968  {
2969  if (RelFileNodeBackendIsTemp(rnodes[i]))
2970  {
2971  if (rnodes[i].backend == MyBackendId)
2972  DropRelFileNodeAllLocalBuffers(rnodes[i].node);
2973  }
2974  else
2975  nodes[n++] = rnodes[i].node;
2976  }
2977 
2978  /*
2979  * If there are no non-local relations, then we're done. Release the
2980  * memory and return.
2981  */
2982  if (n == 0)
2983  {
2984  pfree(nodes);
2985  return;
2986  }
2987 
2988  /*
2989  * For low number of relations to drop just use a simple walk through, to
2990  * save the bsearch overhead. The threshold to use is rather a guess than
2991  * an exactly determined value, as it depends on many factors (CPU and RAM
2992  * speeds, amount of shared buffers etc.).
2993  */
2994  use_bsearch = n > DROP_RELS_BSEARCH_THRESHOLD;
2995 
2996  /* sort the list of rnodes if necessary */
2997  if (use_bsearch)
2998  pg_qsort(nodes, n, sizeof(RelFileNode), rnode_comparator);
2999 
3000  for (i = 0; i < NBuffers; i++)
3001  {
3002  RelFileNode *rnode = NULL;
3003  BufferDesc *bufHdr = GetBufferDescriptor(i);
3004  uint32 buf_state;
3005 
3006  /*
3007  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3008  * and saves some cycles.
3009  */
3010 
3011  if (!use_bsearch)
3012  {
3013  int j;
3014 
3015  for (j = 0; j < n; j++)
3016  {
3017  if (RelFileNodeEquals(bufHdr->tag.rnode, nodes[j]))
3018  {
3019  rnode = &nodes[j];
3020  break;
3021  }
3022  }
3023  }
3024  else
3025  {
3026  rnode = bsearch((const void *) &(bufHdr->tag.rnode),
3027  nodes, n, sizeof(RelFileNode),
3029  }
3030 
3031  /* buffer doesn't belong to any of the given relfilenodes; skip it */
3032  if (rnode == NULL)
3033  continue;
3034 
3035  buf_state = LockBufHdr(bufHdr);
3036  if (RelFileNodeEquals(bufHdr->tag.rnode, (*rnode)))
3037  InvalidateBuffer(bufHdr); /* releases spinlock */
3038  else
3039  UnlockBufHdr(bufHdr, buf_state);
3040  }
3041 
3042  pfree(nodes);
3043 }
BackendId MyBackendId
Definition: globals.c:81
#define RelFileNodeBackendIsTemp(rnode)
Definition: relfilenode.h:78
static void InvalidateBuffer(BufferDesc *buf)
Definition: bufmgr.c:1308
#define DROP_RELS_BSEARCH_THRESHOLD
Definition: bufmgr.c:70
void DropRelFileNodeAllLocalBuffers(RelFileNode rnode)
Definition: localbuf.c:367
void pfree(void *pointer)
Definition: mcxt.c:1056
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:367
static int rnode_comparator(const void *p1, const void *p2)
Definition: bufmgr.c:4101
RelFileNode node
Definition: relfilenode.h:74
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4128
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 3260 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().

3261 {
3262  int i;
3263  BufferDesc *bufHdr;
3264 
3265  /* Make sure we can handle the pin inside the loop */
3267 
3268  for (i = 0; i < NBuffers; i++)
3269  {
3270  uint32 buf_state;
3271 
3272  bufHdr = GetBufferDescriptor(i);
3273 
3274  /*
3275  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3276  * and saves some cycles.
3277  */
3278  if (bufHdr->tag.rnode.dbNode != dbid)
3279  continue;
3280 
3282 
3283  buf_state = LockBufHdr(bufHdr);
3284  if (bufHdr->tag.rnode.dbNode == dbid &&
3285  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3286  {
3287  PinBuffer_Locked(bufHdr);
3289  FlushBuffer(bufHdr, NULL);
3291  UnpinBuffer(bufHdr, true);
3292  }
3293  else
3294  UnlockBufHdr(bufHdr, buf_state);
3295  }
3296 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
#define BM_DIRTY
Definition: buf_internals.h:58
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln)
Definition: bufmgr.c:2631
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1727
#define GetBufferDescriptor(id)
unsigned int uint32
Definition: c.h:367
static void UnpinBuffer(BufferDesc *buf, bool fixOwner)
Definition: bufmgr.c:1650
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:4128
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:1612
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1123
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:193

◆ FlushOneBuffer()

void FlushOneBuffer ( Buffer  buffer)

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

3304 {
3305  BufferDesc *bufHdr;
3306 
3307  /* currently not needed, but no fundamental reason not to support */
3308  Assert(!BufferIsLocal(buffer));
3309 
3310  Assert(BufferIsPinned(buffer));
3311 
3312  bufHdr = GetBufferDescriptor(buffer - 1);
3313 
3315 
3316  FlushBuffer(bufHdr, NULL);
3317 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:426
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1843
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln)
Definition: bufmgr.c:2631
#define GetBufferDescriptor(id)
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37

◆ FlushRelationBuffers()

void FlushRelationBuffers ( Relation  rel)

Definition at line 3162 of file bufmgr.c.

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

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

3163 {
3164  int i;
3165  BufferDesc *bufHdr;
3166 
3167  /* Open rel at the smgr level if not already done */
3168  RelationOpenSmgr(rel);
3169 
3170  if (RelationUsesLocalBuffers(rel))
3171  {
3172  for (i = 0; i < NLocBuffer; i++)
3173  {
3174  uint32 buf_state;
3175 
3176  bufHdr = GetLocalBufferDescriptor(i);
3177  if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
3178  ((buf_state = pg_atomic_read_u32(&bufHdr->state)) &
3179  (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3180  {
3181  ErrorContextCallback errcallback;
3182  Page localpage;
3183 
3184  localpage = (char *) LocalBufHdrGetBlock(bufHdr);
3185 
3186  /* Setup error traceback support for ereport() */
3188  errcallback.arg = (void *) bufHdr;
3189  errcallback.previous = error_context_stack;
3190  error_context_stack = &errcallback;
3191 
3192  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
3193 
3194  smgrwrite(rel->rd_smgr,
3195  bufHdr->tag.forkNum,
3196  bufHdr->tag.blockNum,
3197  localpage,
3198  false);
3199 
3200  buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED);
3201  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
3202 
3203  /* Pop the error context stack */
3204  error_context_stack = errcallback.previous;
3205  }
3206  }
3207 
3208  return;
3209  }
3210 
3211  /* Make sure we can handle the pin inside the loop */
3213 
3214  for (i = 0; i < NBuffers; i++)
3215  {
3216  uint32 buf_state;
3217 
3218  bufHdr = GetBufferDescriptor(i);
3219 
3220  /*
3221  * As in DropRelFileNodeBuffers, an unlocked precheck should be safe
3222  * and saves some cycles.
3223  */
3224  if (!RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
3225  continue;
3226 
3228 
3229  buf_state = LockBufHdr(bufHdr);
3230  if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
3231  (buf_state & (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
3232  {
3233  PinBuffer_Locked(bufHdr);
3235  FlushBuffer(bufHdr, rel->rd_smgr);
3237  UnpinBuffer(bufHdr, true);
3238  }
3239  else
3240  UnlockBufHdr(bufHdr, buf_state);
3241  }
3242 }
#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:4082
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:2631
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1727
ErrorContextCallback * error_context_stack
Definition: elog.c:92
#define RelationOpenSmgr(relation)
Definition: rel.h:493
int NLocBuffer
Definition: localbuf.c:41
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:530
#define GetBufferDescriptor(id)
#define BM_JUST_DIRTIED
Definition: buf_internals.h:63
unsigned int uint32
Definition: c.h:367
static void UnpinBuffer(BufferDesc *buf, bool fixOwner)
Definition: bufmgr.c:1650
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:4128
static void PinBuffer_Locked(BufferDesc *buf)
Definition: bufmgr.c:1612
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1194
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1123
BlockNumber blockNum
Definition: buf_internals.h:94
RelFileNode rnode
Definition: buf_internals.h:92
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:545
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:193
pg_atomic_uint32 state
Pointer Page
Definition: bufpage.h:78
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241

◆ FreeAccessStrategy()

void FreeAccessStrategy ( BufferAccessStrategy  strategy)

Definition at line 597 of file freelist.c.

References pfree().

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

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

◆ GetAccessStrategy()

BufferAccessStrategy GetAccessStrategy ( BufferAccessStrategyType  btype)

Definition at line 542 of file freelist.c.

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

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

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

◆ HoldingBufferPinThatDelaysRecovery()

bool HoldingBufferPinThatDelaysRecovery ( void  )

Definition at line 3728 of file bufmgr.c.

References GetPrivateRefCount(), and GetStartupBufferPinWaitBufId().

Referenced by CheckRecoveryConflictDeadlock(), and RecoveryConflictInterrupt().

3729 {
3730  int bufid = GetStartupBufferPinWaitBufId();
3731 
3732  /*
3733  * If we get woken slowly then it's possible that the Startup process was
3734  * already woken by other backends before we got here. Also possible that
3735  * we get here by multiple interrupts or interrupts at inappropriate
3736  * times, so make sure we do nothing if the bufid is not set.
3737  */
3738  if (bufid < 0)
3739  return false;
3740 
3741  if (GetPrivateRefCount(bufid + 1) > 0)
3742  return true;
3743 
3744  return false;
3745 }
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:365
int GetStartupBufferPinWaitBufId(void)
Definition: proc.c:657

◆ IncrBufferRefCount()

void IncrBufferRefCount ( Buffer  buffer)

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

3362 {
3363  Assert(BufferIsPinned(buffer));
3365  if (BufferIsLocal(buffer))
3366  LocalRefCount[-buffer - 1]++;
3367  else
3368  {
3369  PrivateRefCountEntry *ref;
3370 
3371  ref = GetPrivateRefCountEntry(buffer, true);
3372  Assert(ref != NULL);
3373  ref->refcount++;
3374  }
3376 }
static PrivateRefCountEntry * GetPrivateRefCountEntry(Buffer buffer, bool do_move)
Definition: bufmgr.c:285
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:426
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:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
int32 * LocalRefCount
Definition: localbuf.c:45

◆ InitBufferPool()

void InitBufferPool ( void  )

Definition at line 67 of file buf_init.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

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

Referenced by BaseInit().

2404 {
2405  HASHCTL hash_ctl;
2406 
2407  memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
2408 
2409  MemSet(&hash_ctl, 0, sizeof(hash_ctl));
2410  hash_ctl.keysize = sizeof(int32);
2411  hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
2412 
2413  PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
2414  HASH_ELEM | HASH_BLOBS);
2415 }
struct PrivateRefCountEntry PrivateRefCountEntry
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:971
signed int int32
Definition: c.h:355
static struct PrivateRefCountEntry PrivateRefCountArray[REFCOUNT_ARRAY_ENTRIES]
Definition: bufmgr.c:175
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:317
Size keysize
Definition: hsearch.h:72
static HTAB * PrivateRefCountHash
Definition: bufmgr.c:176

◆ InitBufferPoolBackend()

void InitBufferPoolBackend ( void  )

Definition at line 2427 of file bufmgr.c.

References AtProcExit_Buffers(), and on_shmem_exit().

Referenced by AuxiliaryProcessMain(), and InitPostgres().

2428 {
2430 }
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:2437

◆ IsBufferCleanupOK()

bool IsBufferCleanupOK ( Buffer  buffer)

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

3811 {
3812  BufferDesc *bufHdr;
3813  uint32 buf_state;
3814 
3815  Assert(BufferIsValid(buffer));
3816 
3817  if (BufferIsLocal(buffer))
3818  {
3819  /* There should be exactly one pin */
3820  if (LocalRefCount[-buffer - 1] != 1)
3821  return false;
3822  /* Nobody else to wait for */
3823  return true;
3824  }
3825 
3826  /* There should be exactly one local pin */
3827  if (GetPrivateRefCount(buffer) != 1)
3828  return false;
3829 
3830  bufHdr = GetBufferDescriptor(buffer - 1);
3831 
3832  /* caller must hold exclusive lock on buffer */
3834  LW_EXCLUSIVE));
3835 
3836  buf_state = LockBufHdr(bufHdr);
3837 
3838  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
3839  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
3840  {
3841  /* pincount is OK. */
3842  UnlockBufHdr(bufHdr, buf_state);
3843  return true;
3844  }
3845 
3846  UnlockBufHdr(bufHdr, buf_state);
3847  return false;
3848 }
bool LWLockHeldByMeInMode(LWLock *l, LWLockMode mode)
Definition: lwlock.c:1861
#define GetBufferDescriptor(id)
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:365
unsigned int uint32
Definition: c.h:367
#define BufferDescriptorGetContentLock(bdesc)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4128
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
#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 3560 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().

3561 {
3562  BufferDesc *buf;
3563 
3564  Assert(BufferIsValid(buffer));
3565  if (BufferIsLocal(buffer))
3566  return; /* local buffers need no lock */
3567 
3568  buf = GetBufferDescriptor(buffer - 1);
3569 
3570  if (mode == BUFFER_LOCK_UNLOCK)
3572  else if (mode == BUFFER_LOCK_SHARE)
3574  else if (mode == BUFFER_LOCK_EXCLUSIVE)
3576  else
3577  elog(ERROR, "unrecognized buffer lock mode: %d", mode);
3578 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:84
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:86
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1727
#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:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1123
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
#define elog(elevel,...)
Definition: elog.h:214
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:85

◆ LockBufferForCleanup()

void LockBufferForCleanup ( Buffer  buffer)

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

3618 {
3619  BufferDesc *bufHdr;
3620  char *new_status = NULL;
3621 
3622  Assert(BufferIsValid(buffer));
3623  Assert(PinCountWaitBuf == NULL);
3624 
3625  if (BufferIsLocal(buffer))
3626  {
3627  /* There should be exactly one pin */
3628  if (LocalRefCount[-buffer - 1] != 1)
3629  elog(ERROR, "incorrect local pin count: %d",
3630  LocalRefCount[-buffer - 1]);
3631  /* Nobody else to wait for */
3632  return;
3633  }
3634 
3635  /* There should be exactly one local pin */
3636  if (GetPrivateRefCount(buffer) != 1)
3637  elog(ERROR, "incorrect local pin count: %d",
3638  GetPrivateRefCount(buffer));
3639 
3640  bufHdr = GetBufferDescriptor(buffer - 1);
3641 
3642  for (;;)
3643  {
3644  uint32 buf_state;
3645 
3646  /* Try to acquire lock */
3648  buf_state = LockBufHdr(bufHdr);
3649 
3650  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
3651  if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
3652  {
3653  /* Successfully acquired exclusive lock with pincount 1 */
3654  UnlockBufHdr(bufHdr, buf_state);
3655 
3656  /* Report change to non-waiting status */
3657  if (new_status)
3658  {
3659  set_ps_display(new_status);
3660  pfree(new_status);
3661  }
3662  return;
3663  }
3664  /* Failed, so mark myself as waiting for pincount 1 */
3665  if (buf_state & BM_PIN_COUNT_WAITER)
3666  {
3667  UnlockBufHdr(bufHdr, buf_state);
3668  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3669  elog(ERROR, "multiple backends attempting to wait for pincount 1");
3670  }
3671  bufHdr->wait_backend_pid = MyProcPid;
3672  PinCountWaitBuf = bufHdr;
3673  buf_state |= BM_PIN_COUNT_WAITER;
3674  UnlockBufHdr(bufHdr, buf_state);
3675  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3676 
3677  /* Wait to be signaled by UnpinBuffer() */
3678  if (InHotStandby)
3679  {
3680  /* Report change to waiting status */
3681  if (update_process_title && new_status == NULL)
3682  {
3683  const char *old_status;
3684  int len;
3685 
3686  old_status = get_ps_display(&len);
3687  new_status = (char *) palloc(len + 8 + 1);
3688  memcpy(new_status, old_status, len);
3689  strcpy(new_status + len, " waiting");
3690  set_ps_display(new_status);
3691  new_status[len] = '\0'; /* truncate off " waiting" */
3692  }
3693 
3694  /* Publish the bufid that Startup process waits on */
3695  SetStartupBufferPinWaitBufId(buffer - 1);
3696  /* Set alarm and then wait to be signaled by UnpinBuffer() */
3698  /* Reset the published bufid */
3700  }
3701  else
3703 
3704  /*
3705  * Remove flag marking us as waiter. Normally this will not be set
3706  * anymore, but ProcWaitForSignal() can return for other signals as
3707  * well. We take care to only reset the flag if we're the waiter, as
3708  * theoretically another backend could have started waiting. That's
3709  * impossible with the current usages due to table level locking, but
3710  * better be safe.
3711  */
3712  buf_state = LockBufHdr(bufHdr);
3713  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
3714  bufHdr->wait_backend_pid == MyProcPid)
3715  buf_state &= ~BM_PIN_COUNT_WAITER;
3716  UnlockBufHdr(bufHdr, buf_state);
3717 
3718  PinCountWaitBuf = NULL;
3719  /* Loop back and try again */
3720  }
3721 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:84
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:86
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:475
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:365
unsigned int uint32
Definition: c.h:367
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1800
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3560
#define PG_WAIT_BUFFER_PIN
Definition: pgstat.h:739
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4128
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
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:143
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 1406 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().

1407 {
1408  BufferDesc *bufHdr;
1409  uint32 buf_state;
1410  uint32 old_buf_state;
1411 
1412  if (!BufferIsValid(buffer))
1413  elog(ERROR, "bad buffer ID: %d", buffer);
1414 
1415  if (BufferIsLocal(buffer))
1416  {
1417  MarkLocalBufferDirty(buffer);
1418  return;
1419  }
1420 
1421  bufHdr = GetBufferDescriptor(buffer - 1);
1422 
1423  Assert(BufferIsPinned(buffer));
1425  LW_EXCLUSIVE));
1426 
1427  old_buf_state = pg_atomic_read_u32(&bufHdr->state);
1428  for (;;)
1429  {
1430  if (old_buf_state & BM_LOCKED)
1431  old_buf_state = WaitBufHdrUnlocked(bufHdr);
1432 
1433  buf_state = old_buf_state;
1434 
1435  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
1436  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
1437 
1438  if (pg_atomic_compare_exchange_u32(&bufHdr->state, &old_buf_state,
1439  buf_state))
1440  break;
1441  }
1442 
1443  /*
1444  * If the buffer was not dirty already, do vacuum accounting.
1445  */
1446  if (!(old_buf_state & BM_DIRTY))
1447  {
1448  VacuumPageDirty++;
1450  if (VacuumCostActive)
1452  }
1453 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:426
bool LWLockHeldByMeInMode(LWLock *l, LWLockMode mode)
Definition: lwlock.c:1861
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:367
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:280
#define BM_LOCKED
Definition: buf_internals.h:57
#define BufferDescriptorGetContentLock(bdesc)
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
static uint32 WaitBufHdrUnlocked(BufferDesc *buf)
Definition: bufmgr.c:4156
#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 3393 of file bufmgr.c.

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

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

3394 {
3395  BufferDesc *bufHdr;
3396  Page page = BufferGetPage(buffer);
3397 
3398  if (!BufferIsValid(buffer))
3399  elog(ERROR, "bad buffer ID: %d", buffer);
3400 
3401  if (BufferIsLocal(buffer))
3402  {
3403  MarkLocalBufferDirty(buffer);
3404  return;
3405  }
3406 
3407  bufHdr = GetBufferDescriptor(buffer - 1);
3408 
3409  Assert(GetPrivateRefCount(buffer) > 0);
3410  /* here, either share or exclusive lock is OK */
3412 
3413  /*
3414  * This routine might get called many times on the same page, if we are
3415  * making the first scan after commit of an xact that added/deleted many
3416  * tuples. So, be as quick as we can if the buffer is already dirty. We
3417  * do this by not acquiring spinlock if it looks like the status bits are
3418  * already set. Since we make this test unlocked, there's a chance we
3419  * might fail to notice that the flags have just been cleared, and failed
3420  * to reset them, due to memory-ordering issues. But since this function
3421  * is only intended to be used in cases where failing to write out the
3422  * data would be harmless anyway, it doesn't really matter.
3423  */
3424  if ((pg_atomic_read_u32(&bufHdr->state) & (BM_DIRTY | BM_JUST_DIRTIED)) !=
3426  {
3428  bool dirtied = false;
3429  bool delayChkpt = false;
3430  uint32 buf_state;
3431 
3432  /*
3433  * If we need to protect hint bit updates from torn writes, WAL-log a
3434  * full page image of the page. This full page image is only necessary
3435  * if the hint bit update is the first change to the page since the
3436  * last checkpoint.
3437  *
3438  * We don't check full_page_writes here because that logic is included
3439  * when we call XLogInsert() since the value changes dynamically.
3440  */
3441  if (XLogHintBitIsNeeded() &&
3442  (pg_atomic_read_u32(&bufHdr->state) & BM_PERMANENT))
3443  {
3444  /*
3445  * If we're in recovery we cannot dirty a page because of a hint.
3446  * We can set the hint, just not dirty the page as a result so the
3447  * hint is lost when we evict the page or shutdown.
3448  *
3449  * See src/backend/storage/page/README for longer discussion.
3450  */
3451  if (RecoveryInProgress())
3452  return;
3453 
3454  /*
3455  * If the block is already dirty because we either made a change
3456  * or set a hint already, then we don't need to write a full page
3457  * image. Note that aggressive cleaning of blocks dirtied by hint
3458  * bit setting would increase the call rate. Bulk setting of hint
3459  * bits would reduce the call rate...
3460  *
3461  * We must issue the WAL record before we mark the buffer dirty.
3462  * Otherwise we might write the page before we write the WAL. That
3463  * causes a race condition, since a checkpoint might occur between
3464  * writing the WAL record and marking the buffer dirty. We solve
3465  * that with a kluge, but one that is already in use during
3466  * transaction commit to prevent race conditions. Basically, we
3467  * simply prevent the checkpoint WAL record from being written
3468  * until we have marked the buffer dirty. We don't start the
3469  * checkpoint flush until we have marked dirty, so our checkpoint
3470  * must flush the change to disk successfully or the checkpoint
3471  * never gets written, so crash recovery will fix.
3472  *
3473  * It's possible we may enter here without an xid, so it is
3474  * essential that CreateCheckpoint waits for virtual transactions
3475  * rather than full transactionids.
3476  */
3477  MyPgXact->delayChkpt = delayChkpt = true;
3478  lsn = XLogSaveBufferForHint(buffer, buffer_std);
3479  }
3480 
3481  buf_state = LockBufHdr(bufHdr);
3482 
3483  Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
3484 
3485  if (!(buf_state & BM_DIRTY))
3486  {
3487  dirtied = true; /* Means "will be dirtied by this action" */
3488 
3489  /*
3490  * Set the page LSN if we wrote a backup block. We aren't supposed
3491  * to set this when only holding a share lock but as long as we
3492  * serialise it somehow we're OK. We choose to set LSN while
3493  * holding the buffer header lock, which causes any reader of an
3494  * LSN who holds only a share lock to also obtain a buffer header
3495  * lock before using PageGetLSN(), which is enforced in
3496  * BufferGetLSNAtomic().
3497  *
3498  * If checksums are enabled, you might think we should reset the
3499  * checksum here. That will happen when the page is written
3500  * sometime later in this checkpoint cycle.
3501  */
3502  if (!XLogRecPtrIsInvalid(lsn))
3503  PageSetLSN(page, lsn);
3504  }
3505 
3506  buf_state |= BM_DIRTY | BM_JUST_DIRTIED;
3507  UnlockBufHdr(bufHdr, buf_state);
3508 
3509  if (delayChkpt)
3510  MyPgXact->delayChkpt = false;
3511 
3512  if (dirtied)
3513  {
3514  VacuumPageDirty++;
3516  if (VacuumCostActive)
3518  }
3519  }
3520 }
#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:1843
XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
Definition: xloginsert.c:893
int64 VacuumPageDirty
Definition: globals.c:145
bool RecoveryInProgress(void)
Definition: xlog.c:8051
#define BM_DIRTY
Definition: buf_internals.h:58
int VacuumCostPageDirty
Definition: globals.c:139
PGXACT * MyPgXact
Definition: proc.c:68
#define ERROR
Definition: elog.h:43
#define GetBufferDescriptor(id)
#define BM_JUST_DIRTIED
Definition: buf_internals.h:63
long shared_blks_dirtied
Definition: instrument.h:23
static int32 GetPrivateRefCount(Buffer buffer)
Definition: bufmgr.c:365
unsigned int uint32
Definition: c.h:367
#define BufferGetPage(buffer)
Definition: bufmgr.h:157
bool delayChkpt
Definition: proc.h:235
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:280
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define BufferDescriptorGetContentLock(bdesc)
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4128
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
#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:193
Pointer Page
Definition: bufpage.h:78
BufferUsage pgBufferUsage
Definition: instrument.c:20
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:48
bool VacuumCostActive
Definition: globals.c:148
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241

◆ PrefetchBuffer()

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

Definition at line 479 of file bufmgr.c.

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

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

480 {
481 #ifdef USE_PREFETCH
482  Assert(RelationIsValid(reln));
483  Assert(BlockNumberIsValid(blockNum));
484 
485  /* Open it at the smgr level if not already done */
486  RelationOpenSmgr(reln);
487 
488  if (RelationUsesLocalBuffers(reln))
489  {
490  /* see comments in ReadBufferExtended */
491  if (RELATION_IS_OTHER_TEMP(reln))
492  ereport(ERROR,
493  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
494  errmsg("cannot access temporary tables of other sessions")));
495 
496  /* pass it off to localbuf.c */
497  LocalPrefetchBuffer(reln->rd_smgr, forkNum, blockNum);
498  }
499  else
500  {
501  BufferTag newTag; /* identity of requested block */
502  uint32 newHash; /* hash value for newTag */
503  LWLock *newPartitionLock; /* buffer partition lock for it */
504  int buf_id;
505 
506  /* create a tag so we can lookup the buffer */
507  INIT_BUFFERTAG(newTag, reln->rd_smgr->smgr_rnode.node,
508  forkNum, blockNum);
509 
510  /* determine its hash code and partition lock ID */
511  newHash = BufTableHashCode(&newTag);
512  newPartitionLock = BufMappingPartitionLock(newHash);
513 
514  /* see if the block is in the buffer pool already */
515  LWLockAcquire(newPartitionLock, LW_SHARED);
516  buf_id = BufTableLookup(&newTag, newHash);
517  LWLockRelease(newPartitionLock);
518 
519  /* If not in buffers, initiate prefetch */
520  if (buf_id < 0)
521  smgrprefetch(reln->rd_smgr, forkNum, blockNum);
522 
523  /*
524  * If the block *is* in buffers, we do nothing. This is not really
525  * ideal: the block might be just about to be evicted, which would be
526  * stupid since we know we are going to need it soon. But the only
527  * easy answer is to bump the usage_count, which does not seem like a
528  * great solution: when the caller does ultimately touch the block,
529  * usage_count would get bumped again, resulting in too much
530  * favoritism for blocks that are involved in a prefetch sequence. A
531  * real fix would involve some additional per-buffer state, and it's
532  * not clear that there's enough of a problem to justify that.
533  */
534  }
535 #endif /* USE_PREFETCH */
536 }
Definition: lwlock.h:32
#define BufMappingPartitionLock(hashcode)
void LocalPrefetchBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition: localbuf.c:64
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
uint32 BufTableHashCode(BufferTag *tagPtr)
Definition: buf_table.c:79
int errcode(int sqlerrcode)
Definition: elog.c:610
int BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
Definition: buf_table.c:91
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1727
#define RelationOpenSmgr(relation)
Definition: rel.h:493
#define ERROR
Definition: elog.h:43
#define RelationIsValid(relation)
Definition: rel.h:409
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
unsigned int uint32
Definition: c.h:367
#define ereport(elevel,...)
Definition: elog.h:144
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:738
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:566
#define INIT_BUFFERTAG(a, xx_rnode, xx_forkNum, xx_blockNum)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1123
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:545
int errmsg(const char *fmt,...)
Definition: elog.c:824
void smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: smgr.c:494

◆ PrintBufferLeakWarning()

void PrintBufferLeakWarning ( Buffer  buffer)

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

2498 {
2499  BufferDesc *buf;
2500  int32 loccount;
2501  char *path;
2502  BackendId backend;
2503  uint32 buf_state;
2504 
2505  Assert(BufferIsValid(buffer));
2506  if (BufferIsLocal(buffer))
2507  {
2508  buf = GetLocalBufferDescriptor(-buffer - 1);
2509  loccount = LocalRefCount[-buffer - 1];
2510  backend = MyBackendId;
2511  }
2512  else
2513  {
2514  buf = GetBufferDescriptor(buffer - 1);
2515  loccount = GetPrivateRefCount(buffer);
2516  backend = InvalidBackendId;
2517  }
2518 
2519  /* theoretically we should lock the bufhdr here */
2520  path = relpathbackend(buf->tag.rnode, backend, buf->tag.forkNum);
2521  buf_state = pg_atomic_read_u32(&buf->state);
2522  elog(WARNING,
2523  "buffer refcount leak: [%03d] "
2524  "(rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
2525  buffer, path,
2526  buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
2527  BUF_STATE_GET_REFCOUNT(buf_state), loccount);
2528  pfree(path);
2529 }
BackendId MyBackendId
Definition: globals.c:81
ForkNumber forkNum
Definition: buf_internals.h:93
#define GetLocalBufferDescriptor(id)
signed int int32
Definition: c.h:355
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:365
unsigned int uint32
Definition: c.h:367
#define WARNING
Definition: elog.h:40
#define InvalidBackendId
Definition: backendid.h:23
int BackendId
Definition: backendid.h:21
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
BlockNumber blockNum
Definition: buf_internals.h:94
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
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 544 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().

545 {
546  return ReadBufferExtended(reln, MAIN_FORKNUM, blockNum, RBM_NORMAL, NULL);
547 }
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:590

◆ ReadBufferExtended()

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

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

592 {
593  bool hit;
594  Buffer buf;
595 
596  /* Open it at the smgr level if not already done */
597  RelationOpenSmgr(reln);
598 
599  /*
600  * Reject attempts to read non-local temporary relations; we would be
601  * likely to get wrong data since we have no visibility into the owning
602  * session's local buffers.
603  */
604  if (RELATION_IS_OTHER_TEMP(reln))
605  ereport(ERROR,
606  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
607  errmsg("cannot access temporary tables of other sessions")));
608 
609  /*
610  * Read the buffer, and update pgstat counters to reflect a cache hit or
611  * miss.
612  */
614  buf = ReadBuffer_common(reln->rd_smgr, reln->rd_rel->relpersistence,
615  forkNum, blockNum, mode, strategy, &hit);
616  if (hit)
618  return buf;
619 }
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:89
#define RelationOpenSmgr(relation)
Definition: rel.h:493
#define ERROR
Definition: elog.h:43
#define pgstat_count_buffer_read(rel)
Definition: pgstat.h:1371
static char * buf
Definition: pg_test_fsync.c:67
#define pgstat_count_buffer_hit(rel)
Definition: pgstat.h:1376
static Buffer ReadBuffer_common(SMgrRelation reln, char relpersistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool *hit)
Definition: bufmgr.c:653
#define ereport(elevel,...)
Definition: elog.h:144
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:566
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 632 of file bufmgr.c.

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

Referenced by XLogReadBufferExtended().

635 {
636  bool hit;
637 
638  SMgrRelation smgr = smgropen(rnode, InvalidBackendId);
639 
641 
642  return ReadBuffer_common(smgr, RELPERSISTENCE_PERMANENT, forkNum, blockNum,
643  mode, strategy, &hit);
644 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
bool InRecovery
Definition: xlog.c:202
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:653
#define Assert(condition)
Definition: c.h:738

◆ RelationGetNumberOfBlocksInFork()

BlockNumber RelationGetNumberOfBlocksInFork ( Relation  relation,
ForkNumber  forkNum 
)

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

2759 {
2760  switch (relation->rd_rel->relkind)
2761  {
2762  case RELKIND_SEQUENCE:
2763  case RELKIND_INDEX:
2764  case RELKIND_PARTITIONED_INDEX:
2765  /* Open it at the smgr level if not already done */
2766  RelationOpenSmgr(relation);
2767 
2768  return smgrnblocks(relation->rd_smgr, forkNum);
2769 
2770  case RELKIND_RELATION:
2771  case RELKIND_TOASTVALUE:
2772  case RELKIND_MATVIEW:
2773  {
2774  /*
2775  * Not every table AM uses BLCKSZ wide fixed size blocks.
2776  * Therefore tableam returns the size in bytes - but for the
2777  * purpose of this routine, we want the number of blocks.
2778  * Therefore divide, rounding up.
2779  */
2780  uint64 szbytes;
2781 
2782  szbytes = table_relation_size(relation, forkNum);
2783 
2784  return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
2785  }
2786  case RELKIND_VIEW:
2787  case RELKIND_COMPOSITE_TYPE:
2788  case RELKIND_FOREIGN_TABLE:
2789  case RELKIND_PARTITIONED_TABLE:
2790  default:
2791  Assert(false);
2792  break;
2793  }
2794 
2795  return 0; /* keep compiler quiet */
2796 }
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
Form_pg_class rd_rel
Definition: rel.h:89
#define RelationOpenSmgr(relation)
Definition: rel.h:493
static uint64 table_relation_size(Relation rel, ForkNumber forkNumber)
Definition: tableam.h:1624
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:555
#define Assert(condition)
Definition: c.h:738

◆ ReleaseAndReadBuffer()

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

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

1472 {
1473  ForkNumber forkNum = MAIN_FORKNUM;
1474  BufferDesc *bufHdr;
1475 
1476  if (BufferIsValid(buffer))
1477  {
1478  Assert(BufferIsPinned(buffer));
1479  if (BufferIsLocal(buffer))
1480  {
1481  bufHdr = GetLocalBufferDescriptor(-buffer - 1);
1482  if (bufHdr->tag.blockNum == blockNum &&
1483  RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node) &&
1484  bufHdr->tag.forkNum == forkNum)
1485  return buffer;
1487  LocalRefCount[-buffer - 1]--;
1488  }
1489  else
1490  {
1491  bufHdr = GetBufferDescriptor(buffer - 1);
1492  /* we have pin, so it's ok to examine tag without spinlock */
1493  if (bufHdr->tag.blockNum == blockNum &&
1494  RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node) &&
1495  bufHdr->tag.forkNum == forkNum)
1496  return buffer;
1497  UnpinBuffer(bufHdr, true);
1498  }
1499  }
1500 
1501  return ReadBuffer(relation, blockNum);
1502 }
#define BufferIsPinned(bufnum)
Definition: bufmgr.c:426
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:1650
RelFileNode rd_node
Definition: rel.h:55
#define Assert(condition)
Definition: c.h:738
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:544
#define BufferIsLocal(buffer)
Definition: buf.h:37
BlockNumber blockNum
Definition: buf_internals.h:94
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
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 3323 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().

3324 {
3325  if (!BufferIsValid(buffer))
3326  elog(ERROR, "bad buffer ID: %d", buffer);
3327 
3328  if (BufferIsLocal(buffer))
3329  {
3331 
3332  Assert(LocalRefCount[-buffer - 1] > 0);
3333  LocalRefCount[-buffer - 1]--;
3334  return;
3335  }
3336 
3337  UnpinBuffer(GetBufferDescriptor(buffer - 1), true);
3338 }
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:1650
#define Assert(condition)
Definition: c.h:738
#define BufferIsLocal(buffer)
Definition: buf.h:37
#define BufferIsValid(bufnum)
Definition: bufmgr.h:111
#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 261 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().

262 {
263  Assert(relation != NULL);
264 
265  if (old_snapshot_threshold >= 0
266  && (snapshot) != NULL
267  && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
268  || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
269  && !XLogRecPtrIsInvalid((snapshot)->lsn)
270  && PageGetLSN(page) > (snapshot)->lsn)
271  TestForOldSnapshot_impl(snapshot, relation);
272 }
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define Assert(condition)
Definition: c.h:738
#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:4388

◆ TestForOldSnapshot_impl()

void TestForOldSnapshot_impl ( Snapshot  snapshot,
Relation  relation 
)

Definition at line 4388 of file bufmgr.c.

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

Referenced by TestForOldSnapshot().

4389 {
4390  if (RelationAllowsEarlyPruning(relation)
4391  && (snapshot)->whenTaken < GetOldSnapshotThresholdTimestamp())
4392  ereport(ERROR,
4393  (errcode(ERRCODE_SNAPSHOT_TOO_OLD),
4394  errmsg("snapshot too old")));
4395 }
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 3532 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().

3533 {
3535 
3536  if (buf)
3537  {
3538  uint32 buf_state;
3539 
3540  buf_state = LockBufHdr(buf);
3541 
3542  /*
3543  * Don't complain if flag bit not set; it could have been reset but we
3544  * got a cancel/die interrupt before getting the signal.
3545  */
3546  if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
3547  buf->wait_backend_pid == MyProcPid)
3548  buf_state &= ~BM_PIN_COUNT_WAITER;
3549 
3550  UnlockBufHdr(buf, buf_state);
3551 
3552  PinCountWaitBuf = NULL;
3553  }
3554 }
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:367
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4128
#define UnlockBufHdr(desc, s)
static BufferDesc * PinCountWaitBuf
Definition: bufmgr.c:143
#define BM_PIN_COUNT_WAITER
Definition: buf_internals.h:64

◆ UnlockReleaseBuffer()

void UnlockReleaseBuffer ( Buffer  buffer)

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

3347 {
3348  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3349  ReleaseBuffer(buffer);
3350 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:84
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3323
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3560

Variable Documentation

◆ backend_flush_after

int backend_flush_after

Definition at line 136 of file bufmgr.c.

Referenced by InitBufferPool().

◆ bgwriter_flush_after

int bgwriter_flush_after

Definition at line 135 of file bufmgr.c.

Referenced by BackgroundWriterMain().

◆ bgwriter_lru_maxpages

int bgwriter_lru_maxpages

Definition at line 111 of file bufmgr.c.

Referenced by BgBufferSync().

◆ bgwriter_lru_multiplier

double bgwriter_lru_multiplier

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

Referenced by BufferSync().

◆ effective_io_concurrency

int effective_io_concurrency

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

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

◆ zero_damaged_pages

bool zero_damaged_pages

Definition at line 110 of file bufmgr.c.

Referenced by mdread(), and ReadBuffer_common().