PostgreSQL Source Code git master
Loading...
Searching...
No Matches
copydir.c File Reference
#include "postgres.h"
#include <fcntl.h>
#include <unistd.h>
#include "common/file_utils.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/copydir.h"
#include "storage/fd.h"
#include "utils/wait_event.h"
Include dependency graph for copydir.c:

Go to the source code of this file.

Macros

#define COPY_BUF_SIZE   (8 * BLCKSZ)
 
#define FLUSH_DISTANCE   (1024 * 1024)
 

Functions

static void clone_file (const char *fromfile, const char *tofile)
 
void copydir (const char *fromdir, const char *todir, bool recurse)
 
void copy_file (const char *fromfile, const char *tofile)
 

Variables

int file_copy_method = FILE_COPY_METHOD_COPY
 

Macro Definition Documentation

◆ COPY_BUF_SIZE

#define COPY_BUF_SIZE   (8 * BLCKSZ)

◆ FLUSH_DISTANCE

#define FLUSH_DISTANCE   (1024 * 1024)

Function Documentation

◆ clone_file()

static void clone_file ( const char fromfile,
const char tofile 
)
static

Definition at line 239 of file copydir.c.

240{
241#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
245 errmsg("could not clone file \"%s\" to \"%s\": %m",
246 fromfile, tofile)));
247#elif defined(HAVE_COPY_FILE_RANGE)
248 int srcfd;
249 int dstfd;
250 ssize_t nbytes;
251
253 if (srcfd < 0)
256 errmsg("could not open file \"%s\": %m", fromfile)));
257
259 if (dstfd < 0)
262 errmsg("could not create file \"%s\": %m", tofile)));
263
264 do
265 {
266 /*
267 * Don't copy too much at once, so we can check for interrupts from
268 * time to time if it falls back to a slow copy.
269 */
272 nbytes = copy_file_range(srcfd, NULL, dstfd, NULL, 1024 * 1024, 0);
273 if (nbytes < 0 && errno != EINTR)
276 errmsg("could not clone file \"%s\" to \"%s\": %m",
277 fromfile, tofile)));
279 }
280 while (nbytes != 0);
281
282 if (CloseTransientFile(dstfd) != 0)
285 errmsg("could not close file \"%s\": %m", tofile)));
286
287 if (CloseTransientFile(srcfd) != 0)
290 errmsg("could not close file \"%s\": %m", fromfile)));
291#else
292 /* If there is no CLONE support this function should not be called. */
294#endif
295}
#define PG_BINARY
Definition c.h:1376
#define pg_unreachable()
Definition c.h:361
int errcode_for_file_access(void)
Definition elog.c:897
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
int CloseTransientFile(int fd)
Definition fd.c:2855
int OpenTransientFile(const char *fileName, int fileFlags)
Definition fd.c:2678
static int dstfd
Definition file_ops.c:31
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
static char * errmsg
static int fb(int x)
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition wait_event.h:69
static void pgstat_report_wait_end(void)
Definition wait_event.h:85
#define EINTR
Definition win32_port.h:361

References CHECK_FOR_INTERRUPTS, CloseTransientFile(), dstfd, EINTR, ereport, errcode_for_file_access(), errmsg, ERROR, fb(), OpenTransientFile(), PG_BINARY, pg_unreachable, pgstat_report_wait_end(), and pgstat_report_wait_start().

Referenced by copydir().

◆ copy_file()

void copy_file ( const char fromfile,
const char tofile 
)

Definition at line 134 of file copydir.c.

135{
136 char *buffer;
137 int srcfd;
138 int dstfd;
139 int nbytes;
140 off_t offset;
142
143 /* Size of copy buffer (read and write requests) */
144#define COPY_BUF_SIZE (8 * BLCKSZ)
145
146 /*
147 * Size of data flush requests. It seems beneficial on most platforms to
148 * do this every 1MB or so. But macOS, at least with early releases of
149 * APFS, is really unfriendly to small mmap/msync requests, so there do it
150 * only every 32MB.
151 */
152#if defined(__darwin__)
153#define FLUSH_DISTANCE (32 * 1024 * 1024)
154#else
155#define FLUSH_DISTANCE (1024 * 1024)
156#endif
157
158 /* Use palloc to ensure we get a maxaligned buffer */
159 buffer = palloc(COPY_BUF_SIZE);
160
161 /*
162 * Open the files
163 */
165 if (srcfd < 0)
168 errmsg("could not open file \"%s\": %m", fromfile)));
169
171 if (dstfd < 0)
174 errmsg("could not create file \"%s\": %m", tofile)));
175
176 /*
177 * Do the data copying.
178 */
179 flush_offset = 0;
180 for (offset = 0;; offset += nbytes)
181 {
182 /* If we got a cancel signal during the copy of the file, quit */
184
185 /*
186 * We fsync the files later, but during the copy, flush them every so
187 * often to avoid spamming the cache and hopefully get the kernel to
188 * start writing them out before the fsync comes.
189 */
190 if (offset - flush_offset >= FLUSH_DISTANCE)
191 {
193 flush_offset = offset;
194 }
195
197 nbytes = read(srcfd, buffer, COPY_BUF_SIZE);
199 if (nbytes < 0)
202 errmsg("could not read file \"%s\": %m", fromfile)));
203 if (nbytes == 0)
204 break;
205 errno = 0;
207 if ((int) write(dstfd, buffer, nbytes) != nbytes)
208 {
209 /* if write didn't set errno, assume problem is no disk space */
210 if (errno == 0)
211 errno = ENOSPC;
214 errmsg("could not write to file \"%s\": %m", tofile)));
215 }
217 }
218
219 if (offset > flush_offset)
221
222 if (CloseTransientFile(dstfd) != 0)
225 errmsg("could not close file \"%s\": %m", tofile)));
226
227 if (CloseTransientFile(srcfd) != 0)
230 errmsg("could not close file \"%s\": %m", fromfile)));
231
232 pfree(buffer);
233}
#define FLUSH_DISTANCE
#define COPY_BUF_SIZE
void pg_flush_data(int fd, pgoff_t offset, pgoff_t nbytes)
Definition fd.c:526
#define write(a, b, c)
Definition win32.h:14
#define read(a, b, c)
Definition win32.h:13
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc(Size size)
Definition mcxt.c:1387

References CHECK_FOR_INTERRUPTS, CloseTransientFile(), COPY_BUF_SIZE, dstfd, ereport, errcode_for_file_access(), errmsg, ERROR, fb(), FLUSH_DISTANCE, OpenTransientFile(), palloc(), pfree(), PG_BINARY, pg_flush_data(), pgstat_report_wait_end(), pgstat_report_wait_start(), read, and write.

Referenced by basic_archive_file(), copydir(), process_directory_recursively(), reconstruct_from_incremental_file(), and ResetUnloggedRelationsInDbspaceDir().

◆ copydir()

void copydir ( const char fromdir,
const char todir,
bool  recurse 
)

Definition at line 49 of file copydir.c.

50{
51 DIR *xldir;
52 struct dirent *xlde;
53 char fromfile[MAXPGPATH * 2];
54 char tofile[MAXPGPATH * 2];
55
56 if (MakePGDirectory(todir) != 0)
59 errmsg("could not create directory \"%s\": %m", todir)));
60
62
63 while ((xlde = ReadDir(xldir, fromdir)) != NULL)
64 {
66
67 /* If we got a cancel signal during the copy of the directory, quit */
69
70 if (strcmp(xlde->d_name, ".") == 0 ||
71 strcmp(xlde->d_name, "..") == 0)
72 continue;
73
74 snprintf(fromfile, sizeof(fromfile), "%s/%s", fromdir, xlde->d_name);
75 snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name);
76
78
80 {
81 /* recurse to handle subdirectories */
82 if (recurse)
83 copydir(fromfile, tofile, true);
84 }
85 else if (xlde_type == PGFILETYPE_REG)
86 {
89 else
91 }
92 }
94
95 /*
96 * Be paranoid here and fsync all files to ensure the copy is really done.
97 * But if fsync is disabled, we're done.
98 */
99 if (!enableFsync)
100 return;
101
103
104 while ((xlde = ReadDir(xldir, todir)) != NULL)
105 {
106 if (strcmp(xlde->d_name, ".") == 0 ||
107 strcmp(xlde->d_name, "..") == 0)
108 continue;
109
110 snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name);
111
112 /*
113 * We don't need to sync subdirectories here since the recursive
114 * copydir will do it before it returns
115 */
117 fsync_fname(tofile, false);
118 }
119 FreeDir(xldir);
120
121 /*
122 * It's important to fsync the destination directory itself as individual
123 * file fsyncs don't guarantee that the directory entry for the file is
124 * synced. Recent versions of ext4 have made the window much wider but
125 * it's been true for ext3 and other filesystems in the past.
126 */
127 fsync_fname(todir, true);
128}
int file_copy_method
Definition copydir.c:35
static void clone_file(const char *fromfile, const char *tofile)
Definition copydir.c:239
void copy_file(const char *fromfile, const char *tofile)
Definition copydir.c:134
void copydir(const char *fromdir, const char *todir, bool recurse)
Definition copydir.c:49
@ FILE_COPY_METHOD_CLONE
Definition copydir.h:19
int MakePGDirectory(const char *directoryName)
Definition fd.c:3963
int FreeDir(DIR *dir)
Definition fd.c:3009
void fsync_fname(const char *fname, bool isdir)
Definition fd.c:757
DIR * AllocateDir(const char *dirname)
Definition fd.c:2891
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition fd.c:2957
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition file_utils.c:547
PGFileType
Definition file_utils.h:19
@ PGFILETYPE_DIR
Definition file_utils.h:23
@ PGFILETYPE_REG
Definition file_utils.h:22
bool enableFsync
Definition globals.c:129
#define MAXPGPATH
#define snprintf
Definition port.h:260
Definition dirent.c:26

References AllocateDir(), CHECK_FOR_INTERRUPTS, clone_file(), copy_file(), copydir(), enableFsync, ereport, errcode_for_file_access(), errmsg, ERROR, fb(), file_copy_method, FILE_COPY_METHOD_CLONE, FreeDir(), fsync_fname(), get_dirent_type(), MakePGDirectory(), MAXPGPATH, PGFILETYPE_DIR, PGFILETYPE_REG, ReadDir(), and snprintf.

Referenced by copydir(), CreateDatabaseUsingFileCopy(), dbase_redo(), and movedb().

Variable Documentation

◆ file_copy_method

int file_copy_method = FILE_COPY_METHOD_COPY

Definition at line 35 of file copydir.c.

Referenced by copydir().