Skip to content

Commit ce340e5

Browse files
committed
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
1 parent 47c0acc commit ce340e5

File tree

4 files changed

+24
-44
lines changed

4 files changed

+24
-44
lines changed

src/backend/access/transam/xlog.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2982,7 +2982,7 @@ XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli,
29822982
* indirect blocks are down on disk. Therefore, fdatasync(2) or
29832983
* O_DSYNC will be sufficient to sync future writes to the log file.
29842984
*/
2985-
rc = pg_pwrite_zeros(fd, wal_segment_size);
2985+
rc = pg_pwrite_zeros(fd, wal_segment_size, 0);
29862986

29872987
if (rc < 0)
29882988
save_errno = errno;

src/bin/pg_basebackup/walmethods.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ dir_open_for_write(WalWriteMethod *wwmethod, const char *pathname,
222222
{
223223
ssize_t rc;
224224

225-
rc = pg_pwrite_zeros(fd, pad_to_size);
225+
rc = pg_pwrite_zeros(fd, pad_to_size, 0);
226226

227227
if (rc < 0)
228228
{

src/common/file_utils.c

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -531,68 +531,48 @@ pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
531531
/*
532532
* pg_pwrite_zeros
533533
*
534-
* Writes zeros to file worth "size" bytes, using vectored I/O.
534+
* Writes zeros to file worth "size" bytes at "offset" (from the start of the
535+
* file), using vectored I/O.
535536
*
536537
* Returns the total amount of data written. On failure, a negative value
537538
* is returned with errno set.
538539
*/
539540
ssize_t
540-
pg_pwrite_zeros(int fd, size_t size)
541+
pg_pwrite_zeros(int fd, size_t size, off_t offset)
541542
{
542-
PGAlignedBlock zbuffer; /* worth BLCKSZ */
543-
size_t zbuffer_sz;
543+
const static PGAlignedBlock zbuffer = {0}; /* worth BLCKSZ */
544+
void *zerobuf_addr = unconstify(PGAlignedBlock *, &zbuffer)->data;
544545
struct iovec iov[PG_IOV_MAX];
545-
int blocks;
546-
size_t remaining_size = 0;
547-
int i;
548-
ssize_t written;
546+
size_t remaining_size = size;
549547
ssize_t total_written = 0;
550548

551-
zbuffer_sz = sizeof(zbuffer.data);
552-
553-
/* Zero-fill the buffer. */
554-
memset(zbuffer.data, 0, zbuffer_sz);
555-
556-
/* Prepare to write out a lot of copies of our zero buffer at once. */
557-
for (i = 0; i < lengthof(iov); ++i)
558-
{
559-
iov[i].iov_base = zbuffer.data;
560-
iov[i].iov_len = zbuffer_sz;
561-
}
562-
563549
/* Loop, writing as many blocks as we can for each system call. */
564-
blocks = size / zbuffer_sz;
565-
remaining_size = size % zbuffer_sz;
566-
for (i = 0; i < blocks;)
550+
while (remaining_size > 0)
567551
{
568-
int iovcnt = Min(blocks - i, lengthof(iov));
569-
off_t offset = i * zbuffer_sz;
570-
571-
written = pg_pwritev_with_retry(fd, iov, iovcnt, offset);
552+
int iovcnt = 0;
553+
ssize_t written;
572554

573-
if (written < 0)
574-
return written;
575-
576-
i += iovcnt;
577-
total_written += written;
578-
}
555+
for (; iovcnt < PG_IOV_MAX && remaining_size > 0; iovcnt++)
556+
{
557+
size_t this_iov_size;
579558

580-
/* Now, write the remaining size, if any, of the file with zeros. */
581-
if (remaining_size > 0)
582-
{
583-
/* We'll never write more than one block here */
584-
int iovcnt = 1;
559+
iov[iovcnt].iov_base = zerobuf_addr;
585560

586-
/* Jump on to the end of previously written blocks */
587-
off_t offset = i * zbuffer_sz;
561+
if (remaining_size < BLCKSZ)
562+
this_iov_size = remaining_size;
563+
else
564+
this_iov_size = BLCKSZ;
588565

589-
iov[0].iov_len = remaining_size;
566+
iov[iovcnt].iov_len = this_iov_size;
567+
remaining_size -= this_iov_size;
568+
}
590569

591570
written = pg_pwritev_with_retry(fd, iov, iovcnt, offset);
592571

593572
if (written < 0)
594573
return written;
595574

575+
offset += written;
596576
total_written += written;
597577
}
598578

src/include/common/file_utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@ extern ssize_t pg_pwritev_with_retry(int fd,
4444
int iovcnt,
4545
off_t offset);
4646

47-
extern ssize_t pg_pwrite_zeros(int fd, size_t size);
47+
extern ssize_t pg_pwrite_zeros(int fd, size_t size, off_t offset);
4848

4949
#endif /* FILE_UTILS_H */

0 commit comments

Comments
 (0)