]>
Commit | Line | Data |
---|---|---|
798bfe00 FZ |
1 | /* |
2 | * Copyright (C) 2005 Anthony Liguori <[email protected]> | |
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 | ||
d38ea87a | 19 | #include "qemu/osdep.h" |
da34e65c | 20 | #include "qapi/error.h" |
798bfe00 FZ |
21 | #include "nbd-internal.h" |
22 | ||
1c778ef7 DB |
23 | ssize_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) | |
798bfe00 | 29 | { |
1c778ef7 DB |
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; | |
798bfe00 | 35 | |
1c778ef7 DB |
36 | nlocal_iov = iov_copy(local_iov, nlocal_iov, |
37 | iov, niov, | |
38 | offset, length); | |
798bfe00 | 39 | |
1c778ef7 | 40 | while (nlocal_iov > 0) { |
798bfe00 | 41 | ssize_t len; |
798bfe00 | 42 | if (do_read) { |
1c778ef7 | 43 | len = qio_channel_readv(ioc, local_iov, nlocal_iov, &local_err); |
798bfe00 | 44 | } else { |
1c778ef7 | 45 | len = qio_channel_writev(ioc, local_iov, nlocal_iov, &local_err); |
798bfe00 | 46 | } |
1c778ef7 DB |
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 { | |
54 | qio_channel_wait(ioc, | |
55 | do_read ? G_IO_IN : G_IO_OUT); | |
798bfe00 | 56 | } |
1c778ef7 DB |
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; | |
798bfe00 FZ |
65 | } |
66 | ||
1c778ef7 | 67 | if (do_read && len == 0) { |
798bfe00 FZ |
68 | break; |
69 | } | |
70 | ||
1c778ef7 DB |
71 | iov_discard_front(&local_iov, &nlocal_iov, len); |
72 | done += len; | |
798bfe00 FZ |
73 | } |
74 | ||
1c778ef7 DB |
75 | cleanup: |
76 | g_free(local_iov_head); | |
77 | return done; | |
798bfe00 | 78 | } |
f95910fe DB |
79 | |
80 | ||
81 | void 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 | } |