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
  23ssize_t nbd_wr_syncv(QIOChannel *ioc,
  24                     struct iovec *iov,
  25                     size_t niov,
  26                     size_t offset,
  27                     size_t length,
  28                     bool do_read)
  29{
  30    ssize_t done = 0;
  31    Error *local_err = NULL;
  32    struct iovec *local_iov = g_new(struct iovec, niov);
  33    struct iovec *local_iov_head = local_iov;
  34    unsigned int nlocal_iov = niov;
  35
  36    nlocal_iov = iov_copy(local_iov, nlocal_iov,
  37                          iov, niov,
  38                          offset, length);
  39
  40    while (nlocal_iov > 0) {
  41        ssize_t len;
  42        if (do_read) {
  43            len = qio_channel_readv(ioc, local_iov, nlocal_iov, &local_err);
  44        } else {
  45            len = qio_channel_writev(ioc, local_iov, nlocal_iov, &local_err);
  46        }
  47        if (len == QIO_CHANNEL_ERR_BLOCK) {
  48            if (qemu_in_coroutine()) {
  49                /* XXX figure out if we can create a variant on
  50                 * qio_channel_yield() that works with AIO contexts
  51                 * and consider using that in this branch */
  52                qemu_coroutine_yield();
  53            } else if (done) {
  54                /* XXX this is needed by nbd_reply_ready.  */
  55                qio_channel_wait(ioc,
  56                                 do_read ? G_IO_IN : G_IO_OUT);
  57            } else {
  58                return -EAGAIN;
  59            }
  60            continue;
  61        }
  62        if (len < 0) {
  63            TRACE("I/O error: %s", error_get_pretty(local_err));
  64            error_free(local_err);
  65            /* XXX handle Error objects */
  66            done = -EIO;
  67            goto cleanup;
  68        }
  69
  70        if (do_read && len == 0) {
  71            break;
  72        }
  73
  74        iov_discard_front(&local_iov, &nlocal_iov, len);
  75        done += len;
  76    }
  77
  78 cleanup:
  79    g_free(local_iov_head);
  80    return done;
  81}
  82
  83
  84void nbd_tls_handshake(Object *src,
  85                       Error *err,
  86                       void *opaque)
  87{
  88    struct NBDTLSHandshakeData *data = opaque;
  89
  90    if (err) {
  91        TRACE("TLS failed %s", error_get_pretty(err));
  92        data->error = error_copy(err);
  93    }
  94    data->complete = true;
  95    g_main_loop_quit(data->loop);
  96}
  97