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 "qemu/osdep.h" 20 #include "nbd-internal.h" 21 22 ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) 23 { 24 size_t offset = 0; 25 int err; 26 27 if (qemu_in_coroutine()) { 28 if (do_read) { 29 return qemu_co_recv(fd, buffer, size); 30 } else { 31 return qemu_co_send(fd, buffer, size); 32 } 33 } 34 35 while (offset < size) { 36 ssize_t len; 37 38 if (do_read) { 39 len = qemu_recv(fd, buffer + offset, size - offset, 0); 40 } else { 41 len = send(fd, buffer + offset, size - offset, 0); 42 } 43 44 if (len < 0) { 45 err = socket_error(); 46 47 /* recoverable error */ 48 if (err == EINTR || (offset > 0 && (err == EAGAIN || err == EWOULDBLOCK))) { 49 continue; 50 } 51 52 /* unrecoverable error */ 53 return -err; 54 } 55 56 /* eof */ 57 if (len == 0) { 58 break; 59 } 60 61 offset += len; 62 } 63 64 return offset; 65 } 66