PostgreSQL Source Code git master
test_aio.c File Reference
#include "postgres.h"
#include "access/relation.h"
#include "fmgr.h"
#include "storage/aio.h"
#include "storage/aio_internal.h"
#include "storage/buf_internals.h"
#include "storage/bufmgr.h"
#include "storage/checksum.h"
#include "storage/ipc.h"
#include "storage/lwlock.h"
#include "utils/builtins.h"
#include "utils/injection_point.h"
#include "utils/rel.h"
Include dependency graph for test_aio.c:

Go to the source code of this file.

Data Structures

struct  InjIoErrorState
 

Macros

#define MAX_BUFFERS_TO_EXTEND_BY   64
 

Typedefs

typedef struct InjIoErrorState InjIoErrorState
 

Functions

static void test_aio_shmem_request (void)
 
static void test_aio_shmem_startup (void)
 
void _PG_init (void)
 
 PG_FUNCTION_INFO_V1 (errno_from_string)
 
Datum errno_from_string (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (grow_rel)
 
Datum grow_rel (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (modify_rel_block)
 
Datum modify_rel_block (PG_FUNCTION_ARGS)
 
static Buffer create_toy_buffer (Relation rel, BlockNumber blkno)
 
 PG_FUNCTION_INFO_V1 (read_rel_block_ll)
 
Datum read_rel_block_ll (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (invalidate_rel_block)
 
Datum invalidate_rel_block (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (buffer_create_toy)
 
Datum buffer_create_toy (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (buffer_call_start_io)
 
Datum buffer_call_start_io (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (buffer_call_terminate_io)
 
Datum buffer_call_terminate_io (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (handle_get)
 
Datum handle_get (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (handle_release_last)
 
Datum handle_release_last (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (handle_get_and_error)
 
Datum handle_get_and_error (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (handle_get_twice)
 
Datum handle_get_twice (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (handle_get_release)
 
Datum handle_get_release (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (batch_start)
 
Datum batch_start (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (batch_end)
 
Datum batch_end (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (inj_io_short_read_attach)
 
Datum inj_io_short_read_attach (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (inj_io_short_read_detach)
 
Datum inj_io_short_read_detach (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (inj_io_reopen_attach)
 
Datum inj_io_reopen_attach (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (inj_io_reopen_detach)
 
Datum inj_io_reopen_detach (PG_FUNCTION_ARGS)
 

Variables

 PG_MODULE_MAGIC
 
static InjIoErrorStateinj_io_error_state
 
static shmem_request_hook_type prev_shmem_request_hook = NULL
 
static shmem_startup_hook_type prev_shmem_startup_hook = NULL
 
static PgAioHandlelast_handle
 

Macro Definition Documentation

◆ MAX_BUFFERS_TO_EXTEND_BY

#define MAX_BUFFERS_TO_EXTEND_BY   64

Typedef Documentation

◆ InjIoErrorState

Function Documentation

◆ _PG_init()

void _PG_init ( void  )

Definition at line 122 of file test_aio.c.

123{
125 return;
126
131}
shmem_startup_hook_type shmem_startup_hook
Definition: ipci.c:59
shmem_request_hook_type shmem_request_hook
Definition: miscinit.c:1789
bool process_shared_preload_libraries_in_progress
Definition: miscinit.c:1786
static void test_aio_shmem_request(void)
Definition: test_aio.c:59
static void test_aio_shmem_startup(void)
Definition: test_aio.c:68
static shmem_startup_hook_type prev_shmem_startup_hook
Definition: test_aio.c:51
static shmem_request_hook_type prev_shmem_request_hook
Definition: test_aio.c:50

References prev_shmem_request_hook, prev_shmem_startup_hook, process_shared_preload_libraries_in_progress, shmem_request_hook, shmem_startup_hook, test_aio_shmem_request(), and test_aio_shmem_startup().

◆ batch_end()

Datum batch_end ( PG_FUNCTION_ARGS  )

Definition at line 676 of file test_aio.c.

677{
680}
void pgaio_exit_batchmode(void)
Definition: aio.c:1092
#define PG_RETURN_VOID()
Definition: fmgr.h:349

References PG_RETURN_VOID, and pgaio_exit_batchmode().

◆ batch_start()

Datum batch_start ( PG_FUNCTION_ARGS  )

Definition at line 668 of file test_aio.c.

669{
672}
void pgaio_enter_batchmode(void)
Definition: aio.c:1081

References PG_RETURN_VOID, and pgaio_enter_batchmode().

Referenced by log_newpages().

◆ buffer_call_start_io()

Datum buffer_call_start_io ( PG_FUNCTION_ARGS  )

Definition at line 535 of file test_aio.c.

536{
538 bool for_input = PG_GETARG_BOOL(1);
539 bool nowait = PG_GETARG_BOOL(2);
540 bool can_start;
541
542 if (BufferIsLocal(buf))
544 for_input, nowait);
545 else
546 can_start = StartBufferIO(GetBufferDescriptor(buf - 1),
547 for_input, nowait);
548
549 /*
550 * For tests we don't want the resowner release preventing us from
551 * orchestrating odd scenarios.
552 */
553 if (can_start && !BufferIsLocal(buf))
555 buf);
556
557 ereport(LOG,
558 errmsg("buffer %d after StartBufferIO: %s",
560 errhidestmt(true), errhidecontext(true));
561
562 PG_RETURN_BOOL(can_start);
563}
int Buffer
Definition: buf.h:23
#define BufferIsLocal(buffer)
Definition: buf.h:37
static void ResourceOwnerForgetBufferIO(ResourceOwner owner, Buffer buffer)
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
char * DebugPrintBufferRefcount(Buffer buffer)
Definition: bufmgr.c:4166
bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
Definition: bufmgr.c:6046
int errhidestmt(bool hide_stmt)
Definition: elog.c:1445
int errhidecontext(bool hide_ctx)
Definition: elog.c:1464
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define LOG
Definition: elog.h:31
#define ereport(elevel,...)
Definition: elog.h:150
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
bool StartLocalBufferIO(BufferDesc *bufHdr, bool forInput, bool nowait)
Definition: localbuf.c:523
static char * buf
Definition: pg_test_fsync.c:72
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173

References buf, BufferIsLocal, CurrentResourceOwner, DebugPrintBufferRefcount(), ereport, errhidecontext(), errhidestmt(), errmsg(), GetBufferDescriptor(), GetLocalBufferDescriptor(), LOG, PG_GETARG_BOOL, PG_GETARG_INT32, PG_RETURN_BOOL, ResourceOwnerForgetBufferIO(), StartBufferIO(), and StartLocalBufferIO().

◆ buffer_call_terminate_io()

Datum buffer_call_terminate_io ( PG_FUNCTION_ARGS  )

Definition at line 567 of file test_aio.c.

568{
570 bool for_input = PG_GETARG_BOOL(1);
571 bool succeed = PG_GETARG_BOOL(2);
572 bool io_error = PG_GETARG_BOOL(3);
573 bool release_aio = PG_GETARG_BOOL(4);
574 bool clear_dirty = false;
575 uint32 set_flag_bits = 0;
576
577 if (io_error)
578 set_flag_bits |= BM_IO_ERROR;
579
580 if (for_input)
581 {
582 clear_dirty = false;
583
584 if (succeed)
585 set_flag_bits |= BM_VALID;
586 }
587 else
588 {
589 if (succeed)
590 clear_dirty = true;
591 }
592
593 ereport(LOG,
594 errmsg("buffer %d before Terminate[Local]BufferIO: %s",
596 errhidestmt(true), errhidecontext(true));
597
598 if (BufferIsLocal(buf))
600 clear_dirty, set_flag_bits, release_aio);
601 else
603 clear_dirty, set_flag_bits, false, release_aio);
604
605 ereport(LOG,
606 errmsg("buffer %d after Terminate[Local]BufferIO: %s",
608 errhidestmt(true), errhidecontext(true));
609
611}
#define BM_VALID
Definition: buf_internals.h:70
#define BM_IO_ERROR
Definition: buf_internals.h:73
void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits, bool forget_owner, bool release_aio)
Definition: bufmgr.c:6104
uint32_t uint32
Definition: c.h:541
void TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty, uint32 set_flag_bits, bool release_aio)
Definition: localbuf.c:562

References BM_IO_ERROR, BM_VALID, buf, BufferIsLocal, DebugPrintBufferRefcount(), ereport, errhidecontext(), errhidestmt(), errmsg(), GetBufferDescriptor(), GetLocalBufferDescriptor(), LOG, PG_GETARG_BOOL, PG_GETARG_INT32, PG_RETURN_VOID, TerminateBufferIO(), and TerminateLocalBufferIO().

◆ buffer_create_toy()

Datum buffer_create_toy ( PG_FUNCTION_ARGS  )

Definition at line 516 of file test_aio.c.

517{
518 Oid relid = PG_GETARG_OID(0);
519 BlockNumber blkno = PG_GETARG_UINT32(1);
520 Relation rel;
521 Buffer buf;
522
524
525 buf = create_toy_buffer(rel, blkno);
527
529
531}
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5366
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_UINT32(n)
Definition: fmgr.h:270
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
unsigned int Oid
Definition: postgres_ext.h:32
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
static Buffer create_toy_buffer(Relation rel, BlockNumber blkno)
Definition: test_aio.c:307

References AccessExclusiveLock, buf, create_toy_buffer(), NoLock, PG_GETARG_OID, PG_GETARG_UINT32, PG_RETURN_INT32, relation_close(), relation_open(), and ReleaseBuffer().

◆ create_toy_buffer()

static Buffer create_toy_buffer ( Relation  rel,
BlockNumber  blkno 
)
static

Definition at line 307 of file test_aio.c.

308{
309 Buffer buf;
310 BufferDesc *buf_hdr;
311 uint32 buf_state;
312 bool was_pinned = false;
313 uint32 unset_bits = 0;
314
315 /* place buffer in shared buffers without erroring out */
318
320 {
321 buf_hdr = GetLocalBufferDescriptor(-buf - 1);
322 buf_state = pg_atomic_read_u32(&buf_hdr->state);
323 }
324 else
325 {
326 buf_hdr = GetBufferDescriptor(buf - 1);
327 buf_state = LockBufHdr(buf_hdr);
328 }
329
330 /*
331 * We should be the only backend accessing this buffer. This is just a
332 * small bit of belt-and-suspenders defense, none of this code should ever
333 * run in a cluster with real data.
334 */
335 if (BUF_STATE_GET_REFCOUNT(buf_state) > 1)
336 was_pinned = true;
337 else
338 unset_bits |= BM_VALID | BM_DIRTY;
339
341 {
342 buf_state &= ~unset_bits;
343 pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state);
344 }
345 else
346 {
347 UnlockBufHdrExt(buf_hdr, buf_state, 0, unset_bits, 0);
348 }
349
350 if (was_pinned)
351 elog(ERROR, "toy buffer %d was already pinned",
352 buf);
353
354 return buf;
355}
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:293
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:237
#define BM_DIRTY
Definition: buf_internals.h:69
static uint32 UnlockBufHdrExt(BufferDesc *desc, uint32 old_buf_state, uint32 set_bits, uint32 unset_bits, int refcount_change)
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:59
void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition: bufmgr.c:5604
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:792
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:6264
@ BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:205
@ RBM_ZERO_AND_LOCK
Definition: bufmgr.h:47
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:647
@ MAIN_FORKNUM
Definition: relpath.h:58
pg_atomic_uint32 state

References BM_DIRTY, BM_VALID, buf, BUF_STATE_GET_REFCOUNT, BUFFER_LOCK_UNLOCK, elog, ERROR, GetBufferDescriptor(), GetLocalBufferDescriptor(), LockBuffer(), LockBufHdr(), MAIN_FORKNUM, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), RBM_ZERO_AND_LOCK, ReadBufferExtended(), RelationUsesLocalBuffers, BufferDesc::state, and UnlockBufHdrExt().

Referenced by buffer_create_toy(), and read_rel_block_ll().

◆ errno_from_string()

Datum errno_from_string ( PG_FUNCTION_ARGS  )

Definition at line 136 of file test_aio.c.

137{
138 const char *sym = text_to_cstring(PG_GETARG_TEXT_PP(0));
139
140 if (strcmp(sym, "EIO") == 0)
141 PG_RETURN_INT32(EIO);
142 else if (strcmp(sym, "EAGAIN") == 0)
144 else if (strcmp(sym, "EINTR") == 0)
146 else if (strcmp(sym, "ENOSPC") == 0)
147 PG_RETURN_INT32(ENOSPC);
148 else if (strcmp(sym, "EROFS") == 0)
149 PG_RETURN_INT32(EROFS);
150
152 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
153 errmsg_internal("%s is not a supported errno value", sym));
155}
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1170
int errcode(int sqlerrcode)
Definition: elog.c:863
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
char * text_to_cstring(const text *t)
Definition: varlena.c:214
#define EINTR
Definition: win32_port.h:364
#define EAGAIN
Definition: win32_port.h:362

References EAGAIN, EINTR, ereport, errcode(), errmsg_internal(), ERROR, PG_GETARG_TEXT_PP, PG_RETURN_INT32, and text_to_cstring().

◆ grow_rel()

Datum grow_rel ( PG_FUNCTION_ARGS  )

Definition at line 159 of file test_aio.c.

160{
161 Oid relid = PG_GETARG_OID(0);
162 uint32 nblocks = PG_GETARG_UINT32(1);
163 Relation rel;
164#define MAX_BUFFERS_TO_EXTEND_BY 64
165 Buffer victim_buffers[MAX_BUFFERS_TO_EXTEND_BY];
166
168
169 while (nblocks > 0)
170 {
171 uint32 extend_by_pages;
172
173 extend_by_pages = Min(nblocks, MAX_BUFFERS_TO_EXTEND_BY);
174
177 NULL,
178 0,
179 extend_by_pages,
180 victim_buffers,
181 &extend_by_pages);
182
183 nblocks -= extend_by_pages;
184
185 for (uint32 i = 0; i < extend_by_pages; i++)
186 {
187 ReleaseBuffer(victim_buffers[i]);
188 }
189 }
190
192
194}
BlockNumber ExtendBufferedRelBy(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, Buffer *buffers, uint32 *extended_by)
Definition: bufmgr.c:877
#define BMR_REL(p_rel)
Definition: bufmgr.h:114
#define Min(x, y)
Definition: c.h:1006
int i
Definition: isn.c:77
#define MAX_BUFFERS_TO_EXTEND_BY

References AccessExclusiveLock, BMR_REL, ExtendBufferedRelBy(), i, MAIN_FORKNUM, MAX_BUFFERS_TO_EXTEND_BY, Min, NoLock, PG_GETARG_OID, PG_GETARG_UINT32, PG_RETURN_VOID, relation_close(), relation_open(), and ReleaseBuffer().

◆ handle_get()

Datum handle_get ( PG_FUNCTION_ARGS  )

Definition at line 615 of file test_aio.c.

616{
618
620}
PgAioHandle * pgaio_io_acquire(struct ResourceOwnerData *resowner, PgAioReturn *ret)
Definition: aio.c:162
static PgAioHandle * last_handle
Definition: test_aio.c:54

References CurrentResourceOwner, last_handle, PG_RETURN_VOID, and pgaio_io_acquire().

◆ handle_get_and_error()

Datum handle_get_and_error ( PG_FUNCTION_ARGS  )

Definition at line 636 of file test_aio.c.

637{
639
640 elog(ERROR, "as you command");
642}

References CurrentResourceOwner, elog, ERROR, PG_RETURN_VOID, and pgaio_io_acquire().

◆ handle_get_release()

Datum handle_get_release ( PG_FUNCTION_ARGS  )

Definition at line 656 of file test_aio.c.

657{
658 PgAioHandle *handle;
659
661 pgaio_io_release(handle);
662
664}
void pgaio_io_release(PgAioHandle *ioh)
Definition: aio.c:240

References CurrentResourceOwner, PG_RETURN_VOID, pgaio_io_acquire(), and pgaio_io_release().

◆ handle_get_twice()

Datum handle_get_twice ( PG_FUNCTION_ARGS  )

Definition at line 646 of file test_aio.c.

References CurrentResourceOwner, PG_RETURN_VOID, and pgaio_io_acquire().

◆ handle_release_last()

Datum handle_release_last ( PG_FUNCTION_ARGS  )

Definition at line 624 of file test_aio.c.

625{
626 if (!last_handle)
627 elog(ERROR, "no handle");
628
630
632}

References elog, ERROR, last_handle, PG_RETURN_VOID, and pgaio_io_release().

◆ inj_io_reopen_attach()

Datum inj_io_reopen_attach ( PG_FUNCTION_ARGS  )

Definition at line 795 of file test_aio.c.

796{
797#ifdef USE_INJECTION_POINTS
799#else
800 elog(ERROR, "injection points not supported");
801#endif
802
804}
bool enabled_reopen
Definition: test_aio.c:41
static InjIoErrorState * inj_io_error_state
Definition: test_aio.c:47

References elog, InjIoErrorState::enabled_reopen, ERROR, inj_io_error_state, and PG_RETURN_VOID.

◆ inj_io_reopen_detach()

Datum inj_io_reopen_detach ( PG_FUNCTION_ARGS  )

Definition at line 808 of file test_aio.c.

809{
810#ifdef USE_INJECTION_POINTS
812#else
813 elog(ERROR, "injection points not supported");
814#endif
816}

References elog, InjIoErrorState::enabled_reopen, ERROR, inj_io_error_state, and PG_RETURN_VOID.

◆ inj_io_short_read_attach()

Datum inj_io_short_read_attach ( PG_FUNCTION_ARGS  )

Definition at line 767 of file test_aio.c.

768{
769#ifdef USE_INJECTION_POINTS
774#else
775 elog(ERROR, "injection points not supported");
776#endif
777
779}
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
int short_read_result
Definition: test_aio.c:44
bool enabled_short_read
Definition: test_aio.c:40
bool short_read_result_set
Definition: test_aio.c:43

References elog, InjIoErrorState::enabled_short_read, ERROR, inj_io_error_state, PG_ARGISNULL, PG_GETARG_INT32, PG_RETURN_VOID, InjIoErrorState::short_read_result, and InjIoErrorState::short_read_result_set.

◆ inj_io_short_read_detach()

Datum inj_io_short_read_detach ( PG_FUNCTION_ARGS  )

Definition at line 783 of file test_aio.c.

784{
785#ifdef USE_INJECTION_POINTS
787#else
788 elog(ERROR, "injection points not supported");
789#endif
791}

References elog, InjIoErrorState::enabled_short_read, ERROR, inj_io_error_state, and PG_RETURN_VOID.

◆ invalidate_rel_block()

Datum invalidate_rel_block ( PG_FUNCTION_ARGS  )

Definition at line 463 of file test_aio.c.

464{
465 Oid relid = PG_GETARG_OID(0);
466 BlockNumber blkno = PG_GETARG_UINT32(1);
467 Relation rel;
469 Buffer buf;
470
472
473 /*
474 * This is a gross hack, but there's no other API exposed that allows to
475 * get a buffer ID without actually reading the block in.
476 */
477 pr = PrefetchBuffer(rel, MAIN_FORKNUM, blkno);
478 buf = pr.recent_buffer;
479
480 if (BufferIsValid(buf))
481 {
482 /* if the buffer contents aren't valid, this'll return false */
483 if (ReadRecentBuffer(rel->rd_locator, MAIN_FORKNUM, blkno, buf))
484 {
485 BufferDesc *buf_hdr = BufferIsLocal(buf) ?
488 bool flushed;
489
491
492 if (pg_atomic_read_u32(&buf_hdr->state) & BM_DIRTY)
493 {
494 if (BufferIsLocal(buf))
495 FlushLocalBuffer(buf_hdr, NULL);
496 else
498 }
501
502 if (BufferIsLocal(buf))
504 else if (!EvictUnpinnedBuffer(buf, &flushed))
505 elog(ERROR, "couldn't evict");
506 }
507 }
508
510
512}
PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:653
bool EvictUnpinnedBuffer(Buffer buf, bool *buffer_flushed)
Definition: bufmgr.c:6654
bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, Buffer recent_buffer)
Definition: bufmgr.c:684
void FlushOneBuffer(Buffer buffer)
Definition: bufmgr.c:5346
@ BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:207
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:387
void FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln)
Definition: localbuf.c:183
void InvalidateLocalBuffer(BufferDesc *bufHdr, bool check_unreferenced)
Definition: localbuf.c:605
Buffer recent_buffer
Definition: bufmgr.h:61
RelFileLocator rd_locator
Definition: rel.h:57

References AccessExclusiveLock, BM_DIRTY, buf, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferIsLocal, BufferIsValid(), elog, ERROR, EvictUnpinnedBuffer(), FlushLocalBuffer(), FlushOneBuffer(), GetBufferDescriptor(), GetLocalBufferDescriptor(), InvalidateLocalBuffer(), LockBuffer(), MAIN_FORKNUM, pg_atomic_read_u32(), PG_GETARG_OID, PG_GETARG_UINT32, PG_RETURN_VOID, PrefetchBuffer(), RelationData::rd_locator, ReadRecentBuffer(), PrefetchBufferResult::recent_buffer, relation_close(), relation_open(), ReleaseBuffer(), and BufferDesc::state.

◆ modify_rel_block()

Datum modify_rel_block ( PG_FUNCTION_ARGS  )

Definition at line 198 of file test_aio.c.

199{
200 Oid relid = PG_GETARG_OID(0);
201 BlockNumber blkno = PG_GETARG_UINT32(1);
202 bool zero = PG_GETARG_BOOL(2);
203 bool corrupt_header = PG_GETARG_BOOL(3);
204 bool corrupt_checksum = PG_GETARG_BOOL(4);
205 Page page = palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, 0);
206 bool flushed;
207 Relation rel;
208 Buffer buf;
209 PageHeader ph;
210
212
213 buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno,
214 RBM_ZERO_ON_ERROR, NULL);
215
217
218 /*
219 * copy the page to local memory, seems nicer than to directly modify in
220 * the buffer pool.
221 */
222 memcpy(page, BufferGetPage(buf), BLCKSZ);
223
225
227
228 /*
229 * Don't want to have a buffer in-memory that's marked valid where the
230 * on-disk contents are invalid. Particularly not if the in-memory buffer
231 * could be dirty...
232 *
233 * While we hold an AEL on the relation nobody else should be able to read
234 * the buffer in.
235 *
236 * NB: This is probably racy, better don't copy this to non-test code.
237 */
238 if (BufferIsLocal(buf))
240 else
241 EvictUnpinnedBuffer(buf, &flushed);
242
243 /*
244 * Now modify the page as asked for by the caller.
245 */
246 if (zero)
247 memset(page, 0, BufferGetPageSize(buf));
248
249 if (PageIsEmpty(page) && (corrupt_header || corrupt_checksum))
250 PageInit(page, BufferGetPageSize(buf), 0);
251
252 ph = (PageHeader) page;
253
254 if (corrupt_header)
255 ph->pd_special = BLCKSZ + 1;
256
257 if (corrupt_checksum)
258 {
259 bool successfully_corrupted = 0;
260
261 /*
262 * Any single modification of the checksum could just end up being
263 * valid again, due to e.g. corrupt_header changing the data in a way
264 * that'd result in the "corrupted" checksum, or the checksum already
265 * being invalid. Retry in that, unlikely, case.
266 */
267 for (int i = 0; i < 100; i++)
268 {
269 uint16 verify_checksum;
270 uint16 old_checksum;
271
272 old_checksum = ph->pd_checksum;
273 ph->pd_checksum = old_checksum + 1;
274
275 elog(LOG, "corrupting checksum of blk %u from %u to %u",
276 blkno, old_checksum, ph->pd_checksum);
277
278 verify_checksum = pg_checksum_page(page, blkno);
279 if (verify_checksum != ph->pd_checksum)
280 {
281 successfully_corrupted = true;
282 break;
283 }
284 }
285
286 if (!successfully_corrupted)
287 elog(ERROR, "could not corrupt checksum, what's going on?");
288 }
289 else
290 {
291 PageSetChecksumInplace(page, blkno);
292 }
293
295 MAIN_FORKNUM, blkno, page, true);
296
298
300}
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:436
static Size BufferGetPageSize(Buffer buffer)
Definition: bufmgr.h:425
@ RBM_ZERO_ON_ERROR
Definition: bufmgr.h:51
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1541
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:42
static bool PageIsEmpty(const PageData *page)
Definition: bufpage.h:223
PageHeaderData * PageHeader
Definition: bufpage.h:173
PageData * Page
Definition: bufpage.h:81
uint16_t uint16
Definition: c.h:540
uint16 pg_checksum_page(char *page, BlockNumber blkno)
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1584
#define PG_IO_ALIGN_SIZE
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:577
static void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition: smgr.h:131
LocationIndex pd_special
Definition: bufpage.h:167
uint16 pd_checksum
Definition: bufpage.h:163

References AccessExclusiveLock, buf, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetPage(), BufferGetPageSize(), BufferIsLocal, elog, ERROR, EvictUnpinnedBuffer(), GetLocalBufferDescriptor(), i, InvalidateLocalBuffer(), LockBuffer(), LOG, MAIN_FORKNUM, NoLock, PageInit(), PageIsEmpty(), PageSetChecksumInplace(), palloc_aligned(), PageHeaderData::pd_checksum, PageHeaderData::pd_special, pg_checksum_page(), PG_GETARG_BOOL, PG_GETARG_OID, PG_GETARG_UINT32, PG_IO_ALIGN_SIZE, PG_RETURN_VOID, RBM_ZERO_ON_ERROR, ReadBufferExtended(), relation_close(), relation_open(), RelationGetSmgr(), ReleaseBuffer(), and smgrwrite().

◆ PG_FUNCTION_INFO_V1() [1/19]

PG_FUNCTION_INFO_V1 ( batch_end  )

◆ PG_FUNCTION_INFO_V1() [2/19]

PG_FUNCTION_INFO_V1 ( batch_start  )

◆ PG_FUNCTION_INFO_V1() [3/19]

PG_FUNCTION_INFO_V1 ( buffer_call_start_io  )

◆ PG_FUNCTION_INFO_V1() [4/19]

PG_FUNCTION_INFO_V1 ( buffer_call_terminate_io  )

◆ PG_FUNCTION_INFO_V1() [5/19]

PG_FUNCTION_INFO_V1 ( buffer_create_toy  )

◆ PG_FUNCTION_INFO_V1() [6/19]

PG_FUNCTION_INFO_V1 ( errno_from_string  )

◆ PG_FUNCTION_INFO_V1() [7/19]

PG_FUNCTION_INFO_V1 ( grow_rel  )

◆ PG_FUNCTION_INFO_V1() [8/19]

PG_FUNCTION_INFO_V1 ( handle_get  )

◆ PG_FUNCTION_INFO_V1() [9/19]

PG_FUNCTION_INFO_V1 ( handle_get_and_error  )

◆ PG_FUNCTION_INFO_V1() [10/19]

PG_FUNCTION_INFO_V1 ( handle_get_release  )

◆ PG_FUNCTION_INFO_V1() [11/19]

PG_FUNCTION_INFO_V1 ( handle_get_twice  )

◆ PG_FUNCTION_INFO_V1() [12/19]

PG_FUNCTION_INFO_V1 ( handle_release_last  )

◆ PG_FUNCTION_INFO_V1() [13/19]

PG_FUNCTION_INFO_V1 ( inj_io_reopen_attach  )

◆ PG_FUNCTION_INFO_V1() [14/19]

PG_FUNCTION_INFO_V1 ( inj_io_reopen_detach  )

◆ PG_FUNCTION_INFO_V1() [15/19]

PG_FUNCTION_INFO_V1 ( inj_io_short_read_attach  )

◆ PG_FUNCTION_INFO_V1() [16/19]

PG_FUNCTION_INFO_V1 ( inj_io_short_read_detach  )

◆ PG_FUNCTION_INFO_V1() [17/19]

PG_FUNCTION_INFO_V1 ( invalidate_rel_block  )

◆ PG_FUNCTION_INFO_V1() [18/19]

PG_FUNCTION_INFO_V1 ( modify_rel_block  )

◆ PG_FUNCTION_INFO_V1() [19/19]

PG_FUNCTION_INFO_V1 ( read_rel_block_ll  )

◆ read_rel_block_ll()

Datum read_rel_block_ll ( PG_FUNCTION_ARGS  )

Definition at line 364 of file test_aio.c.

365{
366 Oid relid = PG_GETARG_OID(0);
367 BlockNumber blkno = PG_GETARG_UINT32(1);
368 int nblocks = PG_GETARG_INT32(2);
369 bool wait_complete = PG_GETARG_BOOL(3);
370 bool batchmode_enter = PG_GETARG_BOOL(4);
371 bool call_smgrreleaseall = PG_GETARG_BOOL(5);
372 bool batchmode_exit = PG_GETARG_BOOL(6);
373 bool zero_on_error = PG_GETARG_BOOL(7);
374 Relation rel;
375 Buffer bufs[PG_IOV_MAX];
376 BufferDesc *buf_hdrs[PG_IOV_MAX];
377 Page pages[PG_IOV_MAX];
378 uint8 srb_flags = 0;
379 PgAioReturn ior;
380 PgAioHandle *ioh;
381 PgAioWaitRef iow;
382 SMgrRelation smgr;
383
384 if (nblocks <= 0 || nblocks > PG_IOV_MAX)
385 elog(ERROR, "nblocks is out of range");
386
388
389 for (int i = 0; i < nblocks; i++)
390 {
391 bufs[i] = create_toy_buffer(rel, blkno + i);
392 pages[i] = BufferGetBlock(bufs[i]);
393 buf_hdrs[i] = BufferIsLocal(bufs[i]) ?
394 GetLocalBufferDescriptor(-bufs[i] - 1) :
395 GetBufferDescriptor(bufs[i] - 1);
396 }
397
398 smgr = RelationGetSmgr(rel);
399
401
403 pgaio_io_get_wref(ioh, &iow);
404
406 {
407 for (int i = 0; i < nblocks; i++)
408 StartLocalBufferIO(buf_hdrs[i], true, false);
410 }
411 else
412 {
413 for (int i = 0; i < nblocks; i++)
414 StartBufferIO(buf_hdrs[i], true, false);
415 }
416
417 pgaio_io_set_handle_data_32(ioh, (uint32 *) bufs, nblocks);
418
419 if (zero_on_error | zero_damaged_pages)
420 srb_flags |= READ_BUFFERS_ZERO_ON_ERROR;
423
428 srb_flags);
429
430 if (batchmode_enter)
432
433 smgrstartreadv(ioh, smgr, MAIN_FORKNUM, blkno,
434 (void *) pages, nblocks);
435
436 if (call_smgrreleaseall)
438
439 if (batchmode_exit)
441
442 for (int i = 0; i < nblocks; i++)
443 ReleaseBuffer(bufs[i]);
444
445 if (wait_complete)
446 {
447 pgaio_wref_wait(&iow);
448
449 if (ior.result.status != PGAIO_RS_OK)
451 &ior.target_data,
453 ERROR : WARNING);
454 }
455
457
459}
void pgaio_io_get_wref(PgAioHandle *ioh, PgAioWaitRef *iow)
Definition: aio.c:366
void pgaio_io_set_flag(PgAioHandle *ioh, PgAioHandleFlags flag)
Definition: aio.c:330
void pgaio_wref_wait(PgAioWaitRef *iow)
Definition: aio.c:991
@ PGAIO_HCB_LOCAL_BUFFER_READV
Definition: aio.h:200
@ PGAIO_HCB_SHARED_BUFFER_READV
Definition: aio.h:198
@ PGAIO_HF_REFERENCES_LOCAL
Definition: aio.h:60
void pgaio_io_set_handle_data_32(PgAioHandle *ioh, uint32 *data, uint8 len)
Definition: aio_callback.c:140
void pgaio_io_register_callbacks(PgAioHandle *ioh, PgAioHandleCallbackID cb_id, uint8 cb_data)
Definition: aio_callback.c:86
void pgaio_result_report(PgAioResult result, const PgAioTargetData *target_data, int elevel)
Definition: aio_callback.c:173
@ PGAIO_RS_OK
Definition: aio_types.h:81
@ PGAIO_RS_ERROR
Definition: aio_types.h:84
bool zero_damaged_pages
Definition: bufmgr.c:144
#define READ_BUFFERS_ZERO_ON_ERROR
Definition: bufmgr.h:122
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:403
#define READ_BUFFERS_IGNORE_CHECKSUM_FAILURES
Definition: bufmgr.h:126
bool ignore_checksum_failure
Definition: bufpage.c:27
uint8_t uint8
Definition: c.h:539
#define WARNING
Definition: elog.h:36
#define PG_IOV_MAX
Definition: pg_iovec.h:47
void pgstat_prepare_report_checksum_failure(Oid dboid)
void smgrstartreadv(PgAioHandle *ioh, SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void **buffers, BlockNumber nblocks)
Definition: smgr.c:753
void smgrreleaseall(void)
Definition: smgr.c:412
uint32 status
Definition: aio_types.h:108
PgAioResult result
Definition: aio_types.h:132
PgAioTargetData target_data
Definition: aio_types.h:133
RelFileLocator locator
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:38

References AccessExclusiveLock, BufferGetBlock(), BufferIsLocal, create_toy_buffer(), CurrentResourceOwner, RelFileLocator::dbOid, elog, ERROR, GetBufferDescriptor(), GetLocalBufferDescriptor(), i, ignore_checksum_failure, RelFileLocatorBackend::locator, MAIN_FORKNUM, NoLock, PG_GETARG_BOOL, PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_UINT32, PG_IOV_MAX, PG_RETURN_VOID, pgaio_enter_batchmode(), pgaio_exit_batchmode(), PGAIO_HCB_LOCAL_BUFFER_READV, PGAIO_HCB_SHARED_BUFFER_READV, PGAIO_HF_REFERENCES_LOCAL, pgaio_io_acquire(), pgaio_io_get_wref(), pgaio_io_register_callbacks(), pgaio_io_set_flag(), pgaio_io_set_handle_data_32(), pgaio_result_report(), PGAIO_RS_ERROR, PGAIO_RS_OK, pgaio_wref_wait(), pgstat_prepare_report_checksum_failure(), READ_BUFFERS_IGNORE_CHECKSUM_FAILURES, READ_BUFFERS_ZERO_ON_ERROR, relation_close(), relation_open(), RelationGetSmgr(), RelationUsesLocalBuffers, ReleaseBuffer(), PgAioReturn::result, SMgrRelationData::smgr_rlocator, smgrreleaseall(), smgrstartreadv(), StartBufferIO(), StartLocalBufferIO(), PgAioResult::status, PgAioReturn::target_data, WARNING, and zero_damaged_pages.

◆ test_aio_shmem_request()

static void test_aio_shmem_request ( void  )
static

Definition at line 59 of file test_aio.c.

60{
63
65}
void RequestAddinShmemSpace(Size size)
Definition: ipci.c:75

References prev_shmem_request_hook, and RequestAddinShmemSpace().

Referenced by _PG_init().

◆ test_aio_shmem_startup()

static void test_aio_shmem_startup ( void  )
static

Definition at line 68 of file test_aio.c.

69{
70 bool found;
71
74
75 /* Create or attach to the shared memory state */
76 LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
77
78 inj_io_error_state = ShmemInitStruct("injection_points",
79 sizeof(InjIoErrorState),
80 &found);
81
82 if (!found)
83 {
84 /* First time through, initialize */
87
88#ifdef USE_INJECTION_POINTS
89 InjectionPointAttach("aio-process-completion-before-shared",
90 "test_aio",
91 "inj_io_short_read",
92 NULL,
93 0);
94 InjectionPointLoad("aio-process-completion-before-shared");
95
96 InjectionPointAttach("aio-worker-after-reopen",
97 "test_aio",
98 "inj_io_reopen",
99 NULL,
100 0);
101 InjectionPointLoad("aio-worker-after-reopen");
102
103#endif
104 }
105 else
106 {
107 /*
108 * Pre-load the injection points now, so we can call them in a
109 * critical section.
110 */
111#ifdef USE_INJECTION_POINTS
112 InjectionPointLoad("aio-process-completion-before-shared");
113 InjectionPointLoad("aio-worker-after-reopen");
114 elog(LOG, "injection point loaded");
115#endif
116 }
117
118 LWLockRelease(AddinShmemInitLock);
119}
void InjectionPointLoad(const char *name)
void InjectionPointAttach(const char *name, const char *library, const char *function, const void *private_data, int private_data_size)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1174
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1894
@ LW_EXCLUSIVE
Definition: lwlock.h:112
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:389

References elog, InjIoErrorState::enabled_reopen, InjIoErrorState::enabled_short_read, inj_io_error_state, InjectionPointAttach(), InjectionPointLoad(), LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), prev_shmem_startup_hook, and ShmemInitStruct().

Referenced by _PG_init().

Variable Documentation

◆ inj_io_error_state

◆ last_handle

PgAioHandle* last_handle
static

Definition at line 54 of file test_aio.c.

Referenced by handle_get(), and handle_release_last().

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 35 of file test_aio.c.

◆ prev_shmem_request_hook

shmem_request_hook_type prev_shmem_request_hook = NULL
static

Definition at line 50 of file test_aio.c.

Referenced by _PG_init(), and test_aio_shmem_request().

◆ prev_shmem_startup_hook

shmem_startup_hook_type prev_shmem_startup_hook = NULL
static

Definition at line 51 of file test_aio.c.

Referenced by _PG_init(), and test_aio_shmem_startup().