xref: /openbmc/qemu/nbd/common.c (revision 3e3df0d8)
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     case NBD_OPT_EXTENDED_HEADERS:
83         return "extended headers";
84     default:
85         return "<unknown>";
86     }
87 }
88 
89 
90 const char *nbd_rep_lookup(uint32_t rep)
91 {
92     switch (rep) {
93     case NBD_REP_ACK:
94         return "ack";
95     case NBD_REP_SERVER:
96         return "server";
97     case NBD_REP_INFO:
98         return "info";
99     case NBD_REP_META_CONTEXT:
100         return "meta context";
101     case NBD_REP_ERR_UNSUP:
102         return "unsupported";
103     case NBD_REP_ERR_POLICY:
104         return "denied by policy";
105     case NBD_REP_ERR_INVALID:
106         return "invalid";
107     case NBD_REP_ERR_PLATFORM:
108         return "platform lacks support";
109     case NBD_REP_ERR_TLS_REQD:
110         return "TLS required";
111     case NBD_REP_ERR_UNKNOWN:
112         return "export unknown";
113     case NBD_REP_ERR_SHUTDOWN:
114         return "server shutting down";
115     case NBD_REP_ERR_BLOCK_SIZE_REQD:
116         return "block size required";
117     case NBD_REP_ERR_TOO_BIG:
118         return "option payload too big";
119     case NBD_REP_ERR_EXT_HEADER_REQD:
120         return "extended headers required";
121     default:
122         return "<unknown>";
123     }
124 }
125 
126 
127 const char *nbd_info_lookup(uint16_t info)
128 {
129     switch (info) {
130     case NBD_INFO_EXPORT:
131         return "export";
132     case NBD_INFO_NAME:
133         return "name";
134     case NBD_INFO_DESCRIPTION:
135         return "description";
136     case NBD_INFO_BLOCK_SIZE:
137         return "block size";
138     default:
139         return "<unknown>";
140     }
141 }
142 
143 
144 const char *nbd_cmd_lookup(uint16_t cmd)
145 {
146     switch (cmd) {
147     case NBD_CMD_READ:
148         return "read";
149     case NBD_CMD_WRITE:
150         return "write";
151     case NBD_CMD_DISC:
152         return "disconnect";
153     case NBD_CMD_FLUSH:
154         return "flush";
155     case NBD_CMD_TRIM:
156         return "trim";
157     case NBD_CMD_CACHE:
158         return "cache";
159     case NBD_CMD_WRITE_ZEROES:
160         return "write zeroes";
161     case NBD_CMD_BLOCK_STATUS:
162         return "block status";
163     default:
164         return "<unknown>";
165     }
166 }
167 
168 
169 const char *nbd_reply_type_lookup(uint16_t type)
170 {
171     switch (type) {
172     case NBD_REPLY_TYPE_NONE:
173         return "none";
174     case NBD_REPLY_TYPE_OFFSET_DATA:
175         return "data";
176     case NBD_REPLY_TYPE_OFFSET_HOLE:
177         return "hole";
178     case NBD_REPLY_TYPE_BLOCK_STATUS:
179         return "block status (32-bit)";
180     case NBD_REPLY_TYPE_BLOCK_STATUS_EXT:
181         return "block status (64-bit)";
182     case NBD_REPLY_TYPE_ERROR:
183         return "generic error";
184     case NBD_REPLY_TYPE_ERROR_OFFSET:
185         return "error at offset";
186     default:
187         if (type & (1 << 15)) {
188             return "<unknown error>";
189         }
190         return "<unknown>";
191     }
192 }
193 
194 
195 const char *nbd_err_lookup(int err)
196 {
197     switch (err) {
198     case NBD_SUCCESS:
199         return "success";
200     case NBD_EPERM:
201         return "EPERM";
202     case NBD_EIO:
203         return "EIO";
204     case NBD_ENOMEM:
205         return "ENOMEM";
206     case NBD_EINVAL:
207         return "EINVAL";
208     case NBD_ENOSPC:
209         return "ENOSPC";
210     case NBD_EOVERFLOW:
211         return "EOVERFLOW";
212     case NBD_ENOTSUP:
213         return "ENOTSUP";
214     case NBD_ESHUTDOWN:
215         return "ESHUTDOWN";
216     default:
217         return "<unknown>";
218     }
219 }
220 
221 
222 int nbd_errno_to_system_errno(int err)
223 {
224     int ret;
225     switch (err) {
226     case NBD_SUCCESS:
227         ret = 0;
228         break;
229     case NBD_EPERM:
230         ret = EPERM;
231         break;
232     case NBD_EIO:
233         ret = EIO;
234         break;
235     case NBD_ENOMEM:
236         ret = ENOMEM;
237         break;
238     case NBD_ENOSPC:
239         ret = ENOSPC;
240         break;
241     case NBD_EOVERFLOW:
242         ret = EOVERFLOW;
243         break;
244     case NBD_ENOTSUP:
245         ret = ENOTSUP;
246         break;
247     case NBD_ESHUTDOWN:
248         ret = ESHUTDOWN;
249         break;
250     default:
251         trace_nbd_unknown_error(err);
252         /* fallthrough */
253     case NBD_EINVAL:
254         ret = EINVAL;
255         break;
256     }
257     return ret;
258 }
259 
260 
261 const char *nbd_mode_lookup(NBDMode mode)
262 {
263     switch (mode) {
264     case NBD_MODE_OLDSTYLE:
265         return "oldstyle";
266     case NBD_MODE_EXPORT_NAME:
267         return "export name only";
268     case NBD_MODE_SIMPLE:
269         return "simple headers";
270     case NBD_MODE_STRUCTURED:
271         return "structured replies";
272     case NBD_MODE_EXTENDED:
273         return "extended headers";
274     default:
275         return "<unknown>";
276     }
277 }
278