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 105 106 const char *nbd_opt_lookup(uint32_t opt) 107 { 108 switch (opt) { 109 case NBD_OPT_EXPORT_NAME: 110 return "export name"; 111 case NBD_OPT_ABORT: 112 return "abort"; 113 case NBD_OPT_LIST: 114 return "list"; 115 case NBD_OPT_STARTTLS: 116 return "starttls"; 117 case NBD_OPT_INFO: 118 return "info"; 119 case NBD_OPT_GO: 120 return "go"; 121 case NBD_OPT_STRUCTURED_REPLY: 122 return "structured reply"; 123 default: 124 return "<unknown>"; 125 } 126 } 127 128 129 const char *nbd_rep_lookup(uint32_t rep) 130 { 131 switch (rep) { 132 case NBD_REP_ACK: 133 return "ack"; 134 case NBD_REP_SERVER: 135 return "server"; 136 case NBD_REP_INFO: 137 return "info"; 138 case NBD_REP_ERR_UNSUP: 139 return "unsupported"; 140 case NBD_REP_ERR_POLICY: 141 return "denied by policy"; 142 case NBD_REP_ERR_INVALID: 143 return "invalid"; 144 case NBD_REP_ERR_PLATFORM: 145 return "platform lacks support"; 146 case NBD_REP_ERR_TLS_REQD: 147 return "TLS required"; 148 case NBD_REP_ERR_UNKNOWN: 149 return "export unknown"; 150 case NBD_REP_ERR_SHUTDOWN: 151 return "server shutting down"; 152 case NBD_REP_ERR_BLOCK_SIZE_REQD: 153 return "block size required"; 154 default: 155 return "<unknown>"; 156 } 157 } 158 159 160 const char *nbd_info_lookup(uint16_t info) 161 { 162 switch (info) { 163 case NBD_INFO_EXPORT: 164 return "export"; 165 case NBD_INFO_NAME: 166 return "name"; 167 case NBD_INFO_DESCRIPTION: 168 return "description"; 169 case NBD_INFO_BLOCK_SIZE: 170 return "block size"; 171 default: 172 return "<unknown>"; 173 } 174 } 175 176 177 const char *nbd_cmd_lookup(uint16_t cmd) 178 { 179 switch (cmd) { 180 case NBD_CMD_READ: 181 return "read"; 182 case NBD_CMD_WRITE: 183 return "write"; 184 case NBD_CMD_DISC: 185 return "disconnect"; 186 case NBD_CMD_FLUSH: 187 return "flush"; 188 case NBD_CMD_TRIM: 189 return "trim"; 190 case NBD_CMD_WRITE_ZEROES: 191 return "write zeroes"; 192 default: 193 return "<unknown>"; 194 } 195 } 196