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 "qapi/error.h" 21 #include "nbd-internal.h" 22 23 /* nbd_wr_syncv 24 * The function may be called from coroutine or from non-coroutine context. 25 * When called from non-coroutine context @ioc must be in blocking mode. 26 */ 27 ssize_t nbd_rwv(QIOChannel *ioc, struct iovec *iov, size_t niov, size_t length, 28 bool do_read, Error **errp) 29 { 30 ssize_t done = 0; 31 struct iovec *local_iov = g_new(struct iovec, niov); 32 struct iovec *local_iov_head = local_iov; 33 unsigned int nlocal_iov = niov; 34 35 nlocal_iov = iov_copy(local_iov, nlocal_iov, iov, niov, 0, length); 36 37 while (nlocal_iov > 0) { 38 ssize_t len; 39 if (do_read) { 40 len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp); 41 } else { 42 len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp); 43 } 44 if (len == QIO_CHANNEL_ERR_BLOCK) { 45 /* errp should not be set */ 46 assert(qemu_in_coroutine()); 47 qio_channel_yield(ioc, do_read ? G_IO_IN : G_IO_OUT); 48 continue; 49 } 50 if (len < 0) { 51 done = -EIO; 52 goto cleanup; 53 } 54 55 if (do_read && len == 0) { 56 break; 57 } 58 59 iov_discard_front(&local_iov, &nlocal_iov, len); 60 done += len; 61 } 62 63 cleanup: 64 g_free(local_iov_head); 65 return done; 66 } 67 68 /* Discard length bytes from channel. Return -errno on failure and 0 on 69 * success */ 70 int nbd_drop(QIOChannel *ioc, size_t size, Error **errp) 71 { 72 ssize_t ret = 0; 73 char small[1024]; 74 char *buffer; 75 76 buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size)); 77 while (size > 0) { 78 ssize_t count = MIN(65536, size); 79 ret = nbd_read(ioc, buffer, MIN(65536, size), errp); 80 81 if (ret < 0) { 82 goto cleanup; 83 } 84 size -= count; 85 } 86 87 cleanup: 88 if (buffer != small) { 89 g_free(buffer); 90 } 91 return ret; 92 } 93 94 95 void nbd_tls_handshake(QIOTask *task, 96 void *opaque) 97 { 98 struct NBDTLSHandshakeData *data = opaque; 99 100 qio_task_propagate_error(task, &data->error); 101 data->complete = true; 102 g_main_loop_quit(data->loop); 103 } 104