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