LCOV - code coverage report
Current view: top level - src/backend/utils/activity - pgstat_io.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 85.5 % 221 189
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 15 15
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 80.0 % 230 184

             Branch data     Line data    Source code
       1                 :             : /* -------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * pgstat_io.c
       4                 :             :  *        Implementation of IO statistics.
       5                 :             :  *
       6                 :             :  * This file contains the implementation of IO statistics. It is kept separate
       7                 :             :  * from pgstat.c to enforce the line between the statistics access / storage
       8                 :             :  * implementation and the details about individual types of statistics.
       9                 :             :  *
      10                 :             :  * Copyright (c) 2021-2026, PostgreSQL Global Development Group
      11                 :             :  *
      12                 :             :  * IDENTIFICATION
      13                 :             :  *        src/backend/utils/activity/pgstat_io.c
      14                 :             :  * -------------------------------------------------------------------------
      15                 :             :  */
      16                 :             : 
      17                 :             : #include "postgres.h"
      18                 :             : 
      19                 :             : #include "executor/instrument.h"
      20                 :             : #include "storage/bufmgr.h"
      21                 :             : #include "utils/pgstat_internal.h"
      22                 :             : 
      23                 :             : static PgStat_PendingIO PendingIOStats;
      24                 :             : static bool have_iostats = false;
      25                 :             : 
      26                 :             : /*
      27                 :             :  * Check that stats have not been counted for any combination of IOObject,
      28                 :             :  * IOContext, and IOOp which are not tracked for the passed-in BackendType. If
      29                 :             :  * stats are tracked for this combination and IO times are non-zero, counts
      30                 :             :  * should be non-zero.
      31                 :             :  *
      32                 :             :  * The passed-in PgStat_BktypeIO must contain stats from the BackendType
      33                 :             :  * specified by the second parameter. Caller is responsible for locking the
      34                 :             :  * passed-in PgStat_BktypeIO, if needed.
      35                 :             :  */
      36                 :             : bool
      37                 :        2994 : pgstat_bktype_io_stats_valid(PgStat_BktypeIO *backend_io,
      38                 :             :                                                          BackendType bktype)
      39                 :             : {
      40   [ +  +  -  -  :       11976 :         for (int io_object = 0; io_object < IOOBJECT_NUM_TYPES; io_object++)
                      + ]
      41                 :             :         {
      42   [ +  +  +  - ]:       53892 :                 for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++)
      43                 :             :                 {
      44   [ +  +  -  + ]:      404190 :                         for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++)
      45                 :             :                         {
      46                 :             :                                 /* we do track it */
      47         [ +  + ]:      359280 :                                 if (pgstat_tracks_io_op(bktype, io_object, io_context, io_op))
      48                 :             :                                 {
      49                 :             :                                         /* ensure that if IO times are non-zero, counts are > 0 */
      50   [ -  +  #  # ]:      121696 :                                         if (backend_io->times[io_object][io_context][io_op] != 0 &&
      51                 :           0 :                                                 backend_io->counts[io_object][io_context][io_op] <= 0)
      52                 :           0 :                                                 return false;
      53                 :             : 
      54                 :      121696 :                                         continue;
      55                 :             :                                 }
      56                 :             : 
      57                 :             :                                 /* we don't track it, and it is not 0 */
      58         [ -  + ]:      237584 :                                 if (backend_io->counts[io_object][io_context][io_op] != 0)
      59                 :           0 :                                         return false;
      60                 :      237584 :                         }
      61                 :       44910 :                 }
      62                 :        8982 :         }
      63                 :             : 
      64                 :        2994 :         return true;
      65                 :        2994 : }
      66                 :             : 
      67                 :             : void
      68                 :    11742901 : pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op,
      69                 :             :                                    uint32 cnt, uint64 bytes)
      70                 :             : {
      71         [ +  - ]:    11742901 :         Assert((unsigned int) io_object < IOOBJECT_NUM_TYPES);
      72         [ +  - ]:    11742901 :         Assert((unsigned int) io_context < IOCONTEXT_NUM_TYPES);
      73   [ +  -  #  # ]:    11742901 :         Assert(pgstat_is_ioop_tracked_in_bytes(io_op) || bytes == 0);
      74         [ +  - ]:    11742901 :         Assert(pgstat_tracks_io_op(MyBackendType, io_object, io_context, io_op));
      75                 :             : 
      76                 :    11742901 :         PendingIOStats.counts[io_object][io_context][io_op] += cnt;
      77                 :    11742901 :         PendingIOStats.bytes[io_object][io_context][io_op] += bytes;
      78                 :             : 
      79                 :             :         /* Add the per-backend counts */
      80                 :    11742901 :         pgstat_count_backend_io_op(io_object, io_context, io_op, cnt, bytes);
      81                 :             : 
      82                 :    11742901 :         have_iostats = true;
      83                 :    11742901 :         pgstat_report_fixed = true;
      84                 :    11742901 : }
      85                 :             : 
      86                 :             : /*
      87                 :             :  * Initialize the internal timing for an IO operation, depending on an
      88                 :             :  * IO timing GUC.
      89                 :             :  */
      90                 :             : instr_time
      91                 :       66630 : pgstat_prepare_io_time(bool track_io_guc)
      92                 :             : {
      93                 :             :         instr_time      io_start;
      94                 :             : 
      95         [ -  + ]:       66630 :         if (track_io_guc)
      96                 :           0 :                 INSTR_TIME_SET_CURRENT(io_start);
      97                 :             :         else
      98                 :             :         {
      99                 :             :                 /*
     100                 :             :                  * There is no need to set io_start when an IO timing GUC is disabled.
     101                 :             :                  * Initialize it to zero to avoid compiler warnings and to let
     102                 :             :                  * pgstat_count_io_op_time() know that timings should be ignored.
     103                 :             :                  */
     104                 :       66630 :                 INSTR_TIME_SET_ZERO(io_start);
     105                 :             :         }
     106                 :             : 
     107                 :       66630 :         return io_start;
     108                 :             : }
     109                 :             : 
     110                 :             : /*
     111                 :             :  * Like pgstat_count_io_op() except it also accumulates time.
     112                 :             :  *
     113                 :             :  * The calls related to pgstat_count_buffer_*() are for pgstat_database.  As
     114                 :             :  * pg_stat_database only counts block read and write times, these are done for
     115                 :             :  * IOOP_READ, IOOP_WRITE and IOOP_EXTEND.
     116                 :             :  *
     117                 :             :  * pgBufferUsage is used for EXPLAIN.  pgBufferUsage has write and read stats
     118                 :             :  * for shared, local and temporary blocks.  pg_stat_io does not track the
     119                 :             :  * activity of temporary blocks, so these are ignored here.
     120                 :             :  */
     121                 :             : void
     122                 :       66630 : pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op,
     123                 :             :                                                 instr_time start_time, uint32 cnt, uint64 bytes)
     124                 :             : {
     125         [ +  - ]:       66630 :         if (!INSTR_TIME_IS_ZERO(start_time))
     126                 :             :         {
     127                 :           0 :                 instr_time      io_time;
     128                 :             : 
     129                 :           0 :                 INSTR_TIME_SET_CURRENT(io_time);
     130                 :           0 :                 INSTR_TIME_SUBTRACT(io_time, start_time);
     131                 :             : 
     132         [ #  # ]:           0 :                 if (io_object != IOOBJECT_WAL)
     133                 :             :                 {
     134   [ #  #  #  # ]:           0 :                         if (io_op == IOOP_WRITE || io_op == IOOP_EXTEND)
     135                 :             :                         {
     136                 :           0 :                                 pgstat_count_buffer_write_time(INSTR_TIME_GET_MICROSEC(io_time));
     137         [ #  # ]:           0 :                                 if (io_object == IOOBJECT_RELATION)
     138                 :           0 :                                         INSTR_TIME_ADD(pgBufferUsage.shared_blk_write_time, io_time);
     139         [ #  # ]:           0 :                                 else if (io_object == IOOBJECT_TEMP_RELATION)
     140                 :           0 :                                         INSTR_TIME_ADD(pgBufferUsage.local_blk_write_time, io_time);
     141                 :           0 :                         }
     142         [ #  # ]:           0 :                         else if (io_op == IOOP_READ)
     143                 :             :                         {
     144                 :           0 :                                 pgstat_count_buffer_read_time(INSTR_TIME_GET_MICROSEC(io_time));
     145         [ #  # ]:           0 :                                 if (io_object == IOOBJECT_RELATION)
     146                 :           0 :                                         INSTR_TIME_ADD(pgBufferUsage.shared_blk_read_time, io_time);
     147         [ #  # ]:           0 :                                 else if (io_object == IOOBJECT_TEMP_RELATION)
     148                 :           0 :                                         INSTR_TIME_ADD(pgBufferUsage.local_blk_read_time, io_time);
     149                 :           0 :                         }
     150                 :           0 :                 }
     151                 :             : 
     152                 :           0 :                 INSTR_TIME_ADD(PendingIOStats.pending_times[io_object][io_context][io_op],
     153                 :             :                                            io_time);
     154                 :             : 
     155                 :             :                 /* Add the per-backend count */
     156                 :           0 :                 pgstat_count_backend_io_op_time(io_object, io_context, io_op,
     157                 :             :                                                                                 io_time);
     158                 :           0 :         }
     159                 :             : 
     160                 :       66630 :         pgstat_count_io_op(io_object, io_context, io_op, cnt, bytes);
     161                 :       66630 : }
     162                 :             : 
     163                 :             : PgStat_IO *
     164                 :          21 : pgstat_fetch_stat_io(void)
     165                 :             : {
     166                 :          21 :         pgstat_snapshot_fixed(PGSTAT_KIND_IO);
     167                 :             : 
     168                 :          21 :         return &pgStatLocal.snapshot.io;
     169                 :             : }
     170                 :             : 
     171                 :             : /*
     172                 :             :  * Simpler wrapper of pgstat_io_flush_cb()
     173                 :             :  */
     174                 :             : void
     175                 :        1491 : pgstat_flush_io(bool nowait)
     176                 :             : {
     177                 :        1491 :         (void) pgstat_io_flush_cb(nowait);
     178                 :        1491 : }
     179                 :             : 
     180                 :             : /*
     181                 :             :  * Flush out locally pending IO statistics
     182                 :             :  *
     183                 :             :  * If no stats have been recorded, this function returns false.
     184                 :             :  *
     185                 :             :  * If nowait is true, this function returns true if the lock could not be
     186                 :             :  * acquired. Otherwise, return false.
     187                 :             :  */
     188                 :             : bool
     189                 :        2668 : pgstat_io_flush_cb(bool nowait)
     190                 :             : {
     191                 :        2668 :         LWLock     *bktype_lock;
     192                 :        2668 :         PgStat_BktypeIO *bktype_shstats;
     193                 :             : 
     194         [ +  + ]:        2668 :         if (!have_iostats)
     195                 :          59 :                 return false;
     196                 :             : 
     197                 :        2609 :         bktype_lock = &pgStatLocal.shmem->io.locks[MyBackendType];
     198                 :        2609 :         bktype_shstats =
     199                 :        2609 :                 &pgStatLocal.shmem->io.stats.stats[MyBackendType];
     200                 :             : 
     201         [ +  + ]:        2609 :         if (!nowait)
     202                 :        2256 :                 LWLockAcquire(bktype_lock, LW_EXCLUSIVE);
     203         [ +  - ]:         353 :         else if (!LWLockConditionalAcquire(bktype_lock, LW_EXCLUSIVE))
     204                 :           0 :                 return true;
     205                 :             : 
     206         [ +  + ]:       10436 :         for (int io_object = 0; io_object < IOOBJECT_NUM_TYPES; io_object++)
     207                 :             :         {
     208         [ +  + ]:       46962 :                 for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++)
     209                 :             :                 {
     210         [ +  + ]:      352215 :                         for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++)
     211                 :             :                         {
     212                 :      313080 :                                 instr_time      time;
     213                 :             : 
     214                 :      313080 :                                 bktype_shstats->counts[io_object][io_context][io_op] +=
     215                 :      313080 :                                         PendingIOStats.counts[io_object][io_context][io_op];
     216                 :             : 
     217                 :      313080 :                                 bktype_shstats->bytes[io_object][io_context][io_op] +=
     218                 :      313080 :                                         PendingIOStats.bytes[io_object][io_context][io_op];
     219                 :             : 
     220                 :      313080 :                                 time = PendingIOStats.pending_times[io_object][io_context][io_op];
     221                 :             : 
     222                 :      313080 :                                 bktype_shstats->times[io_object][io_context][io_op] +=
     223                 :      313080 :                                         INSTR_TIME_GET_MICROSEC(time);
     224                 :      313080 :                         }
     225                 :       39135 :                 }
     226                 :        7827 :         }
     227                 :             : 
     228         [ +  - ]:        2609 :         Assert(pgstat_bktype_io_stats_valid(bktype_shstats, MyBackendType));
     229                 :             : 
     230                 :        2609 :         LWLockRelease(bktype_lock);
     231                 :             : 
     232                 :        2609 :         memset(&PendingIOStats, 0, sizeof(PendingIOStats));
     233                 :             : 
     234                 :        2609 :         have_iostats = false;
     235                 :             : 
     236                 :        2609 :         return false;
     237                 :        2668 : }
     238                 :             : 
     239                 :             : const char *
     240                 :        4515 : pgstat_get_io_context_name(IOContext io_context)
     241                 :             : {
     242   [ +  +  +  +  :        4515 :         switch (io_context)
                   +  - ]
     243                 :             :         {
     244                 :             :                 case IOCONTEXT_BULKREAD:
     245                 :         903 :                         return "bulkread";
     246                 :             :                 case IOCONTEXT_BULKWRITE:
     247                 :         903 :                         return "bulkwrite";
     248                 :             :                 case IOCONTEXT_INIT:
     249                 :         903 :                         return "init";
     250                 :             :                 case IOCONTEXT_NORMAL:
     251                 :         903 :                         return "normal";
     252                 :             :                 case IOCONTEXT_VACUUM:
     253                 :         903 :                         return "vacuum";
     254                 :             :         }
     255                 :             : 
     256   [ #  #  #  # ]:           0 :         elog(ERROR, "unrecognized IOContext value: %d", io_context);
     257                 :           0 :         pg_unreachable();
     258                 :        4515 : }
     259                 :             : 
     260                 :             : const char *
     261                 :         903 : pgstat_get_io_object_name(IOObject io_object)
     262                 :             : {
     263   [ +  +  +  - ]:         903 :         switch (io_object)
     264                 :             :         {
     265                 :             :                 case IOOBJECT_RELATION:
     266                 :         301 :                         return "relation";
     267                 :             :                 case IOOBJECT_TEMP_RELATION:
     268                 :         301 :                         return "temp relation";
     269                 :             :                 case IOOBJECT_WAL:
     270                 :         301 :                         return "wal";
     271                 :             :         }
     272                 :             : 
     273   [ #  #  #  # ]:           0 :         elog(ERROR, "unrecognized IOObject value: %d", io_object);
     274                 :           0 :         pg_unreachable();
     275                 :         903 : }
     276                 :             : 
     277                 :             : void
     278                 :           6 : pgstat_io_init_shmem_cb(void *stats)
     279                 :             : {
     280                 :           6 :         PgStatShared_IO *stat_shmem = (PgStatShared_IO *) stats;
     281                 :             : 
     282         [ +  + ]:         114 :         for (int i = 0; i < BACKEND_NUM_TYPES; i++)
     283                 :         108 :                 LWLockInitialize(&stat_shmem->locks[i], LWTRANCHE_PGSTATS_DATA);
     284                 :           6 : }
     285                 :             : 
     286                 :             : void
     287                 :           2 : pgstat_io_reset_all_cb(TimestampTz ts)
     288                 :             : {
     289         [ +  + ]:          38 :         for (int i = 0; i < BACKEND_NUM_TYPES; i++)
     290                 :             :         {
     291                 :          36 :                 LWLock     *bktype_lock = &pgStatLocal.shmem->io.locks[i];
     292                 :          36 :                 PgStat_BktypeIO *bktype_shstats = &pgStatLocal.shmem->io.stats.stats[i];
     293                 :             : 
     294                 :          36 :                 LWLockAcquire(bktype_lock, LW_EXCLUSIVE);
     295                 :             : 
     296                 :             :                 /*
     297                 :             :                  * Use the lock in the first BackendType's PgStat_BktypeIO to protect
     298                 :             :                  * the reset timestamp as well.
     299                 :             :                  */
     300         [ +  + ]:          36 :                 if (i == 0)
     301                 :           2 :                         pgStatLocal.shmem->io.stats.stat_reset_timestamp = ts;
     302                 :             : 
     303                 :          36 :                 memset(bktype_shstats, 0, sizeof(*bktype_shstats));
     304                 :          36 :                 LWLockRelease(bktype_lock);
     305                 :          36 :         }
     306                 :           2 : }
     307                 :             : 
     308                 :             : void
     309                 :          28 : pgstat_io_snapshot_cb(void)
     310                 :             : {
     311         [ +  + ]:         532 :         for (int i = 0; i < BACKEND_NUM_TYPES; i++)
     312                 :             :         {
     313                 :         504 :                 LWLock     *bktype_lock = &pgStatLocal.shmem->io.locks[i];
     314                 :         504 :                 PgStat_BktypeIO *bktype_shstats = &pgStatLocal.shmem->io.stats.stats[i];
     315                 :         504 :                 PgStat_BktypeIO *bktype_snap = &pgStatLocal.snapshot.io.stats[i];
     316                 :             : 
     317                 :         504 :                 LWLockAcquire(bktype_lock, LW_SHARED);
     318                 :             : 
     319                 :             :                 /*
     320                 :             :                  * Use the lock in the first BackendType's PgStat_BktypeIO to protect
     321                 :             :                  * the reset timestamp as well.
     322                 :             :                  */
     323         [ +  + ]:         504 :                 if (i == 0)
     324                 :          28 :                         pgStatLocal.snapshot.io.stat_reset_timestamp =
     325                 :          28 :                                 pgStatLocal.shmem->io.stats.stat_reset_timestamp;
     326                 :             : 
     327                 :             :                 /* using struct assignment due to better type safety */
     328                 :         504 :                 *bktype_snap = *bktype_shstats;
     329                 :         504 :                 LWLockRelease(bktype_lock);
     330                 :         504 :         }
     331                 :          28 : }
     332                 :             : 
     333                 :             : /*
     334                 :             : * IO statistics are not collected for all BackendTypes.
     335                 :             : *
     336                 :             : * The following BackendTypes do not participate in the cumulative stats
     337                 :             : * subsystem or do not perform IO on which we currently track:
     338                 :             : * - Dead-end backend because it is not connected to shared memory and
     339                 :             : *   doesn't do any IO
     340                 :             : * - Syslogger because it is not connected to shared memory
     341                 :             : * - Archiver because most relevant archiving IO is delegated to a
     342                 :             : *   specialized command or module
     343                 :             : *
     344                 :             : * Function returns true if BackendType participates in the cumulative stats
     345                 :             : * subsystem for IO and false if it does not.
     346                 :             : *
     347                 :             : * When adding a new BackendType, also consider adding relevant restrictions to
     348                 :             : * pgstat_tracks_io_object() and pgstat_tracks_io_op().
     349                 :             : */
     350                 :             : bool
     351                 :    23859508 : pgstat_tracks_io_bktype(BackendType bktype)
     352                 :             : {
     353                 :             :         /*
     354                 :             :          * List every type so that new backend types trigger a warning about
     355                 :             :          * needing to adjust this switch.
     356                 :             :          */
     357      [ -  +  + ]:    23859508 :         switch (bktype)
     358                 :             :         {
     359                 :             :                 case B_INVALID:
     360                 :             :                 case B_DEAD_END_BACKEND:
     361                 :             :                 case B_ARCHIVER:
     362                 :             :                 case B_LOGGER:
     363                 :       10164 :                         return false;
     364                 :             : 
     365                 :             :                 case B_AUTOVAC_LAUNCHER:
     366                 :             :                 case B_AUTOVAC_WORKER:
     367                 :             :                 case B_BACKEND:
     368                 :             :                 case B_BG_WORKER:
     369                 :             :                 case B_BG_WRITER:
     370                 :             :                 case B_CHECKPOINTER:
     371                 :             :                 case B_IO_WORKER:
     372                 :             :                 case B_SLOTSYNC_WORKER:
     373                 :             :                 case B_STANDALONE_BACKEND:
     374                 :             :                 case B_STARTUP:
     375                 :             :                 case B_WAL_RECEIVER:
     376                 :             :                 case B_WAL_SENDER:
     377                 :             :                 case B_WAL_SUMMARIZER:
     378                 :             :                 case B_WAL_WRITER:
     379                 :    23849344 :                         return true;
     380                 :             :         }
     381                 :             : 
     382                 :           0 :         return false;
     383                 :    23859508 : }
     384                 :             : 
     385                 :             : /*
     386                 :             :  * Some BackendTypes do not perform IO on certain IOObjects or in certain
     387                 :             :  * IOContexts. Some IOObjects are never operated on in some IOContexts. Check
     388                 :             :  * that the given BackendType is expected to do IO in the given IOContext and
     389                 :             :  * on the given IOObject and that the given IOObject is expected to be operated
     390                 :             :  * on in the given IOContext.
     391                 :             :  */
     392                 :             : bool
     393                 :    23862348 : pgstat_tracks_io_object(BackendType bktype, IOObject io_object,
     394                 :             :                                                 IOContext io_context)
     395                 :             : {
     396                 :    23862348 :         bool            no_temp_rel;
     397                 :             : 
     398                 :             :         /*
     399                 :             :          * Some BackendTypes should never track IO statistics.
     400                 :             :          */
     401         [ +  + ]:    23862348 :         if (!pgstat_tracks_io_bktype(bktype))
     402                 :       10080 :                 return false;
     403                 :             : 
     404                 :             :         /*
     405                 :             :          * Currently, IO on IOOBJECT_WAL objects can only occur in the
     406                 :             :          * IOCONTEXT_NORMAL and IOCONTEXT_INIT IOContexts.
     407                 :             :          */
     408   [ +  +  +  + ]:    23949056 :         if (io_object == IOOBJECT_WAL &&
     409         [ +  + ]:      169900 :                 (io_context != IOCONTEXT_NORMAL &&
     410                 :       96788 :                  io_context != IOCONTEXT_INIT))
     411                 :       70743 :                 return false;
     412                 :             : 
     413                 :             :         /*
     414                 :             :          * Currently, IO on temporary relations can only occur in the
     415                 :             :          * IOCONTEXT_NORMAL IOContext.
     416                 :             :          */
     417   [ +  +  +  + ]:    23781525 :         if (io_context != IOCONTEXT_NORMAL &&
     418                 :      315691 :                 io_object == IOOBJECT_TEMP_RELATION)
     419                 :       94324 :                 return false;
     420                 :             : 
     421                 :             :         /*
     422                 :             :          * In core Postgres, only regular backends and WAL Sender processes
     423                 :             :          * executing queries will use local buffers and operate on temporary
     424                 :             :          * relations. Parallel workers will not use local buffers (see
     425                 :             :          * InitLocalBuffers()); however, extensions leveraging background workers
     426                 :             :          * have no such limitation, so track IO on IOOBJECT_TEMP_RELATION for
     427                 :             :          * BackendType B_BG_WORKER.
     428                 :             :          */
     429   [ +  +  +  + ]:    47366582 :         no_temp_rel = bktype == B_AUTOVAC_LAUNCHER || bktype == B_BG_WRITER ||
     430   [ +  +  +  + ]:    23679381 :                 bktype == B_CHECKPOINTER || bktype == B_AUTOVAC_WORKER ||
     431   [ +  +  +  + ]:    23670196 :                 bktype == B_STANDALONE_BACKEND || bktype == B_STARTUP ||
     432   [ +  +  +  + ]:    23453276 :                 bktype == B_WAL_SUMMARIZER || bktype == B_WAL_WRITER ||
     433                 :    23448718 :                 bktype == B_WAL_RECEIVER;
     434                 :             : 
     435   [ +  +  +  +  :    23687201 :         if (no_temp_rel && io_context == IOCONTEXT_NORMAL &&
                   +  + ]
     436                 :      214756 :                 io_object == IOOBJECT_TEMP_RELATION)
     437                 :        3277 :                 return false;
     438                 :             : 
     439                 :             :         /*
     440                 :             :          * Some BackendTypes only perform IO under IOOBJECT_WAL, hence exclude all
     441                 :             :          * rows for all the other objects for these.
     442                 :             :          */
     443   [ +  +  +  + ]:    23683924 :         if ((bktype == B_WAL_SUMMARIZER || bktype == B_WAL_RECEIVER ||
     444         [ +  + ]:    23683924 :                  bktype == B_WAL_WRITER) && io_object != IOOBJECT_WAL)
     445                 :        3355 :                 return false;
     446                 :             : 
     447                 :             :         /*
     448                 :             :          * Some BackendTypes do not currently perform any IO in certain
     449                 :             :          * IOContexts, and, while it may not be inherently incorrect for them to
     450                 :             :          * do so, excluding those rows from the view makes the view easier to use.
     451                 :             :          */
     452   [ +  +  +  + ]:    23688022 :         if ((bktype == B_CHECKPOINTER || bktype == B_BG_WRITER) &&
     453         [ +  + ]:       14520 :                 (io_context == IOCONTEXT_BULKREAD ||
     454         [ +  + ]:        7839 :                  io_context == IOCONTEXT_BULKWRITE ||
     455                 :        7453 :                  io_context == IOCONTEXT_VACUUM))
     456                 :       14520 :                 return false;
     457                 :             : 
     458   [ +  +  +  + ]:    23676193 :         if (bktype == B_AUTOVAC_LAUNCHER && io_context == IOCONTEXT_VACUUM)
     459                 :         197 :                 return false;
     460                 :             : 
     461   [ +  +  +  + ]:    23675996 :         if ((bktype == B_AUTOVAC_WORKER || bktype == B_AUTOVAC_LAUNCHER) &&
     462                 :    23675996 :                 io_context == IOCONTEXT_BULKWRITE)
     463                 :         394 :                 return false;
     464                 :             : 
     465                 :    23675602 :         return true;
     466                 :    23859130 : }
     467                 :             : 
     468                 :             : /*
     469                 :             :  * Some BackendTypes will never do certain IOOps and some IOOps should not
     470                 :             :  * occur in certain IOContexts or on certain IOObjects. Check that the given
     471                 :             :  * IOOp is valid for the given BackendType in the given IOContext and on the
     472                 :             :  * given IOObject. Note that there are currently no cases of an IOOp being
     473                 :             :  * invalid for a particular BackendType only within a certain IOContext and/or
     474                 :             :  * only on a certain IOObject.
     475                 :             :  */
     476                 :             : bool
     477                 :    23855993 : pgstat_tracks_io_op(BackendType bktype, IOObject io_object,
     478                 :             :                                         IOContext io_context, IOOp io_op)
     479                 :             : {
     480                 :    23855993 :         bool            strategy_io_context;
     481                 :             : 
     482                 :             :         /* if (io_context, io_object) will never collect stats, we're done */
     483         [ +  + ]:    23855993 :         if (!pgstat_tracks_io_object(bktype, io_object, io_context))
     484                 :      180728 :                 return false;
     485                 :             : 
     486                 :             :         /*
     487                 :             :          * Some BackendTypes will not do certain IOOps.
     488                 :             :          */
     489   [ +  +  +  + ]:    23676273 :         if (bktype == B_BG_WRITER &&
     490   [ +  +  +  + ]:        1344 :                 (io_op == IOOP_READ || io_op == IOOP_EVICT || io_op == IOOP_HIT))
     491                 :         504 :                 return false;
     492                 :             : 
     493   [ +  +  +  + ]:    23680058 :         if (bktype == B_CHECKPOINTER &&
     494         [ +  + ]:        5555 :                 ((io_object != IOOBJECT_WAL && io_op == IOOP_READ) ||
     495         [ +  + ]:         689 :                  (io_op == IOOP_EVICT || io_op == IOOP_HIT)))
     496                 :       18518 :                 return false;
     497                 :             : 
     498   [ +  +  +  + ]:    23672953 :         if ((bktype == B_AUTOVAC_LAUNCHER || bktype == B_BG_WRITER ||
     499         [ +  + ]:    23672953 :                  bktype == B_CHECKPOINTER) && io_op == IOOP_EXTEND)
     500                 :         555 :                 return false;
     501                 :             : 
     502                 :             :         /*
     503                 :             :          * Some BackendTypes do not perform reads with IOOBJECT_WAL.
     504                 :             :          */
     505   [ +  +  +  +  :    23678490 :         if (io_object == IOOBJECT_WAL && io_op == IOOP_READ &&
                   +  + ]
     506   [ +  +  +  - ]:        6348 :                 (bktype == B_WAL_RECEIVER || bktype == B_BG_WRITER ||
     507   [ +  +  +  + ]:        6264 :                  bktype == B_AUTOVAC_LAUNCHER || bktype == B_AUTOVAC_WORKER ||
     508                 :        6092 :                  bktype == B_WAL_WRITER))
     509                 :         366 :                 return false;
     510                 :             : 
     511                 :             :         /*
     512                 :             :          * Temporary tables are not logged and thus do not require fsync'ing.
     513                 :             :          * Writeback is not requested for temporary tables.
     514                 :             :          */
     515   [ +  +  +  + ]:    24405394 :         if (io_object == IOOBJECT_TEMP_RELATION &&
     516         [ +  + ]:      735998 :                 (io_op == IOOP_FSYNC || io_op == IOOP_WRITEBACK))
     517                 :        5272 :                 return false;
     518                 :             : 
     519                 :             :         /*
     520                 :             :          * Some IOOps are not valid in certain IOContexts and some IOOps are only
     521                 :             :          * valid in certain contexts.
     522                 :             :          */
     523   [ +  +  +  + ]:    23666760 :         if (io_context == IOCONTEXT_BULKREAD && io_op == IOOP_EXTEND)
     524                 :        2944 :                 return false;
     525                 :             : 
     526         [ +  + ]:    47302615 :         strategy_io_context = io_context == IOCONTEXT_BULKREAD ||
     527         [ +  + ]:    23638799 :                 io_context == IOCONTEXT_BULKWRITE || io_context == IOCONTEXT_VACUUM;
     528                 :             : 
     529                 :             :         /*
     530                 :             :          * IOOP_REUSE is only relevant when a BufferAccessStrategy is in use.
     531                 :             :          */
     532   [ +  +  +  + ]:    23663816 :         if (!strategy_io_context && io_op == IOOP_REUSE)
     533                 :       15202 :                 return false;
     534                 :             : 
     535                 :             :         /*
     536                 :             :          * IOOBJECT_WAL IOObject will not do certain IOOps depending on IOContext.
     537                 :             :          */
     538   [ +  +  +  +  :    23667385 :         if (io_object == IOOBJECT_WAL && io_context == IOCONTEXT_INIT &&
                   +  + ]
     539         [ +  + ]:       22010 :                 !(io_op == IOOP_WRITE || io_op == IOOP_FSYNC))
     540                 :       15532 :                 return false;
     541                 :             : 
     542   [ +  +  +  +  :    23648839 :         if (io_object == IOOBJECT_WAL && io_context == IOCONTEXT_NORMAL &&
                   +  + ]
     543   [ +  +  +  + ]:       69077 :                 !(io_op == IOOP_WRITE || io_op == IOOP_READ || io_op == IOOP_FSYNC))
     544                 :       12546 :                 return false;
     545                 :             : 
     546                 :             :         /*
     547                 :             :          * IOOP_FSYNC IOOps done by a backend using a BufferAccessStrategy are
     548                 :             :          * counted in the IOCONTEXT_NORMAL IOContext. See comment in
     549                 :             :          * register_dirty_segment() for more details.
     550                 :             :          */
     551   [ +  +  +  + ]:    23620536 :         if (strategy_io_context && io_op == IOOP_FSYNC)
     552                 :        8832 :                 return false;
     553                 :             : 
     554                 :             : 
     555                 :    23611704 :         return true;
     556                 :    23854615 : }
        

Generated by: LCOV version 2.3.2-1