aboutsummaryrefslogtreecommitdiff
path: root/src/common/file_utils.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2023-03-06 13:21:33 +0900
committerMichael Paquier <michael@paquier.xyz>2023-03-06 13:21:33 +0900
commitce340e530d1f76367379a8d230ad5f411e5f25d2 (patch)
tree6a17abed06cbd66092ea530a4b2894fc8148a185 /src/common/file_utils.c
parent47c0accbe05b5774a8a30e42e56e8d6026c9a858 (diff)
downloadpostgresql-ce340e530d1f76367379a8d230ad5f411e5f25d2.tar.gz
postgresql-ce340e530d1f76367379a8d230ad5f411e5f25d2.zip
Revise pg_pwrite_zeros()
The following changes are made to pg_write_zeros(), the API able to write series of zeros using vectored I/O: - Add of an "offset" parameter, to write the size from this position (the 'p' of "pwrite" seems to mean position, though POSIX does not outline ythat directly), hence the name of the routine is incorrect if it is not able to handle offsets. - Avoid memset() of "zbuffer" on every call. - Avoid initialization of the whole IOV array if not needed. - Group the trailing write() call with the main write() call, simplifying the function logic. Author: Andres Freund Reviewed-by: Michael Paquier, Bharath Rupireddy Discussion: https://postgr.es/m/20230215005525.mrrlmqrxzjzhaipl@awork3.anarazel.de
Diffstat (limited to 'src/common/file_utils.c')
-rw-r--r--src/common/file_utils.c62
1 files changed, 21 insertions, 41 deletions
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;
}