Signed-off-by: Nick Thomas <n...@bytemark.co.uk> --- nbd.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ nbd.h | 2 ++ 2 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/nbd.c b/nbd.c index abe0ecb..83d3342 100644 --- a/nbd.c +++ b/nbd.c @@ -107,6 +107,57 @@ size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) return offset; } +int nbd_wr_aio(int sockfd, struct iovec *iov, size_t len, off_t offset, + bool do_read) +{ + struct msghdr msg; + int ret, diff; + + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + len += offset; + + while (iov->iov_len < len) { + len -= iov->iov_len; + + iov++; + msg.msg_iovlen++; + } + + diff = iov->iov_len - len; + iov->iov_len -= diff; + + while (msg.msg_iov->iov_len <= offset) { + offset -= msg.msg_iov->iov_len; + + msg.msg_iov++; + msg.msg_iovlen--; + } + + msg.msg_iov->iov_base = (char *) msg.msg_iov->iov_base + offset; + msg.msg_iov->iov_len -= offset; + +retry: + if (do_read) { + ret = recvmsg(sockfd, &msg, 0); + } else { + ret = sendmsg(sockfd, &msg, 0); + } + + /* recoverable error */ + if (ret == -1 && (errno == EAGAIN || errno == EINTR)) { + goto retry; + } + + msg.msg_iov->iov_base = (char *) msg.msg_iov->iov_base - offset; + msg.msg_iov->iov_len += offset; + + iov->iov_len += diff; + return ret; +} + int tcp_socket_outgoing(const char *address, uint16_t port) { int s; diff --git a/nbd.h b/nbd.h index fc3a594..872218c 100644 --- a/nbd.h +++ b/nbd.h @@ -45,6 +45,8 @@ enum { #define NBD_DEFAULT_PORT 10809 size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read); +int nbd_wr_aio(int sockfd, struct iovec *iov, size_t len, off_t offset, + bool do_read); int tcp_socket_outgoing(const char *address, uint16_t port); int tcp_socket_incoming(const char *address, uint16_t port); int unix_socket_outgoing(const char *path); -- 1.7.0.4