11befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner/* 21befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Helpers for getting linearized buffers from iov / filling buffers into iovs 31befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * 41befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Copyright IBM, Corp. 2007, 2008 51befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Copyright (C) 2010 Red Hat, Inc. 61befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * 71befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Author(s): 81befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Anthony Liguori <aliguori@us.ibm.com> 91befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Amit Shah <amit.shah@redhat.com> 101befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Michael Tokarev <mjt@tls.msk.ru> 111befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * 121befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * This work is licensed under the terms of the GNU GPL, version 2. See 131befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * the COPYING file in the top-level directory. 141befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * 151befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Contributions after 2012-01-13 are licensed under the terms of the 161befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * GNU GPL, version 2 or (at your option) any later version. 171befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner */ 181befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 191befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner#include "qemu/iov.h" 201befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 211befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner#ifdef _WIN32 221befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner# include <windows.h> 231befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner# include <winsock2.h> 241befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner#else 251befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner# include <sys/types.h> 261befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner# include <sys/socket.h> 271befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner#endif 281befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 291befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnersize_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, 301befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t offset, const void *buf, size_t bytes) 311befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 321befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t done; 331befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner unsigned int i; 341befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) { 351befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (offset < iov[i].iov_len) { 361befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t len = MIN(iov[i].iov_len - offset, bytes - done); 371befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner memcpy(iov[i].iov_base + offset, buf + done, len); 381befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner done += len; 391befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner offset = 0; 401befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } else { 411befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner offset -= iov[i].iov_len; 421befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 431befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 441befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(offset == 0); 451befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return done; 461befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 471befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 481befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnersize_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, 491befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t offset, void *buf, size_t bytes) 501befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 511befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t done; 521befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner unsigned int i; 531befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) { 541befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (offset < iov[i].iov_len) { 551befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t len = MIN(iov[i].iov_len - offset, bytes - done); 561befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner memcpy(buf + done, iov[i].iov_base + offset, len); 571befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner done += len; 581befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner offset = 0; 591befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } else { 601befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner offset -= iov[i].iov_len; 611befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 621befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 631befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(offset == 0); 641befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return done; 651befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 661befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 671befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnersize_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt, 681befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t offset, int fillc, size_t bytes) 691befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 701befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t done; 711befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner unsigned int i; 721befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) { 731befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (offset < iov[i].iov_len) { 741befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t len = MIN(iov[i].iov_len - offset, bytes - done); 751befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner memset(iov[i].iov_base + offset, fillc, len); 761befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner done += len; 771befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner offset = 0; 781befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } else { 791befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner offset -= iov[i].iov_len; 801befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 811befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 821befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(offset == 0); 831befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return done; 841befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 851befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 861befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnersize_t iov_size(const struct iovec *iov, const unsigned int iov_cnt) 871befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 881befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t len; 891befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner unsigned int i; 901befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 911befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner len = 0; 921befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (i = 0; i < iov_cnt; i++) { 931befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner len += iov[i].iov_len; 941befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 951befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return len; 961befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 971befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 981befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner/* helper function for iov_send_recv() */ 991befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnerstatic ssize_t 1001befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnerdo_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, bool do_send) 1011befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 1021befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner#ifdef CONFIG_POSIX 1031befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ssize_t ret; 1041befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner struct msghdr msg; 1051befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner memset(&msg, 0, sizeof(msg)); 1061befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner msg.msg_iov = iov; 1071befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner msg.msg_iovlen = iov_cnt; 1081befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner do { 1091befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ret = do_send 1101befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ? sendmsg(sockfd, &msg, 0) 1111befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner : recvmsg(sockfd, &msg, 0); 1121befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } while (ret < 0 && errno == EINTR); 1131befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return ret; 1141befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner#else 1151befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* else send piece-by-piece */ 1161befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /*XXX Note: windows has WSASend() and WSARecv() */ 1171befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner unsigned i = 0; 1181befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ssize_t ret = 0; 1191befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner while (i < iov_cnt) { 1201befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ssize_t r = do_send 1211befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ? send(sockfd, iov[i].iov_base, iov[i].iov_len, 0) 1221befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner : recv(sockfd, iov[i].iov_base, iov[i].iov_len, 0); 1231befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (r > 0) { 1241befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ret += r; 1251befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } else if (!r) { 1261befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner break; 1271befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } else if (errno == EINTR) { 1281befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner continue; 1291befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } else { 1301befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* else it is some "other" error, 1311befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * only return if there was no data processed. */ 1321befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (ret == 0) { 1331befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ret = -1; 1341befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 1351befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner break; 1361befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 1371befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner i++; 1381befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 1391befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return ret; 1401befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner#endif 1411befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 1421befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 1431befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnerssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, 1441befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t offset, size_t bytes, 1451befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner bool do_send) 1461befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 1471befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ssize_t total = 0; 1481befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ssize_t ret; 1491befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t orig_len, tail; 1501befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner unsigned niov; 1511befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 1521befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner while (bytes > 0) { 1531befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* Find the start position, skipping `offset' bytes: 1541befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * first, skip all full-sized vector elements, */ 1551befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (niov = 0; niov < iov_cnt && offset >= iov[niov].iov_len; ++niov) { 1561befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner offset -= iov[niov].iov_len; 1571befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 1581befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 1591befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* niov == iov_cnt would only be valid if bytes == 0, which 1601befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * we already ruled out in the loop condition. */ 1611befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(niov < iov_cnt); 1621befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner iov += niov; 1631befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner iov_cnt -= niov; 1641befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 1651befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (offset) { 1661befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* second, skip `offset' bytes from the (now) first element, 1671befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * undo it on exit */ 1681befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner iov[0].iov_base += offset; 1691befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner iov[0].iov_len -= offset; 1701befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 1711befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* Find the end position skipping `bytes' bytes: */ 1721befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* first, skip all full-sized elements */ 1731befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner tail = bytes; 1741befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (niov = 0; niov < iov_cnt && iov[niov].iov_len <= tail; ++niov) { 1751befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner tail -= iov[niov].iov_len; 1761befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 1771befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (tail) { 1781befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* second, fixup the last element, and remember the original 1791befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * length */ 1801befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(niov < iov_cnt); 1811befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(iov[niov].iov_len > tail); 1821befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner orig_len = iov[niov].iov_len; 1831befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner iov[niov++].iov_len = tail; 1841befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ret = do_send_recv(sockfd, iov, niov, do_send); 1851befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* Undo the changes above before checking for errors */ 1861befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner iov[niov-1].iov_len = orig_len; 1871befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } else { 1881befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ret = do_send_recv(sockfd, iov, niov, do_send); 1891befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 1901befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (offset) { 1911befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner iov[0].iov_base -= offset; 1921befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner iov[0].iov_len += offset; 1931befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 1941befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 1951befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (ret < 0) { 1961befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(errno != EINTR); 1971befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (errno == EAGAIN && total > 0) { 1981befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return total; 1991befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 2001befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return -1; 2011befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 2021befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2031befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (ret == 0 && !do_send) { 2041befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* recv returns 0 when the peer has performed an orderly 2051befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * shutdown. */ 2061befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner break; 2071befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 2081befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2091befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner /* Prepare for the next iteration */ 2101befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner offset += ret; 2111befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner total += ret; 2121befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner bytes -= ret; 2131befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 2141befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2151befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return total; 2161befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 2171befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2181befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2191befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnervoid iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, 2201befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner FILE *fp, const char *prefix, size_t limit) 2211befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 2221befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner int v; 2231befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t size = 0; 2241befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner char *buf; 2251befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2261befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (v = 0; v < iov_cnt; v++) { 2271befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size += iov[v].iov_len; 2281befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 2291befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size = size > limit ? limit : size; 2301befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner buf = g_malloc(size); 2311befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner iov_to_buf(iov, iov_cnt, 0, buf, size); 2321befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qemu_hexdump(buf, fp, prefix, size); 2331befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner g_free(buf); 2341befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 2351befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2361befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnerunsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, 2371befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner const struct iovec *iov, unsigned int iov_cnt, 2381befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t offset, size_t bytes) 2391befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 2401befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t len; 2411befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner unsigned int i, j; 2421befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (i = 0, j = 0; i < iov_cnt && j < dst_iov_cnt && bytes; i++) { 2431befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (offset >= iov[i].iov_len) { 2441befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner offset -= iov[i].iov_len; 2451befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner continue; 2461befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 2471befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner len = MIN(bytes, iov[i].iov_len - offset); 2481befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2491befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner dst_iov[j].iov_base = iov[i].iov_base + offset; 2501befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner dst_iov[j].iov_len = len; 2511befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner j++; 2521befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner bytes -= len; 2531befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner offset = 0; 2541befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 2551befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(offset == 0); 2561befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return j; 2571befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 2581befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2591befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner/* io vectors */ 2601befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2611befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnervoid qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint) 2621befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 2631befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->iov = g_malloc(alloc_hint * sizeof(struct iovec)); 2641befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->niov = 0; 2651befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->nalloc = alloc_hint; 2661befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->size = 0; 2671befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 2681befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2691befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnervoid qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov) 2701befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 2711befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner int i; 2721befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2731befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->iov = iov; 2741befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->niov = niov; 2751befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->nalloc = -1; 2761befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->size = 0; 2771befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (i = 0; i < niov; i++) 2781befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->size += iov[i].iov_len; 2791befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 2801befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2811befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnervoid qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) 2821befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 2831befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(qiov->nalloc != -1); 2841befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2851befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (qiov->niov == qiov->nalloc) { 2861befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->nalloc = 2 * qiov->nalloc + 1; 2871befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->iov = g_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec)); 2881befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 2891befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->iov[qiov->niov].iov_base = base; 2901befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->iov[qiov->niov].iov_len = len; 2911befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->size += len; 2921befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner ++qiov->niov; 2931befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 2941befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 2951befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner/* 2961befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Concatenates (partial) iovecs from src_iov to the end of dst. 2971befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * It starts copying after skipping `soffset' bytes at the 2981befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * beginning of src and adds individual vectors from src to 2991befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * dst copies up to `sbytes' bytes total, or up to the end 3001befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * of src_iov if it comes first. This way, it is okay to specify 3011befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * very large value for `sbytes' to indicate "up to the end 3021befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * of src". 3031befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Only vector pointers are processed, not the actual data buffers. 3041befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner */ 3051befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnervoid qemu_iovec_concat_iov(QEMUIOVector *dst, 3061befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner struct iovec *src_iov, unsigned int src_cnt, 3071befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t soffset, size_t sbytes) 3081befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 3091befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner int i; 3101befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t done; 3111befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3121befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (!sbytes) { 3131befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return; 3141befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 3151befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(dst->nalloc != -1); 3161befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (i = 0, done = 0; done < sbytes && i < src_cnt; i++) { 3171befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (soffset < src_iov[i].iov_len) { 3181befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t len = MIN(src_iov[i].iov_len - soffset, sbytes - done); 3191befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qemu_iovec_add(dst, src_iov[i].iov_base + soffset, len); 3201befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner done += len; 3211befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner soffset = 0; 3221befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } else { 3231befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner soffset -= src_iov[i].iov_len; 3241befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 3251befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 3261befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(soffset == 0); /* offset beyond end of src */ 3271befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 3281befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3291befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner/* 3301befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Concatenates (partial) iovecs from src to the end of dst. 3311befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * It starts copying after skipping `soffset' bytes at the 3321befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * beginning of src and adds individual vectors from src to 3331befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * dst copies up to `sbytes' bytes total, or up to the end 3341befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * of src if it comes first. This way, it is okay to specify 3351befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * very large value for `sbytes' to indicate "up to the end 3361befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * of src". 3371befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner * Only vector pointers are processed, not the actual data buffers. 3381befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner */ 3391befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnervoid qemu_iovec_concat(QEMUIOVector *dst, 3401befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner QEMUIOVector *src, size_t soffset, size_t sbytes) 3411befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 3421befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes); 3431befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 3441befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3451befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnervoid qemu_iovec_destroy(QEMUIOVector *qiov) 3461befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 3471befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(qiov->nalloc != -1); 3481befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3491befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qemu_iovec_reset(qiov); 3501befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner g_free(qiov->iov); 3511befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->nalloc = 0; 3521befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->iov = NULL; 3531befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 3541befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3551befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnervoid qemu_iovec_reset(QEMUIOVector *qiov) 3561befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 3571befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner assert(qiov->nalloc != -1); 3581befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3591befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->niov = 0; 3601befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner qiov->size = 0; 3611befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 3621befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3631befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnersize_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset, 3641befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner void *buf, size_t bytes) 3651befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 3661befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes); 3671befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 3681befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3691befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnersize_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset, 3701befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner const void *buf, size_t bytes) 3711befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 3721befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes); 3731befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 3741befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3751befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnersize_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, 3761befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner int fillc, size_t bytes) 3771befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 3781befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes); 3791befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 3801befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3811befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnersize_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, 3821befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t bytes) 3831befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 3841befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t total = 0; 3851befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner struct iovec *cur; 3861befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3871befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner for (cur = *iov; *iov_cnt > 0; cur++) { 3881befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (cur->iov_len > bytes) { 3891befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner cur->iov_base += bytes; 3901befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner cur->iov_len -= bytes; 3911befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner total += bytes; 3921befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner break; 3931befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 3941befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 3951befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner bytes -= cur->iov_len; 3961befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner total += cur->iov_len; 3971befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner *iov_cnt -= 1; 3981befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 3991befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 4001befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner *iov = cur; 4011befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return total; 4021befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 4031befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 4041befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turnersize_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, 4051befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t bytes) 4061befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner{ 4071befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner size_t total = 0; 4081befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner struct iovec *cur; 4091befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 4101befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (*iov_cnt == 0) { 4111befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return 0; 4121befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 4131befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 4141befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner cur = iov + (*iov_cnt - 1); 4151befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 4161befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner while (*iov_cnt > 0) { 4171befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner if (cur->iov_len > bytes) { 4181befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner cur->iov_len -= bytes; 4191befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner total += bytes; 4201befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner break; 4211befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 4221befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 4231befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner bytes -= cur->iov_len; 4241befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner total += cur->iov_len; 4251befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner cur--; 4261befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner *iov_cnt -= 1; 4271befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner } 4281befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner 4291befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner return total; 4301befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner} 431