diff options
-rwxr-xr-x | configure | 3 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | src/backend/access/transam/xlog.c | 93 | ||||
-rw-r--r-- | src/include/pg_config.h.in | 3 | ||||
-rw-r--r-- | src/include/pg_config.h.win32 | 3 |
5 files changed, 67 insertions, 37 deletions
diff --git a/configure b/configure index 7c662c30599..a2d0cfbba07 100755 --- a/configure +++ b/configure @@ -19695,7 +19695,8 @@ LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` -for ac_func in cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat readlink setproctitle setsid sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l + +for ac_func in cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate pstat readlink setproctitle setsid sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/configure.in b/configure.in index 58ece5b3916..3ecdd280066 100644 --- a/configure.in +++ b/configure.in @@ -1222,7 +1222,7 @@ PGAC_FUNC_GETTIMEOFDAY_1ARG LIBS_including_readline="$LIBS" LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` -AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat readlink setproctitle setsid sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l]) +AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate pstat readlink setproctitle setsid sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l]) AC_REPLACE_FUNCS(fseeko) case $host_os in diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 4220859c8a4..f97ab1ae3a2 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -2256,11 +2256,9 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock) { char path[MAXPGPATH]; char tmppath[MAXPGPATH]; - char *zbuffer; XLogSegNo installed_segno; int max_advance; int fd; - int nbytes; XLogFilePath(path, ThisTimeLineID, logsegno); @@ -2294,16 +2292,6 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock) unlink(tmppath); - /* - * Allocate a buffer full of zeros. This is done before opening the file - * so that we don't leak the file descriptor if palloc fails. - * - * Note: palloc zbuffer, instead of just using a local char array, to - * ensure it is reasonably well-aligned; this may save a few cycles - * transferring data to the kernel. - */ - zbuffer = (char *) palloc0(XLOG_BLCKSZ); - /* do not use get_sync_bit() here --- want to fsync only at end of fill */ fd = BasicOpenFile(tmppath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, S_IRUSR | S_IWUSR); @@ -2312,38 +2300,73 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock) (errcode_for_file_access(), errmsg("could not create file \"%s\": %m", tmppath))); - /* - * Zero-fill the file. We have to do this the hard way to ensure that all - * the file space has really been allocated --- on platforms that allow - * "holes" in files, just seeking to the end doesn't allocate intermediate - * space. This way, we know that we have all the space and (after the - * fsync below) that all the indirect blocks are down on disk. Therefore, - * fdatasync(2) or O_DSYNC will be sufficient to sync future writes to the - * log file. - */ - for (nbytes = 0; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ) +#ifdef HAVE_POSIX_FALLOCATE { - errno = 0; - if ((int) write(fd, zbuffer, XLOG_BLCKSZ) != (int) XLOG_BLCKSZ) - { - int save_errno = errno; + errno = posix_fallocate(fd, 0, XLogSegSize); - /* - * If we fail to make the file, delete it to release disk space - */ - unlink(tmppath); + if (errno) + { + int errno_saved = errno; close(fd); - - /* if write didn't set errno, assume problem is no disk space */ - errno = save_errno ? save_errno : ENOSPC; + unlink(tmppath); + errno = errno_saved; ereport(ERROR, (errcode_for_file_access(), - errmsg("could not write to file \"%s\": %m", tmppath))); + errmsg("could not allocate space for file \"%s\" using posix_fallocate: %m", + tmppath))); + } + } +#else /* !HAVE_POSIX_FALLOCATE */ + { + /* + * Allocate a buffer full of zeros. This is done before opening the + * file so that we don't leak the file descriptor if palloc fails. + * + * Note: palloc zbuffer, instead of just using a local char array, to + * ensure it is reasonably well-aligned; this may save a few cycles + * transferring data to the kernel. + */ + + char *zbuffer = (char *) palloc0(XLOG_BLCKSZ); + int nbytes; + + /* + * Zero-fill the file. We have to do this the hard way to ensure that + * all the file space has really been allocated --- on platforms that + * allow "holes" in files, just seeking to the end doesn't allocate + * intermediate space. This way, we know that we have all the space + * and (after the fsync below) that all the indirect blocks are down on + * disk. Therefore, fdatasync(2) or O_DSYNC will be sufficient to sync + * future writes to the log file. + */ + for (nbytes = 0; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ) + { + errno = 0; + if ((int) write(fd, zbuffer, XLOG_BLCKSZ) != (int) XLOG_BLCKSZ) + { + int save_errno = errno; + + /* + * If we fail to make the file, delete it to release disk space + */ + unlink(tmppath); + + close(fd); + + /* if write didn't set errno, assume no disk space */ + errno = save_errno ? save_errno : ENOSPC; + + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not write to file \"%s\": %m", + tmppath))); + } } + pfree(zbuffer); } - pfree(zbuffer); +#endif /* HAVE_POSIX_FALLOCATE */ if (pg_fsync(fd) != 0) { diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 8aabf3c87a4..033127beff8 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -369,6 +369,9 @@ /* Define to 1 if you have the `posix_fadvise' function. */ #undef HAVE_POSIX_FADVISE +/* Define to 1 if you have the `posix_fallocate' function. */ +#undef HAVE_POSIX_FALLOCATE + /* Define to 1 if you have the POSIX signal interface. */ #undef HAVE_POSIX_SIGNALS diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32 index 54db287aff6..931551086b7 100644 --- a/src/include/pg_config.h.win32 +++ b/src/include/pg_config.h.win32 @@ -276,6 +276,9 @@ /* Define to 1 if you have the <poll.h> header file. */ /* #undef HAVE_POLL_H */ +/* Define to 1 if you have the `posix_fallocate' function. */ +/* #undef HAVE_POSIX_FALLOCATE */ + /* Define to 1 if you have the POSIX signal interface. */ /* #undef HAVE_POSIX_SIGNALS */ |