]>
Commit | Line | Data |
---|---|---|
798bfe00 FZ |
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 | ||
d38ea87a | 19 | #include "qemu/osdep.h" |
da34e65c | 20 | #include "qapi/error.h" |
798bfe00 FZ |
21 | #include "nbd-internal.h" |
22 | ||
f250a42d VSO |
23 | /* nbd_wr_syncv |
24 | * The function may be called from coroutine or from non-coroutine context. | |
25 | * When called from non-coroutine context @ioc must be in blocking mode. | |
26 | */ | |
d1fdf257 VSO |
27 | ssize_t nbd_rwv(QIOChannel *ioc, struct iovec *iov, size_t niov, size_t length, |
28 | bool do_read, Error **errp) | |
798bfe00 | 29 | { |
1c778ef7 | 30 | ssize_t done = 0; |
1c778ef7 DB |
31 | struct iovec *local_iov = g_new(struct iovec, niov); |
32 | struct iovec *local_iov_head = local_iov; | |
33 | unsigned int nlocal_iov = niov; | |
798bfe00 | 34 | |
1e2a77a8 | 35 | nlocal_iov = iov_copy(local_iov, nlocal_iov, iov, niov, 0, length); |
798bfe00 | 36 | |
1c778ef7 | 37 | while (nlocal_iov > 0) { |
798bfe00 | 38 | ssize_t len; |
798bfe00 | 39 | if (do_read) { |
f2609565 | 40 | len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp); |
798bfe00 | 41 | } else { |
f2609565 | 42 | len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp); |
798bfe00 | 43 | } |
1c778ef7 | 44 | if (len == QIO_CHANNEL_ERR_BLOCK) { |
f2609565 | 45 | /* errp should not be set */ |
f250a42d VSO |
46 | assert(qemu_in_coroutine()); |
47 | qio_channel_yield(ioc, do_read ? G_IO_IN : G_IO_OUT); | |
1c778ef7 DB |
48 | continue; |
49 | } | |
50 | if (len < 0) { | |
1c778ef7 DB |
51 | done = -EIO; |
52 | goto cleanup; | |
798bfe00 FZ |
53 | } |
54 | ||
1c778ef7 | 55 | if (do_read && len == 0) { |
798bfe00 FZ |
56 | break; |
57 | } | |
58 | ||
1c778ef7 DB |
59 | iov_discard_front(&local_iov, &nlocal_iov, len); |
60 | done += len; | |
798bfe00 FZ |
61 | } |
62 | ||
1c778ef7 DB |
63 | cleanup: |
64 | g_free(local_iov_head); | |
65 | return done; | |
798bfe00 | 66 | } |
f95910fe | 67 | |
44298024 VSO |
68 | /* Discard length bytes from channel. Return -errno on failure and 0 on |
69 | * success */ | |
70 | int nbd_drop(QIOChannel *ioc, size_t size, Error **errp) | |
71 | { | |
72 | ssize_t ret = 0; | |
73 | char small[1024]; | |
74 | char *buffer; | |
75 | ||
76 | buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size)); | |
77 | while (size > 0) { | |
78 | ssize_t count = MIN(65536, size); | |
79 | ret = nbd_read(ioc, buffer, MIN(65536, size), errp); | |
80 | ||
81 | if (ret < 0) { | |
82 | goto cleanup; | |
83 | } | |
84 | size -= count; | |
85 | } | |
86 | ||
87 | cleanup: | |
88 | if (buffer != small) { | |
89 | g_free(buffer); | |
90 | } | |
91 | return ret; | |
92 | } | |
93 | ||
f95910fe | 94 | |
60e705c5 | 95 | void nbd_tls_handshake(QIOTask *task, |
f95910fe DB |
96 | void *opaque) |
97 | { | |
98 | struct NBDTLSHandshakeData *data = opaque; | |
99 | ||
60e705c5 DB |
100 | if (qio_task_propagate_error(task, &data->error)) { |
101 | TRACE("TLS failed %s", error_get_pretty(data->error)); | |
f95910fe DB |
102 | } |
103 | data->complete = true; | |
104 | g_main_loop_quit(data->loop); | |
105 | } |