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.
|
* Helpers for using (partial) iovecs.
|
||||||
*
|
*
|
||||||
|
* Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
|
||||||
* Copyright (C) 2010 Red Hat, Inc.
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* Author(s):
|
* 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 iov_memset(const struct iovec *iov, const unsigned int iov_cnt,
|
||||||
size_t offset, int fillc, size_t bytes);
|
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
|
* 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 IBM, Corp. 2007, 2008
|
||||||
* Copyright (C) 2010 Red Hat, Inc.
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
|
* Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
|
||||||
*
|
*
|
||||||
* Author(s):
|
* Author(s):
|
||||||
* Anthony Liguori <aliguori@us.ibm.com>
|
* 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() */
|
/* helper function for iov_send_recv() */
|
||||||
static ssize_t
|
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
|
#ifdef CONFIG_POSIX
|
||||||
ssize_t ret;
|
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;
|
msg.msg_iovlen = iov_cnt;
|
||||||
do {
|
do {
|
||||||
ret = do_send
|
ret = do_send
|
||||||
? sendmsg(sockfd, &msg, 0)
|
? sendmsg(sockfd, &msg, flags)
|
||||||
: recvmsg(sockfd, &msg, 0);
|
: recvmsg(sockfd, &msg, flags);
|
||||||
} while (ret < 0 && errno == EINTR);
|
} while (ret < 0 && errno == EINTR);
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
#else
|
||||||
@ -114,8 +116,8 @@ do_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, bool do_send)
|
|||||||
ssize_t off = 0;
|
ssize_t off = 0;
|
||||||
while (i < iov_cnt) {
|
while (i < iov_cnt) {
|
||||||
ssize_t r = do_send
|
ssize_t r = do_send
|
||||||
? send(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, 0);
|
: recv(sockfd, iov[i].iov_base + off, iov[i].iov_len - off, flags);
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
ret += r;
|
ret += r;
|
||||||
off += 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,
|
ssize_t iov_send_recv(int sockfd, const struct iovec *_iov, unsigned iov_cnt,
|
||||||
size_t offset, size_t bytes,
|
size_t offset, size_t bytes,
|
||||||
bool do_send)
|
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 total = 0;
|
||||||
ssize_t ret;
|
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);
|
assert(iov[niov].iov_len > tail);
|
||||||
orig_len = iov[niov].iov_len;
|
orig_len = iov[niov].iov_len;
|
||||||
iov[niov++].iov_len = tail;
|
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 */
|
/* Undo the changes above before checking for errors */
|
||||||
iov[niov-1].iov_len = orig_len;
|
iov[niov-1].iov_len = orig_len;
|
||||||
} else {
|
} else {
|
||||||
ret = do_send_recv(sockfd, iov, niov, do_send);
|
ret = do_send_recv(sockfd, sockflags, iov, niov, do_send);
|
||||||
}
|
}
|
||||||
if (offset) {
|
if (offset) {
|
||||||
iov[0].iov_base -= offset;
|
iov[0].iov_base -= offset;
|
||||||
|
Loading…
Reference in New Issue
Block a user