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 "io/channel-socket.h"
22 #include "qapi/error.h"
23 #include "qemu/units.h"
24 #include "nbd-internal.h"
25
26 /* Discard length bytes from channel. Return -errno on failure and 0 on
27 * success */
nbd_drop(QIOChannel * ioc,size_t size,Error ** errp)28 int nbd_drop(QIOChannel *ioc, size_t size, Error **errp)
29 {
30 ssize_t ret = 0;
31 char small[1024];
32 char *buffer;
33
34 buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size));
35 while (size > 0) {
36 ssize_t count = MIN(65536, size);
37 ret = nbd_read(ioc, buffer, MIN(65536, size), NULL, errp);
38
39 if (ret < 0) {
40 goto cleanup;
41 }
42 size -= count;
43 }
44
45 cleanup:
46 if (buffer != small) {
47 g_free(buffer);
48 }
49 return ret;
50 }
51
52
nbd_opt_lookup(uint32_t opt)53 const char *nbd_opt_lookup(uint32_t opt)
54 {
55 switch (opt) {
56 case NBD_OPT_EXPORT_NAME:
57 return "export name";
58 case NBD_OPT_ABORT:
59 return "abort";
60 case NBD_OPT_LIST:
61 return "list";
62 case NBD_OPT_STARTTLS:
63 return "starttls";
64 case NBD_OPT_INFO:
65 return "info";
66 case NBD_OPT_GO:
67 return "go";
68 case NBD_OPT_STRUCTURED_REPLY:
69 return "structured reply";
70 case NBD_OPT_LIST_META_CONTEXT:
71 return "list meta context";
72 case NBD_OPT_SET_META_CONTEXT:
73 return "set meta context";
74 case NBD_OPT_EXTENDED_HEADERS:
75 return "extended headers";
76 default:
77 return "<unknown>";
78 }
79 }
80
81
nbd_rep_lookup(uint32_t rep)82 const char *nbd_rep_lookup(uint32_t rep)
83 {
84 switch (rep) {
85 case NBD_REP_ACK:
86 return "ack";
87 case NBD_REP_SERVER:
88 return "server";
89 case NBD_REP_INFO:
90 return "info";
91 case NBD_REP_META_CONTEXT:
92 return "meta context";
93 case NBD_REP_ERR_UNSUP:
94 return "unsupported";
95 case NBD_REP_ERR_POLICY:
96 return "denied by policy";
97 case NBD_REP_ERR_INVALID:
98 return "invalid";
99 case NBD_REP_ERR_PLATFORM:
100 return "platform lacks support";
101 case NBD_REP_ERR_TLS_REQD:
102 return "TLS required";
103 case NBD_REP_ERR_UNKNOWN:
104 return "export unknown";
105 case NBD_REP_ERR_SHUTDOWN:
106 return "server shutting down";
107 case NBD_REP_ERR_BLOCK_SIZE_REQD:
108 return "block size required";
109 case NBD_REP_ERR_TOO_BIG:
110 return "option payload too big";
111 case NBD_REP_ERR_EXT_HEADER_REQD:
112 return "extended headers required";
113 default:
114 return "<unknown>";
115 }
116 }
117
118
nbd_info_lookup(uint16_t info)119 const char *nbd_info_lookup(uint16_t info)
120 {
121 switch (info) {
122 case NBD_INFO_EXPORT:
123 return "export";
124 case NBD_INFO_NAME:
125 return "name";
126 case NBD_INFO_DESCRIPTION:
127 return "description";
128 case NBD_INFO_BLOCK_SIZE:
129 return "block size";
130 default:
131 return "<unknown>";
132 }
133 }
134
135
nbd_cmd_lookup(uint16_t cmd)136 const char *nbd_cmd_lookup(uint16_t cmd)
137 {
138 switch (cmd) {
139 case NBD_CMD_READ:
140 return "read";
141 case NBD_CMD_WRITE:
142 return "write";
143 case NBD_CMD_DISC:
144 return "disconnect";
145 case NBD_CMD_FLUSH:
146 return "flush";
147 case NBD_CMD_TRIM:
148 return "trim";
149 case NBD_CMD_CACHE:
150 return "cache";
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
nbd_reply_type_lookup(uint16_t type)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 (32-bit)";
172 case NBD_REPLY_TYPE_BLOCK_STATUS_EXT:
173 return "block status (64-bit)";
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
nbd_err_lookup(int err)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
nbd_errno_to_system_errno(int err)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
nbd_mode_lookup(NBDMode mode)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 case NBD_MODE_EXTENDED:
265 return "extended headers";
266 default:
267 return "<unknown>";
268 }
269 }
270
271 /*
272 * Testing shows that 2m send buffer is optimal. Changing the receive buffer
273 * size has no effect on performance.
274 * On Linux we need to increase net.core.wmem_max to make this effective.
275 */
276 #if defined(__APPLE__) || defined(__linux__)
277 #define UNIX_STREAM_SOCKET_SEND_BUFFER_SIZE (2 * MiB)
278 #endif
279
nbd_set_socket_send_buffer(QIOChannelSocket * sioc)280 void nbd_set_socket_send_buffer(QIOChannelSocket *sioc)
281 {
282 #ifdef UNIX_STREAM_SOCKET_SEND_BUFFER_SIZE
283 if (sioc->localAddr.ss_family == AF_UNIX) {
284 size_t size = UNIX_STREAM_SOCKET_SEND_BUFFER_SIZE;
285 Error *errp = NULL;
286
287 if (qio_channel_socket_set_send_buffer(sioc, size, &errp) < 0) {
288 warn_report_err(errp);
289 }
290 }
291 #endif /* UNIX_STREAM_SOCKET_SEND_BUFFER_SIZE */
292 }
293