1c4d7847bSPekka Enberg #include "kvm/read-write.h" 2c4d7847bSPekka Enberg 3c4d7847bSPekka Enberg #include <sys/types.h> 4150aa4c0SPekka Enberg #include <sys/uio.h> 5c4d7847bSPekka Enberg #include <unistd.h> 6c4d7847bSPekka Enberg #include <string.h> 7c4d7847bSPekka Enberg #include <errno.h> 8c4d7847bSPekka Enberg 9c4d7847bSPekka Enberg /* Same as read(2) except that this function never returns EAGAIN or EINTR. */ 10c4d7847bSPekka Enberg ssize_t xread(int fd, void *buf, size_t count) 11c4d7847bSPekka Enberg { 12c4d7847bSPekka Enberg ssize_t nr; 13c4d7847bSPekka Enberg 14c4d7847bSPekka Enberg restart: 15c4d7847bSPekka Enberg nr = read(fd, buf, count); 16c4d7847bSPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 17c4d7847bSPekka Enberg goto restart; 18c4d7847bSPekka Enberg 19c4d7847bSPekka Enberg return nr; 20c4d7847bSPekka Enberg } 21c4d7847bSPekka Enberg 22c4d7847bSPekka Enberg /* Same as write(2) except that this function never returns EAGAIN or EINTR. */ 23c4d7847bSPekka Enberg ssize_t xwrite(int fd, const void *buf, size_t count) 24c4d7847bSPekka Enberg { 25c4d7847bSPekka Enberg ssize_t nr; 26c4d7847bSPekka Enberg 27c4d7847bSPekka Enberg restart: 28c4d7847bSPekka Enberg nr = write(fd, buf, count); 29c4d7847bSPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 30c4d7847bSPekka Enberg goto restart; 31c4d7847bSPekka Enberg 32c4d7847bSPekka Enberg return nr; 33c4d7847bSPekka Enberg } 34c4d7847bSPekka Enberg 35c4d7847bSPekka Enberg ssize_t read_in_full(int fd, void *buf, size_t count) 36c4d7847bSPekka Enberg { 37c4d7847bSPekka Enberg ssize_t total = 0; 38c4d7847bSPekka Enberg char *p = buf; 39c4d7847bSPekka Enberg 40c4d7847bSPekka Enberg while (count > 0) { 41c4d7847bSPekka Enberg ssize_t nr; 42c4d7847bSPekka Enberg 43c4d7847bSPekka Enberg nr = xread(fd, p, count); 44c4d7847bSPekka Enberg if (nr <= 0) { 45c4d7847bSPekka Enberg if (total > 0) 46c4d7847bSPekka Enberg return total; 47c4d7847bSPekka Enberg 48c4d7847bSPekka Enberg return -1; 49c4d7847bSPekka Enberg } 50c4d7847bSPekka Enberg 51c4d7847bSPekka Enberg count -= nr; 52c4d7847bSPekka Enberg total += nr; 53c4d7847bSPekka Enberg p += nr; 54c4d7847bSPekka Enberg } 55c4d7847bSPekka Enberg 56c4d7847bSPekka Enberg return total; 57c4d7847bSPekka Enberg } 58c4d7847bSPekka Enberg 59c4d7847bSPekka Enberg ssize_t write_in_full(int fd, const void *buf, size_t count) 60c4d7847bSPekka Enberg { 61c4d7847bSPekka Enberg const char *p = buf; 62c4d7847bSPekka Enberg ssize_t total = 0; 63c4d7847bSPekka Enberg 64c4d7847bSPekka Enberg while (count > 0) { 65c4d7847bSPekka Enberg ssize_t nr; 66c4d7847bSPekka Enberg 67c4d7847bSPekka Enberg nr = xwrite(fd, p, count); 68c4d7847bSPekka Enberg if (nr < 0) 69c4d7847bSPekka Enberg return -1; 70c4d7847bSPekka Enberg if (nr == 0) { 71c4d7847bSPekka Enberg errno = ENOSPC; 72c4d7847bSPekka Enberg return -1; 73c4d7847bSPekka Enberg } 74c4d7847bSPekka Enberg count -= nr; 75c4d7847bSPekka Enberg total += nr; 76c4d7847bSPekka Enberg p += nr; 77c4d7847bSPekka Enberg } 78c4d7847bSPekka Enberg 79c4d7847bSPekka Enberg return total; 80c4d7847bSPekka Enberg } 816b7deb02SPekka Enberg 826b7deb02SPekka Enberg /* Same as pread(2) except that this function never returns EAGAIN or EINTR. */ 836b7deb02SPekka Enberg ssize_t xpread(int fd, void *buf, size_t count, off_t offset) 846b7deb02SPekka Enberg { 856b7deb02SPekka Enberg ssize_t nr; 866b7deb02SPekka Enberg 876b7deb02SPekka Enberg restart: 886b7deb02SPekka Enberg nr = pread(fd, buf, count, offset); 896b7deb02SPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 906b7deb02SPekka Enberg goto restart; 916b7deb02SPekka Enberg 926b7deb02SPekka Enberg return nr; 936b7deb02SPekka Enberg } 946b7deb02SPekka Enberg 956b7deb02SPekka Enberg /* Same as pwrite(2) except that this function never returns EAGAIN or EINTR. */ 966b7deb02SPekka Enberg ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset) 976b7deb02SPekka Enberg { 986b7deb02SPekka Enberg ssize_t nr; 996b7deb02SPekka Enberg 1006b7deb02SPekka Enberg restart: 1016b7deb02SPekka Enberg nr = pwrite(fd, buf, count, offset); 1026b7deb02SPekka Enberg if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 1036b7deb02SPekka Enberg goto restart; 1046b7deb02SPekka Enberg 1056b7deb02SPekka Enberg return nr; 1066b7deb02SPekka Enberg } 1076b7deb02SPekka Enberg 1086b7deb02SPekka Enberg ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset) 1096b7deb02SPekka Enberg { 1106b7deb02SPekka Enberg ssize_t total = 0; 1116b7deb02SPekka Enberg char *p = buf; 1126b7deb02SPekka Enberg 1136b7deb02SPekka Enberg while (count > 0) { 1146b7deb02SPekka Enberg ssize_t nr; 1156b7deb02SPekka Enberg 1166b7deb02SPekka Enberg nr = xpread(fd, p, count, offset); 1176b7deb02SPekka Enberg if (nr <= 0) { 1186b7deb02SPekka Enberg if (total > 0) 1196b7deb02SPekka Enberg return total; 1206b7deb02SPekka Enberg 1216b7deb02SPekka Enberg return -1; 1226b7deb02SPekka Enberg } 1236b7deb02SPekka Enberg 1246b7deb02SPekka Enberg count -= nr; 1256b7deb02SPekka Enberg total += nr; 1266b7deb02SPekka Enberg p += nr; 1276b7deb02SPekka Enberg offset += nr; 1286b7deb02SPekka Enberg } 1296b7deb02SPekka Enberg 1306b7deb02SPekka Enberg return total; 1316b7deb02SPekka Enberg } 1326b7deb02SPekka Enberg 1336b7deb02SPekka Enberg ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset) 1346b7deb02SPekka Enberg { 1356b7deb02SPekka Enberg const char *p = buf; 1366b7deb02SPekka Enberg ssize_t total = 0; 1376b7deb02SPekka Enberg 1386b7deb02SPekka Enberg while (count > 0) { 1396b7deb02SPekka Enberg ssize_t nr; 1406b7deb02SPekka Enberg 1416b7deb02SPekka Enberg nr = xpwrite(fd, p, count, offset); 1426b7deb02SPekka Enberg if (nr < 0) 1436b7deb02SPekka Enberg return -1; 1446b7deb02SPekka Enberg if (nr == 0) { 1456b7deb02SPekka Enberg errno = ENOSPC; 1466b7deb02SPekka Enberg return -1; 1476b7deb02SPekka Enberg } 1486b7deb02SPekka Enberg count -= nr; 1496b7deb02SPekka Enberg total += nr; 1506b7deb02SPekka Enberg p += nr; 1516b7deb02SPekka Enberg offset += nr; 1526b7deb02SPekka Enberg } 1536b7deb02SPekka Enberg 1546b7deb02SPekka Enberg return total; 1556b7deb02SPekka Enberg } 1561547507fSSasha Levin 1571547507fSSasha Levin /* Same as readv(2) except that this function never returns EAGAIN or EINTR. */ 1581547507fSSasha Levin ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt) 1591547507fSSasha Levin { 1601547507fSSasha Levin ssize_t nr; 1611547507fSSasha Levin 1621547507fSSasha Levin restart: 1631547507fSSasha Levin nr = readv(fd, iov, iovcnt); 1641547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 1651547507fSSasha Levin goto restart; 1661547507fSSasha Levin 1671547507fSSasha Levin return nr; 1681547507fSSasha Levin } 1691547507fSSasha Levin 1701547507fSSasha Levin /* Same as writev(2) except that this function never returns EAGAIN or EINTR. */ 1711547507fSSasha Levin ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt) 1721547507fSSasha Levin { 1731547507fSSasha Levin ssize_t nr; 1741547507fSSasha Levin 1751547507fSSasha Levin restart: 176f42cd9ccSPekka Enberg nr = writev(fd, iov, iovcnt); 1771547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 1781547507fSSasha Levin goto restart; 1791547507fSSasha Levin 1801547507fSSasha Levin return nr; 1811547507fSSasha Levin } 1821547507fSSasha Levin 1831547507fSSasha Levin static inline ssize_t get_iov_size(const struct iovec *iov, int iovcnt) 1841547507fSSasha Levin { 1851547507fSSasha Levin size_t size = 0; 1861547507fSSasha Levin while (iovcnt--) 1871547507fSSasha Levin size += (iov++)->iov_len; 1881547507fSSasha Levin 1891547507fSSasha Levin return size; 1901547507fSSasha Levin } 1911547507fSSasha Levin 1924c0205d0SSasha Levin static inline void shift_iovec(const struct iovec **iov, int *iovcnt, 1934c0205d0SSasha Levin size_t nr, ssize_t *total, size_t *count, off_t *offset) 1944c0205d0SSasha Levin { 1954c0205d0SSasha Levin while (nr >= (*iov)->iov_len) { 1964c0205d0SSasha Levin nr -= (*iov)->iov_len; 1974c0205d0SSasha Levin *total += (*iov)->iov_len; 1984c0205d0SSasha Levin *count -= (*iov)->iov_len; 1994c0205d0SSasha Levin if (offset) 2004c0205d0SSasha Levin *offset += (*iov)->iov_len; 2014c0205d0SSasha Levin (*iovcnt)--; 2024c0205d0SSasha Levin (*iov)++; 2034c0205d0SSasha Levin } 2044c0205d0SSasha Levin } 2054c0205d0SSasha Levin 2061547507fSSasha Levin ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt) 2071547507fSSasha Levin { 2081547507fSSasha Levin ssize_t total = 0; 2094c0205d0SSasha Levin size_t count = get_iov_size(iov, iovcnt); 2101547507fSSasha Levin 2111547507fSSasha Levin while (count > 0) { 2121547507fSSasha Levin ssize_t nr; 2131547507fSSasha Levin 2141547507fSSasha Levin nr = xreadv(fd, iov, iovcnt); 2151547507fSSasha Levin if (nr <= 0) { 2161547507fSSasha Levin if (total > 0) 2171547507fSSasha Levin return total; 2181547507fSSasha Levin 2191547507fSSasha Levin return -1; 2201547507fSSasha Levin } 2211547507fSSasha Levin 2224c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL); 2231547507fSSasha Levin } 2241547507fSSasha Levin 2251547507fSSasha Levin return total; 2261547507fSSasha Levin } 2271547507fSSasha Levin 2281547507fSSasha Levin ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt) 2291547507fSSasha Levin { 2301547507fSSasha Levin ssize_t total = 0; 2311547507fSSasha Levin size_t count = get_iov_size(iov, iovcnt); 2321547507fSSasha Levin 2331547507fSSasha Levin while (count > 0) { 2341547507fSSasha Levin ssize_t nr; 2351547507fSSasha Levin 2361547507fSSasha Levin nr = xwritev(fd, iov, iovcnt); 2371547507fSSasha Levin if (nr < 0) 2381547507fSSasha Levin return -1; 2391547507fSSasha Levin if (nr == 0) { 2401547507fSSasha Levin errno = ENOSPC; 2411547507fSSasha Levin return -1; 2421547507fSSasha Levin } 2431547507fSSasha Levin 2444c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL); 2451547507fSSasha Levin } 2461547507fSSasha Levin 2471547507fSSasha Levin return total; 2481547507fSSasha Levin } 2491547507fSSasha Levin 2501547507fSSasha Levin /* Same as preadv(2) except that this function never returns EAGAIN or EINTR. */ 2511547507fSSasha Levin ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) 2521547507fSSasha Levin { 2531547507fSSasha Levin ssize_t nr; 2541547507fSSasha Levin 2551547507fSSasha Levin restart: 2561547507fSSasha Levin nr = preadv(fd, iov, iovcnt, offset); 2571547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 2581547507fSSasha Levin goto restart; 2591547507fSSasha Levin 2601547507fSSasha Levin return nr; 2611547507fSSasha Levin } 2621547507fSSasha Levin 2631547507fSSasha Levin /* Same as pwritev(2) except that this function never returns EAGAIN or EINTR. */ 2641547507fSSasha Levin ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) 2651547507fSSasha Levin { 2661547507fSSasha Levin ssize_t nr; 2671547507fSSasha Levin 2681547507fSSasha Levin restart: 2691547507fSSasha Levin nr = pwritev(fd, iov, iovcnt, offset); 2701547507fSSasha Levin if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) 2711547507fSSasha Levin goto restart; 2721547507fSSasha Levin 2731547507fSSasha Levin return nr; 2741547507fSSasha Levin } 2751547507fSSasha Levin 2761547507fSSasha Levin ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset) 2771547507fSSasha Levin { 2781547507fSSasha Levin ssize_t total = 0; 2791547507fSSasha Levin size_t count = get_iov_size(iov, iovcnt); 2801547507fSSasha Levin 2811547507fSSasha Levin while (count > 0) { 2821547507fSSasha Levin ssize_t nr; 2831547507fSSasha Levin 2841547507fSSasha Levin nr = xpreadv(fd, iov, iovcnt, offset); 2851547507fSSasha Levin if (nr <= 0) { 2861547507fSSasha Levin if (total > 0) 2871547507fSSasha Levin return total; 2881547507fSSasha Levin 2891547507fSSasha Levin return -1; 2901547507fSSasha Levin } 2911547507fSSasha Levin 2924c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset); 2931547507fSSasha Levin } 2941547507fSSasha Levin 2951547507fSSasha Levin return total; 2961547507fSSasha Levin } 2971547507fSSasha Levin 2981547507fSSasha Levin ssize_t pwritev_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset) 2991547507fSSasha Levin { 3001547507fSSasha Levin ssize_t total = 0; 3011547507fSSasha Levin size_t count = get_iov_size(iov, iovcnt); 3021547507fSSasha Levin 3031547507fSSasha Levin while (count > 0) { 3041547507fSSasha Levin ssize_t nr; 3051547507fSSasha Levin 3061547507fSSasha Levin nr = xpwritev(fd, iov, iovcnt, offset); 3071547507fSSasha Levin if (nr < 0) 3081547507fSSasha Levin return -1; 3091547507fSSasha Levin if (nr == 0) { 3101547507fSSasha Levin errno = ENOSPC; 3111547507fSSasha Levin return -1; 3121547507fSSasha Levin } 3134c0205d0SSasha Levin 3144c0205d0SSasha Levin shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset); 3151547507fSSasha Levin } 3161547507fSSasha Levin 3171547507fSSasha Levin return total; 3181547507fSSasha Levin } 319*1664498dSSasha Levin 320*1664498dSSasha Levin #ifdef CONFIG_HAS_AIO 321*1664498dSSasha Levin int aio_pwritev(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, 322*1664498dSSasha Levin off_t offset, int ev, void *param) 323*1664498dSSasha Levin { 324*1664498dSSasha Levin struct iocb *ios[1] = { iocb }; 325*1664498dSSasha Levin 326*1664498dSSasha Levin io_prep_pwritev(iocb, fd, iov, iovcnt, offset); 327*1664498dSSasha Levin io_set_eventfd(iocb, ev); 328*1664498dSSasha Levin iocb->data = param; 329*1664498dSSasha Levin 330*1664498dSSasha Levin return io_submit(ctx, 1, ios); 331*1664498dSSasha Levin } 332*1664498dSSasha Levin 333*1664498dSSasha Levin int aio_preadv(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, 334*1664498dSSasha Levin off_t offset, int ev, void *param) 335*1664498dSSasha Levin { 336*1664498dSSasha Levin struct iocb *ios[1] = { iocb }; 337*1664498dSSasha Levin 338*1664498dSSasha Levin io_prep_preadv(iocb, fd, iov, iovcnt, offset); 339*1664498dSSasha Levin io_set_eventfd(iocb, ev); 340*1664498dSSasha Levin iocb->data = param; 341*1664498dSSasha Levin 342*1664498dSSasha Levin return io_submit(ctx, 1, ios); 343*1664498dSSasha Levin } 344*1664498dSSasha Levin #endif