LCOV - code coverage report
Current view: top level - src/backend/storage/aio - aio_init.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 95.5 % 88 84
Test Date: 2026-02-17 17:20:33 Functions: 100.0 % 10 10
Legend: Lines:     hit not hit

            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         4407 : AioCtlShmemSize(void)
      32              : {
      33              :     /* pgaio_ctl itself */
      34         4407 :     return sizeof(PgAioCtl);
      35              : }
      36              : 
      37              : static uint32
      38       185636 : 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       185636 :     return MaxBackends + NUM_AUXILIARY_PROCS;
      46              : }
      47              : 
      48              : static Size
      49         3267 : AioBackendShmemSize(void)
      50              : {
      51         3267 :     return mul_size(AioProcs(), sizeof(PgAioBackend));
      52              : }
      53              : 
      54              : static Size
      55         3267 : AioHandleShmemSize(void)
      56              : {
      57              :     Size        sz;
      58              : 
      59              :     /* verify AioChooseMaxConcurrency() did its thing */
      60              :     Assert(io_max_concurrency > 0);
      61              : 
      62              :     /* io handles */
      63         3267 :     sz = mul_size(AioProcs(),
      64              :                   mul_size(io_max_concurrency, sizeof(PgAioHandle)));
      65              : 
      66         3267 :     return sz;
      67              : }
      68              : 
      69              : static Size
      70         3267 : AioHandleIOVShmemSize(void)
      71              : {
      72              :     /* each IO handle can have up to io_max_combine_limit iovec objects */
      73         3267 :     return mul_size(sizeof(struct iovec),
      74         3267 :                     mul_size(mul_size(io_max_combine_limit, AioProcs()),
      75              :                              io_max_concurrency));
      76              : }
      77              : 
      78              : static Size
      79         3267 : AioHandleDataShmemSize(void)
      80              : {
      81              :     /* each buffer referenced by an iovec can have associated data */
      82         3267 :     return mul_size(sizeof(uint64),
      83         3267 :                     mul_size(mul_size(io_max_combine_limit, AioProcs()),
      84              :                              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         1137 : AioChooseMaxConcurrency(void)
      98              : {
      99              :     uint32      max_backends;
     100              :     int         max_proportional_pins;
     101              : 
     102              :     /* Similar logic to LimitAdditionalPins() */
     103         1137 :     max_backends = MaxBackends + NUM_AUXILIARY_PROCS;
     104         1137 :     max_proportional_pins = NBuffers / max_backends;
     105              : 
     106         1137 :     max_proportional_pins = Max(max_proportional_pins, 1);
     107              : 
     108              :     /* apply upper limit */
     109         1137 :     return Min(max_proportional_pins, 64);
     110              : }
     111              : 
     112              : Size
     113         2127 : AioShmemSize(void)
     114              : {
     115         2127 :     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         2127 :     if (io_max_concurrency == -1)
     124              :     {
     125              :         char        buf[32];
     126              : 
     127         1137 :         snprintf(buf, sizeof(buf), "%d", AioChooseMaxConcurrency());
     128         1137 :         SetConfigOption("io_max_concurrency", buf, PGC_POSTMASTER,
     129              :                         PGC_S_DYNAMIC_DEFAULT);
     130         1137 :         if (io_max_concurrency == -1)   /* failed to apply it? */
     131            0 :             SetConfigOption("io_max_concurrency", buf, PGC_POSTMASTER,
     132              :                             PGC_S_OVERRIDE);
     133              :     }
     134              : 
     135         2127 :     sz = add_size(sz, AioCtlShmemSize());
     136         2127 :     sz = add_size(sz, AioBackendShmemSize());
     137         2127 :     sz = add_size(sz, AioHandleShmemSize());
     138         2127 :     sz = add_size(sz, AioHandleIOVShmemSize());
     139         2127 :     sz = add_size(sz, AioHandleDataShmemSize());
     140              : 
     141              :     /* Reserve space for method specific resources. */
     142         2127 :     if (pgaio_method_ops->shmem_size)
     143         2120 :         sz = add_size(sz, pgaio_method_ops->shmem_size());
     144              : 
     145         2127 :     return sz;
     146              : }
     147              : 
     148              : void
     149         1140 : AioShmemInit(void)
     150              : {
     151              :     bool        found;
     152         1140 :     uint32      io_handle_off = 0;
     153         1140 :     uint32      iovec_off = 0;
     154         1140 :     uint32      per_backend_iovecs = io_max_concurrency * io_max_combine_limit;
     155              : 
     156         1140 :     pgaio_ctl = (PgAioCtl *)
     157         1140 :         ShmemInitStruct("AioCtl", AioCtlShmemSize(), &found);
     158              : 
     159         1140 :     if (found)
     160            0 :         goto out;
     161              : 
     162         1140 :     memset(pgaio_ctl, 0, AioCtlShmemSize());
     163              : 
     164         1140 :     pgaio_ctl->io_handle_count = AioProcs() * io_max_concurrency;
     165         1140 :     pgaio_ctl->iovec_count = AioProcs() * per_backend_iovecs;
     166              : 
     167         2280 :     pgaio_ctl->backend_state = (PgAioBackend *)
     168         1140 :         ShmemInitStruct("AioBackend", AioBackendShmemSize(), &found);
     169              : 
     170         2280 :     pgaio_ctl->io_handles = (PgAioHandle *)
     171         1140 :         ShmemInitStruct("AioHandle", AioHandleShmemSize(), &found);
     172              : 
     173         2280 :     pgaio_ctl->iovecs = (struct iovec *)
     174         1140 :         ShmemInitStruct("AioHandleIOV", AioHandleIOVShmemSize(), &found);
     175         2280 :     pgaio_ctl->handle_data = (uint64 *)
     176         1140 :         ShmemInitStruct("AioHandleData", AioHandleDataShmemSize(), &found);
     177              : 
     178       149060 :     for (int procno = 0; procno < AioProcs(); procno++)
     179              :     {
     180       147920 :         PgAioBackend *bs = &pgaio_ctl->backend_state[procno];
     181              : 
     182       147920 :         bs->io_handle_off = io_handle_off;
     183       147920 :         io_handle_off += io_max_concurrency;
     184              : 
     185       147920 :         dclist_init(&bs->idle_ios);
     186       147920 :         memset(bs->staged_ios, 0, sizeof(PgAioHandle *) * PGAIO_SUBMIT_BATCH_SIZE);
     187       147920 :         dclist_init(&bs->in_flight_ios);
     188              : 
     189              :         /* initialize per-backend IOs */
     190      7070923 :         for (int i = 0; i < io_max_concurrency; i++)
     191              :         {
     192      6923003 :             PgAioHandle *ioh = &pgaio_ctl->io_handles[bs->io_handle_off + i];
     193              : 
     194      6923003 :             ioh->generation = 1;
     195      6923003 :             ioh->owner_procno = procno;
     196      6923003 :             ioh->iovec_off = iovec_off;
     197      6923003 :             ioh->handle_data_len = 0;
     198      6923003 :             ioh->report_return = NULL;
     199      6923003 :             ioh->resowner = NULL;
     200      6923003 :             ioh->num_callbacks = 0;
     201      6923003 :             ioh->distilled_result.status = PGAIO_RS_UNKNOWN;
     202      6923003 :             ioh->flags = 0;
     203              : 
     204      6923003 :             ConditionVariableInit(&ioh->cv);
     205              : 
     206      6923003 :             dclist_push_tail(&bs->idle_ios, &ioh->node);
     207      6923003 :             iovec_off += io_max_combine_limit;
     208              :         }
     209              :     }
     210              : 
     211         1140 : out:
     212              :     /* Initialize IO method specific resources. */
     213         1140 :     if (pgaio_method_ops->shmem_init)
     214         1135 :         pgaio_method_ops->shmem_init(!found);
     215         1140 : }
     216              : 
     217              : void
     218        22974 : pgaio_init_backend(void)
     219              : {
     220              :     /* shouldn't be initialized twice */
     221              :     Assert(!pgaio_my_backend);
     222              : 
     223        22974 :     if (MyBackendType == B_IO_WORKER)
     224         1746 :         return;
     225              : 
     226        21228 :     if (MyProc == NULL || MyProcNumber >= AioProcs())
     227            0 :         elog(ERROR, "aio requires a normal PGPROC");
     228              : 
     229        21228 :     pgaio_my_backend = &pgaio_ctl->backend_state[MyProcNumber];
     230              : 
     231        21228 :     if (pgaio_method_ops->init_backend)
     232            0 :         pgaio_method_ops->init_backend();
     233              : 
     234        21228 :     before_shmem_exit(pgaio_shutdown, 0);
     235              : }
        

Generated by: LCOV version 2.0-1