PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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, const char *progname)
 
void fsync_pgdata (const char *pg_data, const char *progname, int serverVersion)
 
void fsync_dir_recurse (const char *dir, const char *progname)
 
int durable_rename (const char *oldfile, const char *newfile, const char *progname)
 
int fsync_parent_path (const char *fname, const char *progname)
 

Function Documentation

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

Definition at line 348 of file file_utils.c.

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

349 {
350  int fd;
351 
352  /*
353  * First fsync the old and target path (if it exists), to ensure that they
354  * are properly persistent on disk. Syncing the target file is not
355  * strictly necessary, but it makes it easier to reason about crashes;
356  * because it's then guaranteed that either source or target file exists
357  * after a crash.
358  */
359  if (fsync_fname(oldfile, false, progname) != 0)
360  return -1;
361 
362  fd = open(newfile, PG_BINARY | O_RDWR, 0);
363  if (fd < 0)
364  {
365  if (errno != ENOENT)
366  {
367  fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
368  progname, newfile, strerror(errno));
369  return -1;
370  }
371  }
372  else
373  {
374  if (fsync(fd) != 0)
375  {
376  fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"),
377  progname, newfile, strerror(errno));
378  close(fd);
379  return -1;
380  }
381  close(fd);
382  }
383 
384  /* Time to do the real deal... */
385  if (rename(oldfile, newfile) != 0)
386  {
387  fprintf(stderr, _("%s: could not rename file \"%s\" to \"%s\": %s\n"),
388  progname, oldfile, newfile, strerror(errno));
389  return -1;
390  }
391 
392  /*
393  * To guarantee renaming the file is persistent, fsync the file with its
394  * new name, and its containing directory.
395  */
396  if (fsync_fname(newfile, false, progname) != 0)
397  return -1;
398 
399  if (fsync_parent_path(newfile, progname) != 0)
400  return -1;
401 
402  return 0;
403 }
const char * progname
Definition: pg_standby.c:37
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1044
#define fsync(fd)
Definition: win32.h:62
int fsync_fname(const char *fname, bool isdir, const char *progname)
Definition: file_utils.c:263
int fsync_parent_path(const char *fname, const char *progname)
Definition: file_utils.c:321
const char * strerror(int errnum)
Definition: strerror.c:19
#define close(a)
Definition: win32.h:12
#define _(x)
Definition: elog.c:84
void fsync_dir_recurse ( const char *  dir,
const char *  progname 
)

Definition at line 124 of file file_utils.c.

References fsync_fname(), and walkdir().

Referenced by _CloseArchive().

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

Definition at line 263 of file file_utils.c.

References _, close, fd(), fsync, PG_BINARY, and strerror().

Referenced by durable_rename(), fsync_dir_recurse(), fsync_parent_path(), and fsync_pgdata().

264 {
265  int fd;
266  int flags;
267  int returncode;
268 
269  /*
270  * Some OSs require directories to be opened read-only whereas other
271  * systems don't allow us to fsync files opened read-only; so we need both
272  * cases here. Using O_RDWR will cause us to fail to fsync files that are
273  * not writable by our userid, but we assume that's OK.
274  */
275  flags = PG_BINARY;
276  if (!isdir)
277  flags |= O_RDWR;
278  else
279  flags |= O_RDONLY;
280 
281  /*
282  * Open the file, silently ignoring errors about unreadable files (or
283  * unsupported operations, e.g. opening a directory under Windows), and
284  * logging others.
285  */
286  fd = open(fname, flags);
287  if (fd < 0)
288  {
289  if (errno == EACCES || (isdir && errno == EISDIR))
290  return 0;
291  fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
292  progname, fname, strerror(errno));
293  return -1;
294  }
295 
296  returncode = fsync(fd);
297 
298  /*
299  * Some OSes don't allow us to fsync directories at all, so we can ignore
300  * those errors. Anything else needs to be reported.
301  */
302  if (returncode != 0 && !(isdir && errno == EBADF))
303  {
304  fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"),
305  progname, fname, strerror(errno));
306  (void) close(fd);
307  return -1;
308  }
309 
310  (void) close(fd);
311  return 0;
312 }
const char * progname
Definition: pg_standby.c:37
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1044
#define fsync(fd)
Definition: win32.h:62
const char * strerror(int errnum)
Definition: strerror.c:19
#define close(a)
Definition: win32.h:12
#define _(x)
Definition: elog.c:84
int fsync_parent_path ( const char *  fname,
const char *  progname 
)

Definition at line 321 of file file_utils.c.

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

Referenced by durable_rename().

322 {
323  char parentpath[MAXPGPATH];
324 
325  strlcpy(parentpath, fname, MAXPGPATH);
326  get_parent_directory(parentpath);
327 
328  /*
329  * get_parent_directory() returns an empty string if the input argument is
330  * just a file name (see comments in path.c), so handle that as being the
331  * current directory.
332  */
333  if (strlen(parentpath) == 0)
334  strlcpy(parentpath, ".", MAXPGPATH);
335 
336  if (fsync_fname(parentpath, true, progname) != 0)
337  return -1;
338 
339  return 0;
340 }
const char * progname
Definition: pg_standby.c:37
#define MAXPGPATH
void get_parent_directory(char *path)
Definition: path.c:854
int fsync_fname(const char *fname, bool isdir, const char *progname)
Definition: file_utils.c:263
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
void fsync_pgdata ( const char *  pg_data,
const char *  progname,
int  serverVersion 
)

Definition at line 58 of file file_utils.c.

References _, fsync_fname(), lstat, MAXPGPATH, MINIMUM_VERSION_FOR_PG_WAL, snprintf(), strerror(), and walkdir().

Referenced by BaseBackup(), and main().

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