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), NULL, 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 const char *nbd_opt_lookup(uint32_t opt) 51 { 52 switch (opt) { 53 case NBD_OPT_EXPORT_NAME: 54 return "export name"; 55 case NBD_OPT_ABORT: 56 return "abort"; 57 case NBD_OPT_LIST: 58 return "list"; 59 case NBD_OPT_STARTTLS: 60 return "starttls"; 61 case NBD_OPT_INFO: 62 return "info"; 63 case NBD_OPT_GO: 64 return "go"; 65 case NBD_OPT_STRUCTURED_REPLY: 66 return "structured reply"; 67 case NBD_OPT_LIST_META_CONTEXT: 68 return "list meta context"; 69 case NBD_OPT_SET_META_CONTEXT: 70 return "set meta context"; 71 case NBD_OPT_EXTENDED_HEADERS: 72 return "extended headers"; 73 default: 74 return "<unknown>"; 75 } 76 } 77 78 79 const char *nbd_rep_lookup(uint32_t rep) 80 { 81 switch (rep) { 82 case NBD_REP_ACK: 83 return "ack"; 84 case NBD_REP_SERVER: 85 return "server"; 86 case NBD_REP_INFO: 87 return "info"; 88 case NBD_REP_META_CONTEXT: 89 return "meta context"; 90 case NBD_REP_ERR_UNSUP: 91 return "unsupported"; 92 case NBD_REP_ERR_POLICY: 93 return "denied by policy"; 94 case NBD_REP_ERR_INVALID: 95 return "invalid"; 96 case NBD_REP_ERR_PLATFORM: 97 return "platform lacks support"; 98 case NBD_REP_ERR_TLS_REQD: 99 return "TLS required"; 100 case NBD_REP_ERR_UNKNOWN: 101 return "export unknown"; 102 case NBD_REP_ERR_SHUTDOWN: 103 return "server shutting down"; 104 case NBD_REP_ERR_BLOCK_SIZE_REQD: 105 return "block size required"; 106 case NBD_REP_ERR_TOO_BIG: 107 return "option payload too big"; 108 case NBD_REP_ERR_EXT_HEADER_REQD: 109 return "extended headers 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_CACHE: 147 return "cache"; 148 case NBD_CMD_WRITE_ZEROES: 149 return "write zeroes"; 150 case NBD_CMD_BLOCK_STATUS: 151 return "block status"; 152 default: 153 return "<unknown>"; 154 } 155 } 156 157 158 const char *nbd_reply_type_lookup(uint16_t type) 159 { 160 switch (type) { 161 case NBD_REPLY_TYPE_NONE: 162 return "none"; 163 case NBD_REPLY_TYPE_OFFSET_DATA: 164 return "data"; 165 case NBD_REPLY_TYPE_OFFSET_HOLE: 166 return "hole"; 167 case NBD_REPLY_TYPE_BLOCK_STATUS: 168 return "block status (32-bit)"; 169 case NBD_REPLY_TYPE_BLOCK_STATUS_EXT: 170 return "block status (64-bit)"; 171 case NBD_REPLY_TYPE_ERROR: 172 return "generic error"; 173 case NBD_REPLY_TYPE_ERROR_OFFSET: 174 return "error at offset"; 175 default: 176 if (type & (1 << 15)) { 177 return "<unknown error>"; 178 } 179 return "<unknown>"; 180 } 181 } 182 183 184 const char *nbd_err_lookup(int err) 185 { 186 switch (err) { 187 case NBD_SUCCESS: 188 return "success"; 189 case NBD_EPERM: 190 return "EPERM"; 191 case NBD_EIO: 192 return "EIO"; 193 case NBD_ENOMEM: 194 return "ENOMEM"; 195 case NBD_EINVAL: 196 return "EINVAL"; 197 case NBD_ENOSPC: 198 return "ENOSPC"; 199 case NBD_EOVERFLOW: 200 return "EOVERFLOW"; 201 case NBD_ENOTSUP: 202 return "ENOTSUP"; 203 case NBD_ESHUTDOWN: 204 return "ESHUTDOWN"; 205 default: 206 return "<unknown>"; 207 } 208 } 209 210 211 int nbd_errno_to_system_errno(int err) 212 { 213 int ret; 214 switch (err) { 215 case NBD_SUCCESS: 216 ret = 0; 217 break; 218 case NBD_EPERM: 219 ret = EPERM; 220 break; 221 case NBD_EIO: 222 ret = EIO; 223 break; 224 case NBD_ENOMEM: 225 ret = ENOMEM; 226 break; 227 case NBD_ENOSPC: 228 ret = ENOSPC; 229 break; 230 case NBD_EOVERFLOW: 231 ret = EOVERFLOW; 232 break; 233 case NBD_ENOTSUP: 234 ret = ENOTSUP; 235 break; 236 case NBD_ESHUTDOWN: 237 ret = ESHUTDOWN; 238 break; 239 default: 240 trace_nbd_unknown_error(err); 241 /* fallthrough */ 242 case NBD_EINVAL: 243 ret = EINVAL; 244 break; 245 } 246 return ret; 247 } 248 249 250 const char *nbd_mode_lookup(NBDMode mode) 251 { 252 switch (mode) { 253 case NBD_MODE_OLDSTYLE: 254 return "oldstyle"; 255 case NBD_MODE_EXPORT_NAME: 256 return "export name only"; 257 case NBD_MODE_SIMPLE: 258 return "simple headers"; 259 case NBD_MODE_STRUCTURED: 260 return "structured replies"; 261 case NBD_MODE_EXTENDED: 262 return "extended headers"; 263 default: 264 return "<unknown>"; 265 } 266 } 267