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 "qapi/error.h"
  21#include "nbd-internal.h"
  22
  23/* nbd_wr_syncv
  24 * The function may be called from coroutine or from non-coroutine context.
  25 * When called from non-coroutine context @ioc must be in blocking mode.
  26 */
  27ssize_t nbd_rwv(QIOChannel *ioc, struct iovec *iov, size_t niov, size_t length,
  28                bool do_read, Error **errp)
  29{
  30    ssize_t done = 0;
  31    struct iovec *local_iov = g_new(struct iovec, niov);
  32    struct iovec *local_iov_head = local_iov;
  33    unsigned int nlocal_iov = niov;
  34
  35    nlocal_iov = iov_copy(local_iov, nlocal_iov, iov, niov, 0, length);
  36
  37    while (nlocal_iov > 0) {
  38        ssize_t len;
  39        if (do_read) {
  40            len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp);
  41        } else {
  42            len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp);
  43        }
  44        if (len == QIO_CHANNEL_ERR_BLOCK) {
  45            /* errp should not be set */
  46            assert(qemu_in_coroutine());
  47            qio_channel_yield(ioc, do_read ? G_IO_IN : G_IO_OUT);
  48            continue;
  49        }
  50        if (len < 0) {
  51            done = -EIO;
  52            goto cleanup;
  53        }
  54
  55        if (do_read && len == 0) {
  56            break;
  57        }
  58
  59        iov_discard_front(&local_iov, &nlocal_iov, len);
  60        done += len;
  61    }
  62
  63 cleanup:
  64    g_free(local_iov_head);
  65    return done;
  66}
  67
  68/* Discard length bytes from channel.  Return -errno on failure and 0 on
  69 * success */
  70int nbd_drop(QIOChannel *ioc, size_t size, Error **errp)
  71{
  72    ssize_t ret = 0;
  73    char small[1024];
  74    char *buffer;
  75
  76    buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size));
  77    while (size > 0) {
  78        ssize_t count = MIN(65536, size);
  79        ret = nbd_read(ioc, buffer, MIN(65536, size), errp);
  80
  81        if (ret < 0) {
  82            goto cleanup;
  83        }
  84        size -= count;
  85    }
  86
  87 cleanup:
  88    if (buffer != small) {
  89        g_free(buffer);
  90    }
  91    return ret;
  92}
  93
  94
  95void nbd_tls_handshake(QIOTask *task,
  96                       void *opaque)
  97{
  98    struct NBDTLSHandshakeData *data = opaque;
  99
 100    qio_task_propagate_error(task, &data->error);
 101    data->complete = true;
 102    g_main_loop_quit(data->loop);
 103}
 104
 105
 106const char *nbd_opt_lookup(uint32_t opt)
 107{
 108    switch (opt) {
 109    case NBD_OPT_EXPORT_NAME:
 110        return "export name";
 111    case NBD_OPT_ABORT:
 112        return "abort";
 113    case NBD_OPT_LIST:
 114        return "list";
 115    case NBD_OPT_STARTTLS:
 116        return "starttls";
 117    case NBD_OPT_INFO:
 118        return "info";
 119    case NBD_OPT_GO:
 120        return "go";
 121    case NBD_OPT_STRUCTURED_REPLY:
 122        return "structured reply";
 123    default:
 124        return "<unknown>";
 125    }
 126}
 127
 128
 129const char *nbd_rep_lookup(uint32_t rep)
 130{
 131    switch (rep) {
 132    case NBD_REP_ACK:
 133        return "ack";
 134    case NBD_REP_SERVER:
 135        return "server";
 136    case NBD_REP_INFO:
 137        return "info";
 138    case NBD_REP_ERR_UNSUP:
 139        return "unsupported";
 140    case NBD_REP_ERR_POLICY:
 141        return "denied by policy";
 142    case NBD_REP_ERR_INVALID:
 143        return "invalid";
 144    case NBD_REP_ERR_PLATFORM:
 145        return "platform lacks support";
 146    case NBD_REP_ERR_TLS_REQD:
 147        return "TLS required";
 148    case NBD_REP_ERR_UNKNOWN:
 149        return "export unknown";
 150    case NBD_REP_ERR_SHUTDOWN:
 151        return "server shutting down";
 152    case NBD_REP_ERR_BLOCK_SIZE_REQD:
 153        return "block size required";
 154    default:
 155        return "<unknown>";
 156    }
 157}
 158
 159
 160const char *nbd_info_lookup(uint16_t info)
 161{
 162    switch (info) {
 163    case NBD_INFO_EXPORT:
 164        return "export";
 165    case NBD_INFO_NAME:
 166        return "name";
 167    case NBD_INFO_DESCRIPTION:
 168        return "description";
 169    case NBD_INFO_BLOCK_SIZE:
 170        return "block size";
 171    default:
 172        return "<unknown>";
 173    }
 174}
 175
 176
 177const char *nbd_cmd_lookup(uint16_t cmd)
 178{
 179    switch (cmd) {
 180    case NBD_CMD_READ:
 181        return "read";
 182    case NBD_CMD_WRITE:
 183        return "write";
 184    case NBD_CMD_DISC:
 185        return "disconnect";
 186    case NBD_CMD_FLUSH:
 187        return "flush";
 188    case NBD_CMD_TRIM:
 189        return "trim";
 190    case NBD_CMD_WRITE_ZEROES:
 191        return "write zeroes";
 192    default:
 193        return "<unknown>";
 194    }
 195}
 196