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 "io/channel-socket.h" 22 #include "qapi/error.h" 23 #include "qemu/units.h" 24 #include "nbd-internal.h" 25 26 /* Discard length bytes from channel. Return -errno on failure and 0 on 27 * success */ 28 int nbd_drop(QIOChannel *ioc, size_t size, Error **errp) 29 { 30 ssize_t ret = 0; 31 char small[1024]; 32 char *buffer; 33 34 buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size)); 35 while (size > 0) { 36 ssize_t count = MIN(65536, size); 37 ret = nbd_read(ioc, buffer, MIN(65536, size), NULL, errp); 38 39 if (ret < 0) { 40 goto cleanup; 41 } 42 size -= count; 43 } 44 45 cleanup: 46 if (buffer != small) { 47 g_free(buffer); 48 } 49 return ret; 50 } 51 52 53 const char *nbd_opt_lookup(uint32_t opt) 54 { 55 switch (opt) { 56 case NBD_OPT_EXPORT_NAME: 57 return "export name"; 58 case NBD_OPT_ABORT: 59 return "abort"; 60 case NBD_OPT_LIST: 61 return "list"; 62 case NBD_OPT_STARTTLS: 63 return "starttls"; 64 case NBD_OPT_INFO: 65 return "info"; 66 case NBD_OPT_GO: 67 return "go"; 68 case NBD_OPT_STRUCTURED_REPLY: 69 return "structured reply"; 70 case NBD_OPT_LIST_META_CONTEXT: 71 return "list meta context"; 72 case NBD_OPT_SET_META_CONTEXT: 73 return "set meta context"; 74 case NBD_OPT_EXTENDED_HEADERS: 75 return "extended headers"; 76 default: 77 return "<unknown>"; 78 } 79 } 80 81 82 const char *nbd_rep_lookup(uint32_t rep) 83 { 84 switch (rep) { 85 case NBD_REP_ACK: 86 return "ack"; 87 case NBD_REP_SERVER: 88 return "server"; 89 case NBD_REP_INFO: 90 return "info"; 91 case NBD_REP_META_CONTEXT: 92 return "meta context"; 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 case NBD_REP_ERR_TOO_BIG: 110 return "option payload too big"; 111 case NBD_REP_ERR_EXT_HEADER_REQD: 112 return "extended headers required"; 113 default: 114 return "<unknown>"; 115 } 116 } 117 118 119 const char *nbd_info_lookup(uint16_t info) 120 { 121 switch (info) { 122 case NBD_INFO_EXPORT: 123 return "export"; 124 case NBD_INFO_NAME: 125 return "name"; 126 case NBD_INFO_DESCRIPTION: 127 return "description"; 128 case NBD_INFO_BLOCK_SIZE: 129 return "block size"; 130 default: 131 return "<unknown>"; 132 } 133 } 134 135 136 const char *nbd_cmd_lookup(uint16_t cmd) 137 { 138 switch (cmd) { 139 case NBD_CMD_READ: 140 return "read"; 141 case NBD_CMD_WRITE: 142 return "write"; 143 case NBD_CMD_DISC: 144 return "disconnect"; 145 case NBD_CMD_FLUSH: 146 return "flush"; 147 case NBD_CMD_TRIM: 148 return "trim"; 149 case NBD_CMD_CACHE: 150 return "cache"; 151 case NBD_CMD_WRITE_ZEROES: 152 return "write zeroes"; 153 case NBD_CMD_BLOCK_STATUS: 154 return "block status"; 155 default: 156 return "<unknown>"; 157 } 158 } 159 160 161 const char *nbd_reply_type_lookup(uint16_t type) 162 { 163 switch (type) { 164 case NBD_REPLY_TYPE_NONE: 165 return "none"; 166 case NBD_REPLY_TYPE_OFFSET_DATA: 167 return "data"; 168 case NBD_REPLY_TYPE_OFFSET_HOLE: 169 return "hole"; 170 case NBD_REPLY_TYPE_BLOCK_STATUS: 171 return "block status (32-bit)"; 172 case NBD_REPLY_TYPE_BLOCK_STATUS_EXT: 173 return "block status (64-bit)"; 174 case NBD_REPLY_TYPE_ERROR: 175 return "generic error"; 176 case NBD_REPLY_TYPE_ERROR_OFFSET: 177 return "error at offset"; 178 default: 179 if (type & (1 << 15)) { 180 return "<unknown error>"; 181 } 182 return "<unknown>"; 183 } 184 } 185 186 187 const char *nbd_err_lookup(int err) 188 { 189 switch (err) { 190 case NBD_SUCCESS: 191 return "success"; 192 case NBD_EPERM: 193 return "EPERM"; 194 case NBD_EIO: 195 return "EIO"; 196 case NBD_ENOMEM: 197 return "ENOMEM"; 198 case NBD_EINVAL: 199 return "EINVAL"; 200 case NBD_ENOSPC: 201 return "ENOSPC"; 202 case NBD_EOVERFLOW: 203 return "EOVERFLOW"; 204 case NBD_ENOTSUP: 205 return "ENOTSUP"; 206 case NBD_ESHUTDOWN: 207 return "ESHUTDOWN"; 208 default: 209 return "<unknown>"; 210 } 211 } 212 213 214 int nbd_errno_to_system_errno(int err) 215 { 216 int ret; 217 switch (err) { 218 case NBD_SUCCESS: 219 ret = 0; 220 break; 221 case NBD_EPERM: 222 ret = EPERM; 223 break; 224 case NBD_EIO: 225 ret = EIO; 226 break; 227 case NBD_ENOMEM: 228 ret = ENOMEM; 229 break; 230 case NBD_ENOSPC: 231 ret = ENOSPC; 232 break; 233 case NBD_EOVERFLOW: 234 ret = EOVERFLOW; 235 break; 236 case NBD_ENOTSUP: 237 ret = ENOTSUP; 238 break; 239 case NBD_ESHUTDOWN: 240 ret = ESHUTDOWN; 241 break; 242 default: 243 trace_nbd_unknown_error(err); 244 /* fallthrough */ 245 case NBD_EINVAL: 246 ret = EINVAL; 247 break; 248 } 249 return ret; 250 } 251 252 253 const char *nbd_mode_lookup(NBDMode mode) 254 { 255 switch (mode) { 256 case NBD_MODE_OLDSTYLE: 257 return "oldstyle"; 258 case NBD_MODE_EXPORT_NAME: 259 return "export name only"; 260 case NBD_MODE_SIMPLE: 261 return "simple headers"; 262 case NBD_MODE_STRUCTURED: 263 return "structured replies"; 264 case NBD_MODE_EXTENDED: 265 return "extended headers"; 266 default: 267 return "<unknown>"; 268 } 269 } 270 271 /* 272 * Testing shows that 2m send buffer is optimal. Changing the receive buffer 273 * size has no effect on performance. 274 * On Linux we need to increase net.core.wmem_max to make this effective. 275 */ 276 #if defined(__APPLE__) || defined(__linux__) 277 #define UNIX_STREAM_SOCKET_SEND_BUFFER_SIZE (2 * MiB) 278 #endif 279 280 void nbd_set_socket_send_buffer(QIOChannelSocket *sioc) 281 { 282 #ifdef UNIX_STREAM_SOCKET_SEND_BUFFER_SIZE 283 if (sioc->localAddr.ss_family == AF_UNIX) { 284 size_t size = UNIX_STREAM_SOCKET_SEND_BUFFER_SIZE; 285 Error *errp = NULL; 286 287 if (qio_channel_socket_set_send_buffer(sioc, size, &errp) < 0) { 288 warn_report_err(errp); 289 } 290 } 291 #endif /* UNIX_STREAM_SOCKET_SEND_BUFFER_SIZE */ 292 } 293