1 /* 2 * Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws> 3 * 4 * Network Block Device Common Code 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; under version 2 of the License. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "nbd-internal.h" 20 21 ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) 22 { 23 size_t offset = 0; 24 int err; 25 26 if (qemu_in_coroutine()) { 27 if (do_read) { 28 return qemu_co_recv(fd, buffer, size); 29 } else { 30 return qemu_co_send(fd, buffer, size); 31 } 32 } 33 34 while (offset < size) { 35 ssize_t len; 36 37 if (do_read) { 38 len = qemu_recv(fd, buffer + offset, size - offset, 0); 39 } else { 40 len = send(fd, buffer + offset, size - offset, 0); 41 } 42 43 if (len < 0) { 44 err = socket_error(); 45 46 /* recoverable error */ 47 if (err == EINTR || (offset > 0 && (err == EAGAIN || err == EWOULDBLOCK))) { 48 continue; 49 } 50 51 /* unrecoverable error */ 52 return -err; 53 } 54 55 /* eof */ 56 if (len == 0) { 57 break; 58 } 59 60 offset += len; 61 } 62 63 return offset; 64 } 65