util/iov: Introduce iov_send_recv_with_flags()
In order to support a new update function, a flag needs to be passed to the kernel via the socket send call (MSG_MORE) to notify it that more data is to be expected to calculate the hash correctly. Add a new iov helper for this purpose. Signed-off-by: Alejandro Zeise <alejandro.zeise@seagate.com> [ clg: - Split iov changes from original patch - Checkpatch fixes ] Signed-off-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
278d596015
commit
78a5822820
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Helpers for using (partial) iovecs.
|
||||
*
|
||||
* Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* Author(s):
|
||||
@ -75,6 +76,32 @@ iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
|
||||
size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt,
|
||||
size_t offset, int fillc, size_t bytes);
|
||||
|
||||
/*
|
||||
* Send/recv data from/to iovec buffers directly, with the provided
|
||||
* socket flags.
|
||||
*
|
||||
* `offset' bytes in the beginning of iovec buffer are skipped and
|
||||
* next `bytes' bytes are used, which must be within data of iovec.
|
||||
*
|
||||
* r = iov_send_recv_with_flags(sockfd, sockflags, iov, iovcnt,
|
||||
* offset, bytes, true);
|
||||
*
|
||||
* is logically equivalent to
|
||||
*
|
||||
* char *buf = malloc(bytes);
|
||||
* iov_to_buf(iov, iovcnt, offset, buf, bytes);
|
||||
* r = send(sockfd, buf, bytes, sockflags);
|
||||
* free(buf);
|
||||
*
|
||||
* For iov_send_recv_with_flags() _whole_ area being sent or received
|
||||
* should be within the iovec, not only beginning of it.
|
||||
*/
|
||||
ssize_t iov_send_recv_with_flags(int sockfd, int sockflags,
|
||||
const struct iovec *iov,
|
||||
unsigned iov_cnt, size_t offset,
|
||||
size_t bytes,
|
||||
bool do_send);
|
||||
|
||||
/*
|
||||
* Send/recv data from/to iovec buffers directly
|
||||
*
|
||||
|
25
util/iov.c
25
util/iov.c
@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright IBM, Corp. 2007, 2008
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
* Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
|
||||
*
|
||||
* Author(s):
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
@ -92,7 +93,8 @@ size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt)
|
||||
|
||||
/* helper function for iov_send_recv() */
|
||||
static ssize_t
|
||||
do_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, bool do_send)
|
||||
do_send_recv(int sockfd, int flags, struct iovec *iov, unsigned iov_cnt,
|
||||
bool do_send)
|
||||
{
|
||||
#ifdef CONFIG_POSIX
|
||||
ssize_t ret;
|
||||
@ -102,8 +104,8 @@ do_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, bool do_send)
|
||||
msg.msg_iovlen = iov_cnt;
|
||||
do {
|
||||
ret = do_send
|
||||
? sendmsg(sockfd, &msg, 0)
|
||||
: recvmsg(sockfd, &msg, 0);
|
||||
? sendmsg(sockfd, &msg, flags)
|
||||
: recvmsg(sockfd, &msg, flags);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
return ret;
|
||||
#else
|
||||
@ -114,8 +116,8 @@ do_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, bool do_send)
|
||||
ssize_t off = 0;
|
||||
while (i < iov_cnt) {
|
||||
ssize_t r = do_send
|
||||
? send(sockfd, iov[i].iov_base + off, iov[i].iov_len - off, 0)
|
||||
: recv(sockfd, iov[i].iov_base + off, iov[i].iov_len - off, 0);
|
||||
? send(sockfd, iov[i].iov_base + off, iov[i].iov_len - off, flags)
|
||||
: recv(sockfd, iov[i].iov_base + off, iov[i].iov_len - off, flags);
|
||||
if (r > 0) {
|
||||
ret += r;
|
||||
off += r;
|
||||
@ -144,6 +146,15 @@ do_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, bool do_send)
|
||||
ssize_t iov_send_recv(int sockfd, const struct iovec *_iov, unsigned iov_cnt,
|
||||
size_t offset, size_t bytes,
|
||||
bool do_send)
|
||||
{
|
||||
return iov_send_recv_with_flags(sockfd, 0, _iov, iov_cnt, offset, bytes,
|
||||
do_send);
|
||||
}
|
||||
|
||||
ssize_t iov_send_recv_with_flags(int sockfd, int sockflags,
|
||||
const struct iovec *_iov,
|
||||
unsigned iov_cnt, size_t offset,
|
||||
size_t bytes, bool do_send)
|
||||
{
|
||||
ssize_t total = 0;
|
||||
ssize_t ret;
|
||||
@ -192,11 +203,11 @@ ssize_t iov_send_recv(int sockfd, const struct iovec *_iov, unsigned iov_cnt,
|
||||
assert(iov[niov].iov_len > tail);
|
||||
orig_len = iov[niov].iov_len;
|
||||
iov[niov++].iov_len = tail;
|
||||
ret = do_send_recv(sockfd, iov, niov, do_send);
|
||||
ret = do_send_recv(sockfd, sockflags, iov, niov, do_send);
|
||||
/* Undo the changes above before checking for errors */
|
||||
iov[niov-1].iov_len = orig_len;
|
||||
} else {
|
||||
ret = do_send_recv(sockfd, iov, niov, do_send);
|
||||
ret = do_send_recv(sockfd, sockflags, iov, niov, do_send);
|
||||
}
|
||||
if (offset) {
|
||||
iov[0].iov_base -= offset;
|
||||
|
Loading…
Reference in New Issue
Block a user