36 #if defined(HAVE_SYNC_FILE_RANGE)
37 #define PG_FLUSH_DATA_WORKS 1
38 #elif defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
39 #define PG_FLUSH_DATA_WORKS 1
45 #define MINIMUM_VERSION_FOR_PG_WAL 100000
47 #ifdef PG_FLUSH_DATA_WORKS
48 static int pre_sync_fname(
const char *fname,
bool isdir);
50 static void walkdir(
const char *path,
51 int (*
action) (
const char *fname,
bool isdir),
52 bool process_symlinks);
65 fsync_pgdata(
const char *
pg_data,
81 xlog_is_symlink =
false;
86 if (
lstat(pg_wal, &st) < 0)
89 xlog_is_symlink =
true;
96 #ifdef PG_FLUSH_DATA_WORKS
99 walkdir(pg_wal, pre_sync_fname,
false);
100 walkdir(pg_tblspc, pre_sync_fname,
true);
124 fsync_dir_recurse(
const char *dir)
130 #ifdef PG_FLUSH_DATA_WORKS
131 walkdir(dir, pre_sync_fname,
false);
153 int (*
action) (
const char *fname,
bool isdir),
154 bool process_symlinks)
162 pg_log_error(
"could not open directory \"%s\": %m", path);
166 while (errno = 0, (de =
readdir(dir)) != NULL)
170 if (strcmp(de->
d_name,
".") == 0 ||
171 strcmp(de->
d_name,
"..") == 0)
196 pg_log_error(
"could not read directory \"%s\": %m", path);
206 (*action) (path,
true);
215 #ifdef PG_FLUSH_DATA_WORKS
218 pre_sync_fname(
const char *fname,
bool isdir)
226 if (errno == EACCES || (isdir && errno == EISDIR))
237 #if defined(HAVE_SYNC_FILE_RANGE)
238 (void) sync_file_range(
fd, 0, 0, SYNC_FILE_RANGE_WRITE);
239 #elif defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
240 (void) posix_fadvise(
fd, 0, 0, POSIX_FADV_DONTNEED);
242 #error PG_FLUSH_DATA_WORKS should not have been defined
282 fd = open(fname, flags, 0);
285 if (errno == EACCES || (isdir && errno == EISDIR))
297 if (returncode != 0 && !(isdir && (errno == EBADF || errno == EINVAL)))
327 if (strlen(parentpath) == 0)
361 pg_log_error(
"could not open file \"%s\": %m", newfile);
369 pg_log_error(
"could not fsync file \"%s\": %m", newfile);
377 if (rename(oldfile, newfile) != 0)
379 pg_log_error(
"could not rename file \"%s\" to \"%s\": %m",
408 bool look_through_symlinks,
419 #if defined(DT_REG) && defined(DT_DIR) && defined(DT_LNK)
424 else if (de->
d_type ==
DT_LNK && !look_through_symlinks)
438 if (look_through_symlinks)
439 sret =
stat(path, &fst);
441 sret =
lstat(path, &fst);
451 errmsg(
"could not stat file \"%s\": %m", path)));
492 #ifdef SIMULATE_SHORT_WRITE
493 part =
Min(part, 4096);
501 while (iovcnt > 0 && iov->iov_len <= part)
503 part -= iov->iov_len;
521 memmove(iov_copy, iov,
sizeof(*iov) * iovcnt);
522 Assert(iov->iov_len > part);
523 iov_copy[0].iov_base = (
char *) iov_copy[0].iov_base + part;
524 iov_copy[0].iov_len -= part;
546 size_t remaining_size = 0;
549 ssize_t total_written = 0;
551 zbuffer_sz =
sizeof(zbuffer.
data);
554 memset(zbuffer.
data, 0, zbuffer_sz);
559 iov[
i].iov_base = zbuffer.
data;
560 iov[
i].iov_len = zbuffer_sz;
564 blocks = size / zbuffer_sz;
565 remaining_size = size % zbuffer_sz;
566 for (
i = 0;
i < blocks;)
569 off_t offset =
i * zbuffer_sz;
577 total_written += written;
581 if (remaining_size > 0)
587 off_t offset =
i * zbuffer_sz;
589 iov[0].iov_len = remaining_size;
596 total_written += written;
599 Assert(total_written == size);
601 return total_written;
struct dirent * readdir(DIR *)
DIR * opendir(const char *)
int errcode_for_file_access(void)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
int durable_rename(const char *oldfile, const char *newfile, int elevel)
void fsync_fname(const char *fname, bool isdir)
static int fsync_parent_path(const char *fname, int elevel)
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
ssize_t pg_pwrite_zeros(int fd, size_t size)
ssize_t pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Assert(fmt[strlen(fmt) - 1] !='\n')
void pg_log_generic(enum pg_log_level level, enum pg_log_part part, const char *pg_restrict fmt,...)
#define pg_log_error(...)
Datum subpath(PG_FUNCTION_ARGS)
#define MINIMUM_VERSION_FOR_PG_WAL
ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
void get_parent_directory(char *path)
size_t strlcpy(char *dst, const char *src, size_t siz)
static int fd(const char *x, int i)