aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlog.c2
-rw-r--r--src/bin/pg_basebackup/walmethods.c2
-rw-r--r--src/common/file_utils.c62
-rw-r--r--src/include/common/file_utils.h2
4 files changed, 24 insertions, 44 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 87af608d155..543d4d897ae 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2982,7 +2982,7 @@ XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli,
* indirect blocks are down on disk. Therefore, fdatasync(2) or
* O_DSYNC will be sufficient to sync future writes to the log file.
*/
- rc = pg_pwrite_zeros(fd, wal_segment_size);
+ rc = pg_pwrite_zeros(fd, wal_segment_size, 0);
if (rc < 0)
save_errno = errno;
diff --git a/src/bin/pg_basebackup/walmethods.c b/src/bin/pg_basebackup/walmethods.c
index 54014e2b84d..6d14b988cb6 100644
--- a/src/bin/pg_basebackup/walmethods.c
+++ b/src/bin/pg_basebackup/walmethods.c
@@ -222,7 +222,7 @@ dir_open_for_write(WalWriteMethod *wwmethod, const char *pathname,
{
ssize_t rc;
- rc = pg_pwrite_zeros(fd, pad_to_size);
+ rc = pg_pwrite_zeros(fd, pad_to_size, 0);
if (rc < 0)
{
diff --git a/src/common/file_utils.c b/src/common/file_utils.c
index 4dae534152f..f19ebfa2837 100644
--- a/src/common/file_utils.c
+++ b/src/common/file_utils.c
@@ -531,68 +531,48 @@ pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
/*
* pg_pwrite_zeros
*
- * Writes zeros to file worth "size" bytes, using vectored I/O.
+ * Writes zeros to file worth "size" bytes at "offset" (from the start of the
+ * file), using vectored I/O.
*
* Returns the total amount of data written. On failure, a negative value
* is returned with errno set.
*/
ssize_t
-pg_pwrite_zeros(int fd, size_t size)
+pg_pwrite_zeros(int fd, size_t size, off_t offset)
{
- PGAlignedBlock zbuffer; /* worth BLCKSZ */
- size_t zbuffer_sz;
+ const static PGAlignedBlock zbuffer = {0}; /* worth BLCKSZ */
+ void *zerobuf_addr = unconstify(PGAlignedBlock *, &zbuffer)->data;
struct iovec iov[PG_IOV_MAX];
- int blocks;
- size_t remaining_size = 0;
- int i;
- ssize_t written;
+ size_t remaining_size = size;
ssize_t total_written = 0;
- zbuffer_sz = sizeof(zbuffer.data);
-
- /* Zero-fill the buffer. */
- memset(zbuffer.data, 0, zbuffer_sz);
-
- /* Prepare to write out a lot of copies of our zero buffer at once. */
- for (i = 0; i < lengthof(iov); ++i)
- {
- iov[i].iov_base = zbuffer.data;
- iov[i].iov_len = zbuffer_sz;
- }
-
/* Loop, writing as many blocks as we can for each system call. */
- blocks = size / zbuffer_sz;
- remaining_size = size % zbuffer_sz;
- for (i = 0; i < blocks;)
+ while (remaining_size > 0)
{
- int iovcnt = Min(blocks - i, lengthof(iov));
- off_t offset = i * zbuffer_sz;
-
- written = pg_pwritev_with_retry(fd, iov, iovcnt, offset);
+ int iovcnt = 0;
+ ssize_t written;
- if (written < 0)
- return written;
-
- i += iovcnt;
- total_written += written;
- }
+ for (; iovcnt < PG_IOV_MAX && remaining_size > 0; iovcnt++)
+ {
+ size_t this_iov_size;
- /* Now, write the remaining size, if any, of the file with zeros. */
- if (remaining_size > 0)
- {
- /* We'll never write more than one block here */
- int iovcnt = 1;
+ iov[iovcnt].iov_base = zerobuf_addr;
- /* Jump on to the end of previously written blocks */
- off_t offset = i * zbuffer_sz;
+ if (remaining_size < BLCKSZ)
+ this_iov_size = remaining_size;
+ else
+ this_iov_size = BLCKSZ;
- iov[0].iov_len = remaining_size;
+ iov[iovcnt].iov_len = this_iov_size;
+ remaining_size -= this_iov_size;
+ }
written = pg_pwritev_with_retry(fd, iov, iovcnt, offset);
if (written < 0)
return written;
+ offset += written;
total_written += written;
}
diff --git a/src/include/common/file_utils.h b/src/include/common/file_utils.h
index bda6d3a5413..b7efa1226d6 100644
--- a/src/include/common/file_utils.h
+++ b/src/include/common/file_utils.h
@@ -44,6 +44,6 @@ extern ssize_t pg_pwritev_with_retry(int fd,
int iovcnt,
off_t offset);
-extern ssize_t pg_pwrite_zeros(int fd, size_t size);
+extern ssize_t pg_pwrite_zeros(int fd, size_t size, off_t offset);
#endif /* FILE_UTILS_H */