xref: /openbmc/qemu/nbd/common.c (revision 53c7c924)
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 "trace.h"
21 #include "nbd-internal.h"
22 
23 /* Discard length bytes from channel.  Return -errno on failure and 0 on
24  * success */
25 int nbd_drop(QIOChannel *ioc, size_t size, Error **errp)
26 {
27     ssize_t ret = 0;
28     char small[1024];
29     char *buffer;
30 
31     buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size));
32     while (size > 0) {
33         ssize_t count = MIN(65536, size);
34         ret = nbd_read(ioc, buffer, MIN(65536, size), NULL, errp);
35 
36         if (ret < 0) {
37             goto cleanup;
38         }
39         size -= count;
40     }
41 
42  cleanup:
43     if (buffer != small) {
44         g_free(buffer);
45     }
46     return ret;
47 }
48 
49 
50 void nbd_tls_handshake(QIOTask *task,
51                        void *opaque)
52 {
53     struct NBDTLSHandshakeData *data = opaque;
54 
55     qio_task_propagate_error(task, &data->error);
56     data->complete = true;
57     g_main_loop_quit(data->loop);
58 }
59 
60 
61 const char *nbd_opt_lookup(uint32_t opt)
62 {
63     switch (opt) {
64     case NBD_OPT_EXPORT_NAME:
65         return "export name";
66     case NBD_OPT_ABORT:
67         return "abort";
68     case NBD_OPT_LIST:
69         return "list";
70     case NBD_OPT_STARTTLS:
71         return "starttls";
72     case NBD_OPT_INFO:
73         return "info";
74     case NBD_OPT_GO:
75         return "go";
76     case NBD_OPT_STRUCTURED_REPLY:
77         return "structured reply";
78     case NBD_OPT_LIST_META_CONTEXT:
79         return "list meta context";
80     case NBD_OPT_SET_META_CONTEXT:
81         return "set meta context";
82     default:
83         return "<unknown>";
84     }
85 }
86 
87 
88 const char *nbd_rep_lookup(uint32_t rep)
89 {
90     switch (rep) {
91     case NBD_REP_ACK:
92         return "ack";
93     case NBD_REP_SERVER:
94         return "server";
95     case NBD_REP_INFO:
96         return "info";
97     case NBD_REP_META_CONTEXT:
98         return "meta context";
99     case NBD_REP_ERR_UNSUP:
100         return "unsupported";
101     case NBD_REP_ERR_POLICY:
102         return "denied by policy";
103     case NBD_REP_ERR_INVALID:
104         return "invalid";
105     case NBD_REP_ERR_PLATFORM:
106         return "platform lacks support";
107     case NBD_REP_ERR_TLS_REQD:
108         return "TLS required";
109     case NBD_REP_ERR_UNKNOWN:
110         return "export unknown";
111     case NBD_REP_ERR_SHUTDOWN:
112         return "server shutting down";
113     case NBD_REP_ERR_BLOCK_SIZE_REQD:
114         return "block size required";
115     default:
116         return "<unknown>";
117     }
118 }
119 
120 
121 const char *nbd_info_lookup(uint16_t info)
122 {
123     switch (info) {
124     case NBD_INFO_EXPORT:
125         return "export";
126     case NBD_INFO_NAME:
127         return "name";
128     case NBD_INFO_DESCRIPTION:
129         return "description";
130     case NBD_INFO_BLOCK_SIZE:
131         return "block size";
132     default:
133         return "<unknown>";
134     }
135 }
136 
137 
138 const char *nbd_cmd_lookup(uint16_t cmd)
139 {
140     switch (cmd) {
141     case NBD_CMD_READ:
142         return "read";
143     case NBD_CMD_WRITE:
144         return "write";
145     case NBD_CMD_DISC:
146         return "disconnect";
147     case NBD_CMD_FLUSH:
148         return "flush";
149     case NBD_CMD_TRIM:
150         return "trim";
151     case NBD_CMD_CACHE:
152         return "cache";
153     case NBD_CMD_WRITE_ZEROES:
154         return "write zeroes";
155     case NBD_CMD_BLOCK_STATUS:
156         return "block status";
157     default:
158         return "<unknown>";
159     }
160 }
161 
162 
163 const char *nbd_reply_type_lookup(uint16_t type)
164 {
165     switch (type) {
166     case NBD_REPLY_TYPE_NONE:
167         return "none";
168     case NBD_REPLY_TYPE_OFFSET_DATA:
169         return "data";
170     case NBD_REPLY_TYPE_OFFSET_HOLE:
171         return "hole";
172     case NBD_REPLY_TYPE_BLOCK_STATUS:
173         return "block status";
174     case NBD_REPLY_TYPE_ERROR:
175         return "generic error";
176     case NBD_REPLY_TYPE_ERROR_OFFSET:
177         return "error at offset";
178     default:
179         if (type & (1 << 15)) {
180             return "<unknown error>";
181         }
182         return "<unknown>";
183     }
184 }
185 
186 
187 const char *nbd_err_lookup(int err)
188 {
189     switch (err) {
190     case NBD_SUCCESS:
191         return "success";
192     case NBD_EPERM:
193         return "EPERM";
194     case NBD_EIO:
195         return "EIO";
196     case NBD_ENOMEM:
197         return "ENOMEM";
198     case NBD_EINVAL:
199         return "EINVAL";
200     case NBD_ENOSPC:
201         return "ENOSPC";
202     case NBD_EOVERFLOW:
203         return "EOVERFLOW";
204     case NBD_ENOTSUP:
205         return "ENOTSUP";
206     case NBD_ESHUTDOWN:
207         return "ESHUTDOWN";
208     default:
209         return "<unknown>";
210     }
211 }
212 
213 
214 int nbd_errno_to_system_errno(int err)
215 {
216     int ret;
217     switch (err) {
218     case NBD_SUCCESS:
219         ret = 0;
220         break;
221     case NBD_EPERM:
222         ret = EPERM;
223         break;
224     case NBD_EIO:
225         ret = EIO;
226         break;
227     case NBD_ENOMEM:
228         ret = ENOMEM;
229         break;
230     case NBD_ENOSPC:
231         ret = ENOSPC;
232         break;
233     case NBD_EOVERFLOW:
234         ret = EOVERFLOW;
235         break;
236     case NBD_ENOTSUP:
237         ret = ENOTSUP;
238         break;
239     case NBD_ESHUTDOWN:
240         ret = ESHUTDOWN;
241         break;
242     default:
243         trace_nbd_unknown_error(err);
244         /* fallthrough */
245     case NBD_EINVAL:
246         ret = EINVAL;
247         break;
248     }
249     return ret;
250 }
251 
252 
253 const char *nbd_mode_lookup(NBDMode mode)
254 {
255     switch (mode) {
256     case NBD_MODE_OLDSTYLE:
257         return "oldstyle";
258     case NBD_MODE_EXPORT_NAME:
259         return "export name only";
260     case NBD_MODE_SIMPLE:
261         return "simple headers";
262     case NBD_MODE_STRUCTURED:
263         return "structured replies";
264     default:
265         return "<unknown>";
266     }
267 }
268