}
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)
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)
}
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)
*/
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)
{
}
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)
{
else
{
/*
- * See comments in FileRead()
+ * See comments in FileReadV()
*/
#ifdef WIN32
DWORD error = GetLastError();
/*
* 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.
#ifndef FD_H
#define FD_H
+#include "port/pg_iovec.h"
+
#include <dirent.h>
#include <fcntl.h>
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);
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 */