LCOV - differential code coverage report
Current view: top level - src/test/modules/test_aio - test_aio.c (source / functions) Coverage Total Hit UNC LBC UBC GNC CBC DUB DCB
Current: bed3ffbf9d952be6c7d739d068cdce44c046dfb7 vs 574581b50ac9c63dd9e4abebb731a3b67e5b50f6 Lines: 94.6 % 502 475 11 1 15 243 232 6 61
Current Date: 2026-05-05 10:23:31 +0900 Functions: 98.4 % 62 61 1 28 33 5
Baseline: lcov-20260505-025707-baseline Branches: 73.8 % 248 183 26 39 84 99 9 19
Baseline Date: 2026-05-05 10:27:06 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 77.8 % 18 14 4 14
(30,360] days: 97.1 % 238 231 7 229 2
(360..) days: 93.5 % 246 230 1 15 230
Function coverage date bins:
(7,30] days: 66.7 % 3 2 1 2
(30,360] days: 100.0 % 20 20 19 1
(360..) days: 100.0 % 39 39 7 32
Branch coverage date bins:
(7,30] days: 0.0 % 2 0 2
(30,360] days: 77.8 % 108 84 24 84
(360..) days: 71.7 % 138 99 39 99

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  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 "catalog/pg_type.h"
                                 23                 :                : #include "fmgr.h"
                                 24                 :                : #include "funcapi.h"
                                 25                 :                : #include "storage/aio.h"
                                 26                 :                : #include "storage/aio_internal.h"
                                 27                 :                : #include "storage/buf_internals.h"
                                 28                 :                : #include "storage/bufmgr.h"
                                 29                 :                : #include "storage/checksum.h"
                                 30                 :                : #include "storage/condition_variable.h"
                                 31                 :                : #include "storage/lwlock.h"
                                 32                 :                : #include "storage/proc.h"
                                 33                 :                : #include "storage/procnumber.h"
                                 34                 :                : #include "storage/read_stream.h"
                                 35                 :                : #include "utils/array.h"
                                 36                 :                : #include "utils/builtins.h"
                                 37                 :                : #include "utils/injection_point.h"
                                 38                 :                : #include "utils/rel.h"
                                 39                 :                : #include "utils/tuplestore.h"
                                 40                 :                : #include "utils/wait_event.h"
                                 41                 :                : 
                                 42                 :                : 
  399 andres@anarazel.de         43                 :CBC          10 : PG_MODULE_MAGIC;
                                 44                 :                : 
                                 45                 :                : 
                                 46                 :                : /* In shared memory */
                                 47                 :                : typedef struct InjIoErrorState
                                 48                 :                : {
                                 49                 :                :     ConditionVariable cv;
                                 50                 :                : 
                                 51                 :                :     bool        enabled_short_read;
                                 52                 :                :     bool        enabled_reopen;
                                 53                 :                : 
                                 54                 :                :     bool        enabled_completion_wait;
                                 55                 :                :     Oid         completion_wait_relfilenode;
                                 56                 :                :     BlockNumber completion_wait_blockno;
                                 57                 :                :     pid_t       completion_wait_pid;
                                 58                 :                :     uint32      completion_wait_event;
                                 59                 :                : 
                                 60                 :                :     bool        short_read_result_set;
                                 61                 :                :     Oid         short_read_relfilenode;
                                 62                 :                :     pid_t       short_read_pid;
                                 63                 :                :     int         short_read_result;
                                 64                 :                : } InjIoErrorState;
                                 65                 :                : 
                                 66                 :                : typedef struct BlocksReadStreamData
                                 67                 :                : {
                                 68                 :                :     int         nblocks;
                                 69                 :                :     int         curblock;
                                 70                 :                :     uint32     *blocks;
                                 71                 :                : } BlocksReadStreamData;
                                 72                 :                : 
                                 73                 :                : 
                                 74                 :                : static InjIoErrorState *inj_io_error_state;
                                 75                 :                : 
                                 76                 :                : /* Shared memory init callbacks */
                                 77                 :                : static void test_aio_shmem_request(void *arg);
                                 78                 :                : static void test_aio_shmem_init(void *arg);
                                 79                 :                : static void test_aio_shmem_attach(void *arg);
                                 80                 :                : 
                                 81                 :                : static const ShmemCallbacks inj_io_shmem_callbacks = {
                                 82                 :                :     .request_fn = test_aio_shmem_request,
                                 83                 :                :     .init_fn = test_aio_shmem_init,
                                 84                 :                :     .attach_fn = test_aio_shmem_attach,
                                 85                 :                : };
                                 86                 :                : 
                                 87                 :                : 
                                 88                 :                : static PgAioHandle *last_handle;
                                 89                 :                : 
                                 90                 :                : 
                                 91                 :                : 
                                 92                 :                : static void
   29 heikki.linnakangas@i       93                 :GNC          10 : test_aio_shmem_request(void *arg)
                                 94                 :                : {
                                 95                 :             10 :     ShmemRequestStruct(.name = "test_aio injection points",
                                 96                 :                :                        .size = sizeof(InjIoErrorState),
                                 97                 :                :                        .ptr = (void **) &inj_io_error_state,
                                 98                 :                :         );
  399 andres@anarazel.de         99                 :CBC          10 : }
                                100                 :                : 
                                101                 :                : static void
   29 heikki.linnakangas@i      102                 :GNC          10 : test_aio_shmem_init(void *arg)
                                103                 :                : {
                                104                 :                :     /* First time through, initialize */
                                105                 :             10 :     inj_io_error_state->enabled_short_read = false;
                                106                 :             10 :     inj_io_error_state->enabled_reopen = false;
                                107                 :             10 :     inj_io_error_state->enabled_completion_wait = false;
                                108                 :                : 
                                109                 :             10 :     ConditionVariableInit(&inj_io_error_state->cv);
                                110                 :             10 :     inj_io_error_state->completion_wait_event = WaitEventInjectionPointNew("completion_wait");
                                111                 :                : 
                                112                 :                : #ifdef USE_INJECTION_POINTS
                                113                 :             10 :     InjectionPointAttach("aio-process-completion-before-shared",
                                114                 :                :                          "test_aio",
                                115                 :                :                          "inj_io_completion_hook",
                                116                 :                :                          NULL,
                                117                 :                :                          0);
                                118                 :             10 :     InjectionPointLoad("aio-process-completion-before-shared");
                                119                 :                : 
                                120                 :             10 :     InjectionPointAttach("aio-worker-after-reopen",
                                121                 :                :                          "test_aio",
                                122                 :                :                          "inj_io_reopen",
                                123                 :                :                          NULL,
                                124                 :                :                          0);
                                125                 :             10 :     InjectionPointLoad("aio-worker-after-reopen");
                                126                 :                : 
                                127                 :                : #endif
                                128                 :             10 : }
                                129                 :                : 
                                130                 :                : static void
   29 heikki.linnakangas@i      131                 :UNC           0 : test_aio_shmem_attach(void *arg)
                                132                 :                : {
                                133                 :                :     /*
                                134                 :                :      * Pre-load the injection points now, so we can call them in a critical
                                135                 :                :      * section.
                                136                 :                :      */
                                137                 :                : #ifdef USE_INJECTION_POINTS
                                138                 :              0 :     InjectionPointLoad("aio-process-completion-before-shared");
                                139                 :              0 :     InjectionPointLoad("aio-worker-after-reopen");
                                140         [ #  # ]:              0 :     elog(LOG, "injection point loaded");
                                141                 :                : #endif
  399 andres@anarazel.de        142                 :LBC         (3) : }
                                143                 :                : 
                                144                 :                : void
  399 andres@anarazel.de        145                 :CBC          10 : _PG_init(void)
                                146                 :                : {
                                147         [ -  + ]:             10 :     if (!process_shared_preload_libraries_in_progress)
  399 andres@anarazel.de        148                 :UBC           0 :         return;
                                149                 :                : 
   29 heikki.linnakangas@i      150                 :GNC          10 :     RegisterShmemCallbacks(&inj_io_shmem_callbacks);
                                151                 :                : }
                                152                 :                : 
                                153                 :                : 
  399 andres@anarazel.de        154                 :CBC          13 : PG_FUNCTION_INFO_V1(errno_from_string);
                                155                 :                : Datum
                                156                 :              9 : errno_from_string(PG_FUNCTION_ARGS)
                                157                 :                : {
                                158                 :              9 :     const char *sym = text_to_cstring(PG_GETARG_TEXT_PP(0));
                                159                 :                : 
                                160         [ +  + ]:              9 :     if (strcmp(sym, "EIO") == 0)
                                161                 :              6 :         PG_RETURN_INT32(EIO);
                                162         [ -  + ]:              3 :     else if (strcmp(sym, "EAGAIN") == 0)
  399 andres@anarazel.de        163                 :UBC           0 :         PG_RETURN_INT32(EAGAIN);
  399 andres@anarazel.de        164         [ -  + ]:CBC           3 :     else if (strcmp(sym, "EINTR") == 0)
  399 andres@anarazel.de        165                 :UBC           0 :         PG_RETURN_INT32(EINTR);
  399 andres@anarazel.de        166         [ -  + ]:CBC           3 :     else if (strcmp(sym, "ENOSPC") == 0)
  399 andres@anarazel.de        167                 :UBC           0 :         PG_RETURN_INT32(ENOSPC);
  399 andres@anarazel.de        168         [ +  - ]:CBC           3 :     else if (strcmp(sym, "EROFS") == 0)
                                169                 :              3 :         PG_RETURN_INT32(EROFS);
                                170                 :                : 
  399 andres@anarazel.de        171         [ #  # ]:UBC           0 :     ereport(ERROR,
                                172                 :                :             errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                173                 :                :             errmsg_internal("%s is not a supported errno value", sym));
                                174                 :                :     PG_RETURN_INT32(0);
                                175                 :                : }
                                176                 :                : 
  399 andres@anarazel.de        177                 :CBC          13 : PG_FUNCTION_INFO_V1(grow_rel);
                                178                 :                : Datum
                                179                 :              9 : grow_rel(PG_FUNCTION_ARGS)
                                180                 :                : {
                                181                 :              9 :     Oid         relid = PG_GETARG_OID(0);
                                182                 :              9 :     uint32      nblocks = PG_GETARG_UINT32(1);
                                183                 :                :     Relation    rel;
                                184                 :                : #define MAX_BUFFERS_TO_EXTEND_BY 64
                                185                 :                :     Buffer      victim_buffers[MAX_BUFFERS_TO_EXTEND_BY];
                                186                 :                : 
                                187                 :              9 :     rel = relation_open(relid, AccessExclusiveLock);
                                188                 :                : 
                                189         [ +  + ]:             18 :     while (nblocks > 0)
                                190                 :                :     {
                                191                 :                :         uint32      extend_by_pages;
                                192                 :                : 
                                193                 :              9 :         extend_by_pages = Min(nblocks, MAX_BUFFERS_TO_EXTEND_BY);
                                194                 :                : 
                                195                 :              9 :         ExtendBufferedRelBy(BMR_REL(rel),
                                196                 :                :                             MAIN_FORKNUM,
                                197                 :                :                             NULL,
                                198                 :                :                             0,
                                199                 :                :                             extend_by_pages,
                                200                 :                :                             victim_buffers,
                                201                 :                :                             &extend_by_pages);
                                202                 :                : 
                                203                 :              9 :         nblocks -= extend_by_pages;
                                204                 :                : 
                                205         [ +  + ]:            117 :         for (uint32 i = 0; i < extend_by_pages; i++)
                                206                 :                :         {
                                207                 :            108 :             ReleaseBuffer(victim_buffers[i]);
                                208                 :                :         }
                                209                 :                :     }
                                210                 :                : 
                                211                 :              9 :     relation_close(rel, NoLock);
                                212                 :                : 
                                213                 :              9 :     PG_RETURN_VOID();
                                214                 :                : }
                                215                 :                : 
                                216                 :             28 : PG_FUNCTION_INFO_V1(modify_rel_block);
                                217                 :                : Datum
                                218                 :            105 : modify_rel_block(PG_FUNCTION_ARGS)
                                219                 :                : {
                                220                 :            105 :     Oid         relid = PG_GETARG_OID(0);
                                221                 :            105 :     BlockNumber blkno = PG_GETARG_UINT32(1);
                                222                 :            105 :     bool        zero = PG_GETARG_BOOL(2);
                                223                 :            105 :     bool        corrupt_header = PG_GETARG_BOOL(3);
                                224                 :            105 :     bool        corrupt_checksum = PG_GETARG_BOOL(4);
                                225                 :            105 :     Page        page = palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, 0);
                                226                 :                :     bool        flushed;
                                227                 :                :     Relation    rel;
                                228                 :                :     Buffer      buf;
                                229                 :                :     PageHeader  ph;
                                230                 :                : 
                                231                 :            105 :     rel = relation_open(relid, AccessExclusiveLock);
                                232                 :                : 
                                233                 :            105 :     buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno,
                                234                 :                :                              RBM_ZERO_ON_ERROR, NULL);
                                235                 :                : 
                                236                 :            105 :     LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
                                237                 :                : 
                                238                 :                :     /*
                                239                 :                :      * copy the page to local memory, seems nicer than to directly modify in
                                240                 :                :      * the buffer pool.
                                241                 :                :      */
                                242                 :            105 :     memcpy(page, BufferGetPage(buf), BLCKSZ);
                                243                 :                : 
   39 andres@anarazel.de        244                 :GNC         105 :     UnlockReleaseBuffer(buf);
                                245                 :                : 
                                246                 :                :     /*
                                247                 :                :      * Don't want to have a buffer in-memory that's marked valid where the
                                248                 :                :      * on-disk contents are invalid. Particularly not if the in-memory buffer
                                249                 :                :      * could be dirty...
                                250                 :                :      *
                                251                 :                :      * While we hold an AEL on the relation nobody else should be able to read
                                252                 :                :      * the buffer in.
                                253                 :                :      *
                                254                 :                :      * NB: This is probably racy, better don't copy this to non-test code.
                                255                 :                :      */
  399 andres@anarazel.de        256         [ +  + ]:CBC         105 :     if (BufferIsLocal(buf))
                                257                 :             27 :         InvalidateLocalBuffer(GetLocalBufferDescriptor(-buf - 1), true);
                                258                 :                :     else
  392                           259                 :             78 :         EvictUnpinnedBuffer(buf, &flushed);
                                260                 :                : 
                                261                 :                :     /*
                                262                 :                :      * Now modify the page as asked for by the caller.
                                263                 :                :      */
  399                           264         [ +  + ]:            105 :     if (zero)
                                265                 :             24 :         memset(page, 0, BufferGetPageSize(buf));
                                266                 :                : 
                                267   [ +  +  +  +  :            105 :     if (PageIsEmpty(page) && (corrupt_header || corrupt_checksum))
                                              +  + ]
                                268                 :             24 :         PageInit(page, BufferGetPageSize(buf), 0);
                                269                 :                : 
                                270                 :            105 :     ph = (PageHeader) page;
                                271                 :                : 
                                272         [ +  + ]:            105 :     if (corrupt_header)
                                273                 :             48 :         ph->pd_special = BLCKSZ + 1;
                                274                 :                : 
                                275         [ +  + ]:            105 :     if (corrupt_checksum)
                                276                 :                :     {
                                277                 :             39 :         bool        successfully_corrupted = 0;
                                278                 :                : 
                                279                 :                :         /*
                                280                 :                :          * Any single modification of the checksum could just end up being
                                281                 :                :          * valid again, due to e.g. corrupt_header changing the data in a way
                                282                 :                :          * that'd result in the "corrupted" checksum, or the checksum already
                                283                 :                :          * being invalid. Retry in that, unlikely, case.
                                284                 :                :          */
                                285         [ +  - ]:             39 :         for (int i = 0; i < 100; i++)
                                286                 :                :         {
                                287                 :                :             uint16      verify_checksum;
                                288                 :                :             uint16      old_checksum;
                                289                 :                : 
                                290                 :             39 :             old_checksum = ph->pd_checksum;
                                291                 :             39 :             ph->pd_checksum = old_checksum + 1;
                                292                 :                : 
                                293         [ +  - ]:             39 :             elog(LOG, "corrupting checksum of blk %u from %u to %u",
                                294                 :                :                  blkno, old_checksum, ph->pd_checksum);
                                295                 :                : 
                                296                 :             39 :             verify_checksum = pg_checksum_page(page, blkno);
                                297         [ +  - ]:             39 :             if (verify_checksum != ph->pd_checksum)
                                298                 :                :             {
                                299                 :             39 :                 successfully_corrupted = true;
                                300                 :             39 :                 break;
                                301                 :                :             }
                                302                 :                :         }
                                303                 :                : 
                                304         [ -  + ]:             39 :         if (!successfully_corrupted)
  399 andres@anarazel.de        305         [ #  # ]:UBC           0 :             elog(ERROR, "could not corrupt checksum, what's going on?");
                                306                 :                :     }
                                307                 :                :     else
                                308                 :                :     {
   39 andres@anarazel.de        309                 :GNC          66 :         PageSetChecksum(page, blkno);
                                310                 :                :     }
                                311                 :                : 
  399 andres@anarazel.de        312                 :CBC         105 :     smgrwrite(RelationGetSmgr(rel),
                                313                 :                :               MAIN_FORKNUM, blkno, page, true);
                                314                 :                : 
                                315                 :            105 :     relation_close(rel, NoLock);
                                316                 :                : 
                                317                 :            105 :     PG_RETURN_VOID();
                                318                 :                : }
                                319                 :                : 
                                320                 :                : /*
                                321                 :                :  * Ensures a buffer for rel & blkno is in shared buffers, without actually
                                322                 :                :  * caring about the buffer contents. Used to set up test scenarios.
                                323                 :                :  */
                                324                 :                : static Buffer
                                325                 :            241 : create_toy_buffer(Relation rel, BlockNumber blkno)
                                326                 :                : {
                                327                 :                :     Buffer      buf;
                                328                 :                :     BufferDesc *buf_hdr;
                                329                 :                :     uint64      buf_state;
                                330                 :            241 :     bool        was_pinned = false;
  110 andres@anarazel.de        331                 :GNC         241 :     uint64      unset_bits = 0;
                                332                 :                : 
                                333                 :                :     /* place buffer in shared buffers without erroring out */
  399 andres@anarazel.de        334                 :CBC         241 :     buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_ZERO_AND_LOCK, NULL);
                                335                 :            241 :     LockBuffer(buf, BUFFER_LOCK_UNLOCK);
                                336                 :                : 
                                337         [ +  + ]:            241 :     if (RelationUsesLocalBuffers(rel))
                                338                 :                :     {
                                339                 :             75 :         buf_hdr = GetLocalBufferDescriptor(-buf - 1);
  110 andres@anarazel.de        340                 :GNC          75 :         buf_state = pg_atomic_read_u64(&buf_hdr->state);
                                341                 :                :     }
                                342                 :                :     else
                                343                 :                :     {
  399 andres@anarazel.de        344                 :CBC         166 :         buf_hdr = GetBufferDescriptor(buf - 1);
                                345                 :            166 :         buf_state = LockBufHdr(buf_hdr);
                                346                 :                :     }
                                347                 :                : 
                                348                 :                :     /*
                                349                 :                :      * We should be the only backend accessing this buffer. This is just a
                                350                 :                :      * small bit of belt-and-suspenders defense, none of this code should ever
                                351                 :                :      * run in a cluster with real data.
                                352                 :                :      */
                                353         [ -  + ]:            241 :     if (BUF_STATE_GET_REFCOUNT(buf_state) > 1)
  399 andres@anarazel.de        354                 :UBC           0 :         was_pinned = true;
                                355                 :                :     else
  180 andres@anarazel.de        356                 :GNC         241 :         unset_bits |= BM_VALID | BM_DIRTY;
                                357                 :                : 
  399 andres@anarazel.de        358         [ +  + ]:CBC         241 :     if (RelationUsesLocalBuffers(rel))
                                359                 :                :     {
  180 andres@anarazel.de        360                 :GNC          75 :         buf_state &= ~unset_bits;
  110                           361                 :             75 :         pg_atomic_unlocked_write_u64(&buf_hdr->state, buf_state);
                                362                 :                :     }
                                363                 :                :     else
                                364                 :                :     {
  180                           365                 :            166 :         UnlockBufHdrExt(buf_hdr, buf_state, 0, unset_bits, 0);
                                366                 :                :     }
                                367                 :                : 
  399 andres@anarazel.de        368         [ -  + ]:CBC         241 :     if (was_pinned)
  399 andres@anarazel.de        369         [ #  # ]:UBC           0 :         elog(ERROR, "toy buffer %d was already pinned",
                                370                 :                :              buf);
                                371                 :                : 
  399 andres@anarazel.de        372                 :CBC         241 :     return buf;
                                373                 :                : }
                                374                 :                : 
                                375                 :                : /*
                                376                 :                :  * A "low level" read. This does similar things to what
                                377                 :                :  * StartReadBuffers()/WaitReadBuffers() do, but provides more control (and
                                378                 :                :  * less sanity).
                                379                 :                :  */
                                380                 :             40 : PG_FUNCTION_INFO_V1(read_rel_block_ll);
                                381                 :                : Datum
                                382                 :            141 : read_rel_block_ll(PG_FUNCTION_ARGS)
                                383                 :                : {
                                384                 :            141 :     Oid         relid = PG_GETARG_OID(0);
                                385                 :            141 :     BlockNumber blkno = PG_GETARG_UINT32(1);
                                386                 :            141 :     int         nblocks = PG_GETARG_INT32(2);
                                387                 :            141 :     bool        wait_complete = PG_GETARG_BOOL(3);
                                388                 :            141 :     bool        batchmode_enter = PG_GETARG_BOOL(4);
                                389                 :            141 :     bool        call_smgrreleaseall = PG_GETARG_BOOL(5);
                                390                 :            141 :     bool        batchmode_exit = PG_GETARG_BOOL(6);
                                391                 :            141 :     bool        zero_on_error = PG_GETARG_BOOL(7);
                                392                 :                :     Relation    rel;
                                393                 :                :     Buffer      bufs[PG_IOV_MAX];
                                394                 :                :     BufferDesc *buf_hdrs[PG_IOV_MAX];
                                395                 :                :     Page        pages[PG_IOV_MAX];
                                396                 :            141 :     uint8       srb_flags = 0;
                                397                 :                :     PgAioReturn ior;
                                398                 :                :     PgAioHandle *ioh;
                                399                 :                :     PgAioWaitRef iow;
                                400                 :                :     SMgrRelation smgr;
                                401                 :                : 
                                402   [ +  -  -  + ]:            141 :     if (nblocks <= 0 || nblocks > PG_IOV_MAX)
  399 andres@anarazel.de        403         [ #  # ]:UBC           0 :         elog(ERROR, "nblocks is out of range");
                                404                 :                : 
   39 andres@anarazel.de        405                 :GNC         141 :     rel = relation_open(relid, AccessShareLock);
                                406                 :                : 
  399 andres@anarazel.de        407         [ +  + ]:CBC         369 :     for (int i = 0; i < nblocks; i++)
                                408                 :                :     {
                                409                 :            228 :         bufs[i] = create_toy_buffer(rel, blkno + i);
                                410                 :            228 :         pages[i] = BufferGetBlock(bufs[i]);
                                411                 :            228 :         buf_hdrs[i] = BufferIsLocal(bufs[i]) ?
                                412         [ +  + ]:            228 :             GetLocalBufferDescriptor(-bufs[i] - 1) :
                                413                 :            156 :             GetBufferDescriptor(bufs[i] - 1);
                                414                 :                :     }
                                415                 :                : 
                                416                 :            141 :     smgr = RelationGetSmgr(rel);
                                417                 :                : 
                                418                 :            141 :     pgstat_prepare_report_checksum_failure(smgr->smgr_rlocator.locator.dbOid);
                                419                 :                : 
                                420                 :            141 :     ioh = pgaio_io_acquire(CurrentResourceOwner, &ior);
                                421                 :            141 :     pgaio_io_get_wref(ioh, &iow);
                                422                 :                : 
                                423         [ +  + ]:            141 :     if (RelationUsesLocalBuffers(rel))
                                424                 :                :     {
                                425         [ +  + ]:            114 :         for (int i = 0; i < nblocks; i++)
   39 andres@anarazel.de        426                 :GNC          72 :             StartLocalBufferIO(buf_hdrs[i], true, true, NULL);
  399 andres@anarazel.de        427                 :CBC          42 :         pgaio_io_set_flag(ioh, PGAIO_HF_REFERENCES_LOCAL);
                                428                 :                :     }
                                429                 :                :     else
                                430                 :                :     {
                                431         [ +  + ]:            255 :         for (int i = 0; i < nblocks; i++)
   39 andres@anarazel.de        432                 :GNC         156 :             StartSharedBufferIO(buf_hdrs[i], true, true, NULL);
                                433                 :                :     }
                                434                 :                : 
  399 andres@anarazel.de        435                 :CBC         141 :     pgaio_io_set_handle_data_32(ioh, (uint32 *) bufs, nblocks);
                                436                 :                : 
                                437         [ +  + ]:            141 :     if (zero_on_error | zero_damaged_pages)
                                438                 :             33 :         srb_flags |= READ_BUFFERS_ZERO_ON_ERROR;
                                439         [ +  + ]:            141 :     if (ignore_checksum_failure)
                                440                 :             15 :         srb_flags |= READ_BUFFERS_IGNORE_CHECKSUM_FAILURES;
                                441                 :                : 
                                442                 :            141 :     pgaio_io_register_callbacks(ioh,
                                443         [ +  + ]:            141 :                                 RelationUsesLocalBuffers(rel) ?
                                444                 :                :                                 PGAIO_HCB_LOCAL_BUFFER_READV :
                                445                 :                :                                 PGAIO_HCB_SHARED_BUFFER_READV,
                                446                 :                :                                 srb_flags);
                                447                 :                : 
                                448         [ +  + ]:            141 :     if (batchmode_enter)
                                449                 :              6 :         pgaio_enter_batchmode();
                                450                 :                : 
                                451                 :            141 :     smgrstartreadv(ioh, smgr, MAIN_FORKNUM, blkno,
                                452                 :                :                    (void *) pages, nblocks);
                                453                 :                : 
                                454         [ +  + ]:            141 :     if (call_smgrreleaseall)
                                455                 :              6 :         smgrreleaseall();
                                456                 :                : 
                                457         [ +  + ]:            141 :     if (batchmode_exit)
                                458                 :              6 :         pgaio_exit_batchmode();
                                459                 :                : 
                                460         [ +  + ]:            369 :     for (int i = 0; i < nblocks; i++)
                                461                 :            228 :         ReleaseBuffer(bufs[i]);
                                462                 :                : 
                                463         [ +  + ]:            141 :     if (wait_complete)
                                464                 :                :     {
                                465                 :             90 :         pgaio_wref_wait(&iow);
                                466                 :                : 
                                467         [ +  + ]:             90 :         if (ior.result.status != PGAIO_RS_OK)
                                468                 :             69 :             pgaio_result_report(ior.result,
                                469                 :                :                                 &ior.target_data,
                                470         [ +  + ]:             69 :                                 ior.result.status == PGAIO_RS_ERROR ?
                                471                 :                :                                 ERROR : WARNING);
                                472                 :                :     }
                                473                 :                : 
                                474                 :            105 :     relation_close(rel, NoLock);
                                475                 :                : 
                                476                 :            105 :     PG_RETURN_VOID();
                                477                 :                : }
                                478                 :                : 
                                479                 :                : /* helper for invalidate_rel_block() and evict_rel() */
                                480                 :                : static void
   39 andres@anarazel.de        481                 :GNC         703 : invalidate_one_block(Relation rel, ForkNumber forknum, BlockNumber blkno)
                                482                 :                : {
                                483                 :                :     PrefetchBufferResult pr;
                                484                 :                :     Buffer      buf;
                                485                 :                : 
                                486                 :                :     /*
                                487                 :                :      * This is a gross hack, but there's no other API exposed that allows to
                                488                 :                :      * get a buffer ID without actually reading the block in.
                                489                 :                :      */
                                490                 :            703 :     pr = PrefetchBuffer(rel, forknum, blkno);
  399 andres@anarazel.de        491                 :CBC         703 :     buf = pr.recent_buffer;
                                492                 :                : 
                                493         [ +  + ]:            703 :     if (BufferIsValid(buf))
                                494                 :                :     {
                                495                 :                :         /* if the buffer contents aren't valid, this'll return false */
   39 andres@anarazel.de        496         [ +  + ]:GNC         345 :         if (ReadRecentBuffer(rel->rd_locator, forknum, blkno, buf))
                                497                 :                :         {
  399 andres@anarazel.de        498                 :CBC         336 :             BufferDesc *buf_hdr = BufferIsLocal(buf) ?
                                499                 :            210 :                 GetLocalBufferDescriptor(-buf - 1)
                                500         [ +  + ]:            336 :                 : GetBufferDescriptor(buf - 1);
                                501                 :                :             bool        flushed;
                                502                 :                : 
                                503                 :            336 :             LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
                                504                 :                : 
  110 andres@anarazel.de        505         [ +  + ]:GNC         336 :             if (pg_atomic_read_u64(&buf_hdr->state) & BM_DIRTY)
                                506                 :                :             {
  399 andres@anarazel.de        507         [ +  + ]:CBC         186 :                 if (BufferIsLocal(buf))
                                508                 :            111 :                     FlushLocalBuffer(buf_hdr, NULL);
                                509                 :                :                 else
                                510                 :             75 :                     FlushOneBuffer(buf);
                                511                 :                :             }
   39 andres@anarazel.de        512                 :GNC         336 :             UnlockReleaseBuffer(buf);
                                513                 :                : 
  399 andres@anarazel.de        514         [ +  + ]:CBC         336 :             if (BufferIsLocal(buf))
                                515                 :            210 :                 InvalidateLocalBuffer(GetLocalBufferDescriptor(-buf - 1), true);
  392                           516         [ -  + ]:            126 :             else if (!EvictUnpinnedBuffer(buf, &flushed))
  399 andres@anarazel.de        517         [ #  # ]:UBC           0 :                 elog(ERROR, "couldn't evict");
                                518                 :                :         }
                                519                 :                :     }
                                520                 :                : 
   39 andres@anarazel.de        521                 :GNC         703 : }
                                522                 :                : 
                                523                 :             23 : PG_FUNCTION_INFO_V1(invalidate_rel_block);
                                524                 :                : Datum
                                525                 :            235 : invalidate_rel_block(PG_FUNCTION_ARGS)
                                526                 :                : {
                                527                 :            235 :     Oid         relid = PG_GETARG_OID(0);
                                528                 :            235 :     BlockNumber blkno = PG_GETARG_UINT32(1);
                                529                 :                :     Relation    rel;
                                530                 :                : 
                                531                 :            235 :     rel = relation_open(relid, AccessExclusiveLock);
                                532                 :                : 
                                533                 :            235 :     invalidate_one_block(rel, MAIN_FORKNUM, blkno);
                                534                 :                : 
  399 andres@anarazel.de        535                 :CBC         235 :     relation_close(rel, AccessExclusiveLock);
                                536                 :                : 
                                537                 :            235 :     PG_RETURN_VOID();
                                538                 :                : }
                                539                 :                : 
   39 andres@anarazel.de        540                 :GNC          19 : PG_FUNCTION_INFO_V1(evict_rel);
                                541                 :                : Datum
                                542                 :             61 : evict_rel(PG_FUNCTION_ARGS)
                                543                 :                : {
                                544                 :             61 :     Oid         relid = PG_GETARG_OID(0);
                                545                 :                :     Relation    rel;
                                546                 :                : 
                                547                 :             61 :     rel = relation_open(relid, AccessExclusiveLock);
                                548                 :                : 
                                549                 :                :     /*
                                550                 :                :      * EvictRelUnpinnedBuffers() doesn't support temp tables, so for temp
                                551                 :                :      * tables we have to do it the expensive way and evict every possible
                                552                 :                :      * buffer.
                                553                 :                :      */
                                554         [ +  + ]:             61 :     if (RelationUsesLocalBuffers(rel))
                                555                 :                :     {
                                556                 :             18 :         SMgrRelation smgr = RelationGetSmgr(rel);
                                557                 :                : 
                                558         [ +  + ]:             90 :         for (int forknum = MAIN_FORKNUM; forknum <= MAX_FORKNUM; forknum++)
                                559                 :                :         {
                                560                 :                :             BlockNumber nblocks;
                                561                 :                : 
                                562         [ +  + ]:             72 :             if (!smgrexists(smgr, forknum))
                                563                 :             36 :                 continue;
                                564                 :                : 
                                565                 :             36 :             nblocks = smgrnblocks(smgr, forknum);
                                566                 :                : 
                                567         [ +  + ]:            504 :             for (int blkno = 0; blkno < nblocks; blkno++)
                                568                 :                :             {
                                569                 :            468 :                 invalidate_one_block(rel, forknum, blkno);
                                570                 :                :             }
                                571                 :                :         }
                                572                 :                :     }
                                573                 :                :     else
                                574                 :                :     {
                                575                 :                :         int32       buffers_evicted,
                                576                 :                :                     buffers_flushed,
                                577                 :                :                     buffers_skipped;
                                578                 :                : 
                                579                 :             43 :         EvictRelUnpinnedBuffers(rel, &buffers_evicted, &buffers_flushed,
                                580                 :                :                                 &buffers_skipped);
                                581                 :                :     }
                                582                 :                : 
                                583                 :             61 :     relation_close(rel, AccessExclusiveLock);
                                584                 :                : 
                                585                 :                : 
                                586                 :             61 :     PG_RETURN_VOID();
                                587                 :                : }
                                588                 :                : 
  399 andres@anarazel.de        589                 :CBC          12 : PG_FUNCTION_INFO_V1(buffer_create_toy);
                                590                 :                : Datum
                                591                 :             13 : buffer_create_toy(PG_FUNCTION_ARGS)
                                592                 :                : {
                                593                 :             13 :     Oid         relid = PG_GETARG_OID(0);
                                594                 :             13 :     BlockNumber blkno = PG_GETARG_UINT32(1);
                                595                 :                :     Relation    rel;
                                596                 :                :     Buffer      buf;
                                597                 :                : 
                                598                 :             13 :     rel = relation_open(relid, AccessExclusiveLock);
                                599                 :                : 
                                600                 :             13 :     buf = create_toy_buffer(rel, blkno);
                                601                 :             13 :     ReleaseBuffer(buf);
                                602                 :                : 
                                603                 :             13 :     relation_close(rel, NoLock);
                                604                 :                : 
                                605                 :             13 :     PG_RETURN_INT32(buf);
                                606                 :                : }
                                607                 :                : 
                                608                 :             15 : PG_FUNCTION_INFO_V1(buffer_call_start_io);
                                609                 :                : Datum
                                610                 :             34 : buffer_call_start_io(PG_FUNCTION_ARGS)
                                611                 :                : {
                                612                 :             34 :     Buffer      buf = PG_GETARG_INT32(0);
                                613                 :             34 :     bool        for_input = PG_GETARG_BOOL(1);
   39 andres@anarazel.de        614                 :GNC          34 :     bool        wait = PG_GETARG_BOOL(2);
                                615                 :                :     StartBufferIOResult result;
                                616                 :                :     bool        can_start;
                                617                 :                : 
  399 andres@anarazel.de        618         [ +  + ]:CBC          34 :     if (BufferIsLocal(buf))
   39 andres@anarazel.de        619                 :GNC          12 :         result = StartLocalBufferIO(GetLocalBufferDescriptor(-buf - 1),
                                620                 :                :                                     for_input, wait, NULL);
                                621                 :                :     else
                                622                 :             22 :         result = StartSharedBufferIO(GetBufferDescriptor(buf - 1),
                                623                 :                :                                      for_input, wait, NULL);
                                624                 :                : 
                                625                 :             34 :     can_start = result == BUFFER_IO_READY_FOR_IO;
                                626                 :                : 
                                627                 :                :     /*
                                628                 :                :      * For tests we don't want the resowner release preventing us from
                                629                 :                :      * orchestrating odd scenarios.
                                630                 :                :      */
  399 andres@anarazel.de        631   [ +  +  +  + ]:CBC          34 :     if (can_start && !BufferIsLocal(buf))
                                632                 :             13 :         ResourceOwnerForgetBufferIO(CurrentResourceOwner,
                                633                 :                :                                     buf);
                                634                 :                : 
                                635         [ +  - ]:             34 :     ereport(LOG,
                                636                 :                :             errmsg("buffer %d after StartBufferIO: %s",
                                637                 :                :                    buf, DebugPrintBufferRefcount(buf)),
                                638                 :                :             errhidestmt(true), errhidecontext(true));
                                639                 :                : 
                                640                 :             34 :     PG_RETURN_BOOL(can_start);
                                641                 :                : }
                                642                 :                : 
                                643                 :             15 : PG_FUNCTION_INFO_V1(buffer_call_terminate_io);
                                644                 :                : Datum
                                645                 :             19 : buffer_call_terminate_io(PG_FUNCTION_ARGS)
                                646                 :                : {
                                647                 :             19 :     Buffer      buf = PG_GETARG_INT32(0);
                                648                 :             19 :     bool        for_input = PG_GETARG_BOOL(1);
                                649                 :             19 :     bool        succeed = PG_GETARG_BOOL(2);
                                650                 :             19 :     bool        io_error = PG_GETARG_BOOL(3);
                                651                 :             19 :     bool        release_aio = PG_GETARG_BOOL(4);
                                652                 :             19 :     bool        clear_dirty = false;
  110 andres@anarazel.de        653                 :GNC          19 :     uint64      set_flag_bits = 0;
                                654                 :                : 
  399 andres@anarazel.de        655         [ -  + ]:CBC          19 :     if (io_error)
  399 andres@anarazel.de        656                 :UBC           0 :         set_flag_bits |= BM_IO_ERROR;
                                657                 :                : 
  399 andres@anarazel.de        658         [ +  - ]:CBC          19 :     if (for_input)
                                659                 :                :     {
                                660                 :             19 :         clear_dirty = false;
                                661                 :                : 
                                662         [ +  + ]:             19 :         if (succeed)
                                663                 :              8 :             set_flag_bits |= BM_VALID;
                                664                 :                :     }
                                665                 :                :     else
                                666                 :                :     {
  399 andres@anarazel.de        667         [ #  # ]:UBC           0 :         if (succeed)
                                668                 :              0 :             clear_dirty = true;
                                669                 :                :     }
                                670                 :                : 
  399 andres@anarazel.de        671         [ +  - ]:CBC          19 :     ereport(LOG,
                                672                 :                :             errmsg("buffer %d before Terminate[Local]BufferIO: %s",
                                673                 :                :                    buf, DebugPrintBufferRefcount(buf)),
                                674                 :                :             errhidestmt(true), errhidecontext(true));
                                675                 :                : 
                                676         [ +  + ]:             19 :     if (BufferIsLocal(buf))
                                677                 :              6 :         TerminateLocalBufferIO(GetLocalBufferDescriptor(-buf - 1),
                                678                 :                :                                clear_dirty, set_flag_bits, release_aio);
                                679                 :                :     else
                                680                 :             13 :         TerminateBufferIO(GetBufferDescriptor(buf - 1),
                                681                 :                :                           clear_dirty, set_flag_bits, false, release_aio);
                                682                 :                : 
                                683         [ +  - ]:             19 :     ereport(LOG,
                                684                 :                :             errmsg("buffer %d after Terminate[Local]BufferIO: %s",
                                685                 :                :                    buf, DebugPrintBufferRefcount(buf)),
                                686                 :                :             errhidestmt(true), errhidecontext(true));
                                687                 :                : 
                                688                 :             19 :     PG_RETURN_VOID();
                                689                 :                : }
                                690                 :                : 
   39 andres@anarazel.de        691                 :GNC          13 : PG_FUNCTION_INFO_V1(read_buffers);
                                692                 :                : /*
                                693                 :                :  * Infrastructure to test StartReadBuffers()
                                694                 :                :  */
                                695                 :                : Datum
                                696                 :            112 : read_buffers(PG_FUNCTION_ARGS)
                                697                 :                : {
                                698                 :            112 :     Oid         relid = PG_GETARG_OID(0);
                                699                 :            112 :     BlockNumber startblock = PG_GETARG_UINT32(1);
                                700                 :            112 :     int32       nblocks = PG_GETARG_INT32(2);
                                701                 :            112 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
                                702                 :                :     Relation    rel;
                                703                 :                :     SMgrRelation smgr;
                                704                 :            112 :     int         nblocks_done = 0;
                                705                 :            112 :     int         nblocks_disp = 0;
                                706                 :            112 :     int         nios = 0;
                                707                 :                :     ReadBuffersOperation *operations;
                                708                 :                :     Buffer     *buffers;
                                709                 :                :     Datum      *buffers_datum;
                                710                 :                :     bool       *io_reqds;
                                711                 :                :     int        *nblocks_per_io;
                                712                 :                : 
                                713         [ -  + ]:            112 :     Assert(nblocks > 0);
                                714                 :                : 
                                715                 :            112 :     InitMaterializedSRF(fcinfo, 0);
                                716                 :                : 
                                717                 :                :     /* at worst each block gets its own IO */
                                718                 :            112 :     operations = palloc0(sizeof(ReadBuffersOperation) * nblocks);
                                719                 :            112 :     buffers = palloc0(sizeof(Buffer) * nblocks);
                                720                 :            112 :     buffers_datum = palloc0(sizeof(Datum) * nblocks);
                                721                 :            112 :     io_reqds = palloc0(sizeof(bool) * nblocks);
   35 melanieplageman@gmai      722                 :            112 :     nblocks_per_io = palloc0(sizeof(int) * nblocks);
                                723                 :                : 
   39 andres@anarazel.de        724                 :            112 :     rel = relation_open(relid, AccessShareLock);
                                725                 :            112 :     smgr = RelationGetSmgr(rel);
                                726                 :                : 
                                727                 :                :     /*
                                728                 :                :      * Do StartReadBuffers() until IO for all the required blocks has been
                                729                 :                :      * started (if required).
                                730                 :                :      */
                                731         [ +  + ]:            326 :     while (nblocks_done < nblocks)
                                732                 :                :     {
                                733                 :            214 :         ReadBuffersOperation *operation = &operations[nios];
                                734                 :            214 :         int         nblocks_this_io =
                                735                 :            214 :             Min(nblocks - nblocks_done, io_combine_limit);
                                736                 :                : 
                                737                 :            214 :         operation->rel = rel;
                                738                 :            214 :         operation->smgr = smgr;
                                739                 :            214 :         operation->persistence = rel->rd_rel->relpersistence;
                                740                 :            214 :         operation->strategy = NULL;
                                741                 :            214 :         operation->forknum = MAIN_FORKNUM;
                                742                 :                : 
                                743                 :            428 :         io_reqds[nios] = StartReadBuffers(operation,
                                744                 :            214 :                                           &buffers[nblocks_done],
                                745                 :                :                                           startblock + nblocks_done,
                                746                 :                :                                           &nblocks_this_io,
                                747                 :                :                                           0);
   35 melanieplageman@gmai      748                 :            214 :         nblocks_per_io[nios] = nblocks_this_io;
   39 andres@anarazel.de        749                 :            214 :         nios++;
                                750                 :            214 :         nblocks_done += nblocks_this_io;
                                751                 :                :     }
                                752                 :                : 
                                753                 :                :     /*
                                754                 :                :      * Now wait for all operations that required IO. This is done at the end,
                                755                 :                :      * as otherwise waiting for IO in progress in other backends could
                                756                 :                :      * influence the result for subsequent buffers / blocks.
                                757                 :                :      */
                                758         [ +  + ]:            326 :     for (int nio = 0; nio < nios; nio++)
                                759                 :                :     {
                                760                 :            214 :         ReadBuffersOperation *operation = &operations[nio];
                                761                 :                : 
                                762         [ +  + ]:            214 :         if (io_reqds[nio])
                                763                 :            122 :             WaitReadBuffers(operation);
                                764                 :                :     }
                                765                 :                : 
                                766                 :                :     /*
                                767                 :                :      * Convert what has been done into SQL SRF return value.
                                768                 :                :      */
                                769         [ +  + ]:            326 :     for (int nio = 0; nio < nios; nio++)
                                770                 :                :     {
                                771                 :            214 :         ReadBuffersOperation *operation = &operations[nio];
   35 melanieplageman@gmai      772                 :            214 :         int         nblocks_this_io = nblocks_per_io[nio];
   39 andres@anarazel.de        773                 :            214 :         Datum       values[6] = {0};
                                774                 :            214 :         bool        nulls[6] = {0};
                                775                 :                :         ArrayType  *buffers_arr;
                                776                 :                : 
                                777                 :                :         /* convert buffer array to datum array */
                                778         [ +  + ]:            504 :         for (int i = 0; i < nblocks_this_io; i++)
                                779                 :                :         {
   35 melanieplageman@gmai      780                 :            290 :             Buffer      buf = buffers[nblocks_disp + i];
                                781                 :                : 
   39 andres@anarazel.de        782         [ -  + ]:            290 :             Assert(BufferGetBlockNumber(buf) == startblock + nblocks_disp + i);
                                783                 :                : 
                                784                 :            290 :             buffers_datum[nblocks_disp + i] = Int32GetDatum(buf);
                                785                 :                :         }
                                786                 :                : 
                                787                 :            214 :         buffers_arr = construct_array_builtin(&buffers_datum[nblocks_disp],
                                788                 :                :                                               nblocks_this_io,
                                789                 :                :                                               INT4OID);
                                790                 :                : 
                                791                 :                :         /* blockoff */
                                792                 :            214 :         values[0] = Int32GetDatum(nblocks_disp);
                                793                 :            214 :         nulls[0] = false;
                                794                 :                : 
                                795                 :                :         /* blocknum */
                                796                 :            214 :         values[1] = UInt32GetDatum(startblock + nblocks_disp);
                                797                 :            214 :         nulls[1] = false;
                                798                 :                : 
                                799                 :                :         /* io_reqd */
                                800                 :            214 :         values[2] = BoolGetDatum(io_reqds[nio]);
                                801                 :            214 :         nulls[2] = false;
                                802                 :                : 
                                803                 :                :         /* foreign IO - only valid when IO was required */
   35 melanieplageman@gmai      804   [ +  +  +  + ]:            214 :         values[3] = BoolGetDatum(io_reqds[nio] ? operation->foreign_io : false);
   39 andres@anarazel.de        805                 :            214 :         nulls[3] = false;
                                806                 :                : 
                                807                 :                :         /* nblocks */
                                808                 :            214 :         values[4] = Int32GetDatum(nblocks_this_io);
                                809                 :            214 :         nulls[4] = false;
                                810                 :                : 
                                811                 :                :         /* array of buffers */
                                812                 :            214 :         values[5] = PointerGetDatum(buffers_arr);
                                813                 :            214 :         nulls[5] = false;
                                814                 :                : 
                                815                 :            214 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
                                816                 :                : 
                                817                 :            214 :         nblocks_disp += nblocks_this_io;
                                818                 :                :     }
                                819                 :                : 
                                820                 :                :     /* release pins on all the buffers */
   35 melanieplageman@gmai      821         [ +  + ]:            402 :     for (int i = 0; i < nblocks_done; i++)
                                822                 :            290 :         ReleaseBuffer(buffers[i]);
                                823                 :                : 
                                824                 :                :     /*
                                825                 :                :      * Free explicitly, to have a chance to detect potential issues with too
                                826                 :                :      * long lived references to the operation.
                                827                 :                :      */
   39 andres@anarazel.de        828                 :            112 :     pfree(operations);
                                829                 :            112 :     pfree(buffers);
                                830                 :            112 :     pfree(buffers_datum);
                                831                 :            112 :     pfree(io_reqds);
   35 melanieplageman@gmai      832                 :            112 :     pfree(nblocks_per_io);
                                833                 :                : 
   39 andres@anarazel.de        834                 :            112 :     relation_close(rel, NoLock);
                                835                 :                : 
                                836                 :            112 :     return (Datum) 0;
                                837                 :                : }
                                838                 :                : 
                                839                 :                : 
                                840                 :                : static BlockNumber
                                841                 :            156 : read_stream_for_blocks_cb(ReadStream *stream,
                                842                 :                :                           void *callback_private_data,
                                843                 :                :                           void *per_buffer_data)
                                844                 :                : {
                                845                 :            156 :     BlocksReadStreamData *stream_data = callback_private_data;
                                846                 :                : 
                                847         [ +  + ]:            156 :     if (stream_data->curblock >= stream_data->nblocks)
                                848                 :             24 :         return InvalidBlockNumber;
                                849                 :            132 :     return stream_data->blocks[stream_data->curblock++];
                                850                 :                : }
                                851                 :                : 
                                852                 :             13 : PG_FUNCTION_INFO_V1(read_stream_for_blocks);
                                853                 :                : Datum
                                854                 :             24 : read_stream_for_blocks(PG_FUNCTION_ARGS)
                                855                 :                : {
                                856                 :             24 :     Oid         relid = PG_GETARG_OID(0);
                                857                 :             24 :     ArrayType  *blocksarray = PG_GETARG_ARRAYTYPE_P(1);
                                858                 :             24 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
                                859                 :                :     Relation    rel;
                                860                 :                :     BlocksReadStreamData stream_data;
                                861                 :                :     ReadStream *stream;
                                862                 :                : 
                                863                 :             24 :     InitMaterializedSRF(fcinfo, 0);
                                864                 :                : 
                                865                 :                :     /*
                                866                 :                :      * We expect the input to be an N-element int4 array; verify that. We
                                867                 :                :      * don't need to use deconstruct_array() since the array data is just
                                868                 :                :      * going to look like a C array of N int4 values.
                                869                 :                :      */
                                870         [ +  - ]:             24 :     if (ARR_NDIM(blocksarray) != 1 ||
                                871         [ +  - ]:             24 :         ARR_HASNULL(blocksarray) ||
                                872         [ -  + ]:             24 :         ARR_ELEMTYPE(blocksarray) != INT4OID)
   39 andres@anarazel.de        873         [ #  # ]:UNC           0 :         elog(ERROR, "expected 1 dimensional int4 array");
                                874                 :                : 
   39 andres@anarazel.de        875                 :GNC          24 :     stream_data.curblock = 0;
                                876                 :             24 :     stream_data.nblocks = ARR_DIMS(blocksarray)[0];
                                877         [ -  + ]:             24 :     stream_data.blocks = (uint32 *) ARR_DATA_PTR(blocksarray);
                                878                 :                : 
                                879                 :             24 :     rel = relation_open(relid, AccessShareLock);
                                880                 :                : 
                                881                 :             24 :     stream = read_stream_begin_relation(READ_STREAM_FULL,
                                882                 :                :                                         NULL,
                                883                 :                :                                         rel,
                                884                 :                :                                         MAIN_FORKNUM,
                                885                 :                :                                         read_stream_for_blocks_cb,
                                886                 :                :                                         &stream_data,
                                887                 :                :                                         0);
                                888                 :                : 
                                889         [ +  + ]:            156 :     for (int i = 0; i < stream_data.nblocks; i++)
                                890                 :                :     {
                                891                 :            132 :         Buffer      buf = read_stream_next_buffer(stream, NULL);
                                892                 :            132 :         Datum       values[3] = {0};
                                893                 :            132 :         bool        nulls[3] = {0};
                                894                 :                : 
                                895         [ -  + ]:            132 :         if (!BufferIsValid(buf))
   39 andres@anarazel.de        896         [ #  # ]:UNC           0 :             elog(ERROR, "read_stream_next_buffer() call %d is unexpectedly invalid", i);
                                897                 :                : 
   39 andres@anarazel.de        898                 :GNC         132 :         values[0] = Int32GetDatum(i);
                                899                 :            132 :         values[1] = UInt32GetDatum(stream_data.blocks[i]);
                                900                 :            132 :         values[2] = UInt32GetDatum(buf);
                                901                 :                : 
                                902                 :            132 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
                                903                 :                : 
                                904                 :            132 :         ReleaseBuffer(buf);
                                905                 :                :     }
                                906                 :                : 
                                907         [ -  + ]:             24 :     if (read_stream_next_buffer(stream, NULL) != InvalidBuffer)
   39 andres@anarazel.de        908         [ #  # ]:UNC           0 :         elog(ERROR, "read_stream_next_buffer() call %d is unexpectedly valid",
                                909                 :                :              stream_data.nblocks);
                                910                 :                : 
   39 andres@anarazel.de        911                 :GNC          24 :     read_stream_end(stream);
                                912                 :                : 
                                913                 :             24 :     relation_close(rel, NoLock);
                                914                 :                : 
                                915                 :             24 :     return (Datum) 0;
                                916                 :                : }
                                917                 :                : 
                                918                 :                : 
  399 andres@anarazel.de        919                 :CBC          10 : PG_FUNCTION_INFO_V1(handle_get);
                                920                 :                : Datum
                                921                 :             18 : handle_get(PG_FUNCTION_ARGS)
                                922                 :                : {
                                923                 :             18 :     last_handle = pgaio_io_acquire(CurrentResourceOwner, NULL);
                                924                 :                : 
                                925                 :             18 :     PG_RETURN_VOID();
                                926                 :                : }
                                927                 :                : 
                                928                 :             10 : PG_FUNCTION_INFO_V1(handle_release_last);
                                929                 :                : Datum
                                930                 :              6 : handle_release_last(PG_FUNCTION_ARGS)
                                931                 :                : {
                                932         [ -  + ]:              6 :     if (!last_handle)
  399 andres@anarazel.de        933         [ #  # ]:UBC           0 :         elog(ERROR, "no handle");
                                934                 :                : 
  399 andres@anarazel.de        935                 :CBC           6 :     pgaio_io_release(last_handle);
                                936                 :                : 
                                937                 :              3 :     PG_RETURN_VOID();
                                938                 :                : }
                                939                 :                : 
                                940                 :             10 : PG_FUNCTION_INFO_V1(handle_get_and_error);
                                941                 :                : Datum
                                942                 :              9 : handle_get_and_error(PG_FUNCTION_ARGS)
                                943                 :                : {
                                944                 :              9 :     pgaio_io_acquire(CurrentResourceOwner, NULL);
                                945                 :                : 
                                946         [ +  - ]:              9 :     elog(ERROR, "as you command");
                                947                 :                :     PG_RETURN_VOID();
                                948                 :                : }
                                949                 :                : 
                                950                 :             10 : PG_FUNCTION_INFO_V1(handle_get_twice);
                                951                 :                : Datum
                                952                 :              3 : handle_get_twice(PG_FUNCTION_ARGS)
                                953                 :                : {
                                954                 :              3 :     pgaio_io_acquire(CurrentResourceOwner, NULL);
                                955                 :              3 :     pgaio_io_acquire(CurrentResourceOwner, NULL);
                                956                 :                : 
  399 andres@anarazel.de        957                 :UBC           0 :     PG_RETURN_VOID();
                                958                 :                : }
                                959                 :                : 
  399 andres@anarazel.de        960                 :CBC          10 : PG_FUNCTION_INFO_V1(handle_get_release);
                                961                 :                : Datum
                                962                 :              9 : handle_get_release(PG_FUNCTION_ARGS)
                                963                 :                : {
                                964                 :                :     PgAioHandle *handle;
                                965                 :                : 
                                966                 :              9 :     handle = pgaio_io_acquire(CurrentResourceOwner, NULL);
                                967                 :              9 :     pgaio_io_release(handle);
                                968                 :                : 
                                969                 :              9 :     PG_RETURN_VOID();
                                970                 :                : }
                                971                 :                : 
                                972                 :             10 : PG_FUNCTION_INFO_V1(batch_start);
                                973                 :                : Datum
                                974                 :              9 : batch_start(PG_FUNCTION_ARGS)
                                975                 :                : {
                                976                 :              9 :     pgaio_enter_batchmode();
                                977                 :              9 :     PG_RETURN_VOID();
                                978                 :                : }
                                979                 :                : 
                                980                 :             10 : PG_FUNCTION_INFO_V1(batch_end);
                                981                 :                : Datum
                                982                 :              3 : batch_end(PG_FUNCTION_ARGS)
                                983                 :                : {
                                984                 :              3 :     pgaio_exit_batchmode();
                                985                 :              3 :     PG_RETURN_VOID();
                                986                 :                : }
                                987                 :                : 
                                988                 :                : #ifdef USE_INJECTION_POINTS
                                989                 :                : extern PGDLLEXPORT void inj_io_completion_hook(const char *name,
                                990                 :                :                                                const void *private_data,
                                991                 :                :                                                void *arg);
                                992                 :                : extern PGDLLEXPORT void inj_io_reopen(const char *name,
                                993                 :                :                                       const void *private_data,
                                994                 :                :                                       void *arg);
                                995                 :                : 
                                996                 :                : static bool
   39 andres@anarazel.de        997                 :GNC        3123 : inj_io_short_read_matches(PgAioHandle *ioh)
                                998                 :                : {
                                999                 :                :     PGPROC     *io_proc;
                               1000                 :                :     int32       io_pid;
                               1001                 :                :     int32       inj_pid;
                               1002                 :                :     PgAioTargetData *td;
                               1003                 :                : 
                               1004         [ +  + ]:           3123 :     if (!inj_io_error_state->enabled_short_read)
                               1005                 :           2879 :         return false;
                               1006                 :                : 
                               1007         [ -  + ]:            244 :     if (!inj_io_error_state->short_read_result_set)
   39 andres@anarazel.de       1008                 :UNC           0 :         return false;
                               1009                 :                : 
   39 andres@anarazel.de       1010                 :GNC         244 :     io_proc = GetPGProcByNumber(pgaio_io_get_owner(ioh));
                               1011                 :            244 :     io_pid = io_proc->pid;
                               1012                 :            244 :     inj_pid = inj_io_error_state->short_read_pid;
                               1013                 :                : 
                               1014   [ +  +  +  + ]:            244 :     if (inj_pid != InvalidPid && inj_pid != io_pid)
                               1015                 :             12 :         return false;
                               1016                 :                : 
                               1017                 :            232 :     td = pgaio_io_get_target_data(ioh);
                               1018                 :                : 
                               1019         [ +  + ]:            232 :     if (inj_io_error_state->short_read_relfilenode != InvalidOid &&
                               1020         [ -  + ]:              3 :         td->smgr.rlocator.relNumber != inj_io_error_state->short_read_relfilenode)
   39 andres@anarazel.de       1021                 :UNC           0 :         return false;
                               1022                 :                : 
                               1023                 :                :     /*
                               1024                 :                :      * Only shorten reads that are actually longer than the target size,
                               1025                 :                :      * otherwise we can trigger over-reads.
                               1026                 :                :      */
   39 andres@anarazel.de       1027         [ +  + ]:GNC         232 :     if (inj_io_error_state->short_read_result >= ioh->result)
                               1028                 :             51 :         return false;
                               1029                 :                : 
                               1030                 :            181 :     return true;
                               1031                 :                : }
                               1032                 :                : 
                               1033                 :                : static bool
                               1034                 :           3153 : inj_io_completion_wait_matches(PgAioHandle *ioh)
                               1035                 :                : {
                               1036                 :                :     PGPROC     *io_proc;
                               1037                 :                :     int32       io_pid;
                               1038                 :                :     PgAioTargetData *td;
                               1039                 :                :     int32       inj_pid;
                               1040                 :                :     BlockNumber io_blockno;
                               1041                 :                :     BlockNumber inj_blockno;
                               1042                 :                :     Oid         inj_relfilenode;
                               1043                 :                : 
                               1044         [ +  + ]:           3153 :     if (!inj_io_error_state->enabled_completion_wait)
                               1045                 :           2945 :         return false;
                               1046                 :                : 
                               1047                 :            208 :     io_proc = GetPGProcByNumber(pgaio_io_get_owner(ioh));
                               1048                 :            208 :     io_pid = io_proc->pid;
                               1049                 :            208 :     inj_pid = inj_io_error_state->completion_wait_pid;
                               1050                 :                : 
                               1051   [ +  -  +  + ]:            208 :     if (inj_pid != InvalidPid && inj_pid != io_pid)
                               1052                 :            166 :         return false;
                               1053                 :                : 
                               1054                 :             42 :     td = pgaio_io_get_target_data(ioh);
                               1055                 :                : 
                               1056                 :             42 :     inj_relfilenode = inj_io_error_state->completion_wait_relfilenode;
                               1057         [ +  - ]:             42 :     if (inj_relfilenode != InvalidOid &&
                               1058         [ +  + ]:             42 :         td->smgr.rlocator.relNumber != inj_relfilenode)
                               1059                 :             12 :         return false;
                               1060                 :                : 
                               1061                 :             30 :     inj_blockno = inj_io_error_state->completion_wait_blockno;
                               1062                 :             30 :     io_blockno = td->smgr.blockNum;
                               1063   [ +  +  +  - ]:             30 :     if (inj_blockno != InvalidBlockNumber &&
                               1064         [ -  + ]:             12 :         !(inj_blockno >= io_blockno && inj_blockno < (io_blockno + td->smgr.nblocks)))
   39 andres@anarazel.de       1065                 :UNC           0 :         return false;
                               1066                 :                : 
   39 andres@anarazel.de       1067                 :GNC          30 :     return true;
                               1068                 :                : }
                               1069                 :                : 
                               1070                 :                : static void
                               1071                 :           3123 : inj_io_completion_wait_hook(const char *name, const void *private_data, void *arg)
                               1072                 :                : {
                               1073                 :           3123 :     PgAioHandle *ioh = (PgAioHandle *) arg;
                               1074                 :                : 
                               1075         [ +  + ]:           3123 :     if (!inj_io_completion_wait_matches(ioh))
                               1076                 :           3108 :         return;
                               1077                 :                : 
                               1078                 :             15 :     ConditionVariablePrepareToSleep(&inj_io_error_state->cv);
                               1079                 :                : 
                               1080                 :                :     while (true)
                               1081                 :                :     {
                               1082         [ +  + ]:             30 :         if (!inj_io_completion_wait_matches(ioh))
                               1083                 :             15 :             break;
                               1084                 :                : 
                               1085                 :             15 :         ConditionVariableSleep(&inj_io_error_state->cv,
                               1086                 :             15 :                                inj_io_error_state->completion_wait_event);
                               1087                 :                :     }
                               1088                 :                : 
                               1089                 :             15 :     ConditionVariableCancelSleep();
                               1090                 :                : }
                               1091                 :                : 
                               1092                 :                : static void
                               1093                 :           3123 : inj_io_short_read_hook(const char *name, const void *private_data, void *arg)
                               1094                 :                : {
  360 michael@paquier.xyz      1095                 :CBC        3123 :     PgAioHandle *ioh = (PgAioHandle *) arg;
                               1096                 :                : 
  399 andres@anarazel.de       1097         [ +  - ]:           3123 :     ereport(LOG,
                               1098                 :                :             errmsg("short read injection point called, is enabled: %d",
                               1099                 :                :                    inj_io_error_state->enabled_short_read),
                               1100                 :                :             errhidestmt(true), errhidecontext(true));
                               1101                 :                : 
   39 andres@anarazel.de       1102         [ +  + ]:GNC        3123 :     if (inj_io_short_read_matches(ioh))
                               1103                 :                :     {
                               1104                 :            181 :         struct iovec *iov = &pgaio_ctl->iovecs[ioh->iovec_off];
                               1105                 :            181 :         int32       old_result = ioh->result;
                               1106                 :            181 :         int32       new_result = inj_io_error_state->short_read_result;
                               1107                 :            181 :         int32       processed = 0;
                               1108                 :                : 
                               1109         [ +  - ]:            181 :         ereport(LOG,
                               1110                 :                :                 errmsg("short read inject point, changing result from %d to %d",
                               1111                 :                :                        old_result, new_result),
                               1112                 :                :                 errhidestmt(true), errhidecontext(true));
                               1113                 :                : 
                               1114                 :                :         /*
                               1115                 :                :          * The underlying IO actually completed OK, and thus the "invalid"
                               1116                 :                :          * portion of the IOV actually contains valid data. That can hide a
                               1117                 :                :          * lot of problems, e.g. if we were to wrongly mark a buffer, that
                               1118                 :                :          * wasn't read according to the shortened-read, IO as valid, the
                               1119                 :                :          * contents would look valid and we might miss a bug.
                               1120                 :                :          *
                               1121                 :                :          * To avoid that, iterate through the IOV and zero out the "failed"
                               1122                 :                :          * portion of the IO.
                               1123                 :                :          */
                               1124         [ +  + ]:            368 :         for (int i = 0; i < ioh->op_data.read.iov_length; i++)
                               1125                 :                :         {
                               1126         [ +  + ]:            187 :             if (processed + iov[i].iov_len <= new_result)
                               1127                 :             18 :                 processed += iov[i].iov_len;
                               1128         [ +  - ]:            169 :             else if (processed <= new_result)
                               1129                 :                :             {
                               1130                 :            169 :                 uint32      ok_part = new_result - processed;
                               1131                 :                : 
                               1132                 :            169 :                 memset((char *) iov[i].iov_base + ok_part, 0, iov[i].iov_len - ok_part);
                               1133                 :            169 :                 processed += iov[i].iov_len;
                               1134                 :                :             }
                               1135                 :                :             else
                               1136                 :                :             {
   39 andres@anarazel.de       1137                 :UNC           0 :                 memset((char *) iov[i].iov_base, 0, iov[i].iov_len);
                               1138                 :                :             }
                               1139                 :                :         }
                               1140                 :                : 
   39 andres@anarazel.de       1141                 :GNC         181 :         ioh->result = new_result;
                               1142                 :                :     }
  399 andres@anarazel.de       1143                 :CBC        3123 : }
                               1144                 :                : 
                               1145                 :                : void
   39 andres@anarazel.de       1146                 :GNC        3123 : inj_io_completion_hook(const char *name, const void *private_data, void *arg)
                               1147                 :                : {
                               1148                 :           3123 :     inj_io_completion_wait_hook(name, private_data, arg);
                               1149                 :           3123 :     inj_io_short_read_hook(name, private_data, arg);
                               1150                 :           3123 : }
                               1151                 :                : 
                               1152                 :                : void
  360 michael@paquier.xyz      1153                 :CBC         505 : inj_io_reopen(const char *name, const void *private_data, void *arg)
                               1154                 :                : {
  399 andres@anarazel.de       1155         [ +  - ]:            505 :     ereport(LOG,
                               1156                 :                :             errmsg("reopen injection point called, is enabled: %d",
                               1157                 :                :                    inj_io_error_state->enabled_reopen),
                               1158                 :                :             errhidestmt(true), errhidecontext(true));
                               1159                 :                : 
                               1160         [ +  + ]:            505 :     if (inj_io_error_state->enabled_reopen)
                               1161         [ +  - ]:              1 :         elog(ERROR, "injection point triggering failure to reopen ");
                               1162                 :            504 : }
                               1163                 :                : #endif
                               1164                 :                : 
   39 andres@anarazel.de       1165                 :GNC          13 : PG_FUNCTION_INFO_V1(inj_io_completion_wait);
                               1166                 :                : Datum
                               1167                 :             15 : inj_io_completion_wait(PG_FUNCTION_ARGS)
                               1168                 :                : {
                               1169                 :                : #ifdef USE_INJECTION_POINTS
                               1170                 :             15 :     inj_io_error_state->enabled_completion_wait = true;
                               1171                 :             15 :     inj_io_error_state->completion_wait_pid =
                               1172         [ +  - ]:             15 :         PG_ARGISNULL(0) ? InvalidPid : PG_GETARG_INT32(0);
                               1173                 :             15 :     inj_io_error_state->completion_wait_relfilenode =
                               1174         [ +  - ]:             15 :         PG_ARGISNULL(1) ? InvalidOid : PG_GETARG_OID(1);
                               1175                 :             15 :     inj_io_error_state->completion_wait_blockno =
                               1176         [ +  + ]:             15 :         PG_ARGISNULL(2) ? InvalidBlockNumber : PG_GETARG_UINT32(2);
                               1177                 :                : #else
                               1178                 :                :     elog(ERROR, "injection points not supported");
                               1179                 :                : #endif
                               1180                 :                : 
                               1181                 :             15 :     PG_RETURN_VOID();
                               1182                 :                : }
                               1183                 :                : 
                               1184                 :             19 : PG_FUNCTION_INFO_V1(inj_io_completion_continue);
                               1185                 :                : Datum
                               1186                 :             15 : inj_io_completion_continue(PG_FUNCTION_ARGS)
                               1187                 :                : {
                               1188                 :                : #ifdef USE_INJECTION_POINTS
                               1189                 :             15 :     inj_io_error_state->enabled_completion_wait = false;
                               1190                 :             15 :     inj_io_error_state->completion_wait_pid = InvalidPid;
                               1191                 :             15 :     inj_io_error_state->completion_wait_relfilenode = InvalidOid;
                               1192                 :             15 :     inj_io_error_state->completion_wait_blockno = InvalidBlockNumber;
                               1193                 :             15 :     ConditionVariableBroadcast(&inj_io_error_state->cv);
                               1194                 :                : #else
                               1195                 :                :     elog(ERROR, "injection points not supported");
                               1196                 :                : #endif
                               1197                 :                : 
                               1198                 :             15 :     PG_RETURN_VOID();
                               1199                 :                : }
                               1200                 :                : 
  399 andres@anarazel.de       1201                 :CBC          13 : PG_FUNCTION_INFO_V1(inj_io_short_read_attach);
                               1202                 :                : Datum
                               1203                 :             24 : inj_io_short_read_attach(PG_FUNCTION_ARGS)
                               1204                 :                : {
                               1205                 :                : #ifdef USE_INJECTION_POINTS
                               1206                 :             24 :     inj_io_error_state->enabled_short_read = true;
                               1207                 :             24 :     inj_io_error_state->short_read_result_set = !PG_ARGISNULL(0);
                               1208         [ +  - ]:             24 :     if (inj_io_error_state->short_read_result_set)
                               1209                 :             24 :         inj_io_error_state->short_read_result = PG_GETARG_INT32(0);
   39 andres@anarazel.de       1210                 :GNC          24 :     inj_io_error_state->short_read_pid =
                               1211         [ +  + ]:             24 :         PG_ARGISNULL(1) ? InvalidPid : PG_GETARG_INT32(1);
                               1212                 :             24 :     inj_io_error_state->short_read_relfilenode =
                               1213         [ +  + ]:             24 :         PG_ARGISNULL(2) ? InvalidOid : PG_GETARG_OID(2);
                               1214                 :                : #else
                               1215                 :                :     elog(ERROR, "injection points not supported");
                               1216                 :                : #endif
                               1217                 :                : 
  399 andres@anarazel.de       1218                 :CBC          24 :     PG_RETURN_VOID();
                               1219                 :                : }
                               1220                 :                : 
                               1221                 :             13 : PG_FUNCTION_INFO_V1(inj_io_short_read_detach);
                               1222                 :                : Datum
                               1223                 :              9 : inj_io_short_read_detach(PG_FUNCTION_ARGS)
                               1224                 :                : {
                               1225                 :                : #ifdef USE_INJECTION_POINTS
                               1226                 :              9 :     inj_io_error_state->enabled_short_read = false;
                               1227                 :                : #else
                               1228                 :                :     elog(ERROR, "injection points not supported");
                               1229                 :                : #endif
                               1230                 :              9 :     PG_RETURN_VOID();
                               1231                 :                : }
                               1232                 :                : 
                               1233                 :              8 : PG_FUNCTION_INFO_V1(inj_io_reopen_attach);
                               1234                 :                : Datum
                               1235                 :              1 : inj_io_reopen_attach(PG_FUNCTION_ARGS)
                               1236                 :                : {
                               1237                 :                : #ifdef USE_INJECTION_POINTS
                               1238                 :              1 :     inj_io_error_state->enabled_reopen = true;
                               1239                 :                : #else
                               1240                 :                :     elog(ERROR, "injection points not supported");
                               1241                 :                : #endif
                               1242                 :                : 
                               1243                 :              1 :     PG_RETURN_VOID();
                               1244                 :                : }
                               1245                 :                : 
                               1246                 :              8 : PG_FUNCTION_INFO_V1(inj_io_reopen_detach);
                               1247                 :                : Datum
                               1248                 :              1 : inj_io_reopen_detach(PG_FUNCTION_ARGS)
                               1249                 :                : {
                               1250                 :                : #ifdef USE_INJECTION_POINTS
                               1251                 :              1 :     inj_io_error_state->enabled_reopen = false;
                               1252                 :                : #else
                               1253                 :                :     elog(ERROR, "injection points not supported");
                               1254                 :                : #endif
                               1255                 :              1 :     PG_RETURN_VOID();
                               1256                 :                : }
        

Generated by: LCOV version 2.5.0-beta