|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v7 2/6] libs/ctrl: Allow writev_exact() to change the iov array
Avoid having to allocate and copy the array if a partial write happens.
Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
---
Changes since v2:
- change prefix in subject.
Changes since v6:
- use a single loop to skip IOVs;
- add a comment to the function.
---
tools/libs/ctrl/xc_private.c | 65 +++++++++---------------------------
tools/libs/ctrl/xc_private.h | 3 +-
2 files changed, 17 insertions(+), 51 deletions(-)
diff --git a/tools/libs/ctrl/xc_private.c b/tools/libs/ctrl/xc_private.c
index bb0f81d6f3..89ec68a183 100644
--- a/tools/libs/ctrl/xc_private.c
+++ b/tools/libs/ctrl/xc_private.c
@@ -635,7 +635,7 @@ int write_exact(int fd, const void *data, size_t size)
/*
* MiniOS's libc doesn't know about writev(). Implement it as multiple
write()s.
*/
-int writev_exact(int fd, const struct iovec *iov, int iovcnt)
+int writev_exact(int fd, struct iovec *iov, int iovcnt)
{
int rc, i;
@@ -649,70 +649,35 @@ int writev_exact(int fd, const struct iovec *iov, int
iovcnt)
return 0;
}
#else
-int writev_exact(int fd, const struct iovec *iov, int iovcnt)
+int writev_exact(int fd, struct iovec *iov, int iovcnt)
{
- struct iovec *local_iov = NULL;
- int rc = 0, iov_idx = 0, saved_errno = 0;
- ssize_t len;
+ int rc = 0, iov_idx = 0;
+ ssize_t len = 0;
while ( iov_idx < iovcnt )
{
- /*
- * Skip over iov[] entries with 0 length.
- *
- * This is needed to cover the case where we took a partial write and
- * all remaining vectors are of 0 length. In such a case, the results
- * from writev() are indistinguishable from EOF.
- */
- while ( iov[iov_idx].iov_len == 0 )
- if ( ++iov_idx == iovcnt )
- goto out;
+ /* Check iov[] to see whether we had a partial or complete write. */
+ if ( len >= iov[iov_idx].iov_len )
+ {
+ len -= iov[iov_idx++].iov_len;
+ continue;
+ }
+
+ /* Partial write of iov[iov_idx]. */
+ iov[iov_idx].iov_base += len;
+ iov[iov_idx].iov_len -= len;
len = writev(fd, &iov[iov_idx], min(iovcnt - iov_idx, IOV_MAX));
- saved_errno = errno;
if ( (len == -1) && (errno == EINTR) )
continue;
if ( len <= 0 )
{
rc = -1;
- goto out;
- }
-
- /* Check iov[] to see whether we had a partial or complete write. */
- while ( (len > 0) && (iov_idx < iovcnt) )
- {
- if ( len >= iov[iov_idx].iov_len )
- len -= iov[iov_idx++].iov_len;
- else
- {
- /* Partial write of iov[iov_idx]. Copy iov so we can adjust
- * element iov_idx and resubmit the rest. */
- if ( !local_iov )
- {
- local_iov = malloc(iovcnt * sizeof(*iov));
- if ( !local_iov )
- {
- saved_errno = ENOMEM;
- rc = -1;
- goto out;
- }
-
- iov = memcpy(local_iov, iov, iovcnt * sizeof(*iov));
- }
-
- local_iov[iov_idx].iov_base += len;
- local_iov[iov_idx].iov_len -= len;
- break;
- }
+ break;
}
}
- saved_errno = 0;
-
- out:
- free(local_iov);
- errno = saved_errno;
return rc;
}
#endif
diff --git a/tools/libs/ctrl/xc_private.h b/tools/libs/ctrl/xc_private.h
index b5892ae8dc..8a325c17b0 100644
--- a/tools/libs/ctrl/xc_private.h
+++ b/tools/libs/ctrl/xc_private.h
@@ -383,7 +383,8 @@ int xc_flush_mmu_updates(xc_interface *xch, struct xc_mmu
*mmu);
/* Return 0 on success; -1 on error setting errno. */
int read_exact(int fd, void *data, size_t size); /* EOF => -1, errno=0 */
int write_exact(int fd, const void *data, size_t size);
-int writev_exact(int fd, const struct iovec *iov, int iovcnt);
+/* May alter @iov to cope with partial writes. */
+int writev_exact(int fd, struct iovec *iov, int iovcnt);
int xc_ffs8(uint8_t x);
int xc_ffs16(uint16_t x);
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |