]>
Commit | Line | Data |
---|---|---|
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 | ssize_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 | qio_channel_yield(ioc, do_read ? G_IO_IN : G_IO_OUT); | |
47 | } else { | |
48 | return -EAGAIN; | |
49 | } | |
50 | continue; | |
51 | } | |
52 | if (len < 0) { | |
53 | TRACE("I/O error: %s", error_get_pretty(local_err)); | |
54 | error_free(local_err); | |
55 | /* XXX handle Error objects */ | |
56 | done = -EIO; | |
57 | goto cleanup; | |
58 | } | |
59 | ||
60 | if (do_read && len == 0) { | |
61 | break; | |
62 | } | |
63 | ||
64 | iov_discard_front(&local_iov, &nlocal_iov, len); | |
65 | done += len; | |
66 | } | |
67 | ||
68 | cleanup: | |
69 | g_free(local_iov_head); | |
70 | return done; | |
71 | } | |
72 | ||
73 | ||
74 | void nbd_tls_handshake(QIOTask *task, | |
75 | void *opaque) | |
76 | { | |
77 | struct NBDTLSHandshakeData *data = opaque; | |
78 | ||
79 | if (qio_task_propagate_error(task, &data->error)) { | |
80 | TRACE("TLS failed %s", error_get_pretty(data->error)); | |
81 | } | |
82 | data->complete = true; | |
83 | g_main_loop_quit(data->loop); | |
84 | } |