PostgreSQL Source Code git master
Loading...
Searching...
No Matches
test_aio.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * test_aio.c
4 * Helpers to write tests for AIO
5 *
6 * This module provides interface functions for C functionality to SQL, to
7 * make it possible to test AIO related behavior in a targeted way from SQL.
8 * It'd not generally be safe to export these functions to SQL, but for a test
9 * that's fine.
10 *
11 * Copyright (c) 2020-2026, PostgreSQL Global Development Group
12 *
13 * IDENTIFICATION
14 * src/test/modules/test_aio/test_aio.c
15 *
16 *-------------------------------------------------------------------------
17 */
18
19#include "postgres.h"
20
21#include "access/relation.h"
22#include "fmgr.h"
23#include "storage/aio.h"
26#include "storage/bufmgr.h"
27#include "storage/checksum.h"
28#include "storage/ipc.h"
29#include "storage/lwlock.h"
30#include "utils/builtins.h"
32#include "utils/rel.h"
33
34
36
37
46
48
49/* Shared memory init callbacks */
52
53
55
56
57
58static void
66
67static void
69{
70 bool found;
71
74
75 /* Create or attach to the shared memory state */
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
119}
120
121void
132
133
135Datum
137{
138 const char *sym = text_to_cstring(PG_GETARG_TEXT_PP(0));
139
140 if (strcmp(sym, "EIO") == 0)
142 else if (strcmp(sym, "EAGAIN") == 0)
144 else if (strcmp(sym, "EINTR") == 0)
146 else if (strcmp(sym, "ENOSPC") == 0)
148 else if (strcmp(sym, "EROFS") == 0)
150
153 errmsg_internal("%s is not a supported errno value", sym));
155}
156
158Datum
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
166
168
169 while (nblocks > 0)
170 {
172
174
177 NULL,
178 0,
182
183 nblocks -= extend_by_pages;
184
185 for (uint32 i = 0; i < extend_by_pages; i++)
186 {
188 }
189 }
190
192
194}
195
197Datum
199{
200 Oid relid = PG_GETARG_OID(0);
201 BlockNumber blkno = PG_GETARG_UINT32(1);
202 bool zero = PG_GETARG_BOOL(2);
206 bool flushed;
207 Relation rel;
208 Buffer buf;
210
212
213 buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno,
215
217
218 /*
219 * copy the page to local memory, seems nicer than to directly modify in
220 * the buffer pool.
221 */
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
242
243 /*
244 * Now modify the page as asked for by the caller.
245 */
246 if (zero)
247 memset(page, 0, BufferGetPageSize(buf));
248
250 PageInit(page, BufferGetPageSize(buf), 0);
251
252 ph = (PageHeader) page;
253
254 if (corrupt_header)
255 ph->pd_special = BLCKSZ + 1;
256
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;
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 {
282 break;
283 }
284 }
285
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}
301
302/*
303 * Ensures a buffer for rel & blkno is in shared buffers, without actually
304 * caring about the buffer contents. Used to set up test scenarios.
305 */
306static Buffer
308{
309 Buffer buf;
312 bool was_pinned = false;
313 uint64 unset_bits = 0;
314
315 /* place buffer in shared buffers without erroring out */
318
320 {
323 }
324 else
325 {
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 */
336 was_pinned = true;
337 else
339
341 {
344 }
345 else
346 {
348 }
349
350 if (was_pinned)
351 elog(ERROR, "toy buffer %d was already pinned",
352 buf);
353
354 return buf;
355}
356
357/*
358 * A "low level" read. This does similar things to what
359 * StartReadBuffers()/WaitReadBuffers() do, but provides more control (and
360 * less sanity).
361 */
363Datum
365{
366 Oid relid = PG_GETARG_OID(0);
367 BlockNumber blkno = PG_GETARG_UINT32(1);
368 int nblocks = PG_GETARG_INT32(2);
374 Relation rel;
377 Page pages[PG_IOV_MAX];
378 uint8 srb_flags = 0;
382 SMgrRelation smgr;
383
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]);
396 }
397
398 smgr = RelationGetSmgr(rel);
399
401
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
418
423
428 srb_flags);
429
430 if (batchmode_enter)
432
433 smgrstartreadv(ioh, smgr, MAIN_FORKNUM, blkno,
434 (void *) pages, nblocks);
435
438
439 if (batchmode_exit)
441
442 for (int i = 0; i < nblocks; i++)
444
445 if (wait_complete)
446 {
448
449 if (ior.result.status != PGAIO_RS_OK)
451 &ior.target_data,
452 ior.result.status == PGAIO_RS_ERROR ?
453 ERROR : WARNING);
454 }
455
457
459}
460
462Datum
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 {
488 bool flushed;
489
491
492 if (pg_atomic_read_u64(&buf_hdr->state) & BM_DIRTY)
493 {
494 if (BufferIsLocal(buf))
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}
513
515Datum
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}
532
534Datum
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
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
563}
564
566Datum
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;
576
577 if (io_error)
579
580 if (for_input)
581 {
582 clear_dirty = false;
583
584 if (succeed)
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))
601 else
604
605 ereport(LOG,
606 errmsg("buffer %d after Terminate[Local]BufferIO: %s",
608 errhidestmt(true), errhidecontext(true));
609
611}
612
614Datum
621
623Datum
625{
626 if (!last_handle)
627 elog(ERROR, "no handle");
628
630
632}
633
635Datum
643
645Datum
653
655Datum
665
667Datum
673
675Datum
681
682#ifdef USE_INJECTION_POINTS
683extern PGDLLEXPORT void inj_io_short_read(const char *name,
684 const void *private_data,
685 void *arg);
686extern PGDLLEXPORT void inj_io_reopen(const char *name,
687 const void *private_data,
688 void *arg);
689
690void
691inj_io_short_read(const char *name, const void *private_data, void *arg)
692{
694
695 ereport(LOG,
696 errmsg("short read injection point called, is enabled: %d",
698 errhidestmt(true), errhidecontext(true));
699
701 {
702 /*
703 * Only shorten reads that are actually longer than the target size,
704 * otherwise we can trigger over-reads.
705 */
707 && ioh->op == PGAIO_OP_READV
709 {
710 struct iovec *iov = &pgaio_ctl->iovecs[ioh->iovec_off];
711 int32 old_result = ioh->result;
713 int32 processed = 0;
714
715 ereport(LOG,
716 errmsg("short read inject point, changing result from %d to %d",
718 errhidestmt(true), errhidecontext(true));
719
720 /*
721 * The underlying IO actually completed OK, and thus the "invalid"
722 * portion of the IOV actually contains valid data. That can hide
723 * a lot of problems, e.g. if we were to wrongly mark a buffer,
724 * that wasn't read according to the shortened-read, IO as valid,
725 * the contents would look valid and we might miss a bug.
726 *
727 * To avoid that, iterate through the IOV and zero out the
728 * "failed" portion of the IO.
729 */
730 for (int i = 0; i < ioh->op_data.read.iov_length; i++)
731 {
732 if (processed + iov[i].iov_len <= new_result)
733 processed += iov[i].iov_len;
734 else if (processed <= new_result)
735 {
736 uint32 ok_part = new_result - processed;
737
738 memset((char *) iov[i].iov_base + ok_part, 0, iov[i].iov_len - ok_part);
739 processed += iov[i].iov_len;
740 }
741 else
742 {
743 memset((char *) iov[i].iov_base, 0, iov[i].iov_len);
744 }
745 }
746
747 ioh->result = new_result;
748 }
749 }
750}
751
752void
753inj_io_reopen(const char *name, const void *private_data, void *arg)
754{
755 ereport(LOG,
756 errmsg("reopen injection point called, is enabled: %d",
758 errhidestmt(true), errhidecontext(true));
759
761 elog(ERROR, "injection point triggering failure to reopen ");
762}
763#endif
764
766Datum
768{
769#ifdef USE_INJECTION_POINTS
774#else
775 elog(ERROR, "injection points not supported");
776#endif
777
779}
780
782Datum
784{
785#ifdef USE_INJECTION_POINTS
787#else
788 elog(ERROR, "injection points not supported");
789#endif
791}
792
794Datum
796{
797#ifdef USE_INJECTION_POINTS
799#else
800 elog(ERROR, "injection points not supported");
801#endif
802
804}
805
807Datum
809{
810#ifdef USE_INJECTION_POINTS
812#else
813 elog(ERROR, "injection points not supported");
814#endif
816}
PgAioHandle * pgaio_io_acquire(struct ResourceOwnerData *resowner, PgAioReturn *ret)
Definition aio.c:162
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
PgAioCtl * pgaio_ctl
Definition aio.c:78
void pgaio_enter_batchmode(void)
Definition aio.c:1081
void pgaio_wref_wait(PgAioWaitRef *iow)
Definition aio.c:991
void pgaio_io_release(PgAioHandle *ioh)
Definition aio.c:240
void pgaio_exit_batchmode(void)
Definition aio.c:1092
@ PGAIO_HCB_LOCAL_BUFFER_READV
Definition aio.h:200
@ PGAIO_HCB_SHARED_BUFFER_READV
Definition aio.h:198
@ PGAIO_OP_READV
Definition aio.h:92
@ PGAIO_HF_REFERENCES_LOCAL
Definition aio.h:60
void pgaio_io_set_handle_data_32(PgAioHandle *ioh, uint32 *data, uint8 len)
void pgaio_io_register_callbacks(PgAioHandle *ioh, PgAioHandleCallbackID cb_id, uint8 cb_data)
void pgaio_result_report(PgAioResult result, const PgAioTargetData *target_data, int elevel)
@ PGAIO_RS_OK
Definition aio_types.h:81
@ PGAIO_RS_ERROR
Definition aio_types.h:84
static void pg_atomic_unlocked_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition atomics.h:494
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition atomics.h:467
uint32 BlockNumber
Definition block.h:31
int Buffer
Definition buf.h:23
#define BufferIsLocal(buffer)
Definition buf.h:37
static uint64 UnlockBufHdrExt(BufferDesc *desc, uint64 old_buf_state, uint64 set_bits, uint64 unset_bits, int refcount_change)
#define BM_DIRTY
static void ResourceOwnerForgetBufferIO(ResourceOwner owner, Buffer buffer)
#define BUF_STATE_GET_REFCOUNT(state)
#define BM_VALID
#define BM_IO_ERROR
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
Definition bufmgr.c:772
bool zero_damaged_pages
Definition bufmgr.c:173
BlockNumber ExtendBufferedRelBy(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, Buffer *buffers, uint32 *extended_by)
Definition bufmgr.c:996
char * DebugPrintBufferRefcount(Buffer buffer)
Definition bufmgr.c:4299
uint64 LockBufHdr(BufferDesc *desc)
Definition bufmgr.c:7097
void ReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5501
bool EvictUnpinnedBuffer(Buffer buf, bool *buffer_flushed)
Definition bufmgr.c:7532
bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, Buffer recent_buffer)
Definition bufmgr.c:803
void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint64 set_flag_bits, bool forget_owner, bool release_aio)
Definition bufmgr.c:6937
bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
Definition bufmgr.c:6879
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition bufmgr.c:911
void FlushOneBuffer(Buffer buffer)
Definition bufmgr.c:5481
#define READ_BUFFERS_ZERO_ON_ERROR
Definition bufmgr.h:122
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:466
static Block BufferGetBlock(Buffer buffer)
Definition bufmgr.h:433
@ BUFFER_LOCK_EXCLUSIVE
Definition bufmgr.h:220
@ BUFFER_LOCK_UNLOCK
Definition bufmgr.h:205
#define READ_BUFFERS_IGNORE_CHECKSUM_FAILURES
Definition bufmgr.h:126
static Size BufferGetPageSize(Buffer buffer)
Definition bufmgr.h:455
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:328
@ RBM_ZERO_ON_ERROR
Definition bufmgr.h:51
@ RBM_ZERO_AND_LOCK
Definition bufmgr.h:47
#define BMR_REL(p_rel)
Definition bufmgr.h:114
static bool BufferIsValid(Buffer bufnum)
Definition bufmgr.h:417
bool ignore_checksum_failure
Definition bufpage.c:27
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
#define Min(x, y)
Definition c.h:997
uint8_t uint8
Definition c.h:544
#define PGDLLEXPORT
Definition c.h:1343
int32_t int32
Definition c.h:542
uint64_t uint64
Definition c.h:547
uint16_t uint16
Definition c.h:545
uint32_t uint32
Definition c.h:546
uint16 pg_checksum_page(char *page, BlockNumber blkno)
int errmsg_internal(const char *fmt,...)
Definition elog.c:1170
int errhidestmt(bool hide_stmt)
Definition elog.c:1445
int errhidecontext(bool hide_ctx)
Definition elog.c:1464
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define LOG
Definition elog.h:31
#define WARNING
Definition elog.h:36
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
#define PG_GETARG_UINT32(n)
Definition fmgr.h:270
#define PG_ARGISNULL(n)
Definition fmgr.h:209
#define PG_FUNCTION_INFO_V1(funcname)
Definition fmgr.h:417
#define PG_RETURN_INT32(x)
Definition fmgr.h:355
#define PG_GETARG_INT32(n)
Definition fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
void InjectionPointLoad(const char *name)
void InjectionPointAttach(const char *name, const char *library, const char *function, const void *private_data, int private_data_size)
void(* shmem_startup_hook_type)(void)
Definition ipc.h:22
shmem_startup_hook_type shmem_startup_hook
Definition ipci.c:59
void RequestAddinShmemSpace(Size size)
Definition ipci.c:75
int i
Definition isn.c:77
void FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln)
Definition localbuf.c:183
bool StartLocalBufferIO(BufferDesc *bufHdr, bool forInput, bool nowait)
Definition localbuf.c:523
void InvalidateLocalBuffer(BufferDesc *bufHdr, bool check_unreferenced)
Definition localbuf.c:605
void TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty, uint64 set_flag_bits, bool release_aio)
Definition localbuf.c:562
#define NoLock
Definition lockdefs.h:34
#define AccessExclusiveLock
Definition lockdefs.h:43
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1176
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1793
@ LW_EXCLUSIVE
Definition lwlock.h:112
void * palloc_aligned(Size size, Size alignto, int flags)
Definition mcxt.c:1606
void(* shmem_request_hook_type)(void)
Definition miscadmin.h:533
shmem_request_hook_type shmem_request_hook
Definition miscinit.c:1789
bool process_shared_preload_libraries_in_progress
Definition miscinit.c:1786
void * arg
#define PG_IO_ALIGN_SIZE
#define PG_IOV_MAX
Definition pg_iovec.h:47
static char buf[DEFAULT_XLOG_SEG_SIZE]
void pgstat_prepare_report_checksum_failure(Oid dboid)
uint64_t Datum
Definition postgres.h:70
unsigned int Oid
static int fb(int x)
static SMgrRelation RelationGetSmgr(Relation rel)
Definition rel.h:576
#define RelationUsesLocalBuffers(relation)
Definition rel.h:646
@ MAIN_FORKNUM
Definition relpath.h:58
ResourceOwner CurrentResourceOwner
Definition resowner.c:173
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:389
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
static void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition smgr.h:131
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:47
bool enabled_reopen
Definition test_aio.c:41
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
struct iovec * iovecs
RelFileLocator locator
RelFileLocator rd_locator
Definition rel.h:57
RelFileLocatorBackend smgr_rlocator
Definition smgr.h:38
static void test_aio_shmem_request(void)
Definition test_aio.c:59
Datum batch_end(PG_FUNCTION_ARGS)
Definition test_aio.c:676
static Buffer create_toy_buffer(Relation rel, BlockNumber blkno)
Definition test_aio.c:307
void _PG_init(void)
Definition test_aio.c:122
Datum buffer_create_toy(PG_FUNCTION_ARGS)
Definition test_aio.c:516
Datum inj_io_reopen_detach(PG_FUNCTION_ARGS)
Definition test_aio.c:808
Datum buffer_call_terminate_io(PG_FUNCTION_ARGS)
Definition test_aio.c:567
static PgAioHandle * last_handle
Definition test_aio.c:54
Datum read_rel_block_ll(PG_FUNCTION_ARGS)
Definition test_aio.c:364
PG_MODULE_MAGIC
Definition test_aio.c:35
Datum invalidate_rel_block(PG_FUNCTION_ARGS)
Definition test_aio.c:463
Datum grow_rel(PG_FUNCTION_ARGS)
Definition test_aio.c:159
static void test_aio_shmem_startup(void)
Definition test_aio.c:68
Datum handle_get_release(PG_FUNCTION_ARGS)
Definition test_aio.c:656
Datum buffer_call_start_io(PG_FUNCTION_ARGS)
Definition test_aio.c:535
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
#define MAX_BUFFERS_TO_EXTEND_BY
Datum inj_io_reopen_attach(PG_FUNCTION_ARGS)
Definition test_aio.c:795
Datum inj_io_short_read_detach(PG_FUNCTION_ARGS)
Definition test_aio.c:783
Datum handle_get(PG_FUNCTION_ARGS)
Definition test_aio.c:615
Datum batch_start(PG_FUNCTION_ARGS)
Definition test_aio.c:668
Datum modify_rel_block(PG_FUNCTION_ARGS)
Definition test_aio.c:198
Datum handle_get_and_error(PG_FUNCTION_ARGS)
Definition test_aio.c:636
Datum inj_io_short_read_attach(PG_FUNCTION_ARGS)
Definition test_aio.c:767
static InjIoErrorState * inj_io_error_state
Definition test_aio.c:47
Datum handle_release_last(PG_FUNCTION_ARGS)
Definition test_aio.c:624
Datum handle_get_twice(PG_FUNCTION_ARGS)
Definition test_aio.c:646
Datum errno_from_string(PG_FUNCTION_ARGS)
Definition test_aio.c:136
char * text_to_cstring(const text *t)
Definition varlena.c:214
const char * name
#define EINTR
Definition win32_port.h:361
#define EAGAIN
Definition win32_port.h:359