From 5750b7e3f971e02e1d5c676484eb10c779c6ac13 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Fri, 2 Jun 2017 18:31:16 -0700
Subject: [PATCH] Use LO_HI_LONG_FLAGS for p{readv,writev}{64}v2
The kernel interface for p{readv,writev}{64}v is
(unsigned long fd, {const }struct iovec *iov, unsigned long vlen,
unsigned long pos_l, unsigned long pos_h)
The LO_HI_LONG macro is used to pass offset to the pos_l and pos_h pair.
Since pos_h is ignored when size of offset == sizeof of pos_l, x86-64
has
#define LO_HI_LONG(val) (val)
But the kernel interface for p{readv,writev}{64}v2 is
(unsigned long fd, {const }struct iovec *iov, unsigned long vlen,
unsigned long pos_l, unsigned long pos_h, int flags)
Except for targets which define __ARCH_WANT_COMPAT_SYS_PREADV64V2 and
__ARCH_WANT_COMPAT_SYS_PWRITEV64V2,
(unsigned long fd, {const }struct iovec *iov, unsigned long vlen,
unsigned long pos, int flags)
will be used for p{readv,writev}{64}v2. X32 is the only such target.
The x86-64 LO_HI_LONG can't be used for p{readv,writev}{64}v2. Add a
new macro, LO_HI_LONG_FLAGS, to pass the off{64}_t and flags arguments.
Tested on i686, x32 and x86-64.
* sysdeps/unix/sysv/linux/preadv2.c (preadv2): Replace LO_HI_LONG
with LO_HI_LONG_FLAGS.
* sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise.
* sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise.
* sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise.
* sysdeps/unix/sysv/linux/sysdep.h (LO_HI_LONG_FLAGS): New.
* sysdeps/unix/sysv/linux/x86_64/sysdep.h (LO_HI_LONG_FLAGS):
Likewise.
* sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h (LO_HI_LONG_FLAGS):
Likewise.
---
sysdeps/unix/sysv/linux/preadv2.c | 2 +-
sysdeps/unix/sysv/linux/preadv64v2.c | 2 +-
sysdeps/unix/sysv/linux/pwritev2.c | 2 +-
sysdeps/unix/sysv/linux/pwritev64v2.c | 2 +-
sysdeps/unix/sysv/linux/sysdep.h | 7 +++++++
sysdeps/unix/sysv/linux/x86_64/sysdep.h | 5 +++++
sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h | 5 +++++
7 files changed, 21 insertions(+), 4 deletions(-)
@@ -31,7 +31,7 @@ preadv2 (int fd, const struct iovec *vector, int count, off_t offset,
{
# ifdef __NR_preadv2
ssize_t result = SYSCALL_CANCEL (preadv2, fd, vector, count,
- LO_HI_LONG (offset), flags);
+ LO_HI_LONG_FLAGS (offset, flags));
if (result >= 0 || errno != ENOSYS)
return result;
# endif
@@ -29,7 +29,7 @@ preadv64v2 (int fd, const struct iovec *vector, int count, off64_t offset,
{
#ifdef __NR_preadv64v2
ssize_t result = SYSCALL_CANCEL (preadv64v2, fd, vector, count,
- LO_HI_LONG (offset), flags);
+ LO_HI_LONG_FLAGS (offset, flags));
if (result >= 0 || errno != ENOSYS)
return result;
#endif
@@ -27,7 +27,7 @@ pwritev2 (int fd, const struct iovec *vector, int count, off_t offset,
{
# ifdef __NR_pwritev2
ssize_t result = SYSCALL_CANCEL (pwritev2, fd, vector, count,
- LO_HI_LONG (offset), flags);
+ LO_HI_LONG_FLAGS (offset, flags));
if (result >= 0 || errno != ENOSYS)
return result;
# endif
@@ -29,7 +29,7 @@ pwritev64v2 (int fd, const struct iovec *vector, int count, off64_t offset,
{
#ifdef __NR_pwritev64v2
ssize_t result = SYSCALL_CANCEL (pwritev64v2, fd, vector, count,
- LO_HI_LONG (offset), flags);
+ LO_HI_LONG_FLAGS (offset, flags));
if (result >= 0 || errno != ENOSYS)
return result;
#endif
@@ -63,6 +63,13 @@
(long) (val), \
(long) (((uint64_t) (val)) >> 32)
+/* Provide a macro to pass the off{64}_t and flags arguments on
+ p{readv,writev}{64}v2. */
+#define LO_HI_LONG_FLAGS(val, flags) \
+ (long) (val), \
+ (long) (((uint64_t) (val)) >> 32), \
+ (int) (flags)
+
/* Exports the __send symbol on send.c linux implementation (some ABI have
it missing due the usage of a old generic version without it). */
#define HAVE_INTERNAL_SEND_SYMBOL 1
@@ -389,4 +389,9 @@
#undef LO_HI_LONG
#define LO_HI_LONG(val) (val)
+/* Provide a macro to pass the off{64}_t and flags arguments on
+ p{readv,writev}{64}v2. */
+#undef LO_HI_LONG_FLAGS
+#define LO_HI_LONG_FLAGS(val, flags) (val), 0, (flags)
+
#endif /* linux/x86_64/sysdep.h */
@@ -22,4 +22,9 @@
#include <sysdeps/unix/sysv/linux/x86_64/sysdep.h>
#include <sysdeps/x86_64/x32/sysdep.h>
+/* Provide a macro to pass the off{64}_t and flags arguments on
+ p{readv,writev}{64}v2. */
+#undef LO_HI_LONG_FLAGS
+#define LO_HI_LONG_FLAGS(val, flags) (val), (flags)
+
#endif /* linux/x86_64/x32/sysdep.h */
--
2.9.4