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