qemu/nbd/common.c
<<
>>
Prefs
   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 */
  28int 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
  53const 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
  82const 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
 119const 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
 136const 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
 161const 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
 187const 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
 214int 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
 253const 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
 280void 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