From bea87a678f755b9d205dc95802a38ee91c0d067e Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 5 Oct 2017 18:16:34 -0700 Subject: LDPRELOAD: readv writev v2 Move the vector iteration down to vcom_socket Change-Id: I5bb8d0d34a18ea15daf7a385443e046cb64313a1 Signed-off-by: Steven --- vcl-ldpreload/src/libvcl-ldpreload/vcom.c | 94 ++++++---------- vcl-ldpreload/src/libvcl-ldpreload/vcom.h | 4 + vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c | 131 +++++++++++++++++++++++ vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h | 4 + 4 files changed, 173 insertions(+), 60 deletions(-) diff --git a/vcl-ldpreload/src/libvcl-ldpreload/vcom.c b/vcl-ldpreload/src/libvcl-ldpreload/vcom.c index 75054eb..4da2d99 100644 --- a/vcl-ldpreload/src/libvcl-ldpreload/vcom.c +++ b/vcl-ldpreload/src/libvcl-ldpreload/vcom.c @@ -18,10 +18,6 @@ #include #include #include -#include -#include -#define __need_IOV_MAX -#include #include #include @@ -263,42 +259,31 @@ read (int __fd, void *__buf, size_t __nbytes) return libc_read (__fd, __buf, __nbytes); } +ssize_t +vcom_readv (int __fd, const struct iovec * __iov, int __iovcnt) +{ + if (vcom_init () != 0) + { + return -1; + } + + return vcom_socket_readv (__fd, __iov, __iovcnt); +} + ssize_t readv (int __fd, const struct iovec * __iov, int __iovcnt) { - size_t len = 0; - ssize_t total = 0; + ssize_t size = 0; if (is_vcom_socket_fd (__fd)) { - if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX) - return -EINVAL; - - /* Sanity check */ - for (int i = 0; i < __iovcnt; ++i) - { - if (SSIZE_MAX - len < __iov[i].iov_len) - return -EINVAL; - len += __iov[i].iov_len; - } - - for (int i = 0; i < __iovcnt; ++i) + size = vcom_readv (__fd, __iov, __iovcnt); + if (size < 0) { - len = vcom_read (__fd, __iov[i].iov_base, __iov[i].iov_len); - if (len < 0) - { - if (total > 0) - return total; - else - { - errno = len;; - return -1; - } - } - else - total += len; + errno = -size; + return -1; } - return (total); + return size; } else return libc_readv (__fd, __iov, __iovcnt); @@ -351,42 +336,31 @@ write (int __fd, const void *__buf, size_t __n) return libc_write (__fd, __buf, __n); } +ssize_t +vcom_writev (int __fd, const struct iovec * __iov, int __iovcnt) +{ + if (vcom_init () != 0) + { + return -1; + } + + return vcom_socket_writev (__fd, __iov, __iovcnt); +} + ssize_t writev (int __fd, const struct iovec * __iov, int __iovcnt) { - size_t len = 0; - ssize_t total = 0; + ssize_t size = 0; if (is_vcom_socket_fd (__fd)) { - if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX) - return -EINVAL; - - /* Sanity check */ - for (int i = 0; i < __iovcnt; ++i) - { - if (SSIZE_MAX - len < __iov[i].iov_len) - return -EINVAL; - len += __iov[i].iov_len; - } - - for (int i = 0; i < __iovcnt; ++i) + size = vcom_writev (__fd, __iov, __iovcnt); + if (size < 0) { - len = vcom_write (__fd, __iov[i].iov_base, __iov[i].iov_len); - if (len < 0) - { - if (total > 0) - return total; - else - { - errno = len;; - return -1; - } - } - else - total += len; + errno = -size; + return -1; } - return (total); + return size; } else return libc_writev (__fd, __iov, __iovcnt); diff --git a/vcl-ldpreload/src/libvcl-ldpreload/vcom.h b/vcl-ldpreload/src/libvcl-ldpreload/vcom.h index d751fe1..1706c0e 100644 --- a/vcl-ldpreload/src/libvcl-ldpreload/vcom.h +++ b/vcl-ldpreload/src/libvcl-ldpreload/vcom.h @@ -44,6 +44,10 @@ extern ssize_t __wur vcom_read (int __fd, void *__buf, size_t __nbytes); extern ssize_t __wur vcom_write (int __fd, const void *__buf, size_t __n); +extern ssize_t __wur vcom_readv (int __fd, const struct iovec * __iov, int __iovcnt); + +extern ssize_t __wur vcom_writev (int __fd, const struct iovec * __iov, int __iovcnt); + /* * vpp implementation of glibc APIs from */ diff --git a/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c b/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c index ba8a489..0fd2bb1 100644 --- a/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c +++ b/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c @@ -14,6 +14,10 @@ */ #include #include +#include +#include +#define __need_IOV_MAX +#include #include #include @@ -541,6 +545,93 @@ vcom_socket_read (int __fd, void *__buf, size_t __nbytes) return rv; } +ssize_t +vcom_socket_readv (int __fd, const struct iovec * __iov, int __iovcnt) +{ + int rv; + vcom_socket_main_t *vsm = &vcom_socket_main; + uword *p; + vcom_socket_t *vsock; + ssize_t total = 0, len = 0; + + p = hash_get (vsm->sockidx_by_fd, __fd); + if (!p) + return -EBADF; + + vsock = pool_elt_at_index (vsm->vsockets, p[0]); + if (!vsock) + return -ENOTSOCK; + + if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) + return -EINVAL; + + if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX) + return -EINVAL; + + /* Sanity check */ + for (int i = 0; i < __iovcnt; ++i) + { + if (SSIZE_MAX - len < __iov[i].iov_len) + return -EINVAL; + len += __iov[i].iov_len; + } + + rv = vcom_fcntl (__fd, F_GETFL, 0); + if (rv < 0) + { + return rv; + } + + /* is blocking */ + if (!(rv & O_NONBLOCK)) + { + do + { + for (int i = 0; i < __iovcnt; ++i) + { + rv = vppcom_session_read (vsock->sid, __iov[i].iov_base, + __iov[i].iov_len); + if (rv < 0) + break; + else + { + total += rv; + if (rv < __iov[i].iov_len) + /* Read less than buffer provided, no point to continue */ + break; + } + } + } + while ((rv == -EAGAIN || rv == -EWOULDBLOCK) && total == 0); + return total; + } + + /* is non blocking */ + for (int i = 0; i < __iovcnt; ++i) + { + rv = vppcom_session_read (vsock->sid, __iov[i].iov_base, + __iov[i].iov_len); + if (rv < 0) + { + if (total > 0) + break; + else + { + errno = rv; + return rv; + } + } + else + { + total += rv; + if (rv < __iov[i].iov_len) + /* Read less than buffer provided, no point to continue */ + break; + } + } + return total; +} + ssize_t vcom_socket_write (int __fd, const void *__buf, size_t __n) { @@ -569,6 +660,46 @@ vcom_socket_write (int __fd, const void *__buf, size_t __n) return rv; } +ssize_t +vcom_socket_writev (int __fd, const struct iovec * __iov, int __iovcnt) +{ + int rv = -1; + ssize_t total = 0; + vcom_socket_main_t *vsm = &vcom_socket_main; + uword *p; + vcom_socket_t *vsock; + + p = hash_get (vsm->sockidx_by_fd, __fd); + if (!p) + return -EBADF; + + vsock = pool_elt_at_index (vsm->vsockets, p[0]); + if (!vsock) + return -ENOTSOCK; + + if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) + return -EINVAL; + + if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX) + return -EINVAL; + + for (int i = 0; i < __iovcnt; ++i) + { + rv = vppcom_session_write (vsock->sid, __iov[i].iov_base, + __iov[i].iov_len); + if (rv < 0) + { + if (total > 0) + break; + else + return rv; + } + else + total += rv; + } + return total; +} + /* * RETURN: 0 - invalid cmd * 1 - cmd not handled by vcom and vppcom diff --git a/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h b/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h index 903f740..e966895 100644 --- a/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h +++ b/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h @@ -314,8 +314,12 @@ int vcom_socket_close (int __fd); ssize_t vcom_socket_read (int __fd, void *__buf, size_t __nbytes); +ssize_t vcom_socket_readv (int __fd, const struct iovec * __iov, int __iovcnt); + ssize_t vcom_socket_write (int __fd, const void *__buf, size_t __n); +ssize_t vcom_socket_writev (int __fd, const struct iovec * __iov, int __iovcnt); + int vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap); int -- cgit 1.2.3-korg