From 19f89b5ba164272758f17a35973eae69475f7400 Mon Sep 17 00:00:00 2001 From: Melanie Plageman Date: Mon, 22 Aug 2022 11:08:23 -0400 Subject: [PATCH v28 3/5] Track IO operation statistics locally Introduce "IOOp", an IO operation done by a backend, and "IOContext", the IO location source or target or IO type done by a backend. For example, the checkpointer may write a shared buffer out. This would be counted as an IOOp "write" on an IOContext IOCONTEXT_SHARED by BackendType "checkpointer". Each IOOp (alloc, extend, fsync, read, write) is counted per IOContext (local, shared, or strategy) through a call to pgstat_count_io_op(). The primary concern of these statistics is IO operations on data blocks during the course of normal database operations. IO done by, for example, the archiver or syslogger is not counted in these statistics. IOCONTEXT_LOCAL and IOCONTEXT_SHARED IOContexts concern operations on local and shared buffers. The IOCONTEXT_STRATEGY IOContext concerns buffers alloc'd/extended/fsync'd/read/written as part of a BufferAccessStrategy. IOOP_ALLOC is counted for IOCONTEXT_SHARED and IOCONTEXT_LOCAL whenever a buffer is acquired through [Local]BufferAlloc(). IOOP_ALLOC for IOCONTEXT_STRATEGY is counted whenever a buffer already in the strategy ring is reused. And IOOP_WRITE for IOCONTEXT_STRATEGY is counted whenever the reused dirty buffer is written out. Stats on IOOps for all IOContexts for a backend are counted in a backend's local memory. This commit does not expose any functions for aggregating or viewing these stats. Author: Melanie Plageman Reviewed-by: Justin Pryzby , Kyotaro Horiguchi Discussion: https://www.postgresql.org/message-id/flat/20200124195226.lth52iydq2n2uilq%40alap3.anarazel.de --- src/backend/postmaster/checkpointer.c | 12 ++ src/backend/storage/buffer/bufmgr.c | 64 +++++-- src/backend/storage/buffer/freelist.c | 23 ++- src/backend/storage/buffer/localbuf.c | 5 + src/backend/storage/sync/sync.c | 9 + src/backend/utils/activity/Makefile | 1 + src/backend/utils/activity/pgstat_io_ops.c | 191 +++++++++++++++++++++ src/include/pgstat.h | 54 ++++++ src/include/storage/buf_internals.h | 2 +- src/tools/pgindent/typedefs.list | 4 + 10 files changed, 352 insertions(+), 13 deletions(-) create mode 100644 src/backend/utils/activity/pgstat_io_ops.c diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 5fc076fc14..bd2e1de7c2 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -1116,6 +1116,18 @@ ForwardSyncRequest(const FileTag *ftag, SyncRequestType type) if (!AmBackgroundWriterProcess()) CheckpointerShmem->num_backend_fsync++; LWLockRelease(CheckpointerCommLock); + + /* + * We have no way of knowing if the current IOContext is + * IOCONTEXT_SHARED or IOCONTEXT_STRATEGY at this point, so count the + * fsync as being in the IOCONTEXT_SHARED IOContext. This is probably + * okay, because the number of backend fsyncs doesn't say anything + * about the efficacy of the BufferAccessStrategy. And counting both + * fsyncs done in IOCONTEXT_SHARED and IOCONTEXT_STRATEGY under + * IOCONTEXT_SHARED is likely clearer when investigating the number of + * backend fsyncs. + */ + pgstat_count_io_op(IOOP_FSYNC, IOCONTEXT_SHARED); return false; } diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 7a1202c609..fbe8f69b7b 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -482,7 +482,7 @@ static BufferDesc *BufferAlloc(SMgrRelation smgr, BlockNumber blockNum, BufferAccessStrategy strategy, bool *foundPtr); -static void FlushBuffer(BufferDesc *buf, SMgrRelation reln); +static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOContext io_context); static void FindAndDropRelationBuffers(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber nForkBlock, @@ -823,6 +823,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, BufferDesc *bufHdr; Block bufBlock; bool found; + IOContext io_context; bool isExtend; bool isLocalBuf = SmgrIsTemp(smgr); @@ -986,10 +987,25 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, */ Assert(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID)); /* spinlock not needed */ - bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr); + if (isLocalBuf) + { + bufBlock = LocalBufHdrGetBlock(bufHdr); + io_context = IOCONTEXT_LOCAL; + } + else + { + bufBlock = BufHdrGetBlock(bufHdr); + + if (strategy != NULL) + io_context = IOCONTEXT_STRATEGY; + else + io_context = IOCONTEXT_SHARED; + } if (isExtend) { + + pgstat_count_io_op(IOOP_EXTEND, io_context); /* new buffers are zero-filled */ MemSet((char *) bufBlock, 0, BLCKSZ); /* don't set checksum for all-zero page */ @@ -1020,6 +1036,8 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, smgrread(smgr, forkNum, blockNum, (char *) bufBlock); + pgstat_count_io_op(IOOP_READ, io_context); + if (track_io_timing) { INSTR_TIME_SET_CURRENT(io_time); @@ -1190,6 +1208,8 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, /* Loop here in case we have to try another victim buffer */ for (;;) { + bool from_ring; + /* * Ensure, while the spinlock's not yet held, that there's a free * refcount entry. @@ -1200,7 +1220,7 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, * Select a victim buffer. The buffer is returned with its header * spinlock still held! */ - buf = StrategyGetBuffer(strategy, &buf_state); + buf = StrategyGetBuffer(strategy, &buf_state, &from_ring); Assert(BUF_STATE_GET_REFCOUNT(buf_state) == 0); @@ -1237,6 +1257,8 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, if (LWLockConditionalAcquire(BufferDescriptorGetContentLock(buf), LW_SHARED)) { + IOContext io_context; + /* * If using a nondefault strategy, and writing the buffer * would require a WAL flush, let the strategy decide whether @@ -1263,13 +1285,28 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, } } + /* + * When a strategy is in use, if the target dirty buffer is an + * existing strategy buffer being reused, count this as a + * strategy write for the purposes of IO Operations statistics + * tracking. + * + * All dirty shared buffers upon first being added to the ring + * will be counted as shared buffer writes. + * + * When a strategy is not in use, the write can only be a + * "regular" write of a dirty shared buffer. + */ + + io_context = from_ring ? IOCONTEXT_STRATEGY : IOCONTEXT_SHARED; + /* OK, do the I/O */ TRACE_POSTGRESQL_BUFFER_WRITE_DIRTY_START(forkNum, blockNum, smgr->smgr_rlocator.locator.spcOid, smgr->smgr_rlocator.locator.dbOid, smgr->smgr_rlocator.locator.relNumber); - FlushBuffer(buf, NULL); + FlushBuffer(buf, NULL, io_context); LWLockRelease(BufferDescriptorGetContentLock(buf)); ScheduleBufferTagForWriteback(&BackendWritebackContext, @@ -2573,7 +2610,7 @@ SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context) PinBuffer_Locked(bufHdr); LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED); - FlushBuffer(bufHdr, NULL); + FlushBuffer(bufHdr, NULL, IOCONTEXT_SHARED); LWLockRelease(BufferDescriptorGetContentLock(bufHdr)); @@ -2820,9 +2857,12 @@ BufferGetTag(Buffer buffer, RelFileLocator *rlocator, ForkNumber *forknum, * * If the caller has an smgr reference for the buffer's relation, pass it * as the second parameter. If not, pass NULL. + * + * IOContext will always be IOCONTEXT_SHARED except when a buffer access strategy is + * used and the buffer being flushed is a buffer from the strategy ring. */ static void -FlushBuffer(BufferDesc *buf, SMgrRelation reln) +FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOContext io_context) { XLogRecPtr recptr; ErrorContextCallback errcallback; @@ -2902,6 +2942,8 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln) */ bufToWrite = PageSetChecksumCopy((Page) bufBlock, buf->tag.blockNum); + pgstat_count_io_op(IOOP_WRITE, io_context); + if (track_io_timing) INSTR_TIME_SET_CURRENT(io_start); @@ -3549,6 +3591,8 @@ FlushRelationBuffers(Relation rel) localpage, false); + pgstat_count_io_op(IOOP_WRITE, IOCONTEXT_LOCAL); + buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED); pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); @@ -3584,7 +3628,7 @@ FlushRelationBuffers(Relation rel) { PinBuffer_Locked(bufHdr); LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED); - FlushBuffer(bufHdr, RelationGetSmgr(rel)); + FlushBuffer(bufHdr, RelationGetSmgr(rel), IOCONTEXT_SHARED); LWLockRelease(BufferDescriptorGetContentLock(bufHdr)); UnpinBuffer(bufHdr, true); } @@ -3679,7 +3723,7 @@ FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels) { PinBuffer_Locked(bufHdr); LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED); - FlushBuffer(bufHdr, srelent->srel); + FlushBuffer(bufHdr, srelent->srel, IOCONTEXT_SHARED); LWLockRelease(BufferDescriptorGetContentLock(bufHdr)); UnpinBuffer(bufHdr, true); } @@ -3889,7 +3933,7 @@ FlushDatabaseBuffers(Oid dbid) { PinBuffer_Locked(bufHdr); LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED); - FlushBuffer(bufHdr, NULL); + FlushBuffer(bufHdr, NULL, IOCONTEXT_SHARED); LWLockRelease(BufferDescriptorGetContentLock(bufHdr)); UnpinBuffer(bufHdr, true); } @@ -3916,7 +3960,7 @@ FlushOneBuffer(Buffer buffer) Assert(LWLockHeldByMe(BufferDescriptorGetContentLock(bufHdr))); - FlushBuffer(bufHdr, NULL); + FlushBuffer(bufHdr, NULL, IOCONTEXT_SHARED); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 990e081aae..237a48e8d8 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -15,6 +15,7 @@ */ #include "postgres.h" +#include "pgstat.h" #include "port/atomics.h" #include "storage/buf_internals.h" #include "storage/bufmgr.h" @@ -198,13 +199,15 @@ have_free_buffer(void) * return the buffer with the buffer header spinlock still held. */ BufferDesc * -StrategyGetBuffer(BufferAccessStrategy strategy, uint32 *buf_state) +StrategyGetBuffer(BufferAccessStrategy strategy, uint32 *buf_state, bool *from_ring) { BufferDesc *buf; int bgwprocno; int trycounter; uint32 local_buf_state; /* to avoid repeated (de-)referencing */ + *from_ring = false; + /* * If given a strategy object, see whether it can select a buffer. We * assume strategy objects don't need buffer_strategy_lock. @@ -212,8 +215,23 @@ StrategyGetBuffer(BufferAccessStrategy strategy, uint32 *buf_state) if (strategy != NULL) { buf = GetBufferFromRing(strategy, buf_state); - if (buf != NULL) + *from_ring = buf != NULL; + if (*from_ring) + { + /* + * When a strategy is in use, reused buffers from the strategy + * ring will be counted as IOCONTEXT_STRATEGY allocations for the + * purposes of IO Operation statistics tracking. + * + * However, even when a strategy is in use, if a new buffer must + * be allocated from shared buffers and added to the ring, this is + * counted instead as an IOCONTEXT_SHARED allocation. So, only + * reused buffers are counted as being in the IOCONTEXT_STRATEGY + * IOContext. + */ + pgstat_count_io_op(IOOP_ALLOC, IOCONTEXT_STRATEGY); return buf; + } } /* @@ -247,6 +265,7 @@ StrategyGetBuffer(BufferAccessStrategy strategy, uint32 *buf_state) * the rate of buffer consumption. Note that buffers recycled by a * strategy object are intentionally not counted here. */ + pgstat_count_io_op(IOOP_ALLOC, IOCONTEXT_SHARED); pg_atomic_fetch_add_u32(&StrategyControl->numBufferAllocs, 1); /* diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index 014f644bf9..a3d76599bf 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -15,6 +15,7 @@ */ #include "postgres.h" +#include "pgstat.h" #include "access/parallel.h" #include "catalog/catalog.h" #include "executor/instrument.h" @@ -196,6 +197,8 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, LocalRefCount[b]++; ResourceOwnerRememberBuffer(CurrentResourceOwner, BufferDescriptorGetBuffer(bufHdr)); + + pgstat_count_io_op(IOOP_ALLOC, IOCONTEXT_LOCAL); break; } } @@ -226,6 +229,8 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, localpage, false); + pgstat_count_io_op(IOOP_WRITE, IOCONTEXT_LOCAL); + /* Mark not-dirty now in case we error out below */ buf_state &= ~BM_DIRTY; pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); diff --git a/src/backend/storage/sync/sync.c b/src/backend/storage/sync/sync.c index 9d6a9e9109..f310b7a435 100644 --- a/src/backend/storage/sync/sync.c +++ b/src/backend/storage/sync/sync.c @@ -432,6 +432,15 @@ ProcessSyncRequests(void) total_elapsed += elapsed; processed++; + /* + * Note that if a backend using a BufferAccessStrategy is + * forced to do its own fsync (as opposed to the + * checkpointer doing it), it will not be counted as an + * IOCONTEXT_STRATEGY IOOP_FSYNC and instead will be + * counted as an IOCONTEXT_SHARED IOOP_FSYNC. + */ + pgstat_count_io_op(IOOP_FSYNC, IOCONTEXT_SHARED); + if (log_checkpoints) elog(DEBUG1, "checkpoint sync: number=%d file=%s time=%.3f ms", processed, diff --git a/src/backend/utils/activity/Makefile b/src/backend/utils/activity/Makefile index a2e8507fd6..0098785089 100644 --- a/src/backend/utils/activity/Makefile +++ b/src/backend/utils/activity/Makefile @@ -22,6 +22,7 @@ OBJS = \ pgstat_checkpointer.o \ pgstat_database.o \ pgstat_function.o \ + pgstat_io_ops.o \ pgstat_relation.o \ pgstat_replslot.o \ pgstat_shmem.o \ diff --git a/src/backend/utils/activity/pgstat_io_ops.c b/src/backend/utils/activity/pgstat_io_ops.c new file mode 100644 index 0000000000..9c70a4a6dd --- /dev/null +++ b/src/backend/utils/activity/pgstat_io_ops.c @@ -0,0 +1,191 @@ +/* ------------------------------------------------------------------------- + * + * pgstat_io_ops.c + * Implementation of IO operation statistics. + * + * This file contains the implementation of IO operation statistics. It is kept + * separate from pgstat.c to enforce the line between the statistics access / + * storage implementation and the details about individual types of + * statistics. + * + * Copyright (c) 2001-2022, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/utils/activity/pgstat_io_ops.c + * ------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "utils/pgstat_internal.h" + +static PgStat_IOContextOps pending_IOOpStats; + +void +pgstat_count_io_op(IOOp io_op, IOContext io_context) +{ + PgStat_IOOpCounters *pending_counters = &pending_IOOpStats.data[io_context]; + + Assert(pgstat_expect_io_op(MyBackendType, io_context, io_op)); + + switch (io_op) + { + case IOOP_ALLOC: + pending_counters->allocs++; + break; + case IOOP_EXTEND: + pending_counters->extends++; + break; + case IOOP_FSYNC: + pending_counters->fsyncs++; + break; + case IOOP_READ: + pending_counters->reads++; + break; + case IOOP_WRITE: + pending_counters->writes++; + break; + } + +} + +const char * +pgstat_io_context_desc(IOContext io_context) +{ + switch (io_context) + { + case IOCONTEXT_LOCAL: + return "Local"; + case IOCONTEXT_SHARED: + return "Shared"; + case IOCONTEXT_STRATEGY: + return "Strategy"; + } + + elog(ERROR, "unrecognized IOContext value: %d", io_context); +} + +const char * +pgstat_io_op_desc(IOOp io_op) +{ + switch (io_op) + { + case IOOP_ALLOC: + return "Alloc"; + case IOOP_EXTEND: + return "Extend"; + case IOOP_FSYNC: + return "Fsync"; + case IOOP_READ: + return "Read"; + case IOOP_WRITE: + return "Write"; + } + + elog(ERROR, "unrecognized IOOp value: %d", io_op); +} + +/* +* IO Operation statistics are not collected for all BackendTypes. +* +* The following BackendTypes do not participate in the cumulative stats +* subsystem or do not do IO operations worth reporting statistics on: +* - Syslogger because it is not connected to shared memory +* - Archiver because most relevant archiving IO is delegated to a +* specialized command or module +* - WAL Receiver and WAL Writer IO is not tracked in pg_stat_io for now +* +* Function returns true if BackendType participates in the cumulative stats +* subsystem for IO Operations and false if it does not. +*/ +bool +pgstat_io_op_stats_collected(BackendType bktype) +{ + return bktype != B_INVALID && bktype != B_ARCHIVER && bktype != B_LOGGER && + bktype != B_WAL_RECEIVER && bktype != B_WAL_WRITER; +} + +bool +pgstat_bktype_io_context_valid(BackendType bktype, IOContext io_context) +{ + bool no_strategy; + bool no_local; + + /* + * Not all BackendTypes will use a BufferAccessStrategy. + */ + no_strategy = bktype == B_AUTOVAC_LAUNCHER || bktype == + B_BG_WRITER || bktype == B_CHECKPOINTER; + + /* + * Only regular backends and WAL Sender processes executing queries should + * use local buffers. + */ + no_local = bktype == B_AUTOVAC_LAUNCHER || bktype == + B_BG_WRITER || bktype == B_CHECKPOINTER || bktype == + B_AUTOVAC_WORKER || bktype == B_BG_WORKER || bktype == + B_STANDALONE_BACKEND || bktype == B_STARTUP; + + if (io_context == IOCONTEXT_STRATEGY && no_strategy) + return false; + + if (io_context == IOCONTEXT_LOCAL && no_local) + return false; + + return true; +} + +bool +pgstat_bktype_io_op_valid(BackendType bktype, IOOp io_op) +{ + if ((bktype == B_BG_WRITER || bktype == B_CHECKPOINTER) && io_op == + IOOP_READ) + return false; + + if ((bktype == B_AUTOVAC_LAUNCHER || bktype == B_BG_WRITER || bktype == + B_CHECKPOINTER) && io_op == IOOP_EXTEND) + return false; + + return true; +} + +bool +pgstat_io_context_io_op_valid(IOContext io_context, IOOp io_op) +{ + /* + * Temporary tables using local buffers are not logged and thus do not + * require fsync'ing. Set this cell to NULL to differentiate between an + * invalid combination and 0 observed IO Operations. + * + * IOOP_FSYNC IOOps done by a backend using a BufferAccessStrategy are + * counted in the IOCONTEXT_SHARED IOContext. See comment in + * ForwardSyncRequest() for more details. + */ + if ((io_context == IOCONTEXT_LOCAL || io_context == IOCONTEXT_STRATEGY) && + io_op == IOOP_FSYNC) + return false; + + return true; +} + +bool +pgstat_expect_io_op(BackendType bktype, IOContext io_context, IOOp io_op) +{ + if (!pgstat_io_op_stats_collected(bktype)) + return false; + + if (!pgstat_bktype_io_context_valid(bktype, io_context)) + return false; + + if (!pgstat_bktype_io_op_valid(bktype, io_op)) + return false; + + if (!pgstat_io_context_io_op_valid(io_context, io_op)) + return false; + + /* + * There are currently no cases of a BackendType, IOContext, IOOp + * combination that are specifically invalid. + */ + return true; +} diff --git a/src/include/pgstat.h b/src/include/pgstat.h index ac28f813b4..32d1aec540 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -276,6 +276,44 @@ typedef struct PgStat_CheckpointerStats PgStat_Counter buf_fsync_backend; } PgStat_CheckpointerStats; +/* + * Types related to counting IO Operations for various IO Contexts + */ + +typedef enum IOOp +{ + IOOP_ALLOC, + IOOP_EXTEND, + IOOP_FSYNC, + IOOP_READ, + IOOP_WRITE, +} IOOp; + +#define IOOP_NUM_TYPES (IOOP_WRITE + 1) + +typedef enum IOContext +{ + IOCONTEXT_LOCAL, + IOCONTEXT_SHARED, + IOCONTEXT_STRATEGY, +} IOContext; + +#define IOCONTEXT_NUM_TYPES (IOCONTEXT_STRATEGY + 1) + +typedef struct PgStat_IOOpCounters +{ + PgStat_Counter allocs; + PgStat_Counter extends; + PgStat_Counter fsyncs; + PgStat_Counter reads; + PgStat_Counter writes; +} PgStat_IOOpCounters; + +typedef struct PgStat_IOContextOps +{ + PgStat_IOOpCounters data[IOCONTEXT_NUM_TYPES]; +} PgStat_IOContextOps; + typedef struct PgStat_StatDBEntry { PgStat_Counter n_xact_commit; @@ -453,6 +491,22 @@ extern void pgstat_report_checkpointer(void); extern PgStat_CheckpointerStats *pgstat_fetch_stat_checkpointer(void); +/* + * Functions in pgstat_io_ops.c + */ + +extern void pgstat_count_io_op(IOOp io_op, IOContext io_context); +extern const char *pgstat_io_context_desc(IOContext io_context); +extern const char *pgstat_io_op_desc(IOOp io_op); + +/* Validation functions in pgstat_io_ops.c */ +extern bool pgstat_io_op_stats_collected(BackendType bktype); +extern bool pgstat_bktype_io_context_valid(BackendType bktype, IOContext io_context); +extern bool pgstat_bktype_io_op_valid(BackendType bktype, IOOp io_op); +extern bool pgstat_io_context_io_op_valid(IOContext io_context, IOOp io_op); +extern bool pgstat_expect_io_op(BackendType bktype, IOContext io_context, IOOp io_op); + + /* * Functions in pgstat_database.c */ diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index 72466551d7..aa064173ee 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -346,7 +346,7 @@ extern void ScheduleBufferTagForWriteback(WritebackContext *context, BufferTag * /* freelist.c */ extern BufferDesc *StrategyGetBuffer(BufferAccessStrategy strategy, - uint32 *buf_state); + uint32 *buf_state, bool *from_ring); extern void StrategyFreeBuffer(BufferDesc *buf); extern bool StrategyRejectBuffer(BufferAccessStrategy strategy, BufferDesc *buf); diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 35c9f1efce..72378b2148 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -1105,7 +1105,9 @@ ID INFIX INT128 INTERFACE_INFO +IOContext IOFuncSelector +IOOp IPCompareMethod ITEM IV @@ -2037,6 +2039,8 @@ PgStat_FetchConsistency PgStat_FunctionCallUsage PgStat_FunctionCounts PgStat_HashKey +PgStat_IOContextOps +PgStat_IOOpCounters PgStat_Kind PgStat_KindInfo PgStat_LocalState -- 2.34.1