diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/storage/file/fd.c | 43 | ||||
-rw-r--r-- | src/include/storage/fd.h | 32 |
2 files changed, 54 insertions, 21 deletions
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index a185fb3d08c..fbffdd72f0b 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -2110,18 +2110,18 @@ FileWriteback(File file, off_t offset, off_t nbytes, uint32 wait_event_info) } int -FileRead(File file, void *buffer, size_t amount, off_t offset, - uint32 wait_event_info) +FileReadV(File file, const struct iovec *iov, int iovcnt, off_t offset, + uint32 wait_event_info) { int returnCode; Vfd *vfdP; Assert(FileIsValid(file)); - DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %zu %p", + DO_DB(elog(LOG, "FileReadV: %d (%s) " INT64_FORMAT " %d", file, VfdCache[file].fileName, (int64) offset, - amount, buffer)); + iovcnt)); returnCode = FileAccess(file); if (returnCode < 0) @@ -2131,7 +2131,7 @@ FileRead(File file, void *buffer, size_t amount, off_t offset, retry: pgstat_report_wait_start(wait_event_info); - returnCode = pg_pread(vfdP->fd, buffer, amount, offset); + returnCode = pg_preadv(vfdP->fd, iov, iovcnt, offset); pgstat_report_wait_end(); if (returnCode < 0) @@ -2166,18 +2166,18 @@ retry: } int -FileWrite(File file, const void *buffer, size_t amount, off_t offset, - uint32 wait_event_info) +FileWriteV(File file, const struct iovec *iov, int iovcnt, off_t offset, + uint32 wait_event_info) { int returnCode; Vfd *vfdP; Assert(FileIsValid(file)); - DO_DB(elog(LOG, "FileWrite: %d (%s) " INT64_FORMAT " %zu %p", + DO_DB(elog(LOG, "FileWriteV: %d (%s) " INT64_FORMAT " %d", file, VfdCache[file].fileName, (int64) offset, - amount, buffer)); + iovcnt)); returnCode = FileAccess(file); if (returnCode < 0) @@ -2195,7 +2195,10 @@ FileWrite(File file, const void *buffer, size_t amount, off_t offset, */ if (temp_file_limit >= 0 && (vfdP->fdstate & FD_TEMP_FILE_LIMIT)) { - off_t past_write = offset + amount; + off_t past_write = offset; + + for (int i = 0; i < iovcnt; ++i) + past_write += iov[i].iov_len; if (past_write > vfdP->fileSize) { @@ -2211,23 +2214,27 @@ FileWrite(File file, const void *buffer, size_t amount, off_t offset, } retry: - errno = 0; pgstat_report_wait_start(wait_event_info); - returnCode = pg_pwrite(VfdCache[file].fd, buffer, amount, offset); + returnCode = pg_pwritev(vfdP->fd, iov, iovcnt, offset); pgstat_report_wait_end(); - /* if write didn't set errno, assume problem is no disk space */ - if (returnCode != amount && errno == 0) - errno = ENOSPC; - if (returnCode >= 0) { /* + * Some callers expect short writes to set errno, and traditionally we + * have assumed that they imply disk space shortage. We don't want to + * waste CPU cycles adding up the total size here, so we'll just set + * it for all successful writes in case such a caller determines that + * the write was short and ereports "%m". + */ + errno = ENOSPC; + + /* * Maintain fileSize and temporary_files_size if it's a temp file. */ if (vfdP->fdstate & FD_TEMP_FILE_LIMIT) { - off_t past_write = offset + amount; + off_t past_write = offset + returnCode; if (past_write > vfdP->fileSize) { @@ -2239,7 +2246,7 @@ retry: else { /* - * See comments in FileRead() + * See comments in FileReadV() */ #ifdef WIN32 DWORD error = GetLastError(); diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index d9d5d9da5fb..b931adce5bd 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -15,7 +15,7 @@ /* * calls: * - * File {Close, Read, Write, Size, Sync} + * File {Close, Read, ReadV, Write, WriteV, Size, Sync} * {Path Name Open, Allocate, Free} File * * These are NOT JUST RENAMINGS OF THE UNIX ROUTINES. @@ -43,6 +43,8 @@ #ifndef FD_H #define FD_H +#include "port/pg_iovec.h" + #include <dirent.h> #include <fcntl.h> @@ -105,8 +107,8 @@ extern File PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fil extern File OpenTemporaryFile(bool interXact); extern void FileClose(File file); extern int FilePrefetch(File file, off_t offset, off_t amount, uint32 wait_event_info); -extern int FileRead(File file, void *buffer, size_t amount, off_t offset, uint32 wait_event_info); -extern int FileWrite(File file, const void *buffer, size_t amount, off_t offset, uint32 wait_event_info); +extern int FileReadV(File file, const struct iovec *ioc, int iovcnt, off_t offset, uint32 wait_event_info); +extern int FileWriteV(File file, const struct iovec *ioc, int iovcnt, off_t offset, uint32 wait_event_info); extern int FileSync(File file, uint32 wait_event_info); extern int FileZero(File file, off_t offset, off_t amount, uint32 wait_event_info); extern int FileFallocate(File file, off_t offset, off_t amount, uint32 wait_event_info); @@ -189,4 +191,28 @@ extern int durable_unlink(const char *fname, int elevel); extern void SyncDataDirectory(void); extern int data_sync_elevel(int elevel); +static inline int +FileRead(File file, void *buffer, size_t amount, off_t offset, + uint32 wait_event_info) +{ + struct iovec iov = { + .iov_base = buffer, + .iov_len = amount + }; + + return FileReadV(file, &iov, 1, offset, wait_event_info); +} + +static inline int +FileWrite(File file, const void *buffer, size_t amount, off_t offset, + uint32 wait_event_info) +{ + struct iovec iov = { + .iov_base = unconstify(void *, buffer), + .iov_len = amount + }; + + return FileWriteV(file, &iov, 1, offset, wait_event_info); +} + #endif /* FD_H */ |