PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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-2025, 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
38typedef struct InjIoErrorState
39{
42
46
48
49/* Shared memory init callbacks */
52
53
55
56
57
58static void
60{
63
65}
66
67static void
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}
120
121void
123{
125 return;
126
131}
132
133
135Datum
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}
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
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}
195
197Datum
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}
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;
310 BufferDesc *buf_hdr;
311 uint32 buf_state;
312 bool was_pinned = false;
313
314 /* place buffer in shared buffers without erroring out */
317
319 {
320 buf_hdr = GetLocalBufferDescriptor(-buf - 1);
321 buf_state = pg_atomic_read_u32(&buf_hdr->state);
322 }
323 else
324 {
325 buf_hdr = GetBufferDescriptor(buf - 1);
326 buf_state = LockBufHdr(buf_hdr);
327 }
328
329 /*
330 * We should be the only backend accessing this buffer. This is just a
331 * small bit of belt-and-suspenders defense, none of this code should ever
332 * run in a cluster with real data.
333 */
334 if (BUF_STATE_GET_REFCOUNT(buf_state) > 1)
335 was_pinned = true;
336 else
337 buf_state &= ~(BM_VALID | BM_DIRTY);
338
340 pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state);
341 else
342 UnlockBufHdr(buf_hdr, buf_state);
343
344 if (was_pinned)
345 elog(ERROR, "toy buffer %d was already pinned",
346 buf);
347
348 return buf;
349}
350
351/*
352 * A "low level" read. This does similar things to what
353 * StartReadBuffers()/WaitReadBuffers() do, but provides more control (and
354 * less sanity).
355 */
357Datum
359{
360 Oid relid = PG_GETARG_OID(0);
361 BlockNumber blkno = PG_GETARG_UINT32(1);
362 int nblocks = PG_GETARG_INT32(2);
363 bool wait_complete = PG_GETARG_BOOL(3);
364 bool batchmode_enter = PG_GETARG_BOOL(4);
365 bool call_smgrreleaseall = PG_GETARG_BOOL(5);
366 bool batchmode_exit = PG_GETARG_BOOL(6);
367 bool zero_on_error = PG_GETARG_BOOL(7);
368 Relation rel;
369 Buffer bufs[PG_IOV_MAX];
370 BufferDesc *buf_hdrs[PG_IOV_MAX];
371 Page pages[PG_IOV_MAX];
372 uint8 srb_flags = 0;
373 PgAioReturn ior;
374 PgAioHandle *ioh;
375 PgAioWaitRef iow;
376 SMgrRelation smgr;
377
378 if (nblocks <= 0 || nblocks > PG_IOV_MAX)
379 elog(ERROR, "nblocks is out of range");
380
382
383 for (int i = 0; i < nblocks; i++)
384 {
385 bufs[i] = create_toy_buffer(rel, blkno + i);
386 pages[i] = BufferGetBlock(bufs[i]);
387 buf_hdrs[i] = BufferIsLocal(bufs[i]) ?
388 GetLocalBufferDescriptor(-bufs[i] - 1) :
389 GetBufferDescriptor(bufs[i] - 1);
390 }
391
392 smgr = RelationGetSmgr(rel);
393
395
397 pgaio_io_get_wref(ioh, &iow);
398
400 {
401 for (int i = 0; i < nblocks; i++)
402 StartLocalBufferIO(buf_hdrs[i], true, false);
404 }
405 else
406 {
407 for (int i = 0; i < nblocks; i++)
408 StartBufferIO(buf_hdrs[i], true, false);
409 }
410
411 pgaio_io_set_handle_data_32(ioh, (uint32 *) bufs, nblocks);
412
413 if (zero_on_error | zero_damaged_pages)
414 srb_flags |= READ_BUFFERS_ZERO_ON_ERROR;
417
422 srb_flags);
423
424 if (batchmode_enter)
426
427 smgrstartreadv(ioh, smgr, MAIN_FORKNUM, blkno,
428 (void *) pages, nblocks);
429
430 if (call_smgrreleaseall)
432
433 if (batchmode_exit)
435
436 for (int i = 0; i < nblocks; i++)
437 ReleaseBuffer(bufs[i]);
438
439 if (wait_complete)
440 {
441 pgaio_wref_wait(&iow);
442
443 if (ior.result.status != PGAIO_RS_OK)
445 &ior.target_data,
447 ERROR : WARNING);
448 }
449
451
453}
454
456Datum
458{
459 Oid relid = PG_GETARG_OID(0);
460 BlockNumber blkno = PG_GETARG_UINT32(1);
461 Relation rel;
463 Buffer buf;
464
466
467 /*
468 * This is a gross hack, but there's no other API exposed that allows to
469 * get a buffer ID without actually reading the block in.
470 */
471 pr = PrefetchBuffer(rel, MAIN_FORKNUM, blkno);
472 buf = pr.recent_buffer;
473
474 if (BufferIsValid(buf))
475 {
476 /* if the buffer contents aren't valid, this'll return false */
477 if (ReadRecentBuffer(rel->rd_locator, MAIN_FORKNUM, blkno, buf))
478 {
479 BufferDesc *buf_hdr = BufferIsLocal(buf) ?
482 bool flushed;
483
485
486 if (pg_atomic_read_u32(&buf_hdr->state) & BM_DIRTY)
487 {
488 if (BufferIsLocal(buf))
489 FlushLocalBuffer(buf_hdr, NULL);
490 else
492 }
495
496 if (BufferIsLocal(buf))
498 else if (!EvictUnpinnedBuffer(buf, &flushed))
499 elog(ERROR, "couldn't evict");
500 }
501 }
502
504
506}
507
509Datum
511{
512 Oid relid = PG_GETARG_OID(0);
513 BlockNumber blkno = PG_GETARG_UINT32(1);
514 Relation rel;
515 Buffer buf;
516
518
519 buf = create_toy_buffer(rel, blkno);
521
523
525}
526
528Datum
530{
532 bool for_input = PG_GETARG_BOOL(1);
533 bool nowait = PG_GETARG_BOOL(2);
534 bool can_start;
535
536 if (BufferIsLocal(buf))
538 for_input, nowait);
539 else
540 can_start = StartBufferIO(GetBufferDescriptor(buf - 1),
541 for_input, nowait);
542
543 /*
544 * For tests we don't want the resowner release preventing us from
545 * orchestrating odd scenarios.
546 */
547 if (can_start && !BufferIsLocal(buf))
549 buf);
550
551 ereport(LOG,
552 errmsg("buffer %d after StartBufferIO: %s",
554 errhidestmt(true), errhidecontext(true));
555
556 PG_RETURN_BOOL(can_start);
557}
558
560Datum
562{
564 bool for_input = PG_GETARG_BOOL(1);
565 bool succeed = PG_GETARG_BOOL(2);
566 bool io_error = PG_GETARG_BOOL(3);
567 bool release_aio = PG_GETARG_BOOL(4);
568 bool clear_dirty = false;
569 uint32 set_flag_bits = 0;
570
571 if (io_error)
572 set_flag_bits |= BM_IO_ERROR;
573
574 if (for_input)
575 {
576 clear_dirty = false;
577
578 if (succeed)
579 set_flag_bits |= BM_VALID;
580 }
581 else
582 {
583 if (succeed)
584 clear_dirty = true;
585 }
586
587 ereport(LOG,
588 errmsg("buffer %d before Terminate[Local]BufferIO: %s",
590 errhidestmt(true), errhidecontext(true));
591
592 if (BufferIsLocal(buf))
594 clear_dirty, set_flag_bits, release_aio);
595 else
597 clear_dirty, set_flag_bits, false, release_aio);
598
599 ereport(LOG,
600 errmsg("buffer %d after Terminate[Local]BufferIO: %s",
602 errhidestmt(true), errhidecontext(true));
603
605}
606
608Datum
610{
612
614}
615
617Datum
619{
620 if (!last_handle)
621 elog(ERROR, "no handle");
622
624
626}
627
629Datum
631{
633
634 elog(ERROR, "as you command");
636}
637
639Datum
641{
644
646}
647
649Datum
651{
652 PgAioHandle *handle;
653
655 pgaio_io_release(handle);
656
658}
659
661Datum
663{
666}
667
669Datum
671{
674}
675
676#ifdef USE_INJECTION_POINTS
677extern PGDLLEXPORT void inj_io_short_read(const char *name, const void *private_data);
678extern PGDLLEXPORT void inj_io_reopen(const char *name, const void *private_data);
679
680void
681inj_io_short_read(const char *name, const void *private_data)
682{
683 PgAioHandle *ioh;
684
685 ereport(LOG,
686 errmsg("short read injection point called, is enabled: %d",
688 errhidestmt(true), errhidecontext(true));
689
691 {
692 ioh = pgaio_inj_io_get();
693
694 /*
695 * Only shorten reads that are actually longer than the target size,
696 * otherwise we can trigger over-reads.
697 */
699 && ioh->op == PGAIO_OP_READV
701 {
702 struct iovec *iov = &pgaio_ctl->iovecs[ioh->iovec_off];
703 int32 old_result = ioh->result;
705 int32 processed = 0;
706
707 ereport(LOG,
708 errmsg("short read inject point, changing result from %d to %d",
709 old_result, new_result),
710 errhidestmt(true), errhidecontext(true));
711
712 /*
713 * The underlying IO actually completed OK, and thus the "invalid"
714 * portion of the IOV actually contains valid data. That can hide
715 * a lot of problems, e.g. if we were to wrongly mark a buffer,
716 * that wasn't read according to the shortened-read, IO as valid,
717 * the contents would look valid and we might miss a bug.
718 *
719 * To avoid that, iterate through the IOV and zero out the
720 * "failed" portion of the IO.
721 */
722 for (int i = 0; i < ioh->op_data.read.iov_length; i++)
723 {
724 if (processed + iov[i].iov_len <= new_result)
725 processed += iov[i].iov_len;
726 else if (processed <= new_result)
727 {
728 uint32 ok_part = new_result - processed;
729
730 memset((char *) iov[i].iov_base + ok_part, 0, iov[i].iov_len - ok_part);
731 processed += iov[i].iov_len;
732 }
733 else
734 {
735 memset((char *) iov[i].iov_base, 0, iov[i].iov_len);
736 }
737 }
738
739 ioh->result = new_result;
740 }
741 }
742}
743
744void
745inj_io_reopen(const char *name, const void *private_data)
746{
747 ereport(LOG,
748 errmsg("reopen injection point called, is enabled: %d",
750 errhidestmt(true), errhidecontext(true));
751
753 elog(ERROR, "injection point triggering failure to reopen ");
754}
755#endif
756
758Datum
760{
761#ifdef USE_INJECTION_POINTS
766#else
767 elog(ERROR, "injection points not supported");
768#endif
769
771}
772
774Datum
776{
777#ifdef USE_INJECTION_POINTS
779#else
780 elog(ERROR, "injection points not supported");
781#endif
783}
784
786Datum
788{
789#ifdef USE_INJECTION_POINTS
791#else
792 elog(ERROR, "injection points not supported");
793#endif
794
796}
797
799Datum
801{
802#ifdef USE_INJECTION_POINTS
804#else
805 elog(ERROR, "injection points not supported");
806#endif
808}
PgAioHandle * pgaio_io_acquire(struct ResourceOwnerData *resowner, PgAioReturn *ret)
Definition: aio.c:173
void pgaio_io_get_wref(PgAioHandle *ioh, PgAioWaitRef *iow)
Definition: aio.c:354
void pgaio_io_set_flag(PgAioHandle *ioh, PgAioHandleFlags flag)
Definition: aio.c:318
PgAioCtl * pgaio_ctl
Definition: aio.c:81
void pgaio_enter_batchmode(void)
Definition: aio.c:978
void pgaio_wref_wait(PgAioWaitRef *iow)
Definition: aio.c:893
void pgaio_io_release(PgAioHandle *ioh)
Definition: aio.c:242
void pgaio_exit_batchmode(void)
Definition: aio.c:989
@ 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)
Definition: aio_callback.c:139
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:171
@ PGAIO_RS_OK
Definition: aio_types.h:81
@ PGAIO_RS_ERROR
Definition: aio_types.h:84
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:295
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:239
uint32 BlockNumber
Definition: block.h:31
int Buffer
Definition: buf.h:23
#define BufferIsLocal(buffer)
Definition: buf.h:37
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
#define BM_DIRTY
Definition: buf_internals.h:69
static void ResourceOwnerForgetBufferIO(ResourceOwner owner, Buffer buffer)
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:59
#define BM_VALID
Definition: buf_internals.h:70
#define BM_IO_ERROR
Definition: buf_internals.h:73
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static BufferDesc * GetBufferDescriptor(uint32 id)
PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:644
bool zero_damaged_pages
Definition: bufmgr.c:141
BlockNumber ExtendBufferedRelBy(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, Buffer *buffers, uint32 *extended_by)
Definition: bufmgr.c:883
char * DebugPrintBufferRefcount(Buffer buffer)
Definition: bufmgr.c:4104
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5303
void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits, bool forget_owner, bool release_aio)
Definition: bufmgr.c:6032
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5537
bool EvictUnpinnedBuffer(Buffer buf, bool *buffer_flushed)
Definition: bufmgr.c:6581
bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, Buffer recent_buffer)
Definition: bufmgr.c:675
bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait)
Definition: bufmgr.c:5975
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:798
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:6189
void FlushOneBuffer(Buffer buffer)
Definition: bufmgr.c:5283
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:196
#define READ_BUFFERS_ZERO_ON_ERROR
Definition: bufmgr.h:112
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:414
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:381
#define READ_BUFFERS_IGNORE_CHECKSUM_FAILURES
Definition: bufmgr.h:116
static Size BufferGetPageSize(Buffer buffer)
Definition: bufmgr.h:403
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:198
@ RBM_ZERO_ON_ERROR
Definition: bufmgr.h:51
@ RBM_ZERO_AND_LOCK
Definition: bufmgr.h:47
#define BMR_REL(p_rel)
Definition: bufmgr.h:108
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:365
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:224
PageHeaderData * PageHeader
Definition: bufpage.h:174
PageData * Page
Definition: bufpage.h:82
#define Min(x, y)
Definition: c.h:975
uint8_t uint8
Definition: c.h:500
#define PGDLLEXPORT
Definition: c.h:1306
int32_t int32
Definition: c.h:498
uint16_t uint16
Definition: c.h:501
uint32_t uint32
Definition: c.h:502
uint16 pg_checksum_page(char *page, BlockNumber blkno)
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1158
int errhidestmt(bool hide_stmt)
Definition: elog.c:1433
int errhidecontext(bool hide_ctx)
Definition: elog.c:1452
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#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:149
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_GETARG_UINT32(n)
Definition: fmgr.h:270
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#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:359
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:182
bool StartLocalBufferIO(BufferDesc *bufHdr, bool forInput, bool nowait)
Definition: localbuf.c:521
void TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty, uint32 set_flag_bits, bool release_aio)
Definition: localbuf.c:560
void InvalidateLocalBuffer(BufferDesc *bufHdr, bool check_unreferenced)
Definition: localbuf.c:603
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1182
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1902
@ LW_EXCLUSIVE
Definition: lwlock.h:114
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:2137
void(* shmem_request_hook_type)(void)
Definition: miscadmin.h:533
shmem_request_hook_type shmem_request_hook
Definition: miscinit.c:1840
bool process_shared_preload_libraries_in_progress
Definition: miscinit.c:1837
#define PG_IO_ALIGN_SIZE
#define PG_IOV_MAX
Definition: pg_iovec.h:41
static char * buf
Definition: pg_test_fsync.c:72
void pgstat_prepare_report_checksum_failure(Oid dboid)
uintptr_t Datum
Definition: postgres.h:69
unsigned int Oid
Definition: postgres_ext.h:30
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:578
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:648
@ MAIN_FORKNUM
Definition: relpath.h:58
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
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
pg_atomic_uint32 state
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
LocationIndex pd_special
Definition: bufpage.h:168
uint16 pd_checksum
Definition: bufpage.h:164
struct iovec * iovecs
Definition: aio_internal.h:234
PgAioOp op
Definition: aio_internal.h:105
PgAioOpData op_data
Definition: aio_internal.h:174
uint32 iovec_off
Definition: aio_internal.h:164
uint32 status
Definition: aio_types.h:108
PgAioResult result
Definition: aio_types.h:132
PgAioTargetData target_data
Definition: aio_types.h:133
Buffer recent_buffer
Definition: bufmgr.h:61
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:670
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:510
Datum inj_io_reopen_detach(PG_FUNCTION_ARGS)
Definition: test_aio.c:800
Datum buffer_call_terminate_io(PG_FUNCTION_ARGS)
Definition: test_aio.c:561
static PgAioHandle * last_handle
Definition: test_aio.c:54
Datum read_rel_block_ll(PG_FUNCTION_ARGS)
Definition: test_aio.c:358
PG_MODULE_MAGIC
Definition: test_aio.c:35
Datum invalidate_rel_block(PG_FUNCTION_ARGS)
Definition: test_aio.c:457
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:650
Datum buffer_call_start_io(PG_FUNCTION_ARGS)
Definition: test_aio.c:529
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:787
Datum inj_io_short_read_detach(PG_FUNCTION_ARGS)
Definition: test_aio.c:775
Datum handle_get(PG_FUNCTION_ARGS)
Definition: test_aio.c:609
Datum batch_start(PG_FUNCTION_ARGS)
Definition: test_aio.c:662
Datum modify_rel_block(PG_FUNCTION_ARGS)
Definition: test_aio.c:198
Datum handle_get_and_error(PG_FUNCTION_ARGS)
Definition: test_aio.c:630
struct InjIoErrorState InjIoErrorState
Datum inj_io_short_read_attach(PG_FUNCTION_ARGS)
Definition: test_aio.c:759
static InjIoErrorState * inj_io_error_state
Definition: test_aio.c:47
PG_FUNCTION_INFO_V1(errno_from_string)
Datum handle_release_last(PG_FUNCTION_ARGS)
Definition: test_aio.c:618
Datum handle_get_twice(PG_FUNCTION_ARGS)
Definition: test_aio.c:640
Datum errno_from_string(PG_FUNCTION_ARGS)
Definition: test_aio.c:136
uint16 iov_length
Definition: aio.h:139
struct PgAioOpData::@122 read
char * text_to_cstring(const text *t)
Definition: varlena.c:225
const char * name
#define EINTR
Definition: win32_port.h:364
#define EAGAIN
Definition: win32_port.h:362