PostgreSQL Source Code git master
buf_internals.h
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * buf_internals.h
4 * Internal definitions for buffer manager and the buffer replacement
5 * strategy.
6 *
7 *
8 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
10 *
11 * src/include/storage/buf_internals.h
12 *
13 *-------------------------------------------------------------------------
14 */
15#ifndef BUFMGR_INTERNALS_H
16#define BUFMGR_INTERNALS_H
17
18#include "pgstat.h"
19#include "port/atomics.h"
20#include "storage/buf.h"
21#include "storage/bufmgr.h"
23#include "storage/lwlock.h"
24#include "storage/procnumber.h"
25#include "storage/shmem.h"
26#include "storage/smgr.h"
27#include "storage/spin.h"
28#include "utils/relcache.h"
29#include "utils/resowner.h"
30
31/*
32 * Buffer state is a single 32-bit variable where following data is combined.
33 *
34 * - 18 bits refcount
35 * - 4 bits usage count
36 * - 10 bits of flags
37 *
38 * Combining these values allows to perform some operations without locking
39 * the buffer header, by modifying them together with a CAS loop.
40 *
41 * The definition of buffer state components is below.
42 */
43#define BUF_REFCOUNT_BITS 18
44#define BUF_USAGECOUNT_BITS 4
45#define BUF_FLAG_BITS 10
46
48 "parts of buffer state space need to equal 32");
49
50#define BUF_REFCOUNT_ONE 1
51#define BUF_REFCOUNT_MASK ((1U << BUF_REFCOUNT_BITS) - 1)
52#define BUF_USAGECOUNT_MASK (((1U << BUF_USAGECOUNT_BITS) - 1) << (BUF_REFCOUNT_BITS))
53#define BUF_USAGECOUNT_ONE (1U << BUF_REFCOUNT_BITS)
54#define BUF_USAGECOUNT_SHIFT BUF_REFCOUNT_BITS
55#define BUF_FLAG_MASK (((1U << BUF_FLAG_BITS) - 1) << (BUF_REFCOUNT_BITS + BUF_USAGECOUNT_BITS))
56
57/* Get refcount and usagecount from buffer state */
58#define BUF_STATE_GET_REFCOUNT(state) ((state) & BUF_REFCOUNT_MASK)
59#define BUF_STATE_GET_USAGECOUNT(state) (((state) & BUF_USAGECOUNT_MASK) >> BUF_USAGECOUNT_SHIFT)
60
61/*
62 * Flags for buffer descriptors
63 *
64 * Note: BM_TAG_VALID essentially means that there is a buffer hashtable
65 * entry associated with the buffer's tag.
66 */
67#define BM_LOCKED (1U << 22) /* buffer header is locked */
68#define BM_DIRTY (1U << 23) /* data needs writing */
69#define BM_VALID (1U << 24) /* data is valid */
70#define BM_TAG_VALID (1U << 25) /* tag is assigned */
71#define BM_IO_IN_PROGRESS (1U << 26) /* read or write in progress */
72#define BM_IO_ERROR (1U << 27) /* previous I/O failed */
73#define BM_JUST_DIRTIED (1U << 28) /* dirtied since write started */
74#define BM_PIN_COUNT_WAITER (1U << 29) /* have waiter for sole pin */
75#define BM_CHECKPOINT_NEEDED (1U << 30) /* must write for checkpoint */
76#define BM_PERMANENT (1U << 31) /* permanent buffer (not unlogged,
77 * or init fork) */
78/*
79 * The maximum allowed value of usage_count represents a tradeoff between
80 * accuracy and speed of the clock-sweep buffer management algorithm. A
81 * large value (comparable to NBuffers) would approximate LRU semantics.
82 * But it can take as many as BM_MAX_USAGE_COUNT+1 complete cycles of
83 * clock sweeps to find a free buffer, so in practice we don't want the
84 * value to be very large.
85 */
86#define BM_MAX_USAGE_COUNT 5
89 "BM_MAX_USAGE_COUNT doesn't fit in BUF_USAGECOUNT_BITS bits");
91 "MAX_BACKENDS_BITS needs to be <= BUF_REFCOUNT_BITS");
92
93/*
94 * Buffer tag identifies which disk block the buffer contains.
95 *
96 * Note: the BufferTag data must be sufficient to determine where to write the
97 * block, without reference to pg_class or pg_tablespace entries. It's
98 * possible that the backend flushing the buffer doesn't even believe the
99 * relation is visible yet (its xact may have started before the xact that
100 * created the rel). The storage manager must be able to cope anyway.
101 *
102 * Note: if there's any pad bytes in the struct, InitBufferTag will have
103 * to be fixed to zero them, since this struct is used as a hash key.
104 */
105typedef struct buftag
107 Oid spcOid; /* tablespace oid */
108 Oid dbOid; /* database oid */
109 RelFileNumber relNumber; /* relation file number */
110 ForkNumber forkNum; /* fork number */
111 BlockNumber blockNum; /* blknum relative to begin of reln */
112} BufferTag;
113
114static inline RelFileNumber
116{
117 return tag->relNumber;
118}
119
120static inline ForkNumber
121BufTagGetForkNum(const BufferTag *tag)
122{
123 return tag->forkNum;
124}
125
126static inline void
128 ForkNumber forknum)
129{
130 tag->relNumber = relnumber;
131 tag->forkNum = forknum;
132}
133
134static inline RelFileLocator
136{
137 RelFileLocator rlocator;
138
139 rlocator.spcOid = tag->spcOid;
140 rlocator.dbOid = tag->dbOid;
141 rlocator.relNumber = BufTagGetRelNumber(tag);
142
143 return rlocator;
144}
145
146static inline void
148{
149 tag->spcOid = InvalidOid;
150 tag->dbOid = InvalidOid;
153}
154
155static inline void
156InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator,
157 ForkNumber forkNum, BlockNumber blockNum)
158{
159 tag->spcOid = rlocator->spcOid;
160 tag->dbOid = rlocator->dbOid;
161 BufTagSetRelForkDetails(tag, rlocator->relNumber, forkNum);
162 tag->blockNum = blockNum;
163}
164
165static inline bool
166BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
167{
168 return (tag1->spcOid == tag2->spcOid) &&
169 (tag1->dbOid == tag2->dbOid) &&
170 (tag1->relNumber == tag2->relNumber) &&
171 (tag1->blockNum == tag2->blockNum) &&
172 (tag1->forkNum == tag2->forkNum);
173}
174
175static inline bool
177 const RelFileLocator *rlocator)
178{
179 return (tag->spcOid == rlocator->spcOid) &&
180 (tag->dbOid == rlocator->dbOid) &&
181 (BufTagGetRelNumber(tag) == rlocator->relNumber);
182}
183
184
185/*
186 * The shared buffer mapping table is partitioned to reduce contention.
187 * To determine which partition lock a given tag requires, compute the tag's
188 * hash code with BufTableHashCode(), then apply BufMappingPartitionLock().
189 * NB: NUM_BUFFER_PARTITIONS must be a power of 2!
190 */
191static inline uint32
193{
194 return hashcode % NUM_BUFFER_PARTITIONS;
195}
196
197static inline LWLock *
199{
201 BufTableHashPartition(hashcode)].lock;
202}
203
204static inline LWLock *
206{
208}
209
210/*
211 * BufferDesc -- shared descriptor/state data for a single shared buffer.
212 *
213 * Note: Buffer header lock (BM_LOCKED flag) must be held to examine or change
214 * tag, state or wait_backend_pgprocno fields. In general, buffer header lock
215 * is a spinlock which is combined with flags, refcount and usagecount into
216 * single atomic variable. This layout allow us to do some operations in a
217 * single atomic operation, without actually acquiring and releasing spinlock;
218 * for instance, increase or decrease refcount. buf_id field never changes
219 * after initialization, so does not need locking. freeNext is protected by
220 * the buffer_strategy_lock not buffer header lock. The LWLock can take care
221 * of itself. The buffer header lock is *not* used to control access to the
222 * data in the buffer!
223 *
224 * It's assumed that nobody changes the state field while buffer header lock
225 * is held. Thus buffer header lock holder can do complex updates of the
226 * state variable in single write, simultaneously with lock release (cleaning
227 * BM_LOCKED flag). On the other hand, updating of state without holding
228 * buffer header lock is restricted to CAS, which ensures that BM_LOCKED flag
229 * is not set. Atomic increment/decrement, OR/AND etc. are not allowed.
230 *
231 * An exception is that if we have the buffer pinned, its tag can't change
232 * underneath us, so we can examine the tag without locking the buffer header.
233 * Also, in places we do one-time reads of the flags without bothering to
234 * lock the buffer header; this is generally for situations where we don't
235 * expect the flag bit being tested to be changing.
236 *
237 * We can't physically remove items from a disk page if another backend has
238 * the buffer pinned. Hence, a backend may need to wait for all other pins
239 * to go away. This is signaled by storing its own pgprocno into
240 * wait_backend_pgprocno and setting flag bit BM_PIN_COUNT_WAITER. At present,
241 * there can be only one such waiter per buffer.
242 *
243 * We use this same struct for local buffer headers, but the locks are not
244 * used and not all of the flag bits are useful either. To avoid unnecessary
245 * overhead, manipulations of the state field should be done without actual
246 * atomic operations (i.e. only pg_atomic_read_u32() and
247 * pg_atomic_unlocked_write_u32()).
248 *
249 * Be careful to avoid increasing the size of the struct when adding or
250 * reordering members. Keeping it below 64 bytes (the most common CPU
251 * cache line size) is fairly important for performance.
252 *
253 * Per-buffer I/O condition variables are currently kept outside this struct in
254 * a separate array. They could be moved in here and still fit within that
255 * limit on common systems, but for now that is not done.
256 */
257typedef struct BufferDesc
259 BufferTag tag; /* ID of page contained in buffer */
260 int buf_id; /* buffer's index number (from 0) */
261
262 /* state of the tag, containing flags, refcount and usagecount */
265 int wait_backend_pgprocno; /* backend of pin-count waiter */
266 int freeNext; /* link in freelist chain */
267 LWLock content_lock; /* to lock access to buffer contents */
268} BufferDesc;
269
270/*
271 * Concurrent access to buffer headers has proven to be more efficient if
272 * they're cache line aligned. So we force the start of the BufferDescriptors
273 * array to be on a cache line boundary and force the elements to be cache
274 * line sized.
275 *
276 * XXX: As this is primarily matters in highly concurrent workloads which
277 * probably all are 64bit these days, and the space wastage would be a bit
278 * more noticeable on 32bit systems, we don't force the stride to be cache
279 * line sized on those. If somebody does actual performance testing, we can
280 * reevaluate.
281 *
282 * Note that local buffer descriptors aren't forced to be aligned - as there's
283 * no concurrent access to those it's unlikely to be beneficial.
284 *
285 * We use a 64-byte cache line size here, because that's the most common
286 * size. Making it bigger would be a waste of memory. Even if running on a
287 * platform with either 32 or 128 byte line sizes, it's good to align to
288 * boundaries and avoid false sharing.
289 */
290#define BUFFERDESC_PAD_TO_SIZE (SIZEOF_VOID_P == 8 ? 64 : 1)
292typedef union BufferDescPadded
297
298/*
299 * The PendingWriteback & WritebackContext structure are used to keep
300 * information about pending flush requests to be issued to the OS.
301 */
302typedef struct PendingWriteback
303{
304 /* could store different types of pending flushes here */
307
308/* struct forward declared in bufmgr.h */
309typedef struct WritebackContext
310{
311 /* pointer to the max number of writeback requests to coalesce */
312 int *max_pending;
313
314 /* current number of pending writeback requests */
315 int nr_pending;
316
317 /* pending requests */
320
321/* in buf_init.c */
325
326/* in localbuf.c */
328
329
330static inline BufferDesc *
332{
333 return &(BufferDescriptors[id]).bufferdesc;
334}
335
336static inline BufferDesc *
338{
339 return &LocalBufferDescriptors[id];
340}
341
342static inline Buffer
344{
345 return (Buffer) (bdesc->buf_id + 1);
346}
347
348static inline ConditionVariable *
350{
351 return &(BufferIOCVArray[bdesc->buf_id]).cv;
352}
353
354static inline LWLock *
356{
357 return (LWLock *) (&bdesc->content_lock);
358}
359
360/*
361 * The freeNext field is either the index of the next freelist entry,
362 * or one of these special values:
363 */
364#define FREENEXT_END_OF_LIST (-1)
365#define FREENEXT_NOT_IN_LIST (-2)
366
367/*
368 * Functions for acquiring/releasing a shared buffer header's spinlock. Do
369 * not apply these to local buffers!
370 */
371extern uint32 LockBufHdr(BufferDesc *desc);
372
373static inline void
374UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
375{
377 pg_atomic_write_u32(&desc->state, buf_state & (~BM_LOCKED));
378}
379
380/* in bufmgr.c */
381
382/*
383 * Structure to sort buffers per file on checkpoints.
384 *
385 * This structure is allocated per buffer in shared memory, so it should be
386 * kept as small as possible.
387 */
388typedef struct CkptSortItem
396
398
399/* ResourceOwner callbacks to hold buffer I/Os and pins */
402
403/* Convenience wrappers over ResourceOwnerRemember/Forget */
404static inline void
406{
408}
409static inline void
411{
413}
414static inline void
416{
418}
419static inline void
421{
423}
424
425/*
426 * Internal buffer management routines
427 */
428/* bufmgr.c */
429extern void WritebackContextInit(WritebackContext *context, int *max_pending);
430extern void IssuePendingWritebacks(WritebackContext *wb_context, IOContext io_context);
431extern void ScheduleBufferTagForWriteback(WritebackContext *wb_context,
432 IOContext io_context, BufferTag *tag);
433
434/* freelist.c */
437 uint32 *buf_state, bool *from_ring);
438extern void StrategyFreeBuffer(BufferDesc *buf);
439extern bool StrategyRejectBuffer(BufferAccessStrategy strategy,
440 BufferDesc *buf, bool from_ring);
441
442extern int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc);
443extern void StrategyNotifyBgWriter(int bgwprocno);
444
445extern Size StrategyShmemSize(void);
446extern void StrategyInitialize(bool init);
447extern bool have_free_buffer(void);
448
449/* buf_table.c */
450extern Size BufTableShmemSize(int size);
451extern void InitBufTable(int size);
452extern uint32 BufTableHashCode(BufferTag *tagPtr);
453extern int BufTableLookup(BufferTag *tagPtr, uint32 hashcode);
454extern int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id);
455extern void BufTableDelete(BufferTag *tagPtr, uint32 hashcode);
456
457/* localbuf.c */
458extern bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount);
459extern void UnpinLocalBuffer(Buffer buffer);
460extern void UnpinLocalBufferNoOwner(Buffer buffer);
462 ForkNumber forkNum,
463 BlockNumber blockNum);
465 BlockNumber blockNum, bool *foundPtr);
467 ForkNumber fork,
468 uint32 flags,
469 uint32 extend_by,
470 BlockNumber extend_upto,
471 Buffer *buffers,
472 uint32 *extended_by);
473extern void MarkLocalBufferDirty(Buffer buffer);
474extern void TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty,
475 uint32 set_flag_bits);
476extern bool StartLocalBufferIO(BufferDesc *bufHdr, bool forInput);
477extern void FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln);
478extern void DropRelationLocalBuffers(RelFileLocator rlocator,
479 ForkNumber forkNum,
480 BlockNumber firstDelBlock);
481extern void DropRelationAllLocalBuffers(RelFileLocator rlocator);
482extern void AtEOXact_LocalBuffers(bool isCommit);
483
484#endif /* BUFMGR_INTERNALS_H */
#define pg_write_barrier()
Definition: atomics.h:157
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:276
uint32 BlockNumber
Definition: block.h:31
#define InvalidBlockNumber
Definition: block.h:33
int Buffer
Definition: buf.h:23
#define BM_MAX_USAGE_COUNT
Definition: buf_internals.h:85
void FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln)
Definition: localbuf.c:181
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
struct CkptSortItem CkptSortItem
static uint32 BufTableHashPartition(uint32 hashcode)
static LWLock * BufMappingPartitionLockByIndex(uint32 index)
void BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
Definition: buf_table.c:148
union BufferDescPadded BufferDescPadded
void UnpinLocalBuffer(Buffer buffer)
Definition: localbuf.c:762
int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc)
Definition: freelist.c:394
StaticAssertDecl(BUF_REFCOUNT_BITS+BUF_USAGECOUNT_BITS+BUF_FLAG_BITS==32, "parts of buffer state space need to equal 32")
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static ConditionVariable * BufferDescriptorGetIOCV(const BufferDesc *bdesc)
#define BUF_FLAG_BITS
Definition: buf_internals.h:45
struct BufferDesc BufferDesc
void AtEOXact_LocalBuffers(bool isCommit)
Definition: localbuf.c:900
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
bool have_free_buffer(void)
Definition: freelist.c:175
void DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber firstDelBlock)
Definition: localbuf.c:605
int BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
Definition: buf_table.c:90
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
static RelFileNumber BufTagGetRelNumber(const BufferTag *tag)
static LWLock * BufferDescriptorGetContentLock(const BufferDesc *bdesc)
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
#define BUF_REFCOUNT_BITS
Definition: buf_internals.h:43
struct WritebackContext WritebackContext
bool PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount)
Definition: localbuf.c:736
struct PendingWriteback PendingWriteback
static void BufTagSetRelForkDetails(BufferTag *tag, RelFileNumber relnumber, ForkNumber forknum)
void InitBufTable(int size)
Definition: buf_table.c:51
PGDLLIMPORT const ResourceOwnerDesc buffer_io_resowner_desc
Definition: bufmgr.c:228
void StrategyInitialize(bool init)
Definition: freelist.c:474
#define BUF_USAGECOUNT_BITS
Definition: buf_internals.h:44
static void ResourceOwnerRememberBufferIO(ResourceOwner owner, Buffer buffer)
#define BM_LOCKED
Definition: buf_internals.h:67
void TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty, uint32 set_flag_bits)
Definition: localbuf.c:532
void MarkLocalBufferDirty(Buffer buffer)
Definition: localbuf.c:479
#define BUFFERDESC_PAD_TO_SIZE
PGDLLIMPORT WritebackContext BackendWritebackContext
Definition: buf_init.c:23
static void ResourceOwnerForgetBufferIO(ResourceOwner owner, Buffer buffer)
Size BufTableShmemSize(int size)
Definition: buf_table.c:41
uint32 BufTableHashCode(BufferTag *tagPtr)
Definition: buf_table.c:78
void DropRelationAllLocalBuffers(RelFileLocator rlocator)
Definition: localbuf.c:635
void ScheduleBufferTagForWriteback(WritebackContext *wb_context, IOContext io_context, BufferTag *tag)
Definition: bufmgr.c:5835
int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
Definition: buf_table.c:118
static void ClearBufferTag(BufferTag *tag)
static void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
void WritebackContextInit(WritebackContext *context, int *max_pending)
Definition: bufmgr.c:5823
void StrategyNotifyBgWriter(int bgwprocno)
Definition: freelist.c:431
struct buftag BufferTag
static void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
PGDLLIMPORT BufferDescPadded * BufferDescriptors
Definition: buf_init.c:20
bool StartLocalBufferIO(BufferDesc *bufHdr, bool forInput)
Definition: localbuf.c:511
PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
Definition: localbuf.c:70
PGDLLIMPORT ConditionVariableMinimallyPadded * BufferIOCVArray
Definition: buf_init.c:22
BlockNumber ExtendBufferedRelLocal(BufferManagerRelation bmr, ForkNumber fork, uint32 flags, uint32 extend_by, BlockNumber extend_upto, Buffer *buffers, uint32 *extended_by)
Definition: localbuf.c:335
void IssuePendingWritebacks(WritebackContext *wb_context, IOContext io_context)
Definition: bufmgr.c:5885
PGDLLIMPORT CkptSortItem * CkptBufferIds
Definition: buf_init.c:24
IOContext IOContextForStrategy(BufferAccessStrategy strategy)
Definition: freelist.c:758
void UnpinLocalBufferNoOwner(Buffer buffer)
Definition: localbuf.c:769
static LWLock * BufMappingPartitionLock(uint32 hashcode)
BufferDesc * StrategyGetBuffer(BufferAccessStrategy strategy, uint32 *buf_state, bool *from_ring)
Definition: freelist.c:196
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)
Size StrategyShmemSize(void)
Definition: freelist.c:453
PGDLLIMPORT BufferDesc * LocalBufferDescriptors
Definition: localbuf.c:44
PGDLLIMPORT const ResourceOwnerDesc buffer_pin_resowner_desc
Definition: bufmgr.c:237
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:5681
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
void StrategyFreeBuffer(BufferDesc *buf)
Definition: freelist.c:363
bool StrategyRejectBuffer(BufferAccessStrategy strategy, BufferDesc *buf, bool from_ring)
Definition: freelist.c:798
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
BufferDesc * LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, bool *foundPtr)
Definition: localbuf.c:117
#define PGDLLIMPORT
Definition: c.h:1291
uint32_t uint32
Definition: c.h:502
size_t Size
Definition: c.h:576
int init
Definition: isn.c:76
LWLockPadded * MainLWLockArray
Definition: lwlock.c:199
#define BUFFER_MAPPING_LWLOCK_OFFSET
Definition: lwlock.h:104
#define NUM_BUFFER_PARTITIONS
Definition: lwlock.h:93
#define WRITEBACK_MAX_PENDING_FLUSHES
static char * buf
Definition: pg_test_fsync.c:72
IOContext
Definition: pgstat.h:282
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define MAX_BACKENDS_BITS
Definition: procnumber.h:38
Oid RelFileNumber
Definition: relpath.h:25
ForkNumber
Definition: relpath.h:56
@ InvalidForkNumber
Definition: relpath.h:57
#define InvalidRelFileNumber
Definition: relpath.h:26
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:564
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:524
LWLock content_lock
int wait_backend_pgprocno
BufferTag tag
pg_atomic_uint32 state
ForkNumber forkNum
RelFileNumber relNumber
BlockNumber blockNum
Definition: lwlock.h:42
RelFileNumber relNumber
PendingWriteback pending_writebacks[WRITEBACK_MAX_PENDING_FLUSHES]
BlockNumber blockNum
RelFileNumber relNumber
ForkNumber forkNum
Oid spcOid
Definition: type.h:96
char pad[BUFFERDESC_PAD_TO_SIZE]
BufferDesc bufferdesc
LWLock lock
Definition: lwlock.h:70