xref: /openbmc/qemu/nbd/common.c (revision fe7f9b8e)
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), 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_WRITE_ZEROES:
152         return "write zeroes";
153     case NBD_CMD_BLOCK_STATUS:
154         return "block status";
155     default:
156         return "<unknown>";
157     }
158 }
159 
160 
161 const char *nbd_reply_type_lookup(uint16_t type)
162 {
163     switch (type) {
164     case NBD_REPLY_TYPE_NONE:
165         return "none";
166     case NBD_REPLY_TYPE_OFFSET_DATA:
167         return "data";
168     case NBD_REPLY_TYPE_OFFSET_HOLE:
169         return "hole";
170     case NBD_REPLY_TYPE_BLOCK_STATUS:
171         return "block status";
172     case NBD_REPLY_TYPE_ERROR:
173         return "generic error";
174     case NBD_REPLY_TYPE_ERROR_OFFSET:
175         return "error at offset";
176     default:
177         if (type & (1 << 15)) {
178             return "<unknown error>";
179         }
180         return "<unknown>";
181     }
182 }
183 
184 
185 const char *nbd_err_lookup(int err)
186 {
187     switch (err) {
188     case NBD_SUCCESS:
189         return "success";
190     case NBD_EPERM:
191         return "EPERM";
192     case NBD_EIO:
193         return "EIO";
194     case NBD_ENOMEM:
195         return "ENOMEM";
196     case NBD_EINVAL:
197         return "EINVAL";
198     case NBD_ENOSPC:
199         return "ENOSPC";
200     case NBD_EOVERFLOW:
201         return "EOVERFLOW";
202     case NBD_ESHUTDOWN:
203         return "ESHUTDOWN";
204     default:
205         return "<unknown>";
206     }
207 }
208 
209 
210 int nbd_errno_to_system_errno(int err)
211 {
212     int ret;
213     switch (err) {
214     case NBD_SUCCESS:
215         ret = 0;
216         break;
217     case NBD_EPERM:
218         ret = EPERM;
219         break;
220     case NBD_EIO:
221         ret = EIO;
222         break;
223     case NBD_ENOMEM:
224         ret = ENOMEM;
225         break;
226     case NBD_ENOSPC:
227         ret = ENOSPC;
228         break;
229     case NBD_EOVERFLOW:
230         ret = EOVERFLOW;
231         break;
232     case NBD_ESHUTDOWN:
233         ret = ESHUTDOWN;
234         break;
235     default:
236         trace_nbd_unknown_error(err);
237         /* fallthrough */
238     case NBD_EINVAL:
239         ret = EINVAL;
240         break;
241     }
242     return ret;
243 }
244