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 "trace.h" 22 #include "nbd-internal.h" 23 24 /* Discard length bytes from channel. Return -errno on failure and 0 on 25 * success */ 26 int nbd_drop(QIOChannel *ioc, size_t size, Error **errp) 27 { 28 ssize_t ret = 0; 29 char small[1024]; 30 char *buffer; 31 32 buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size)); 33 while (size > 0) { 34 ssize_t count = MIN(65536, size); 35 ret = nbd_read(ioc, buffer, MIN(65536, size), errp); 36 37 if (ret < 0) { 38 goto cleanup; 39 } 40 size -= count; 41 } 42 43 cleanup: 44 if (buffer != small) { 45 g_free(buffer); 46 } 47 return ret; 48 } 49 50 51 void nbd_tls_handshake(QIOTask *task, 52 void *opaque) 53 { 54 struct NBDTLSHandshakeData *data = opaque; 55 56 qio_task_propagate_error(task, &data->error); 57 data->complete = true; 58 g_main_loop_quit(data->loop); 59 } 60 61 62 const char *nbd_opt_lookup(uint32_t opt) 63 { 64 switch (opt) { 65 case NBD_OPT_EXPORT_NAME: 66 return "export name"; 67 case NBD_OPT_ABORT: 68 return "abort"; 69 case NBD_OPT_LIST: 70 return "list"; 71 case NBD_OPT_STARTTLS: 72 return "starttls"; 73 case NBD_OPT_INFO: 74 return "info"; 75 case NBD_OPT_GO: 76 return "go"; 77 case NBD_OPT_STRUCTURED_REPLY: 78 return "structured reply"; 79 default: 80 return "<unknown>"; 81 } 82 } 83 84 85 const char *nbd_rep_lookup(uint32_t rep) 86 { 87 switch (rep) { 88 case NBD_REP_ACK: 89 return "ack"; 90 case NBD_REP_SERVER: 91 return "server"; 92 case NBD_REP_INFO: 93 return "info"; 94 case NBD_REP_ERR_UNSUP: 95 return "unsupported"; 96 case NBD_REP_ERR_POLICY: 97 return "denied by policy"; 98 case NBD_REP_ERR_INVALID: 99 return "invalid"; 100 case NBD_REP_ERR_PLATFORM: 101 return "platform lacks support"; 102 case NBD_REP_ERR_TLS_REQD: 103 return "TLS required"; 104 case NBD_REP_ERR_UNKNOWN: 105 return "export unknown"; 106 case NBD_REP_ERR_SHUTDOWN: 107 return "server shutting down"; 108 case NBD_REP_ERR_BLOCK_SIZE_REQD: 109 return "block size required"; 110 default: 111 return "<unknown>"; 112 } 113 } 114 115 116 const char *nbd_info_lookup(uint16_t info) 117 { 118 switch (info) { 119 case NBD_INFO_EXPORT: 120 return "export"; 121 case NBD_INFO_NAME: 122 return "name"; 123 case NBD_INFO_DESCRIPTION: 124 return "description"; 125 case NBD_INFO_BLOCK_SIZE: 126 return "block size"; 127 default: 128 return "<unknown>"; 129 } 130 } 131 132 133 const char *nbd_cmd_lookup(uint16_t cmd) 134 { 135 switch (cmd) { 136 case NBD_CMD_READ: 137 return "read"; 138 case NBD_CMD_WRITE: 139 return "write"; 140 case NBD_CMD_DISC: 141 return "disconnect"; 142 case NBD_CMD_FLUSH: 143 return "flush"; 144 case NBD_CMD_TRIM: 145 return "trim"; 146 case NBD_CMD_WRITE_ZEROES: 147 return "write zeroes"; 148 default: 149 return "<unknown>"; 150 } 151 } 152 153 154 const char *nbd_reply_type_lookup(uint16_t type) 155 { 156 switch (type) { 157 case NBD_REPLY_TYPE_NONE: 158 return "none"; 159 case NBD_REPLY_TYPE_OFFSET_DATA: 160 return "data"; 161 case NBD_REPLY_TYPE_OFFSET_HOLE: 162 return "hole"; 163 case NBD_REPLY_TYPE_ERROR: 164 return "generic error"; 165 case NBD_REPLY_TYPE_ERROR_OFFSET: 166 return "error at offset"; 167 default: 168 if (type & (1 << 15)) { 169 return "<unknown error>"; 170 } 171 return "<unknown>"; 172 } 173 } 174 175 176 const char *nbd_err_lookup(int err) 177 { 178 switch (err) { 179 case NBD_SUCCESS: 180 return "success"; 181 case NBD_EPERM: 182 return "EPERM"; 183 case NBD_EIO: 184 return "EIO"; 185 case NBD_ENOMEM: 186 return "ENOMEM"; 187 case NBD_EINVAL: 188 return "EINVAL"; 189 case NBD_ENOSPC: 190 return "ENOSPC"; 191 case NBD_EOVERFLOW: 192 return "EOVERFLOW"; 193 case NBD_ESHUTDOWN: 194 return "ESHUTDOWN"; 195 default: 196 return "<unknown>"; 197 } 198 } 199 200 201 int nbd_errno_to_system_errno(int err) 202 { 203 int ret; 204 switch (err) { 205 case NBD_SUCCESS: 206 ret = 0; 207 break; 208 case NBD_EPERM: 209 ret = EPERM; 210 break; 211 case NBD_EIO: 212 ret = EIO; 213 break; 214 case NBD_ENOMEM: 215 ret = ENOMEM; 216 break; 217 case NBD_ENOSPC: 218 ret = ENOSPC; 219 break; 220 case NBD_EOVERFLOW: 221 ret = EOVERFLOW; 222 break; 223 case NBD_ESHUTDOWN: 224 ret = ESHUTDOWN; 225 break; 226 default: 227 trace_nbd_unknown_error(err); 228 /* fallthrough */ 229 case NBD_EINVAL: 230 ret = EINVAL; 231 break; 232 } 233 return ret; 234 } 235