]>
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(); | |
dacca04c PB |
53 | } else if (done) { |
54 | /* XXX this is needed by nbd_reply_ready. */ | |
1c778ef7 DB |
55 | qio_channel_wait(ioc, |
56 | do_read ? G_IO_IN : G_IO_OUT); | |
dacca04c PB |
57 | } else { |
58 | return -EAGAIN; | |
798bfe00 | 59 | } |
1c778ef7 DB |
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; | |
798bfe00 FZ |
68 | } |
69 | ||
1c778ef7 | 70 | if (do_read && len == 0) { |
798bfe00 FZ |
71 | break; |
72 | } | |
73 | ||
1c778ef7 DB |
74 | iov_discard_front(&local_iov, &nlocal_iov, len); |
75 | done += len; | |
798bfe00 FZ |
76 | } |
77 | ||
1c778ef7 DB |
78 | cleanup: |
79 | g_free(local_iov_head); | |
80 | return done; | |
798bfe00 | 81 | } |
f95910fe DB |
82 | |
83 | ||
84 | void 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 | } |