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