]> granicus.if.org Git - postgresql/commitdiff
Use posix_fallocate() for new WAL files, where available.
authorJeff Davis <jdavis@postgresql.org>
Fri, 5 Jul 2013 19:30:29 +0000 (12:30 -0700)
committerJeff Davis <jdavis@postgresql.org>
Fri, 5 Jul 2013 19:30:29 +0000 (12:30 -0700)
This function is more efficient than actually writing out zeroes to
the new file, per microbenchmarks by Jon Nelson. Also, it may reduce
the likelihood of WAL file fragmentation.

Jon Nelson, with review by Andres Freund, Greg Smith and me.

configure
configure.in
src/backend/access/transam/xlog.c
src/include/pg_config.h.in
src/include/pg_config.h.win32

index 7c662c30599660e4f48c7037c75a0f3b63156ca7..a2d0cfbba07d53c7d9d9a98636579af61151c4bc 100755 (executable)
--- 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
index 58ece5b39160f2b262cca431e31e16193895b1ca..3ecdd2800661cca13824fbd3153c6b7f1b13064b 100644 (file)
@@ -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
index 4220859c8a4a26bae0e0f9d4b8eea11cd5ac7672..f97ab1ae3a221bf0b75f205314b43a4dbbf9a36d 100644 (file)
@@ -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)
        {
index 8aabf3c87a4706a2181f5d59eb93d8587ce65044..033127beff86b6051a31c0a5c21ee1c393d47861 100644 (file)
 /* 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
 
index 54db287aff6178c81c1f794208459a40b5aea0e2..931551086b7040a41ced9a29f42871753a72ad8f 100644 (file)
 /* 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 */