LCOV - code coverage report
Current view: top level - src/backend/storage/aio - aio_init.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 96.2 % 104 100
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 10 10
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 59.4 % 32 19

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * aio_init.c
       4                 :             :  *    AIO - Subsystem Initialization
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  * IDENTIFICATION
      10                 :             :  *    src/backend/storage/aio/aio_init.c
      11                 :             :  *
      12                 :             :  *-------------------------------------------------------------------------
      13                 :             :  */
      14                 :             : 
      15                 :             : #include "postgres.h"
      16                 :             : 
      17                 :             : #include "miscadmin.h"
      18                 :             : #include "storage/aio.h"
      19                 :             : #include "storage/aio_internal.h"
      20                 :             : #include "storage/aio_subsys.h"
      21                 :             : #include "storage/bufmgr.h"
      22                 :             : #include "storage/io_worker.h"
      23                 :             : #include "storage/ipc.h"
      24                 :             : #include "storage/proc.h"
      25                 :             : #include "storage/shmem.h"
      26                 :             : #include "utils/guc.h"
      27                 :             : 
      28                 :             : 
      29                 :             : 
      30                 :             : static Size
      31                 :          21 : AioCtlShmemSize(void)
      32                 :             : {
      33                 :             :         /* pgaio_ctl itself */
      34                 :          21 :         return sizeof(PgAioCtl);
      35                 :             : }
      36                 :             : 
      37                 :             : static uint32
      38                 :        1915 : AioProcs(void)
      39                 :             : {
      40                 :             :         /*
      41                 :             :          * While AIO workers don't need their own AIO context, we can't currently
      42                 :             :          * guarantee that nothing gets assigned to an IO worker's ProcNumber if we
      43                 :             :          * just subtracted MAX_IO_WORKERS.
      44                 :             :          */
      45                 :        1915 :         return MaxBackends + NUM_AUXILIARY_PROCS;
      46                 :             : }
      47                 :             : 
      48                 :             : static Size
      49                 :          15 : AioBackendShmemSize(void)
      50                 :             : {
      51                 :          15 :         return mul_size(AioProcs(), sizeof(PgAioBackend));
      52                 :             : }
      53                 :             : 
      54                 :             : static Size
      55                 :          15 : AioHandleShmemSize(void)
      56                 :             : {
      57                 :          15 :         Size            sz;
      58                 :             : 
      59                 :             :         /* verify AioChooseMaxConcurrency() did its thing */
      60         [ +  - ]:          15 :         Assert(io_max_concurrency > 0);
      61                 :             : 
      62                 :             :         /* io handles */
      63                 :          30 :         sz = mul_size(AioProcs(),
      64                 :          15 :                                   mul_size(io_max_concurrency, sizeof(PgAioHandle)));
      65                 :             : 
      66                 :          30 :         return sz;
      67                 :          15 : }
      68                 :             : 
      69                 :             : static Size
      70                 :          15 : AioHandleIOVShmemSize(void)
      71                 :             : {
      72                 :             :         /* each IO handle can have up to io_max_combine_limit iovec objects */
      73                 :          15 :         return mul_size(sizeof(struct iovec),
      74                 :          30 :                                         mul_size(mul_size(io_max_combine_limit, AioProcs()),
      75                 :          15 :                                                          io_max_concurrency));
      76                 :             : }
      77                 :             : 
      78                 :             : static Size
      79                 :          15 : AioHandleDataShmemSize(void)
      80                 :             : {
      81                 :             :         /* each buffer referenced by an iovec can have associated data */
      82                 :          15 :         return mul_size(sizeof(uint64),
      83                 :          30 :                                         mul_size(mul_size(io_max_combine_limit, AioProcs()),
      84                 :          15 :                                                          io_max_concurrency));
      85                 :             : }
      86                 :             : 
      87                 :             : /*
      88                 :             :  * Choose a suitable value for io_max_concurrency.
      89                 :             :  *
      90                 :             :  * It's unlikely that we could have more IOs in flight than buffers that we
      91                 :             :  * would be allowed to pin.
      92                 :             :  *
      93                 :             :  * On the upper end, apply a cap too - just because shared_buffers is large,
      94                 :             :  * it doesn't make sense have millions of buffers undergo IO concurrently.
      95                 :             :  */
      96                 :             : static int
      97                 :           6 : AioChooseMaxConcurrency(void)
      98                 :             : {
      99                 :           6 :         uint32          max_backends;
     100                 :           6 :         int                     max_proportional_pins;
     101                 :             : 
     102                 :             :         /* Similar logic to LimitAdditionalPins() */
     103                 :           6 :         max_backends = MaxBackends + NUM_AUXILIARY_PROCS;
     104                 :           6 :         max_proportional_pins = NBuffers / max_backends;
     105                 :             : 
     106         [ +  - ]:           6 :         max_proportional_pins = Max(max_proportional_pins, 1);
     107                 :             : 
     108                 :             :         /* apply upper limit */
     109         [ +  + ]:           6 :         return Min(max_proportional_pins, 64);
     110                 :           6 : }
     111                 :             : 
     112                 :             : Size
     113                 :           9 : AioShmemSize(void)
     114                 :             : {
     115                 :           9 :         Size            sz = 0;
     116                 :             : 
     117                 :             :         /*
     118                 :             :          * We prefer to report this value's source as PGC_S_DYNAMIC_DEFAULT.
     119                 :             :          * However, if the DBA explicitly set io_max_concurrency = -1 in the
     120                 :             :          * config file, then PGC_S_DYNAMIC_DEFAULT will fail to override that and
     121                 :             :          * we must force the matter with PGC_S_OVERRIDE.
     122                 :             :          */
     123         [ +  + ]:           9 :         if (io_max_concurrency == -1)
     124                 :             :         {
     125                 :           6 :                 char            buf[32];
     126                 :             : 
     127                 :           6 :                 snprintf(buf, sizeof(buf), "%d", AioChooseMaxConcurrency());
     128                 :           6 :                 SetConfigOption("io_max_concurrency", buf, PGC_POSTMASTER,
     129                 :             :                                                 PGC_S_DYNAMIC_DEFAULT);
     130         [ +  - ]:           6 :                 if (io_max_concurrency == -1)   /* failed to apply it? */
     131                 :           0 :                         SetConfigOption("io_max_concurrency", buf, PGC_POSTMASTER,
     132                 :             :                                                         PGC_S_OVERRIDE);
     133                 :           6 :         }
     134                 :             : 
     135                 :           9 :         sz = add_size(sz, AioCtlShmemSize());
     136                 :           9 :         sz = add_size(sz, AioBackendShmemSize());
     137                 :           9 :         sz = add_size(sz, AioHandleShmemSize());
     138                 :           9 :         sz = add_size(sz, AioHandleIOVShmemSize());
     139                 :           9 :         sz = add_size(sz, AioHandleDataShmemSize());
     140                 :             : 
     141                 :             :         /* Reserve space for method specific resources. */
     142         [ -  + ]:           9 :         if (pgaio_method_ops->shmem_size)
     143                 :           9 :                 sz = add_size(sz, pgaio_method_ops->shmem_size());
     144                 :             : 
     145                 :          18 :         return sz;
     146                 :           9 : }
     147                 :             : 
     148                 :             : void
     149                 :           6 : AioShmemInit(void)
     150                 :             : {
     151                 :           6 :         bool            found;
     152                 :           6 :         uint32          io_handle_off = 0;
     153                 :           6 :         uint32          iovec_off = 0;
     154                 :           6 :         uint32          per_backend_iovecs = io_max_concurrency * io_max_combine_limit;
     155                 :             : 
     156                 :           6 :         pgaio_ctl = (PgAioCtl *)
     157                 :           6 :                 ShmemInitStruct("AioCtl", AioCtlShmemSize(), &found);
     158                 :             : 
     159         [ -  + ]:           6 :         if (found)
     160                 :           0 :                 goto out;
     161                 :             : 
     162                 :           6 :         memset(pgaio_ctl, 0, AioCtlShmemSize());
     163                 :             : 
     164                 :           6 :         pgaio_ctl->io_handle_count = AioProcs() * io_max_concurrency;
     165                 :           6 :         pgaio_ctl->iovec_count = AioProcs() * per_backend_iovecs;
     166                 :             : 
     167                 :           6 :         pgaio_ctl->backend_state = (PgAioBackend *)
     168                 :           6 :                 ShmemInitStruct("AioBackend", AioBackendShmemSize(), &found);
     169                 :             : 
     170                 :           6 :         pgaio_ctl->io_handles = (PgAioHandle *)
     171                 :           6 :                 ShmemInitStruct("AioHandle", AioHandleShmemSize(), &found);
     172                 :             : 
     173                 :           6 :         pgaio_ctl->iovecs = (struct iovec *)
     174                 :           6 :                 ShmemInitStruct("AioHandleIOV", AioHandleIOVShmemSize(), &found);
     175                 :           6 :         pgaio_ctl->handle_data = (uint64 *)
     176                 :           6 :                 ShmemInitStruct("AioHandleData", AioHandleDataShmemSize(), &found);
     177                 :             : 
     178         [ +  + ]:        1040 :         for (int procno = 0; procno < AioProcs(); procno++)
     179                 :             :         {
     180                 :        1034 :                 PgAioBackend *bs = &pgaio_ctl->backend_state[procno];
     181                 :             : 
     182                 :        1034 :                 bs->io_handle_off = io_handle_off;
     183                 :        1034 :                 io_handle_off += io_max_concurrency;
     184                 :             : 
     185                 :        1034 :                 dclist_init(&bs->idle_ios);
     186                 :        1034 :                 memset(bs->staged_ios, 0, sizeof(PgAioHandle *) * PGAIO_SUBMIT_BATCH_SIZE);
     187                 :        1034 :                 dclist_init(&bs->in_flight_ios);
     188                 :             : 
     189                 :             :                 /* initialize per-backend IOs */
     190         [ +  + ]:       56944 :                 for (int i = 0; i < io_max_concurrency; i++)
     191                 :             :                 {
     192                 :       55910 :                         PgAioHandle *ioh = &pgaio_ctl->io_handles[bs->io_handle_off + i];
     193                 :             : 
     194                 :       55910 :                         ioh->generation = 1;
     195                 :       55910 :                         ioh->owner_procno = procno;
     196                 :       55910 :                         ioh->iovec_off = iovec_off;
     197                 :       55910 :                         ioh->handle_data_len = 0;
     198                 :       55910 :                         ioh->report_return = NULL;
     199                 :       55910 :                         ioh->resowner = NULL;
     200                 :       55910 :                         ioh->num_callbacks = 0;
     201                 :       55910 :                         ioh->distilled_result.status = PGAIO_RS_UNKNOWN;
     202                 :       55910 :                         ioh->flags = 0;
     203                 :             : 
     204                 :       55910 :                         ConditionVariableInit(&ioh->cv);
     205                 :             : 
     206                 :       55910 :                         dclist_push_tail(&bs->idle_ios, &ioh->node);
     207                 :       55910 :                         iovec_off += io_max_combine_limit;
     208                 :       55910 :                 }
     209                 :        1040 :         }
     210                 :             : 
     211                 :             : out:
     212                 :             :         /* Initialize IO method specific resources. */
     213         [ -  + ]:           6 :         if (pgaio_method_ops->shmem_init)
     214                 :           6 :                 pgaio_method_ops->shmem_init(!found);
     215                 :           6 : }
     216                 :             : 
     217                 :             : void
     218                 :         806 : pgaio_init_backend(void)
     219                 :             : {
     220                 :             :         /* shouldn't be initialized twice */
     221         [ +  - ]:         806 :         Assert(!pgaio_my_backend);
     222                 :             : 
     223         [ +  + ]:         806 :         if (MyBackendType == B_IO_WORKER)
     224                 :           3 :                 return;
     225                 :             : 
     226         [ +  - ]:         803 :         if (MyProc == NULL || MyProcNumber >= AioProcs())
     227   [ #  #  #  # ]:           0 :                 elog(ERROR, "aio requires a normal PGPROC");
     228                 :             : 
     229                 :         803 :         pgaio_my_backend = &pgaio_ctl->backend_state[MyProcNumber];
     230                 :             : 
     231         [ +  - ]:         803 :         if (pgaio_method_ops->init_backend)
     232                 :           0 :                 pgaio_method_ops->init_backend();
     233                 :             : 
     234                 :         803 :         before_shmem_exit(pgaio_shutdown, 0);
     235                 :         806 : }
        

Generated by: LCOV version 2.3.2-1