mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Move pg_pwritev_with_retry() to src/common/file_utils.c
This commit moves pg_pwritev_with_retry(), a convenience wrapper of pg_writev() able to handle partial writes, to common/file_utils.c so that the frontend code is able to use it. A first use-case targetted for this routine is pg_basebackup and pg_receivewal, for the zero-padding of a newly-initialized WAL segment. This is used currently in the backend when the GUC wal_init_zero is enabled (default). Author: Bharath Rupireddy Reviewed-by: Nathan Bossart, Thomas Munro Discussion: https://postgr.es/m/CALj2ACUq7nAb7=bJNbK3yYmp-SZhJcXFR_pLk8un6XgDzDF3OA@mail.gmail.com
This commit is contained in:
@ -93,7 +93,6 @@
|
||||
#include "common/pg_prng.h"
|
||||
#include "miscadmin.h"
|
||||
#include "pgstat.h"
|
||||
#include "port/pg_iovec.h"
|
||||
#include "portability/mem.h"
|
||||
#include "postmaster/startup.h"
|
||||
#include "storage/fd.h"
|
||||
@ -3738,67 +3737,3 @@ data_sync_elevel(int elevel)
|
||||
{
|
||||
return data_sync_retry ? elevel : PANIC;
|
||||
}
|
||||
|
||||
/*
|
||||
* A convenience wrapper for pg_pwritev() that retries on partial write. If an
|
||||
* error is returned, it is unspecified how much has been written.
|
||||
*/
|
||||
ssize_t
|
||||
pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
|
||||
{
|
||||
struct iovec iov_copy[PG_IOV_MAX];
|
||||
ssize_t sum = 0;
|
||||
ssize_t part;
|
||||
|
||||
/* We'd better have space to make a copy, in case we need to retry. */
|
||||
if (iovcnt > PG_IOV_MAX)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Write as much as we can. */
|
||||
part = pg_pwritev(fd, iov, iovcnt, offset);
|
||||
if (part < 0)
|
||||
return -1;
|
||||
|
||||
#ifdef SIMULATE_SHORT_WRITE
|
||||
part = Min(part, 4096);
|
||||
#endif
|
||||
|
||||
/* Count our progress. */
|
||||
sum += part;
|
||||
offset += part;
|
||||
|
||||
/* Step over iovecs that are done. */
|
||||
while (iovcnt > 0 && iov->iov_len <= part)
|
||||
{
|
||||
part -= iov->iov_len;
|
||||
++iov;
|
||||
--iovcnt;
|
||||
}
|
||||
|
||||
/* Are they all done? */
|
||||
if (iovcnt == 0)
|
||||
{
|
||||
/* We don't expect the kernel to write more than requested. */
|
||||
Assert(part == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move whatever's left to the front of our mutable copy and adjust
|
||||
* the leading iovec.
|
||||
*/
|
||||
Assert(iovcnt > 0);
|
||||
memmove(iov_copy, iov, sizeof(*iov) * iovcnt);
|
||||
Assert(iov->iov_len > part);
|
||||
iov_copy[0].iov_base = (char *) iov_copy[0].iov_base + part;
|
||||
iov_copy[0].iov_len -= part;
|
||||
iov = iov_copy;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
Reference in New Issue
Block a user