diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 17273abbadc..880e83035dc 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2295,6 +2295,43 @@ include_dir 'conf.d'
+
+ file_extend_method (enum)
+
+ file_extend_method configuration parameter
+
+
+
+
+ Specifies the method used to extend data files during bulk operations
+ such as COPY. The first available option is used as
+ the default, depending on the operating system:
+
+
+
+ posix_fallocate (Unix) uses the standard POSIX
+ interface for allocating disk space, but is missing on some systems.
+ If it is present but the underlying file system doesn't support it,
+ this option silently falls back to write_zeros.
+ Current versions of BTRFS are known to disable compression when
+ this option is used.
+ This is the default on systems that have the function.
+
+
+
+
+ write_zeros extends files by writing out blocks
+ of zero bytes. This is the default on systems that don't have the
+ function posix_fallocate.
+
+
+
+ The write_zeros method is always used when data
+ files are extended by 8 blocks or fewer.
+
+
+
+
max_notify_queue_pages (integer)
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 66008275bec..95d8982f88b 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -164,6 +164,9 @@ bool data_sync_retry = false;
/* How SyncDataDirectory() should do its job. */
int recovery_init_sync_method = DATA_DIR_SYNC_METHOD_FSYNC;
+/* How data files should be bulk-extended with zeros. */
+int file_extend_method = DEFAULT_FILE_EXTEND_METHOD;
+
/* Which kinds of files should be opened with PG_O_DIRECT. */
int io_direct_flags;
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index f1ff257119b..5e4e209c496 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -575,13 +575,24 @@ mdzeroextend(SMgrRelation reln, ForkNumber forknum,
* that decision should be made though? For now just use a cutoff of
* 8, anything between 4 and 8 worked OK in some local testing.
*/
- if (numblocks > 8)
+ if (numblocks > 8 &&
+ file_extend_method != FILE_EXTEND_METHOD_WRITE_ZEROS)
{
- int ret;
+ int ret = 0;
- ret = FileFallocate(v->mdfd_vfd,
- seekpos, (off_t) BLCKSZ * numblocks,
- WAIT_EVENT_DATA_FILE_EXTEND);
+#ifdef HAVE_POSIX_FALLOCATE
+ if (file_extend_method == FILE_EXTEND_METHOD_POSIX_FALLOCATE)
+ {
+ ret = FileFallocate(v->mdfd_vfd,
+ seekpos, (off_t) BLCKSZ * numblocks,
+ WAIT_EVENT_DATA_FILE_EXTEND);
+ }
+ else
+#endif
+ {
+ elog(ERROR, "unsupported file_extend_method: %d",
+ file_extend_method);
+ }
if (ret != 0)
{
ereport(ERROR,
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index a997dcb7dbc..6eccfa85428 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -71,6 +71,7 @@
#include "replication/slotsync.h"
#include "replication/syncrep.h"
#include "storage/bufmgr.h"
+#include "storage/fd.h"
#include "storage/large_object.h"
#include "storage/pg_shmem.h"
#include "storage/predicate.h"
@@ -483,6 +484,14 @@ static const struct config_enum_entry wal_compression_options[] = {
{NULL, 0, false}
};
+static const struct config_enum_entry file_extend_method_options[] = {
+#ifdef HAVE_POSIX_FALLOCATE
+ {"posix_fallocate", FILE_EXTEND_METHOD_POSIX_FALLOCATE, false},
+#endif
+ {"write_zeros", FILE_EXTEND_METHOD_WRITE_ZEROS, false},
+ {NULL, 0, false}
+};
+
/*
* Options for enum values stored in other modules
*/
@@ -4991,6 +5000,16 @@ struct config_enum ConfigureNamesEnum[] =
NULL, NULL, NULL
},
+ {
+ {"file_extend_method", PGC_SIGHUP, RESOURCES_DISK,
+ gettext_noop("Selects the method used for extending data files."),
+ NULL
+ },
+ &file_extend_method,
+ DEFAULT_FILE_EXTEND_METHOD, file_extend_method_options,
+ NULL, NULL, NULL
+ },
+
{
{"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
gettext_noop("Selects the method used for forcing WAL updates to disk."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 7e8d3294ec3..6c761f83165 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -175,6 +175,11 @@
#temp_file_limit = -1 # limits per-process temp file space
# in kilobytes, or -1 for no limit
+#file_extend_method = posix_fallocate # the default is the first option supported
+ # by the operating system:
+ # posix_fallocate (most Unix-like systems)
+ # write_zeros
+
#max_notify_queue_pages = 1048576 # limits the number of SLRU pages allocated
# for NOTIFY / LISTEN queue
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index 1456ab383a4..b709a860268 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -55,12 +55,23 @@ typedef int File;
#define IO_DIRECT_WAL 0x02
#define IO_DIRECT_WAL_INIT 0x04
+enum FileExtendMethod
+{
+#ifdef HAVE_POSIX_FALLOCATE
+ FILE_EXTEND_METHOD_POSIX_FALLOCATE,
+#endif
+ FILE_EXTEND_METHOD_WRITE_ZEROS,
+};
+
+/* Default to the first available file_extend_method. */
+#define DEFAULT_FILE_EXTEND_METHOD 0
/* GUC parameter */
extern PGDLLIMPORT int max_files_per_process;
extern PGDLLIMPORT bool data_sync_retry;
extern PGDLLIMPORT int recovery_init_sync_method;
extern PGDLLIMPORT int io_direct_flags;
+extern PGDLLIMPORT int file_extend_method;
/*
* This is private to fd.c, but exported for save/restore_backend_variables()