LCOV - differential code coverage report
Current view: top level - src/bin/pg_upgrade - slru_io.c (source / functions) Coverage Total Hit UNC
Current: 7a15cff1f11193467898da1c1fabf06fd2caee04 vs 84a3778c79c2d28b4dc281d03ef2ab019b16483b Lines: 0.0 % 103 0 103
Current Date: 2025-12-15 18:36:29 -0500 Functions: 0.0 % 9 0 9
Baseline: lcov-20251216-010103-baseline Branches: 0.0 % 58 0 58
Baseline Date: 2025-12-15 13:30:48 -0800 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(1,7] days: 0.0 % 103 0 103
Function coverage date bins:
(1,7] days: 0.0 % 9 0 9
Branch coverage date bins:
(1,7] days: 0.0 % 58 0 58

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * slru_io.c
                                  3                 :                :  *
                                  4                 :                :  * Routines for reading and writing SLRU files during upgrade.
                                  5                 :                :  *
                                  6                 :                :  * Copyright (c) 2025, PostgreSQL Global Development Group
                                  7                 :                :  * src/bin/pg_upgrade/slru_io.c
                                  8                 :                :  */
                                  9                 :                : 
                                 10                 :                : #include "postgres_fe.h"
                                 11                 :                : 
                                 12                 :                : #include <fcntl.h>
                                 13                 :                : 
                                 14                 :                : #include "common/fe_memutils.h"
                                 15                 :                : #include "common/file_perm.h"
                                 16                 :                : #include "common/file_utils.h"
                                 17                 :                : #include "pg_upgrade.h"
                                 18                 :                : #include "port/pg_iovec.h"
                                 19                 :                : #include "slru_io.h"
                                 20                 :                : 
                                 21                 :                : static SlruSegState *AllocSlruSegState(const char *dir);
                                 22                 :                : static char *SlruFileName(SlruSegState *state, int64 segno);
                                 23                 :                : static void SlruFlush(SlruSegState *state);
                                 24                 :                : 
                                 25                 :                : /* common parts of AllocSlruRead and AllocSlruWrite */
                                 26                 :                : static SlruSegState *
    7 heikki.linnakangas@i       27                 :UNC           0 : AllocSlruSegState(const char *dir)
                                 28                 :                : {
                                 29                 :              0 :     SlruSegState *state = pg_malloc(sizeof(*state));
                                 30                 :                : 
                                 31                 :              0 :     state->dir = pstrdup(dir);
                                 32                 :              0 :     state->fn = NULL;
                                 33                 :              0 :     state->fd = -1;
                                 34                 :              0 :     state->segno = -1;
                                 35                 :              0 :     state->pageno = 0;
                                 36                 :                : 
                                 37                 :                :     /* state->writing and state->long_segment_names must be set by caller! */
                                 38                 :                : 
                                 39                 :              0 :     return state;
                                 40                 :                : }
                                 41                 :                : 
                                 42                 :                : /* similar to the backend function with the same name */
                                 43                 :                : static char *
                                 44                 :              0 : SlruFileName(SlruSegState *state, int64 segno)
                                 45                 :                : {
                                 46         [ #  # ]:              0 :     if (state->long_segment_names)
                                 47                 :                :     {
                                 48   [ #  #  #  # ]:              0 :         Assert(segno >= 0 && segno <= INT64CONST(0xFFFFFFFFFFFFFFF));
                                 49                 :              0 :         return psprintf("%s/%015" PRIX64, state->dir, segno);
                                 50                 :                :     }
                                 51                 :                :     else
                                 52                 :                :     {
                                 53   [ #  #  #  # ]:              0 :         Assert(segno >= 0 && segno <= INT64CONST(0xFFFFFF));
                                 54                 :              0 :         return psprintf("%s/%04X", state->dir, (unsigned int) segno);
                                 55                 :                :     }
                                 56                 :                : }
                                 57                 :                : 
                                 58                 :                : /*
                                 59                 :                :  * Create SLRU reader for dir.
                                 60                 :                :  */
                                 61                 :                : SlruSegState *
                                 62                 :              0 : AllocSlruRead(const char *dir, bool long_segment_names)
                                 63                 :                : {
                                 64                 :              0 :     SlruSegState *state = AllocSlruSegState(dir);
                                 65                 :                : 
                                 66                 :              0 :     state->writing = false;
                                 67                 :              0 :     state->long_segment_names = long_segment_names;
                                 68                 :                : 
                                 69                 :              0 :     return state;
                                 70                 :                : }
                                 71                 :                : 
                                 72                 :                : /*
                                 73                 :                :  * Read the given page into memory buffer.
                                 74                 :                :  *
                                 75                 :                :  * Reading can be done in random order.
                                 76                 :                :  *
                                 77                 :                :  * If the file containing 'pageno' does not exist, a fatal error is raised.
                                 78                 :                :  * If the file exists but is shorter than expected, the missing part is read
                                 79                 :                :  * as zeros and a warning is logged.  That is reasonable behavior for current
                                 80                 :                :  * callers.
                                 81                 :                :  *
                                 82                 :                :  * This is the slow path of the inlineable SlruReadSwitchPage() function.
                                 83                 :                :  */
                                 84                 :                : char *
                                 85                 :              0 : SlruReadSwitchPageSlow(SlruSegState *state, uint64 pageno)
                                 86                 :                : {
                                 87                 :                :     int64       segno;
                                 88                 :                :     off_t       offset;
                                 89                 :                :     ssize_t     bytes_read;
                                 90                 :                : 
                                 91         [ #  # ]:              0 :     Assert(!state->writing); /* read only mode */
                                 92                 :                : 
                                 93   [ #  #  #  # ]:              0 :     if (state->segno != -1 && pageno == state->pageno)
                                 94                 :              0 :         return state->buf.data;
                                 95                 :                : 
                                 96                 :                :     /* If the new page is on a different SLRU segment, open the new segment */
                                 97                 :              0 :     segno = pageno / SLRU_PAGES_PER_SEGMENT;
                                 98         [ #  # ]:              0 :     if (segno != state->segno)
                                 99                 :                :     {
                                100         [ #  # ]:              0 :         if (state->segno != -1)
                                101                 :                :         {
                                102                 :              0 :             close(state->fd);
                                103                 :              0 :             state->fd = -1;
                                104                 :                : 
                                105                 :              0 :             pg_free(state->fn);
                                106                 :              0 :             state->fn = NULL;
                                107                 :                : 
                                108                 :              0 :             state->segno = -1;
                                109                 :                :         }
                                110                 :                : 
                                111                 :              0 :         state->fn = SlruFileName(state, segno);
                                112         [ #  # ]:              0 :         if ((state->fd = open(state->fn, O_RDONLY | PG_BINARY, 0)) < 0)
                                113                 :              0 :             pg_fatal("could not open file \"%s\": %m", state->fn);
                                114                 :              0 :         state->segno = segno;
                                115                 :                :     }
                                116                 :                : 
                                117                 :              0 :     offset = (pageno % SLRU_PAGES_PER_SEGMENT) * BLCKSZ;
                                118                 :              0 :     bytes_read = 0;
                                119         [ #  # ]:              0 :     while (bytes_read < BLCKSZ)
                                120                 :                :     {
                                121                 :                :         ssize_t     rc;
                                122                 :                : 
                                123                 :              0 :         rc = pg_pread(state->fd,
                                124                 :              0 :                       &state->buf.data + bytes_read,
                                125                 :              0 :                       BLCKSZ - bytes_read,
                                126                 :                :                       offset);
                                127         [ #  # ]:              0 :         if (rc < 0)
                                128                 :                :         {
                                129         [ #  # ]:              0 :             if (errno == EINTR)
                                130                 :              0 :                 continue;
                                131                 :              0 :             pg_fatal("could not read file \"%s\": %m", state->fn);
                                132                 :                :         }
                                133         [ #  # ]:              0 :         if (rc == 0)
                                134                 :                :         {
                                135                 :                :             /* unexpected EOF */
                                136                 :              0 :             pg_log(PG_WARNING, "unexpected EOF reading file \"%s\" at offset %u, reading as zeros",
                                137                 :                :                    state->fn, (unsigned int) offset);
                                138                 :              0 :             memset(&state->buf.data + bytes_read, 0, BLCKSZ - bytes_read);
                                139                 :              0 :             break;
                                140                 :                :         }
                                141                 :              0 :         bytes_read += rc;
                                142                 :              0 :         offset += rc;
                                143                 :                :     }
                                144                 :              0 :     state->pageno = pageno;
                                145                 :                : 
                                146                 :              0 :     return state->buf.data;
                                147                 :                : }
                                148                 :                : 
                                149                 :                : /*
                                150                 :                :  * Free the reader.
                                151                 :                :  */
                                152                 :                : void
                                153                 :              0 : FreeSlruRead(SlruSegState *state)
                                154                 :                : {
                                155         [ #  # ]:              0 :     Assert(!state->writing); /* read only mode */
                                156                 :                : 
                                157         [ #  # ]:              0 :     if (state->fd != -1)
                                158                 :              0 :         close(state->fd);
                                159                 :              0 :     pg_free(state);
                                160                 :              0 : }
                                161                 :                : 
                                162                 :                : /*
                                163                 :                :  * Create SLRU writer for dir.
                                164                 :                :  */
                                165                 :                : SlruSegState *
                                166                 :              0 : AllocSlruWrite(const char *dir, bool long_segment_names)
                                167                 :                : {
                                168                 :              0 :     SlruSegState *state = AllocSlruSegState(dir);
                                169                 :                : 
                                170                 :              0 :     state->writing = true;
                                171                 :              0 :     state->long_segment_names = long_segment_names;
                                172                 :                : 
                                173                 :              0 :     return state;
                                174                 :                : }
                                175                 :                : 
                                176                 :                : /*
                                177                 :                :  * Open the given page for writing.
                                178                 :                :  *
                                179                 :                :  * NOTE: This uses O_EXCL when stepping to a new segment, so this assumes that
                                180                 :                :  * each segment is written in full before moving on to the next one.  This
                                181                 :                :  * limitation would be easy to lift if needed, but it fits the usage pattern
                                182                 :                :  * of current callers.
                                183                 :                :  *
                                184                 :                :  * This is the slow path of the inlineable SlruWriteSwitchPage() function.
                                185                 :                :  */
                                186                 :                : char *
                                187                 :              0 : SlruWriteSwitchPageSlow(SlruSegState *state, uint64 pageno)
                                188                 :                : {
                                189                 :                :     int64       segno;
                                190                 :                :     off_t       offset;
                                191                 :                : 
                                192         [ #  # ]:              0 :     Assert(state->writing);
                                193                 :                : 
                                194   [ #  #  #  # ]:              0 :     if (state->segno != -1 && pageno == state->pageno)
                                195                 :              0 :         return state->buf.data;
                                196                 :                : 
                                197                 :              0 :     segno = pageno / SLRU_PAGES_PER_SEGMENT;
                                198                 :              0 :     offset = (pageno % SLRU_PAGES_PER_SEGMENT) * BLCKSZ;
                                199                 :                : 
                                200                 :              0 :     SlruFlush(state);
                                201                 :              0 :     memset(state->buf.data, 0, BLCKSZ);
                                202                 :                : 
                                203         [ #  # ]:              0 :     if (segno != state->segno)
                                204                 :                :     {
                                205         [ #  # ]:              0 :         if (state->segno != -1)
                                206                 :                :         {
                                207                 :              0 :             close(state->fd);
                                208                 :              0 :             state->fd = -1;
                                209                 :                : 
                                210                 :              0 :             pg_free(state->fn);
                                211                 :              0 :             state->fn = NULL;
                                212                 :                : 
                                213                 :              0 :             state->segno = -1;
                                214                 :                :         }
                                215                 :                : 
                                216                 :                :         /* Create the segment */
                                217                 :              0 :         state->fn = SlruFileName(state, segno);
                                218         [ #  # ]:              0 :         if ((state->fd = open(state->fn, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
                                219                 :                :                               pg_file_create_mode)) < 0)
                                220                 :                :         {
                                221                 :              0 :             pg_fatal("could not create file \"%s\": %m", state->fn);
                                222                 :                :         }
                                223                 :                : 
                                224                 :              0 :         state->segno = segno;
                                225                 :                : 
                                226         [ #  # ]:              0 :         if (offset > 0)
                                227                 :                :         {
                                228         [ #  # ]:              0 :             if (pg_pwrite_zeros(state->fd, offset, 0) < 0)
                                229                 :              0 :                 pg_fatal("could not write file \"%s\": %m", state->fn);
                                230                 :                :         }
                                231                 :                :     }
                                232                 :                : 
                                233                 :              0 :     state->pageno = pageno;
                                234                 :                : 
                                235                 :              0 :     return state->buf.data;
                                236                 :                : }
                                237                 :                : 
                                238                 :                : static void
                                239                 :              0 : SlruFlush(SlruSegState *state)
                                240                 :                : {
                                241                 :              0 :     struct iovec iovec = {
                                242                 :              0 :         .iov_base = &state->buf,
                                243                 :                :         .iov_len = BLCKSZ,
                                244                 :                :     };
                                245                 :                :     off_t       offset;
                                246                 :                : 
                                247         [ #  # ]:              0 :     if (state->segno == -1)
                                248                 :              0 :         return;
                                249                 :                : 
                                250                 :              0 :     offset = (state->pageno % SLRU_PAGES_PER_SEGMENT) * BLCKSZ;
                                251                 :                : 
                                252         [ #  # ]:              0 :     if (pg_pwritev_with_retry(state->fd, &iovec, 1, offset) < 0)
                                253                 :              0 :         pg_fatal("could not write file \"%s\": %m", state->fn);
                                254                 :                : }
                                255                 :                : 
                                256                 :                : /*
                                257                 :                :  * Free the writer.
                                258                 :                :  */
                                259                 :                : void
                                260                 :              0 : FreeSlruWrite(SlruSegState *state)
                                261                 :                : {
                                262         [ #  # ]:              0 :     Assert(state->writing);
                                263                 :                : 
                                264                 :              0 :     SlruFlush(state);
                                265                 :                : 
                                266         [ #  # ]:              0 :     if (state->fd != -1)
                                267                 :              0 :         close(state->fd);
                                268                 :              0 :     pg_free(state);
                                269                 :              0 : }
        

Generated by: LCOV version 2.4-beta