PostgreSQL Source Code  git master
file_utils.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int fsync_fname (const char *fname, bool isdir)
 
void fsync_pgdata (const char *pg_data, int serverVersion)
 
void fsync_dir_recurse (const char *dir)
 
int durable_rename (const char *oldfile, const char *newfile)
 
int fsync_parent_path (const char *fname)
 

Function Documentation

◆ durable_rename()

int durable_rename ( const char *  oldfile,
const char *  newfile 
)

Definition at line 340 of file file_utils.c.

References close, fd(), fsync, fsync_fname(), fsync_parent_path(), PG_BINARY, and pg_log_error.

341 {
342  int fd;
343 
344  /*
345  * First fsync the old and target path (if it exists), to ensure that they
346  * are properly persistent on disk. Syncing the target file is not
347  * strictly necessary, but it makes it easier to reason about crashes;
348  * because it's then guaranteed that either source or target file exists
349  * after a crash.
350  */
351  if (fsync_fname(oldfile, false) != 0)
352  return -1;
353 
354  fd = open(newfile, PG_BINARY | O_RDWR, 0);
355  if (fd < 0)
356  {
357  if (errno != ENOENT)
358  {
359  pg_log_error("could not open file \"%s\": %m", newfile);
360  return -1;
361  }
362  }
363  else
364  {
365  if (fsync(fd) != 0)
366  {
367  pg_log_error("could not fsync file \"%s\": %m", newfile);
368  close(fd);
369  return -1;
370  }
371  close(fd);
372  }
373 
374  /* Time to do the real deal... */
375  if (rename(oldfile, newfile) != 0)
376  {
377  pg_log_error("could not rename file \"%s\" to \"%s\": %m",
378  oldfile, newfile);
379  return -1;
380  }
381 
382  /*
383  * To guarantee renaming the file is persistent, fsync the file with its
384  * new name, and its containing directory.
385  */
386  if (fsync_fname(newfile, false) != 0)
387  return -1;
388 
389  if (fsync_parent_path(newfile) != 0)
390  return -1;
391 
392  return 0;
393 }
int fsync_fname(const char *fname, bool isdir)
Definition: file_utils.c:257
int fsync_parent_path(const char *fname)
Definition: file_utils.c:313
#define pg_log_error(...)
Definition: logging.h:79
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1222
#define fsync(fd)
Definition: win32_port.h:63
#define close(a)
Definition: win32.h:12

◆ fsync_dir_recurse()

void fsync_dir_recurse ( const char *  dir)

Definition at line 122 of file file_utils.c.

References fsync_fname(), and walkdir().

Referenced by _CloseArchive(), and BaseBackup().

123 {
124  /*
125  * If possible, hint to the kernel that we're soon going to fsync the data
126  * directory and its contents.
127  */
128 #ifdef PG_FLUSH_DATA_WORKS
129  walkdir(dir, pre_sync_fname, false);
130 #endif
131 
132  walkdir(dir, fsync_fname, false);
133 }
int fsync_fname(const char *fname, bool isdir)
Definition: file_utils.c:257
static void walkdir(const char *path, int(*action)(const char *fname, bool isdir), bool process_symlinks)
Definition: file_utils.c:150

◆ fsync_fname()

int fsync_fname ( const char *  fname,
bool  isdir 
)

Definition at line 617 of file fd.c.

618 {
619  fsync_fname_ext(fname, isdir, false, data_sync_elevel(ERROR));
620 }
#define ERROR
Definition: elog.h:43
int data_sync_elevel(int elevel)
Definition: fd.c:3519
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3380

◆ fsync_parent_path()

int fsync_parent_path ( const char *  fname)

Definition at line 313 of file file_utils.c.

References fsync_fname(), get_parent_directory(), MAXPGPATH, and strlcpy().

Referenced by durable_rename().

314 {
315  char parentpath[MAXPGPATH];
316 
317  strlcpy(parentpath, fname, MAXPGPATH);
318  get_parent_directory(parentpath);
319 
320  /*
321  * get_parent_directory() returns an empty string if the input argument is
322  * just a file name (see comments in path.c), so handle that as being the
323  * current directory.
324  */
325  if (strlen(parentpath) == 0)
326  strlcpy(parentpath, ".", MAXPGPATH);
327 
328  if (fsync_fname(parentpath, true) != 0)
329  return -1;
330 
331  return 0;
332 }
int fsync_fname(const char *fname, bool isdir)
Definition: file_utils.c:257
#define MAXPGPATH
void get_parent_directory(char *path)
Definition: path.c:854
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45

◆ fsync_pgdata()

void fsync_pgdata ( const char *  pg_data,
int  serverVersion 
)

Definition at line 58 of file file_utils.c.

References fsync_fname(), lstat, MAXPGPATH, MINIMUM_VERSION_FOR_PG_WAL, pg_log_error, pgwin32_is_junction(), snprintf, stat, and walkdir().

Referenced by BaseBackup(), main(), and syncTargetDirectory().

60 {
61  bool xlog_is_symlink;
62  char pg_wal[MAXPGPATH];
63  char pg_tblspc[MAXPGPATH];
64 
65  /* handle renaming of pg_xlog to pg_wal in post-10 clusters */
66  snprintf(pg_wal, MAXPGPATH, "%s/%s", pg_data,
67  serverVersion < MINIMUM_VERSION_FOR_PG_WAL ? "pg_xlog" : "pg_wal");
68  snprintf(pg_tblspc, MAXPGPATH, "%s/pg_tblspc", pg_data);
69 
70  /*
71  * If pg_wal is a symlink, we'll need to recurse into it separately,
72  * because the first walkdir below will ignore it.
73  */
74  xlog_is_symlink = false;
75 
76 #ifndef WIN32
77  {
78  struct stat st;
79 
80  if (lstat(pg_wal, &st) < 0)
81  pg_log_error("could not stat file \"%s\": %m", pg_wal);
82  else if (S_ISLNK(st.st_mode))
83  xlog_is_symlink = true;
84  }
85 #else
86  if (pgwin32_is_junction(pg_wal))
87  xlog_is_symlink = true;
88 #endif
89 
90  /*
91  * If possible, hint to the kernel that we're soon going to fsync the data
92  * directory and its contents.
93  */
94 #ifdef PG_FLUSH_DATA_WORKS
95  walkdir(pg_data, pre_sync_fname, false);
96  if (xlog_is_symlink)
97  walkdir(pg_wal, pre_sync_fname, false);
98  walkdir(pg_tblspc, pre_sync_fname, true);
99 #endif
100 
101  /*
102  * Now we do the fsync()s in the same order.
103  *
104  * The main call ignores symlinks, so in addition to specially processing
105  * pg_wal if it's a symlink, pg_tblspc has to be visited separately with
106  * process_symlinks = true. Note that if there are any plain directories
107  * in pg_tblspc, they'll get fsync'd twice. That's not an expected case
108  * so we don't worry about optimizing it.
109  */
110  walkdir(pg_data, fsync_fname, false);
111  if (xlog_is_symlink)
112  walkdir(pg_wal, fsync_fname, false);
113  walkdir(pg_tblspc, fsync_fname, true);
114 }
int fsync_fname(const char *fname, bool isdir)
Definition: file_utils.c:257
#define MINIMUM_VERSION_FOR_PG_WAL
Definition: file_utils.c:36
#define pg_log_error(...)
Definition: logging.h:79
static void walkdir(const char *path, int(*action)(const char *fname, bool isdir), bool process_symlinks)
Definition: file_utils.c:150
#define MAXPGPATH
static char * pg_data
Definition: initdb.c:123
#define stat(a, b)
Definition: win32_port.h:255
#define lstat(path, sb)
Definition: win32_port.h:244
#define snprintf
Definition: port.h:192
bool pgwin32_is_junction(const char *path)