Skip to content

Commit 4ab8c81

Browse files
committed
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
1 parent 1b9cd69 commit 4ab8c81

File tree

4 files changed

+74
-71
lines changed

4 files changed

+74
-71
lines changed

src/backend/storage/file/fd.c

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@
9393
#include "common/pg_prng.h"
9494
#include "miscadmin.h"
9595
#include "pgstat.h"
96-
#include "port/pg_iovec.h"
9796
#include "portability/mem.h"
9897
#include "postmaster/startup.h"
9998
#include "storage/fd.h"
@@ -3738,67 +3737,3 @@ data_sync_elevel(int elevel)
37383737
{
37393738
return data_sync_retry ? elevel : PANIC;
37403739
}
3741-
3742-
/*
3743-
* A convenience wrapper for pg_pwritev() that retries on partial write. If an
3744-
* error is returned, it is unspecified how much has been written.
3745-
*/
3746-
ssize_t
3747-
pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
3748-
{
3749-
struct iovec iov_copy[PG_IOV_MAX];
3750-
ssize_t sum = 0;
3751-
ssize_t part;
3752-
3753-
/* We'd better have space to make a copy, in case we need to retry. */
3754-
if (iovcnt > PG_IOV_MAX)
3755-
{
3756-
errno = EINVAL;
3757-
return -1;
3758-
}
3759-
3760-
for (;;)
3761-
{
3762-
/* Write as much as we can. */
3763-
part = pg_pwritev(fd, iov, iovcnt, offset);
3764-
if (part < 0)
3765-
return -1;
3766-
3767-
#ifdef SIMULATE_SHORT_WRITE
3768-
part = Min(part, 4096);
3769-
#endif
3770-
3771-
/* Count our progress. */
3772-
sum += part;
3773-
offset += part;
3774-
3775-
/* Step over iovecs that are done. */
3776-
while (iovcnt > 0 && iov->iov_len <= part)
3777-
{
3778-
part -= iov->iov_len;
3779-
++iov;
3780-
--iovcnt;
3781-
}
3782-
3783-
/* Are they all done? */
3784-
if (iovcnt == 0)
3785-
{
3786-
/* We don't expect the kernel to write more than requested. */
3787-
Assert(part == 0);
3788-
break;
3789-
}
3790-
3791-
/*
3792-
* Move whatever's left to the front of our mutable copy and adjust
3793-
* the leading iovec.
3794-
*/
3795-
Assert(iovcnt > 0);
3796-
memmove(iov_copy, iov, sizeof(*iov) * iovcnt);
3797-
Assert(iov->iov_len > part);
3798-
iov_copy[0].iov_base = (char *) iov_copy[0].iov_base + part;
3799-
iov_copy[0].iov_len -= part;
3800-
iov = iov_copy;
3801-
}
3802-
3803-
return sum;
3804-
}

src/common/file_utils.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#ifdef FRONTEND
2929
#include "common/logging.h"
3030
#endif
31+
#include "port/pg_iovec.h"
3132

3233
#ifdef FRONTEND
3334

@@ -460,3 +461,69 @@ get_dirent_type(const char *path,
460461

461462
return result;
462463
}
464+
465+
/*
466+
* pg_pwritev_with_retry
467+
*
468+
* Convenience wrapper for pg_pwritev() that retries on partial write. If an
469+
* error is returned, it is unspecified how much has been written.
470+
*/
471+
ssize_t
472+
pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
473+
{
474+
struct iovec iov_copy[PG_IOV_MAX];
475+
ssize_t sum = 0;
476+
ssize_t part;
477+
478+
/* We'd better have space to make a copy, in case we need to retry. */
479+
if (iovcnt > PG_IOV_MAX)
480+
{
481+
errno = EINVAL;
482+
return -1;
483+
}
484+
485+
for (;;)
486+
{
487+
/* Write as much as we can. */
488+
part = pg_pwritev(fd, iov, iovcnt, offset);
489+
if (part < 0)
490+
return -1;
491+
492+
#ifdef SIMULATE_SHORT_WRITE
493+
part = Min(part, 4096);
494+
#endif
495+
496+
/* Count our progress. */
497+
sum += part;
498+
offset += part;
499+
500+
/* Step over iovecs that are done. */
501+
while (iovcnt > 0 && iov->iov_len <= part)
502+
{
503+
part -= iov->iov_len;
504+
++iov;
505+
--iovcnt;
506+
}
507+
508+
/* Are they all done? */
509+
if (iovcnt == 0)
510+
{
511+
/* We don't expect the kernel to write more than requested. */
512+
Assert(part == 0);
513+
break;
514+
}
515+
516+
/*
517+
* Move whatever's left to the front of our mutable copy and adjust
518+
* the leading iovec.
519+
*/
520+
Assert(iovcnt > 0);
521+
memmove(iov_copy, iov, sizeof(*iov) * iovcnt);
522+
Assert(iov->iov_len > part);
523+
iov_copy[0].iov_base = (char *) iov_copy[0].iov_base + part;
524+
iov_copy[0].iov_len -= part;
525+
iov = iov_copy;
526+
}
527+
528+
return sum;
529+
}

src/include/common/file_utils.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ typedef enum PGFileType
2424
PGFILETYPE_LNK
2525
} PGFileType;
2626

27+
struct iovec; /* avoid including port/pg_iovec.h here */
28+
2729
#ifdef FRONTEND
2830
extern int fsync_fname(const char *fname, bool isdir);
2931
extern void fsync_pgdata(const char *pg_data, int serverVersion);
@@ -37,4 +39,9 @@ extern PGFileType get_dirent_type(const char *path,
3739
bool look_through_symlinks,
3840
int elevel);
3941

42+
extern ssize_t pg_pwritev_with_retry(int fd,
43+
const struct iovec *iov,
44+
int iovcnt,
45+
off_t offset);
46+
4047
#endif /* FILE_UTILS_H */

src/include/storage/fd.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ typedef enum RecoveryInitSyncMethod
5151
RECOVERY_INIT_SYNC_METHOD_SYNCFS
5252
} RecoveryInitSyncMethod;
5353

54-
struct iovec; /* avoid including port/pg_iovec.h here */
55-
5654
typedef int File;
5755

5856

@@ -178,10 +176,6 @@ extern int pg_fsync_no_writethrough(int fd);
178176
extern int pg_fsync_writethrough(int fd);
179177
extern int pg_fdatasync(int fd);
180178
extern void pg_flush_data(int fd, off_t offset, off_t nbytes);
181-
extern ssize_t pg_pwritev_with_retry(int fd,
182-
const struct iovec *iov,
183-
int iovcnt,
184-
off_t offset);
185179
extern int pg_truncate(const char *path, off_t length);
186180
extern void fsync_fname(const char *fname, bool isdir);
187181
extern int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy