LCOV - differential code coverage report
Current view: top level - src/backend/storage/file - copydir.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 68.2 % 66 45 21 45
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 2 2 2
Baseline: 16@8cea358b128 Branches: 38.7 % 62 24 38 24
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 68.2 % 66 45 21 45
Function coverage date bins:
(240..) days: 100.0 % 2 2 2
Branch coverage date bins:
(240..) days: 38.7 % 62 24 38 24

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * copydir.c
                                  4                 :                :  *    copies a directory
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *  While "xcopy /e /i /q" works fine for copying directories, on Windows XP
                                 10                 :                :  *  it requires a Window handle which prevents it from working when invoked
                                 11                 :                :  *  as a service.
                                 12                 :                :  *
                                 13                 :                :  * IDENTIFICATION
                                 14                 :                :  *    src/backend/storage/file/copydir.c
                                 15                 :                :  *
                                 16                 :                :  *-------------------------------------------------------------------------
                                 17                 :                :  */
                                 18                 :                : 
                                 19                 :                : #include "postgres.h"
                                 20                 :                : 
                                 21                 :                : #include <fcntl.h>
                                 22                 :                : #include <unistd.h>
                                 23                 :                : 
                                 24                 :                : #include "common/file_utils.h"
                                 25                 :                : #include "miscadmin.h"
                                 26                 :                : #include "pgstat.h"
                                 27                 :                : #include "storage/copydir.h"
                                 28                 :                : #include "storage/fd.h"
                                 29                 :                : 
                                 30                 :                : /*
                                 31                 :                :  * copydir: copy a directory
                                 32                 :                :  *
                                 33                 :                :  * If recurse is false, subdirectories are ignored.  Anything that's not
                                 34                 :                :  * a directory or a regular file is ignored.
                                 35                 :                :  */
                                 36                 :                : void
  452 michael@paquier.xyz        37                 :CBC         104 : copydir(const char *fromdir, const char *todir, bool recurse)
                                 38                 :                : {
                                 39                 :                :     DIR        *xldir;
                                 40                 :                :     struct dirent *xlde;
                                 41                 :                :     char        fromfile[MAXPGPATH * 2];
                                 42                 :                :     char        tofile[MAXPGPATH * 2];
                                 43                 :                : 
 2199 sfrost@snowman.net         44         [ -  + ]:            104 :     if (MakePGDirectory(todir) != 0)
 6830 tgl@sss.pgh.pa.us          45         [ #  # ]:UBC           0 :         ereport(ERROR,
                                 46                 :                :                 (errcode_for_file_access(),
                                 47                 :                :                  errmsg("could not create directory \"%s\": %m", todir)));
                                 48                 :                : 
 7356 tgl@sss.pgh.pa.us          49                 :CBC         104 :     xldir = AllocateDir(fromdir);
                                 50                 :                : 
 6830                            51         [ +  + ]:          31050 :     while ((xlde = ReadDir(xldir, fromdir)) != NULL)
                                 52                 :                :     {
                                 53                 :                :         PGFileType  xlde_type;
                                 54                 :                : 
                                 55                 :                :         /* If we got a cancel signal during the copy of the directory, quit */
 5031 bruce@momjian.us           56         [ -  + ]:          30946 :         CHECK_FOR_INTERRUPTS();
                                 57                 :                : 
 6756                            58         [ +  + ]:          30946 :         if (strcmp(xlde->d_name, ".") == 0 ||
 6830 tgl@sss.pgh.pa.us          59         [ +  + ]:          30842 :             strcmp(xlde->d_name, "..") == 0)
 6756 bruce@momjian.us           60                 :            208 :             continue;
                                 61                 :                : 
 2560 peter_e@gmx.net            62                 :          30738 :         snprintf(fromfile, sizeof(fromfile), "%s/%s", fromdir, xlde->d_name);
                                 63                 :          30738 :         snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name);
                                 64                 :                : 
  590 michael@paquier.xyz        65                 :          30738 :         xlde_type = get_dirent_type(fromfile, xlde, false, ERROR);
                                 66                 :                : 
                                 67         [ -  + ]:          30738 :         if (xlde_type == PGFILETYPE_DIR)
                                 68                 :                :         {
                                 69                 :                :             /* recurse to handle subdirectories */
 6830 tgl@sss.pgh.pa.us          70         [ #  # ]:UBC           0 :             if (recurse)
                                 71                 :              0 :                 copydir(fromfile, tofile, true);
                                 72                 :                :         }
  590 michael@paquier.xyz        73         [ +  - ]:CBC       30738 :         else if (xlde_type == PGFILETYPE_REG)
 6830 tgl@sss.pgh.pa.us          74                 :          30738 :             copy_file(fromfile, tofile);
                                 75                 :                :     }
 5165                            76                 :            104 :     FreeDir(xldir);
                                 77                 :                : 
                                 78                 :                :     /*
                                 79                 :                :      * Be paranoid here and fsync all files to ensure the copy is really done.
                                 80                 :                :      * But if fsync is disabled, we're done.
                                 81                 :                :      */
 4285                            82         [ +  - ]:            104 :     if (!enableFsync)
                                 83                 :            104 :         return;
                                 84                 :                : 
 5165 tgl@sss.pgh.pa.us          85                 :UBC           0 :     xldir = AllocateDir(todir);
                                 86                 :                : 
                                 87         [ #  # ]:              0 :     while ((xlde = ReadDir(xldir, todir)) != NULL)
                                 88                 :                :     {
 5172 stark@mit.edu              89         [ #  # ]:              0 :         if (strcmp(xlde->d_name, ".") == 0 ||
                                 90         [ #  # ]:              0 :             strcmp(xlde->d_name, "..") == 0)
                                 91                 :              0 :             continue;
                                 92                 :                : 
 2560 peter_e@gmx.net            93                 :              0 :         snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name);
                                 94                 :                : 
                                 95                 :                :         /*
                                 96                 :                :          * We don't need to sync subdirectories here since the recursive
                                 97                 :                :          * copydir will do it before it returns
                                 98                 :                :          */
  590 michael@paquier.xyz        99         [ #  # ]:              0 :         if (get_dirent_type(tofile, xlde, false, ERROR) == PGFILETYPE_REG)
 5159 stark@mit.edu             100                 :              0 :             fsync_fname(tofile, false);
                                101                 :                :     }
 5172                           102                 :              0 :     FreeDir(xldir);
                                103                 :                : 
                                104                 :                :     /*
                                105                 :                :      * It's important to fsync the destination directory itself as individual
                                106                 :                :      * file fsyncs don't guarantee that the directory entry for the file is
                                107                 :                :      * synced. Recent versions of ext4 have made the window much wider but
                                108                 :                :      * it's been true for ext3 and other filesystems in the past.
                                109                 :                :      */
 5159                           110                 :              0 :     fsync_fname(todir, true);
                                111                 :                : }
                                112                 :                : 
                                113                 :                : /*
                                114                 :                :  * copy one file
                                115                 :                :  */
                                116                 :                : void
  452 michael@paquier.xyz       117                 :CBC       30747 : copy_file(const char *fromfile, const char *tofile)
                                118                 :                : {
                                119                 :                :     char       *buffer;
                                120                 :                :     int         srcfd;
                                121                 :                :     int         dstfd;
                                122                 :                :     int         nbytes;
                                123                 :                :     off_t       offset;
                                124                 :                :     off_t       flush_offset;
                                125                 :                : 
                                126                 :                :     /* Size of copy buffer (read and write requests) */
                                127                 :                : #define COPY_BUF_SIZE (8 * BLCKSZ)
                                128                 :                : 
                                129                 :                :     /*
                                130                 :                :      * Size of data flush requests.  It seems beneficial on most platforms to
                                131                 :                :      * do this every 1MB or so.  But macOS, at least with early releases of
                                132                 :                :      * APFS, is really unfriendly to small mmap/msync requests, so there do it
                                133                 :                :      * only every 32MB.
                                134                 :                :      */
                                135                 :                : #if defined(__darwin__)
                                136                 :                : #define FLUSH_DISTANCE (32 * 1024 * 1024)
                                137                 :                : #else
                                138                 :                : #define FLUSH_DISTANCE (1024 * 1024)
                                139                 :                : #endif
                                140                 :                : 
                                141                 :                :     /* Use palloc to ensure we get a maxaligned buffer */
 6799 tgl@sss.pgh.pa.us         142                 :          30747 :     buffer = palloc(COPY_BUF_SIZE);
                                143                 :                : 
                                144                 :                :     /*
                                145                 :                :      * Open the files
                                146                 :                :      */
 2395 peter_e@gmx.net           147                 :          30747 :     srcfd = OpenTransientFile(fromfile, O_RDONLY | PG_BINARY);
 6830 tgl@sss.pgh.pa.us         148         [ -  + ]:          30747 :     if (srcfd < 0)
 6830 tgl@sss.pgh.pa.us         149         [ #  # ]:UBC           0 :         ereport(ERROR,
                                150                 :                :                 (errcode_for_file_access(),
                                151                 :                :                  errmsg("could not open file \"%s\": %m", fromfile)));
                                152                 :                : 
 2395 peter_e@gmx.net           153                 :CBC       30747 :     dstfd = OpenTransientFile(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
 6830 tgl@sss.pgh.pa.us         154         [ -  + ]:          30747 :     if (dstfd < 0)
 6830 tgl@sss.pgh.pa.us         155         [ #  # ]:UBC           0 :         ereport(ERROR,
                                156                 :                :                 (errcode_for_file_access(),
                                157                 :                :                  errmsg("could not create file \"%s\": %m", tofile)));
                                158                 :                : 
                                159                 :                :     /*
                                160                 :                :      * Do the data copying.
                                161                 :                :      */
 2380 tgl@sss.pgh.pa.us         162                 :CBC       30747 :     flush_offset = 0;
 5161 bruce@momjian.us          163                 :          30747 :     for (offset = 0;; offset += nbytes)
                                164                 :                :     {
                                165                 :                :         /* If we got a cancel signal during the copy of the file, quit */
 5031                           166         [ -  + ]:          62092 :         CHECK_FOR_INTERRUPTS();
                                167                 :                : 
                                168                 :                :         /*
                                169                 :                :          * We fsync the files later, but during the copy, flush them every so
                                170                 :                :          * often to avoid spamming the cache and hopefully get the kernel to
                                171                 :                :          * start writing them out before the fsync comes.
                                172                 :                :          */
 2380 tgl@sss.pgh.pa.us         173         [ +  + ]:          62092 :         if (offset - flush_offset >= FLUSH_DISTANCE)
                                174                 :                :         {
                                175                 :             32 :             pg_flush_data(dstfd, flush_offset, offset - flush_offset);
                                176                 :             32 :             flush_offset = offset;
                                177                 :                :         }
                                178                 :                : 
 2584 rhaas@postgresql.org      179                 :          62092 :         pgstat_report_wait_start(WAIT_EVENT_COPY_FILE_READ);
 6799 tgl@sss.pgh.pa.us         180                 :          62092 :         nbytes = read(srcfd, buffer, COPY_BUF_SIZE);
 2584 rhaas@postgresql.org      181                 :          62092 :         pgstat_report_wait_end();
 6830 tgl@sss.pgh.pa.us         182         [ -  + ]:          62092 :         if (nbytes < 0)
 6830 tgl@sss.pgh.pa.us         183         [ #  # ]:UBC           0 :             ereport(ERROR,
                                184                 :                :                     (errcode_for_file_access(),
                                185                 :                :                      errmsg("could not read file \"%s\": %m", fromfile)));
 6830 tgl@sss.pgh.pa.us         186         [ +  + ]:CBC       62092 :         if (nbytes == 0)
                                187                 :          30747 :             break;
                                188                 :          31345 :         errno = 0;
 2584 rhaas@postgresql.org      189                 :          31345 :         pgstat_report_wait_start(WAIT_EVENT_COPY_FILE_WRITE);
 6830 tgl@sss.pgh.pa.us         190         [ -  + ]:          31345 :         if ((int) write(dstfd, buffer, nbytes) != nbytes)
                                191                 :                :         {
                                192                 :                :             /* if write didn't set errno, assume problem is no disk space */
 6830 tgl@sss.pgh.pa.us         193         [ #  # ]:UBC           0 :             if (errno == 0)
                                194                 :              0 :                 errno = ENOSPC;
                                195         [ #  # ]:              0 :             ereport(ERROR,
                                196                 :                :                     (errcode_for_file_access(),
                                197                 :                :                      errmsg("could not write to file \"%s\": %m", tofile)));
                                198                 :                :         }
 2584 rhaas@postgresql.org      199                 :CBC       31345 :         pgstat_report_wait_end();
                                200                 :                :     }
                                201                 :                : 
 2380 tgl@sss.pgh.pa.us         202         [ +  + ]:          30747 :     if (offset > flush_offset)
                                203                 :          25494 :         pg_flush_data(dstfd, flush_offset, offset - flush_offset);
                                204                 :                : 
 1744 peter@eisentraut.org      205         [ -  + ]:          30747 :     if (CloseTransientFile(dstfd) != 0)
 6830 tgl@sss.pgh.pa.us         206         [ #  # ]:UBC           0 :         ereport(ERROR,
                                207                 :                :                 (errcode_for_file_access(),
                                208                 :                :                  errmsg("could not close file \"%s\": %m", tofile)));
                                209                 :                : 
 1744 peter@eisentraut.org      210         [ -  + ]:CBC       30747 :     if (CloseTransientFile(srcfd) != 0)
 1863 michael@paquier.xyz       211         [ #  # ]:UBC           0 :         ereport(ERROR,
                                212                 :                :                 (errcode_for_file_access(),
                                213                 :                :                  errmsg("could not close file \"%s\": %m", fromfile)));
                                214                 :                : 
 6799 tgl@sss.pgh.pa.us         215                 :CBC       30747 :     pfree(buffer);
 7640 bruce@momjian.us          216                 :          30747 : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622