Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 13a021f

Browse files
committed
Provide pg_preadv() and pg_pwritev().
Provide synchronous vectored file I/O routines. These map to preadv() and pwritev(), with fallback implementations for systems that don't have them. Also provide a wrapper pg_pwritev_with_retry() that automatically retries on short writes. Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/CA%2BhUKGJA%2Bu-220VONeoREBXJ9P3S94Y7J%2BkqCnTYmahvZJwM%3Dg%40mail.gmail.com
1 parent 01334c9 commit 13a021f

File tree

9 files changed

+238
-34
lines changed

9 files changed

+238
-34
lines changed

configure

+2-28
Original file line numberDiff line numberDiff line change
@@ -13061,7 +13061,7 @@ $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
1306113061
fi
1306213062

1306313063

13064-
for ac_header in atomic.h copyfile.h execinfo.h getopt.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/event.h sys/ipc.h sys/prctl.h sys/procctl.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h wctype.h
13064+
for ac_header in atomic.h copyfile.h execinfo.h getopt.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/event.h sys/ipc.h sys/prctl.h sys/procctl.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/uio.h sys/un.h termios.h ucred.h wctype.h
1306513065
do :
1306613066
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
1306713067
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -15155,7 +15155,7 @@ fi
1515515155
LIBS_including_readline="$LIBS"
1515615156
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
1515715157

15158-
for ac_func in backtrace_symbols clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit kqueue mbstowcs_l memset_s poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink setproctitle setproctitle_fast setsid shm_open strchrnul strsignal symlink sync_file_range uselocale wcstombs_l
15158+
for ac_func in backtrace_symbols clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit kqueue mbstowcs_l memset_s poll posix_fallocate ppoll pread preadv pstat pthread_is_threaded_np pwrite pwritev readlink readv setproctitle setproctitle_fast setsid shm_open strchrnul strsignal symlink sync_file_range uselocale wcstombs_l writev
1515915159
do :
1516015160
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
1516115161
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -15832,32 +15832,6 @@ esac
1583215832

1583315833
fi
1583415834

15835-
ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread"
15836-
if test "x$ac_cv_func_pread" = xyes; then :
15837-
$as_echo "#define HAVE_PREAD 1" >>confdefs.h
15838-
15839-
else
15840-
case " $LIBOBJS " in
15841-
*" pread.$ac_objext "* ) ;;
15842-
*) LIBOBJS="$LIBOBJS pread.$ac_objext"
15843-
;;
15844-
esac
15845-
15846-
fi
15847-
15848-
ac_fn_c_check_func "$LINENO" "pwrite" "ac_cv_func_pwrite"
15849-
if test "x$ac_cv_func_pwrite" = xyes; then :
15850-
$as_echo "#define HAVE_PWRITE 1" >>confdefs.h
15851-
15852-
else
15853-
case " $LIBOBJS " in
15854-
*" pwrite.$ac_objext "* ) ;;
15855-
*) LIBOBJS="$LIBOBJS pwrite.$ac_objext"
15856-
;;
15857-
esac
15858-
15859-
fi
15860-
1586115835
ac_fn_c_check_func "$LINENO" "random" "ac_cv_func_random"
1586215836
if test "x$ac_cv_func_random" = xyes; then :
1586315837
$as_echo "#define HAVE_RANDOM 1" >>confdefs.h

configure.ac

+7-2
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,7 @@ AC_CHECK_HEADERS(m4_normalize([
13311331
sys/shm.h
13321332
sys/sockio.h
13331333
sys/tas.h
1334+
sys/uio.h
13341335
sys/un.h
13351336
termios.h
13361337
ucred.h
@@ -1660,9 +1661,14 @@ AC_CHECK_FUNCS(m4_normalize([
16601661
poll
16611662
posix_fallocate
16621663
ppoll
1664+
pread
1665+
preadv
16631666
pstat
16641667
pthread_is_threaded_np
1668+
pwrite
1669+
pwritev
16651670
readlink
1671+
readv
16661672
setproctitle
16671673
setproctitle_fast
16681674
setsid
@@ -1673,6 +1679,7 @@ AC_CHECK_FUNCS(m4_normalize([
16731679
sync_file_range
16741680
uselocale
16751681
wcstombs_l
1682+
writev
16761683
]))
16771684

16781685
# These typically are compiler builtins, for which AC_CHECK_FUNCS fails.
@@ -1733,8 +1740,6 @@ AC_REPLACE_FUNCS(m4_normalize([
17331740
inet_aton
17341741
link
17351742
mkdtemp
1736-
pread
1737-
pwrite
17381743
random
17391744
srandom
17401745
strlcat

src/include/pg_config.h.in

+15
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,9 @@
412412
/* Define to 1 if you have the `pread' function. */
413413
#undef HAVE_PREAD
414414

415+
/* Define to 1 if you have the `preadv' function. */
416+
#undef HAVE_PREADV
417+
415418
/* Define to 1 if you have the `pstat' function. */
416419
#undef HAVE_PSTAT
417420

@@ -430,6 +433,9 @@
430433
/* Define to 1 if you have the `pwrite' function. */
431434
#undef HAVE_PWRITE
432435

436+
/* Define to 1 if you have the `pwritev' function. */
437+
#undef HAVE_PWRITEV
438+
433439
/* Define to 1 if you have the `random' function. */
434440
#undef HAVE_RANDOM
435441

@@ -445,6 +451,9 @@
445451
/* Define to 1 if you have the `readlink' function. */
446452
#undef HAVE_READLINK
447453

454+
/* Define to 1 if you have the `readv' function. */
455+
#undef HAVE_READV
456+
448457
/* Define to 1 if you have the global variable
449458
'rl_completion_append_character'. */
450459
#undef HAVE_RL_COMPLETION_APPEND_CHARACTER
@@ -629,6 +638,9 @@
629638
/* Define to 1 if you have the <sys/ucred.h> header file. */
630639
#undef HAVE_SYS_UCRED_H
631640

641+
/* Define to 1 if you have the <sys/uio.h> header file. */
642+
#undef HAVE_SYS_UIO_H
643+
632644
/* Define to 1 if you have the <sys/un.h> header file. */
633645
#undef HAVE_SYS_UN_H
634646

@@ -683,6 +695,9 @@
683695
/* Define to 1 if you have the <winldap.h> header file. */
684696
#undef HAVE_WINLDAP_H
685697

698+
/* Define to 1 if you have the `writev' function. */
699+
#undef HAVE_WRITEV
700+
686701
/* Define to 1 if you have the `X509_get_signature_nid' function. */
687702
#undef HAVE_X509_GET_SIGNATURE_NID
688703

src/include/port.h

+2
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,8 @@ extern ssize_t pg_pread(int fd, void *buf, size_t nbyte, off_t offset);
431431
extern ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset);
432432
#endif
433433

434+
/* For pg_pwritev() and pg_preadv(), see port/pg_iovec.h. */
435+
434436
#if !HAVE_DECL_STRLCAT
435437
extern size_t strlcat(char *dst, const char *src, size_t siz);
436438
#endif

src/include/port/pg_iovec.h

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* pg_iovec.h
4+
* Header for the vectored I/O functions in src/port/p{read,write}.c.
5+
*
6+
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* src/include/port/pg_iovec.h
10+
*
11+
*-------------------------------------------------------------------------
12+
*/
13+
#ifndef PG_IOVEC_H
14+
#define PG_IOVEC_H
15+
16+
#include <limits.h>
17+
18+
#ifdef HAVE_SYS_UIO_H
19+
#include <sys/uio.h>
20+
#endif
21+
22+
/* If <sys/uio.h> is missing, define our own POSIX-compatible iovec struct. */
23+
#ifndef HAVE_SYS_UIO_H
24+
struct iovec
25+
{
26+
void *iov_base;
27+
size_t iov_len;
28+
};
29+
#endif
30+
31+
/*
32+
* If <limits.h> didn't define IOV_MAX, define our own. POSIX requires at
33+
* least 16.
34+
*/
35+
#ifndef IOV_MAX
36+
#define IOV_MAX 16
37+
#endif
38+
39+
/* Define a reasonable maximum that is safe to use on the stack. */
40+
#define PG_IOV_MAX Min(IOV_MAX, 32)
41+
42+
#ifdef HAVE_PREADV
43+
#define pg_preadv preadv
44+
#else
45+
extern ssize_t pg_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
46+
#endif
47+
48+
#ifdef HAVE_PWRITEV
49+
#define pg_pwritev pwritev
50+
#else
51+
extern ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
52+
#endif
53+
54+
extern ssize_t pg_pwritev_with_retry(int fd,
55+
const struct iovec *iov,
56+
int iovcnt,
57+
off_t offset);
58+
59+
#endif /* PG_IOVEC_H */

src/port/Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ OBJS = \
5353
pgstrcasecmp.o \
5454
pgstrsignal.o \
5555
pqsignal.o \
56+
pread.o \
57+
pwrite.o \
5658
qsort.o \
5759
qsort_arg.o \
5860
quotes.o \

src/port/pread.c

+41-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
/*-------------------------------------------------------------------------
22
*
33
* pread.c
4-
* Implementation of pread(2) for platforms that lack one.
4+
* Implementation of pread[v](2) for platforms that lack one.
55
*
66
* Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
77
*
88
* IDENTIFICATION
99
* src/port/pread.c
1010
*
1111
* Note that this implementation changes the current file position, unlike
12-
* the POSIX function, so we use the name pg_pread().
12+
* the POSIX function, so we use the name pg_pread(). Likewise for the
13+
* iovec version.
1314
*
1415
*-------------------------------------------------------------------------
1516
*/
@@ -23,6 +24,9 @@
2324
#include <unistd.h>
2425
#endif
2526

27+
#include "port/pg_iovec.h"
28+
29+
#ifndef HAVE_PREAD
2630
ssize_t
2731
pg_pread(int fd, void *buf, size_t size, off_t offset)
2832
{
@@ -56,3 +60,38 @@ pg_pread(int fd, void *buf, size_t size, off_t offset)
5660
return read(fd, buf, size);
5761
#endif
5862
}
63+
#endif
64+
65+
#ifndef HAVE_PREADV
66+
ssize_t
67+
pg_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
68+
{
69+
#ifdef HAVE_READV
70+
if (iovcnt == 1)
71+
return pg_pread(fd, iov[0].iov_base, iov[0].iov_len, offset);
72+
if (lseek(fd, offset, SEEK_SET) < 0)
73+
return -1;
74+
return readv(fd, iov, iovcnt);
75+
#else
76+
ssize_t sum = 0;
77+
ssize_t part;
78+
79+
for (int i = 0; i < iovcnt; ++i)
80+
{
81+
part = pg_pread(fd, iov[i].iov_base, iov[i].iov_len, offset);
82+
if (part < 0)
83+
{
84+
if (i == 0)
85+
return -1;
86+
else
87+
return sum;
88+
}
89+
sum += part;
90+
offset += part;
91+
if (part < iov[i].iov_len)
92+
return sum;
93+
}
94+
return sum;
95+
#endif
96+
}
97+
#endif

0 commit comments

Comments
 (0)