blob: 6caa8d17be7370e493a6d2aa152511f3fade8536 [file] [log] [blame]
ths75818252008-07-03 13:41:03 +00001/*
Eric Blakea16a7902018-01-10 17:08:20 -06002 * Copyright (C) 2016-2018 Red Hat, Inc.
bellard7a5ca862008-05-27 21:13:40 +00003 * Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws>
4 *
Fam Zheng798bfe02016-01-14 16:41:02 +08005 * Network Block Device Server Side
bellard7a5ca862008-05-27 21:13:40 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; under version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
ths75818252008-07-03 13:41:03 +000018 */
bellard7a5ca862008-05-27 21:13:40 +000019
Peter Maydelld38ea872016-01-29 17:50:05 +000020#include "qemu/osdep.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010021#include "qapi/error.h"
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +030022#include "trace.h"
Fam Zheng798bfe02016-01-14 16:41:02 +080023#include "nbd-internal.h"
Paolo Bonzinica441482015-05-07 17:25:10 +020024
25static int system_errno_to_nbd_errno(int err)
26{
27 switch (err) {
28 case 0:
29 return NBD_SUCCESS;
30 case EPERM:
Eric Blakec0301fc2016-04-05 21:35:02 -060031 case EROFS:
Paolo Bonzinica441482015-05-07 17:25:10 +020032 return NBD_EPERM;
33 case EIO:
34 return NBD_EIO;
35 case ENOMEM:
36 return NBD_ENOMEM;
37#ifdef EDQUOT
38 case EDQUOT:
39#endif
40 case EFBIG:
41 case ENOSPC:
42 return NBD_ENOSPC;
Eric Blakebae245d2017-10-27 12:40:28 +020043 case EOVERFLOW:
44 return NBD_EOVERFLOW;
Eric Blakeb6f5d3b2016-10-14 13:33:16 -050045 case ESHUTDOWN:
46 return NBD_ESHUTDOWN;
Paolo Bonzinica441482015-05-07 17:25:10 +020047 case EINVAL:
48 default:
49 return NBD_EINVAL;
50 }
51}
52
Paolo Bonzini9a304d22012-08-22 15:30:31 +020053/* Definitions for opaque data types */
54
Eric Blake315f78a2016-10-14 13:33:05 -050055typedef struct NBDRequestData NBDRequestData;
Paolo Bonzini9a304d22012-08-22 15:30:31 +020056
Eric Blake315f78a2016-10-14 13:33:05 -050057struct NBDRequestData {
58 QSIMPLEQ_ENTRY(NBDRequestData) entry;
Paolo Bonzini9a304d22012-08-22 15:30:31 +020059 NBDClient *client;
60 uint8_t *data;
Eric Blake29b6c3b2016-05-11 16:39:37 -060061 bool complete;
Paolo Bonzini9a304d22012-08-22 15:30:31 +020062};
63
64struct NBDExport {
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +020065 int refcount;
Paolo Bonzini0ddf08d2012-09-18 13:59:03 +020066 void (*close)(NBDExport *exp);
67
Max Reitzaadf99a2014-11-18 12:21:18 +010068 BlockBackend *blk;
Paolo Bonziniee0a19e2012-08-22 15:59:23 +020069 char *name;
Eric Blakeb1a75b32016-10-14 13:33:03 -050070 char *description;
Paolo Bonzini9a304d22012-08-22 15:30:31 +020071 off_t dev_offset;
72 off_t size;
Eric Blake7423f412016-07-21 13:34:46 -060073 uint16_t nbdflags;
Paolo Bonzini4b9441f2012-09-18 13:58:25 +020074 QTAILQ_HEAD(, NBDClient) clients;
Paolo Bonziniee0a19e2012-08-22 15:59:23 +020075 QTAILQ_ENTRY(NBDExport) next;
Max Reitz958c7172014-06-20 21:57:32 +020076
77 AioContext *ctx;
Max Reitz741cc432016-01-29 16:36:06 +010078
Kevin Wolfcd7fca92016-07-06 11:22:39 +020079 BlockBackend *eject_notifier_blk;
Max Reitz741cc432016-01-29 16:36:06 +010080 Notifier eject_notifier;
Paolo Bonzini9a304d22012-08-22 15:30:31 +020081};
82
Paolo Bonziniee0a19e2012-08-22 15:59:23 +020083static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
84
Paolo Bonzini9a304d22012-08-22 15:30:31 +020085struct NBDClient {
86 int refcount;
Eric Blake0c9390d2017-06-08 17:26:17 -050087 void (*close_fn)(NBDClient *client, bool negotiated);
Paolo Bonzini9a304d22012-08-22 15:30:31 +020088
89 NBDExport *exp;
Daniel P. Berrangef95910f2016-02-10 18:41:11 +000090 QCryptoTLSCreds *tlscreds;
91 char *tlsaclname;
Daniel P. Berrange1c778ef2016-02-10 18:41:04 +000092 QIOChannelSocket *sioc; /* The underlying data channel */
93 QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
Paolo Bonzini9a304d22012-08-22 15:30:31 +020094
95 Coroutine *recv_coroutine;
96
97 CoMutex send_lock;
98 Coroutine *send_coroutine;
99
Paolo Bonzini4b9441f2012-09-18 13:58:25 +0200100 QTAILQ_ENTRY(NBDClient) next;
Paolo Bonzini9a304d22012-08-22 15:30:31 +0200101 int nb_requests;
Paolo Bonziniff2b68a2012-08-22 18:45:12 +0200102 bool closing;
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +0200103
104 bool structured_reply;
Paolo Bonzini9a304d22012-08-22 15:30:31 +0200105
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600106 uint32_t opt; /* Current option being negotiated */
107 uint32_t optlen; /* remaining length of data in ioc for the option being
108 negotiated now */
109};
bellard7a5ca862008-05-27 21:13:40 +0000110
Paolo Bonziniff829112017-02-13 14:52:24 +0100111static void nbd_client_receive_next_request(NBDClient *client);
Max Reitz958c7172014-06-20 21:57:32 +0200112
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200113/* Basic flow for negotiation
bellard7a5ca862008-05-27 21:13:40 +0000114
115 Server Client
bellard7a5ca862008-05-27 21:13:40 +0000116 Negotiate
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200117
118 or
119
120 Server Client
121 Negotiate #1
122 Option
123 Negotiate #2
124
125 ----
126
127 followed by
128
129 Server Client
bellard7a5ca862008-05-27 21:13:40 +0000130 Request
131 Response
132 Request
133 Response
134 ...
135 ...
136 Request (type == 2)
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200137
bellard7a5ca862008-05-27 21:13:40 +0000138*/
139
Vladimir Sementsov-Ogievskiy1d179222018-01-10 17:08:25 -0600140static inline void set_be_option_rep(NBDOptionReply *rep, uint32_t option,
141 uint32_t type, uint32_t length)
142{
143 stq_be_p(&rep->magic, NBD_REP_MAGIC);
144 stl_be_p(&rep->option, option);
145 stl_be_p(&rep->type, type);
146 stl_be_p(&rep->length, length);
147}
148
Eric Blake526e5c62016-10-14 13:33:08 -0500149/* Send a reply header, including length, but no payload.
150 * Return -errno on error, 0 on success. */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600151static int nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type,
152 uint32_t len, Error **errp)
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200153{
Vladimir Sementsov-Ogievskiy1d179222018-01-10 17:08:25 -0600154 NBDOptionReply rep;
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100155
Vladimir Sementsov-Ogievskiy1d179222018-01-10 17:08:25 -0600156 trace_nbd_negotiate_send_rep_len(client->opt, nbd_opt_lookup(client->opt),
Eric Blake3736cc52017-07-07 15:30:43 -0500157 type, nbd_rep_lookup(type), len);
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000158
Eric Blakef37708f2017-07-07 15:30:46 -0500159 assert(len < NBD_MAX_BUFFER_SIZE);
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300160
Vladimir Sementsov-Ogievskiy1d179222018-01-10 17:08:25 -0600161 set_be_option_rep(&rep, client->opt, type, len);
162 return nbd_write(client->ioc, &rep, sizeof(rep), errp);
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100163}
164
Eric Blake526e5c62016-10-14 13:33:08 -0500165/* Send a reply header with default 0 length.
166 * Return -errno on error, 0 on success. */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600167static int nbd_negotiate_send_rep(NBDClient *client, uint32_t type,
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300168 Error **errp)
Eric Blake526e5c62016-10-14 13:33:08 -0500169{
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600170 return nbd_negotiate_send_rep_len(client, type, 0, errp);
Eric Blake526e5c62016-10-14 13:33:08 -0500171}
172
Eric Blake36683282016-10-14 13:33:09 -0500173/* Send an error reply.
174 * Return -errno on error, 0 on success. */
Eric Blake41f5dfa2018-01-10 17:08:23 -0600175static int GCC_FMT_ATTR(4, 0)
176nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type,
177 Error **errp, const char *fmt, va_list va)
Eric Blake36683282016-10-14 13:33:09 -0500178{
Eric Blake36683282016-10-14 13:33:09 -0500179 char *msg;
180 int ret;
181 size_t len;
182
Eric Blake36683282016-10-14 13:33:09 -0500183 msg = g_strdup_vprintf(fmt, va);
Eric Blake36683282016-10-14 13:33:09 -0500184 len = strlen(msg);
185 assert(len < 4096);
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300186 trace_nbd_negotiate_send_rep_err(msg);
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600187 ret = nbd_negotiate_send_rep_len(client, type, len, errp);
Eric Blake36683282016-10-14 13:33:09 -0500188 if (ret < 0) {
189 goto out;
190 }
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600191 if (nbd_write(client->ioc, msg, len, errp) < 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300192 error_prepend(errp, "write failed (error message): ");
Eric Blake36683282016-10-14 13:33:09 -0500193 ret = -EIO;
194 } else {
195 ret = 0;
196 }
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300197
Eric Blake36683282016-10-14 13:33:09 -0500198out:
199 g_free(msg);
200 return ret;
201}
202
Eric Blake41f5dfa2018-01-10 17:08:23 -0600203/* Send an error reply.
204 * Return -errno on error, 0 on success. */
205static int GCC_FMT_ATTR(4, 5)
206nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
207 Error **errp, const char *fmt, ...)
208{
209 va_list va;
210 int ret;
211
212 va_start(va, fmt);
213 ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va);
214 va_end(va);
215 return ret;
216}
217
Eric Blake894e0282018-01-10 17:08:24 -0600218/* Drop remainder of the current option, and send a reply with the
219 * given error type and message. Return -errno on read or write
220 * failure; or 0 if connection is still live. */
221static int GCC_FMT_ATTR(4, 5)
222nbd_opt_drop(NBDClient *client, uint32_t type, Error **errp,
223 const char *fmt, ...)
224{
225 int ret = nbd_drop(client->ioc, client->optlen, errp);
226 va_list va;
227
228 client->optlen = 0;
229 if (!ret) {
230 va_start(va, fmt);
231 ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va);
232 va_end(va);
233 }
234 return ret;
235}
236
237/* Read size bytes from the unparsed payload of the current option.
238 * Return -errno on I/O error, 0 if option was completely handled by
239 * sending a reply about inconsistent lengths, or 1 on success. */
240static int nbd_opt_read(NBDClient *client, void *buffer, size_t size,
241 Error **errp)
242{
243 if (size > client->optlen) {
244 return nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp,
245 "Inconsistent lengths in option %s",
246 nbd_opt_lookup(client->opt));
247 }
248 client->optlen -= size;
249 return qio_channel_read_all(client->ioc, buffer, size, errp) < 0 ? -EIO : 1;
250}
251
Eric Blake526e5c62016-10-14 13:33:08 -0500252/* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
253 * Return -errno on error, 0 on success. */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600254static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300255 Error **errp)
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100256{
Eric Blakeb1a75b32016-10-14 13:33:03 -0500257 size_t name_len, desc_len;
Eric Blake526e5c62016-10-14 13:33:08 -0500258 uint32_t len;
Eric Blakeb1a75b32016-10-14 13:33:03 -0500259 const char *name = exp->name ? exp->name : "";
260 const char *desc = exp->description ? exp->description : "";
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600261 QIOChannel *ioc = client->ioc;
Vladimir Sementsov-Ogievskiy2e5c9ad2017-06-02 18:01:49 +0300262 int ret;
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100263
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300264 trace_nbd_negotiate_send_rep_list(name, desc);
Eric Blakeb1a75b32016-10-14 13:33:03 -0500265 name_len = strlen(name);
266 desc_len = strlen(desc);
Eric Blake526e5c62016-10-14 13:33:08 -0500267 len = name_len + desc_len + sizeof(len);
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600268 ret = nbd_negotiate_send_rep_len(client, NBD_REP_SERVER, len, errp);
Vladimir Sementsov-Ogievskiy2e5c9ad2017-06-02 18:01:49 +0300269 if (ret < 0) {
270 return ret;
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100271 }
Eric Blake526e5c62016-10-14 13:33:08 -0500272
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100273 len = cpu_to_be32(name_len);
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300274 if (nbd_write(ioc, &len, sizeof(len), errp) < 0) {
275 error_prepend(errp, "write failed (name length): ");
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100276 return -EINVAL;
277 }
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300278
279 if (nbd_write(ioc, name, name_len, errp) < 0) {
280 error_prepend(errp, "write failed (name buffer): ");
Eric Blakeb1a75b32016-10-14 13:33:03 -0500281 return -EINVAL;
282 }
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300283
284 if (nbd_write(ioc, desc, desc_len, errp) < 0) {
285 error_prepend(errp, "write failed (description buffer): ");
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100286 return -EINVAL;
287 }
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300288
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100289 return 0;
290}
291
Eric Blake526e5c62016-10-14 13:33:08 -0500292/* Process the NBD_OPT_LIST command, with a potential series of replies.
293 * Return -errno on error, 0 on success. */
Eric Blakee68c35c2017-10-27 12:40:31 +0200294static int nbd_negotiate_handle_list(NBDClient *client, Error **errp)
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100295{
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100296 NBDExport *exp;
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600297 assert(client->opt == NBD_OPT_LIST);
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100298
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100299 /* For each export, send a NBD_REP_SERVER reply. */
300 QTAILQ_FOREACH(exp, &exports, next) {
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600301 if (nbd_negotiate_send_rep_list(client, exp, errp)) {
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100302 return -EINVAL;
303 }
304 }
305 /* Finish with a NBD_REP_ACK. */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600306 return nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100307}
308
Eric Blakef37708f2017-07-07 15:30:46 -0500309/* Send a reply to NBD_OPT_EXPORT_NAME.
310 * Return -errno on error, 0 on success. */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600311static int nbd_negotiate_handle_export_name(NBDClient *client,
Eric Blake23e099c2017-07-07 15:30:45 -0500312 uint16_t myflags, bool no_zeroes,
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300313 Error **errp)
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100314{
Eric Blake943cec82016-05-11 16:39:44 -0600315 char name[NBD_MAX_NAME_SIZE + 1];
Eric Blake5f66d062017-07-17 14:26:35 -0500316 char buf[NBD_REPLY_EXPORT_NAME_SIZE] = "";
Eric Blake23e099c2017-07-07 15:30:45 -0500317 size_t len;
318 int ret;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200319
320 /* Client sends:
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200321 [20 .. xx] export name (length bytes)
Eric Blake5f66d062017-07-17 14:26:35 -0500322 Server replies:
323 [ 0 .. 7] size
324 [ 8 .. 9] export flags
325 [10 .. 133] reserved (0) [unless no_zeroes]
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200326 */
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300327 trace_nbd_negotiate_handle_export_name();
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600328 if (client->optlen >= sizeof(name)) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300329 error_setg(errp, "Bad length received");
Vladimir Sementsov-Ogievskiyd9faeed2017-06-02 18:01:48 +0300330 return -EINVAL;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200331 }
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600332 if (nbd_read(client->ioc, name, client->optlen, errp) < 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300333 error_prepend(errp, "read failed: ");
Eric Blake32f158a2018-01-10 17:08:22 -0600334 return -EIO;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200335 }
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600336 name[client->optlen] = '\0';
337 client->optlen = 0;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200338
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300339 trace_nbd_negotiate_handle_export_name_request(name);
Daniel P. Berrange9344e5f2016-02-10 18:41:09 +0000340
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200341 client->exp = nbd_export_find(name);
342 if (!client->exp) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300343 error_setg(errp, "export not found");
Vladimir Sementsov-Ogievskiyd9faeed2017-06-02 18:01:48 +0300344 return -EINVAL;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200345 }
346
Eric Blake23e099c2017-07-07 15:30:45 -0500347 trace_nbd_negotiate_new_style_size_flags(client->exp->size,
348 client->exp->nbdflags | myflags);
349 stq_be_p(buf, client->exp->size);
350 stw_be_p(buf + 8, client->exp->nbdflags | myflags);
351 len = no_zeroes ? 10 : sizeof(buf);
352 ret = nbd_write(client->ioc, buf, len, errp);
353 if (ret < 0) {
354 error_prepend(errp, "write failed: ");
355 return ret;
356 }
357
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200358 QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
359 nbd_export_get(client->exp);
Vladimir Sementsov-Ogievskiyd9faeed2017-06-02 18:01:48 +0300360
361 return 0;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200362}
363
Eric Blakef37708f2017-07-07 15:30:46 -0500364/* Send a single NBD_REP_INFO, with a buffer @buf of @length bytes.
365 * The buffer does NOT include the info type prefix.
366 * Return -errno on error, 0 if ready to send more. */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600367static int nbd_negotiate_send_info(NBDClient *client,
Eric Blakef37708f2017-07-07 15:30:46 -0500368 uint16_t info, uint32_t length, void *buf,
369 Error **errp)
370{
371 int rc;
372
373 trace_nbd_negotiate_send_info(info, nbd_info_lookup(info), length);
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600374 rc = nbd_negotiate_send_rep_len(client, NBD_REP_INFO,
Eric Blakef37708f2017-07-07 15:30:46 -0500375 sizeof(info) + length, errp);
376 if (rc < 0) {
377 return rc;
378 }
379 cpu_to_be16s(&info);
380 if (nbd_write(client->ioc, &info, sizeof(info), errp) < 0) {
381 return -EIO;
382 }
383 if (nbd_write(client->ioc, buf, length, errp) < 0) {
384 return -EIO;
385 }
386 return 0;
387}
388
Eric Blakea16a7902018-01-10 17:08:20 -0600389/* nbd_reject_length: Handle any unexpected payload.
390 * @fatal requests that we quit talking to the client, even if we are able
391 * to successfully send an error reply.
392 * Return:
393 * -errno transmission error occurred or @fatal was requested, errp is set
394 * 0 error message successfully sent to client, errp is not set
395 */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600396static int nbd_reject_length(NBDClient *client, bool fatal, Error **errp)
Eric Blakea16a7902018-01-10 17:08:20 -0600397{
398 int ret;
399
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600400 assert(client->optlen);
Eric Blake894e0282018-01-10 17:08:24 -0600401 ret = nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp,
402 "option '%s' has unexpected length",
403 nbd_opt_lookup(client->opt));
Eric Blakea16a7902018-01-10 17:08:20 -0600404 if (fatal && !ret) {
Eric Blake894e0282018-01-10 17:08:24 -0600405 error_setg(errp, "option '%s' has unexpected length",
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600406 nbd_opt_lookup(client->opt));
Eric Blakea16a7902018-01-10 17:08:20 -0600407 return -EINVAL;
408 }
409 return ret;
410}
411
Eric Blakef37708f2017-07-07 15:30:46 -0500412/* Handle NBD_OPT_INFO and NBD_OPT_GO.
413 * Return -errno on error, 0 if ready for next option, and 1 to move
414 * into transmission phase. */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600415static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
Eric Blakef37708f2017-07-07 15:30:46 -0500416 Error **errp)
417{
418 int rc;
419 char name[NBD_MAX_NAME_SIZE + 1];
420 NBDExport *exp;
421 uint16_t requests;
422 uint16_t request;
423 uint32_t namelen;
424 bool sendname = false;
Eric Blake0c1d50b2017-07-07 15:30:48 -0500425 bool blocksize = false;
426 uint32_t sizes[3];
Eric Blakef37708f2017-07-07 15:30:46 -0500427 char buf[sizeof(uint64_t) + sizeof(uint16_t)];
Eric Blakef37708f2017-07-07 15:30:46 -0500428
429 /* Client sends:
430 4 bytes: L, name length (can be 0)
431 L bytes: export name
432 2 bytes: N, number of requests (can be 0)
433 N * 2 bytes: N requests
434 */
Eric Blake894e0282018-01-10 17:08:24 -0600435 rc = nbd_opt_read(client, &namelen, sizeof(namelen), errp);
436 if (rc <= 0) {
437 return rc;
Eric Blakef37708f2017-07-07 15:30:46 -0500438 }
439 be32_to_cpus(&namelen);
Eric Blake51ae4f82017-11-22 15:07:22 -0600440 if (namelen >= sizeof(name)) {
Eric Blake894e0282018-01-10 17:08:24 -0600441 return nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp,
442 "name too long for qemu");
Eric Blake51ae4f82017-11-22 15:07:22 -0600443 }
Eric Blake894e0282018-01-10 17:08:24 -0600444 rc = nbd_opt_read(client, name, namelen, errp);
445 if (rc <= 0) {
446 return rc;
Eric Blakef37708f2017-07-07 15:30:46 -0500447 }
448 name[namelen] = '\0';
Eric Blakef37708f2017-07-07 15:30:46 -0500449 trace_nbd_negotiate_handle_export_name_request(name);
450
Eric Blake894e0282018-01-10 17:08:24 -0600451 rc = nbd_opt_read(client, &requests, sizeof(requests), errp);
452 if (rc <= 0) {
453 return rc;
Eric Blakef37708f2017-07-07 15:30:46 -0500454 }
455 be16_to_cpus(&requests);
Eric Blakef37708f2017-07-07 15:30:46 -0500456 trace_nbd_negotiate_handle_info_requests(requests);
Eric Blakef37708f2017-07-07 15:30:46 -0500457 while (requests--) {
Eric Blake894e0282018-01-10 17:08:24 -0600458 rc = nbd_opt_read(client, &request, sizeof(request), errp);
459 if (rc <= 0) {
460 return rc;
Eric Blakef37708f2017-07-07 15:30:46 -0500461 }
462 be16_to_cpus(&request);
Eric Blakef37708f2017-07-07 15:30:46 -0500463 trace_nbd_negotiate_handle_info_request(request,
464 nbd_info_lookup(request));
Eric Blake0c1d50b2017-07-07 15:30:48 -0500465 /* We care about NBD_INFO_NAME and NBD_INFO_BLOCK_SIZE;
466 * everything else is either a request we don't know or
467 * something we send regardless of request */
468 switch (request) {
469 case NBD_INFO_NAME:
Eric Blakef37708f2017-07-07 15:30:46 -0500470 sendname = true;
Eric Blake0c1d50b2017-07-07 15:30:48 -0500471 break;
472 case NBD_INFO_BLOCK_SIZE:
473 blocksize = true;
474 break;
Eric Blakef37708f2017-07-07 15:30:46 -0500475 }
476 }
Eric Blake894e0282018-01-10 17:08:24 -0600477 if (client->optlen) {
478 return nbd_reject_length(client, false, errp);
479 }
Eric Blakef37708f2017-07-07 15:30:46 -0500480
481 exp = nbd_export_find(name);
482 if (!exp) {
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600483 return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_UNKNOWN,
484 errp, "export '%s' not present",
Eric Blakef37708f2017-07-07 15:30:46 -0500485 name);
486 }
487
488 /* Don't bother sending NBD_INFO_NAME unless client requested it */
489 if (sendname) {
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600490 rc = nbd_negotiate_send_info(client, NBD_INFO_NAME, namelen, name,
Eric Blakef37708f2017-07-07 15:30:46 -0500491 errp);
492 if (rc < 0) {
493 return rc;
494 }
495 }
496
497 /* Send NBD_INFO_DESCRIPTION only if available, regardless of
498 * client request */
499 if (exp->description) {
500 size_t len = strlen(exp->description);
501
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600502 rc = nbd_negotiate_send_info(client, NBD_INFO_DESCRIPTION,
Eric Blakef37708f2017-07-07 15:30:46 -0500503 len, exp->description, errp);
504 if (rc < 0) {
505 return rc;
506 }
507 }
508
Eric Blake0c1d50b2017-07-07 15:30:48 -0500509 /* Send NBD_INFO_BLOCK_SIZE always, but tweak the minimum size
510 * according to whether the client requested it, and according to
511 * whether this is OPT_INFO or OPT_GO. */
512 /* minimum - 1 for back-compat, or 512 if client is new enough.
513 * TODO: consult blk_bs(blk)->bl.request_alignment? */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600514 sizes[0] =
515 (client->opt == NBD_OPT_INFO || blocksize) ? BDRV_SECTOR_SIZE : 1;
Eric Blake0c1d50b2017-07-07 15:30:48 -0500516 /* preferred - Hard-code to 4096 for now.
517 * TODO: is blk_bs(blk)->bl.opt_transfer appropriate? */
518 sizes[1] = 4096;
519 /* maximum - At most 32M, but smaller as appropriate. */
520 sizes[2] = MIN(blk_get_max_transfer(exp->blk), NBD_MAX_BUFFER_SIZE);
521 trace_nbd_negotiate_handle_info_block_size(sizes[0], sizes[1], sizes[2]);
522 cpu_to_be32s(&sizes[0]);
523 cpu_to_be32s(&sizes[1]);
524 cpu_to_be32s(&sizes[2]);
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600525 rc = nbd_negotiate_send_info(client, NBD_INFO_BLOCK_SIZE,
Eric Blake0c1d50b2017-07-07 15:30:48 -0500526 sizeof(sizes), sizes, errp);
527 if (rc < 0) {
528 return rc;
529 }
530
Eric Blakef37708f2017-07-07 15:30:46 -0500531 /* Send NBD_INFO_EXPORT always */
532 trace_nbd_negotiate_new_style_size_flags(exp->size,
533 exp->nbdflags | myflags);
534 stq_be_p(buf, exp->size);
535 stw_be_p(buf + 8, exp->nbdflags | myflags);
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600536 rc = nbd_negotiate_send_info(client, NBD_INFO_EXPORT,
Eric Blakef37708f2017-07-07 15:30:46 -0500537 sizeof(buf), buf, errp);
538 if (rc < 0) {
539 return rc;
540 }
541
Eric Blake0c1d50b2017-07-07 15:30:48 -0500542 /* If the client is just asking for NBD_OPT_INFO, but forgot to
543 * request block sizes, return an error.
544 * TODO: consult blk_bs(blk)->request_align, and only error if it
545 * is not 1? */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600546 if (client->opt == NBD_OPT_INFO && !blocksize) {
547 return nbd_negotiate_send_rep_err(client,
548 NBD_REP_ERR_BLOCK_SIZE_REQD,
Eric Blake0c1d50b2017-07-07 15:30:48 -0500549 errp,
550 "request NBD_INFO_BLOCK_SIZE to "
551 "use this export");
552 }
553
Eric Blakef37708f2017-07-07 15:30:46 -0500554 /* Final reply */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600555 rc = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
Eric Blakef37708f2017-07-07 15:30:46 -0500556 if (rc < 0) {
557 return rc;
558 }
559
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600560 if (client->opt == NBD_OPT_GO) {
Eric Blakef37708f2017-07-07 15:30:46 -0500561 client->exp = exp;
562 QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
563 nbd_export_get(client->exp);
564 rc = 1;
565 }
566 return rc;
Eric Blakef37708f2017-07-07 15:30:46 -0500567}
568
569
Eric Blake36683282016-10-14 13:33:09 -0500570/* Handle NBD_OPT_STARTTLS. Return NULL to drop connection, or else the
571 * new channel for all further (now-encrypted) communication. */
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000572static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300573 Error **errp)
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000574{
575 QIOChannel *ioc;
576 QIOChannelTLS *tioc;
577 struct NBDTLSHandshakeData data = { 0 };
578
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600579 assert(client->opt == NBD_OPT_STARTTLS);
580
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300581 trace_nbd_negotiate_handle_starttls();
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000582 ioc = client->ioc;
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000583
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600584 if (nbd_negotiate_send_rep(client, NBD_REP_ACK, errp) < 0) {
Eric Blake63d5ef82016-05-11 16:39:36 -0600585 return NULL;
586 }
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000587
588 tioc = qio_channel_tls_new_server(ioc,
589 client->tlscreds,
590 client->tlsaclname,
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300591 errp);
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000592 if (!tioc) {
593 return NULL;
594 }
595
Daniel P. Berrange0d73f722016-09-30 11:57:14 +0100596 qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-server-tls");
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300597 trace_nbd_negotiate_handle_starttls_handshake();
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000598 data.loop = g_main_loop_new(g_main_context_default(), FALSE);
599 qio_channel_tls_handshake(tioc,
600 nbd_tls_handshake,
601 &data,
602 NULL);
603
604 if (!data.complete) {
605 g_main_loop_run(data.loop);
606 }
607 g_main_loop_unref(data.loop);
608 if (data.error) {
609 object_unref(OBJECT(tioc));
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300610 error_propagate(errp, data.error);
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000611 return NULL;
612 }
613
614 return QIO_CHANNEL(tioc);
615}
616
Vladimir Sementsov-Ogievskiy1e120ff2017-07-07 18:29:09 +0300617/* nbd_negotiate_options
Eric Blakef37708f2017-07-07 15:30:46 -0500618 * Process all NBD_OPT_* client option commands, during fixed newstyle
619 * negotiation.
Vladimir Sementsov-Ogievskiy1e120ff2017-07-07 18:29:09 +0300620 * Return:
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300621 * -errno on error, errp is set
622 * 0 on successful negotiation, errp is not set
623 * 1 if client sent NBD_OPT_ABORT, i.e. on valid disconnect,
624 * errp is not set
Vladimir Sementsov-Ogievskiy1e120ff2017-07-07 18:29:09 +0300625 */
Eric Blake23e099c2017-07-07 15:30:45 -0500626static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
627 Error **errp)
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100628{
Max Reitz9c122ad2015-02-25 13:08:31 -0500629 uint32_t flags;
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000630 bool fixedNewstyle = false;
Eric Blake23e099c2017-07-07 15:30:45 -0500631 bool no_zeroes = false;
Max Reitz9c122ad2015-02-25 13:08:31 -0500632
633 /* Client sends:
634 [ 0 .. 3] client flags
635
Eric Blakef37708f2017-07-07 15:30:46 -0500636 Then we loop until NBD_OPT_EXPORT_NAME or NBD_OPT_GO:
Max Reitz9c122ad2015-02-25 13:08:31 -0500637 [ 0 .. 7] NBD_OPTS_MAGIC
638 [ 8 .. 11] NBD option
639 [12 .. 15] Data length
640 ... Rest of request
641
642 [ 0 .. 7] NBD_OPTS_MAGIC
643 [ 8 .. 11] Second NBD option
644 [12 .. 15] Data length
645 ... Rest of request
646 */
647
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300648 if (nbd_read(client->ioc, &flags, sizeof(flags), errp) < 0) {
649 error_prepend(errp, "read failed: ");
Max Reitz9c122ad2015-02-25 13:08:31 -0500650 return -EIO;
651 }
Max Reitz9c122ad2015-02-25 13:08:31 -0500652 be32_to_cpus(&flags);
Eric Blake621c4f42017-07-07 15:30:44 -0500653 trace_nbd_negotiate_options_flags(flags);
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000654 if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000655 fixedNewstyle = true;
656 flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
657 }
Eric Blakec203c592016-10-14 13:33:14 -0500658 if (flags & NBD_FLAG_C_NO_ZEROES) {
Eric Blake23e099c2017-07-07 15:30:45 -0500659 no_zeroes = true;
Eric Blakec203c592016-10-14 13:33:14 -0500660 flags &= ~NBD_FLAG_C_NO_ZEROES;
661 }
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000662 if (flags != 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300663 error_setg(errp, "Unknown client flags 0x%" PRIx32 " received", flags);
Eric Blake621c4f42017-07-07 15:30:44 -0500664 return -EINVAL;
Max Reitz9c122ad2015-02-25 13:08:31 -0500665 }
666
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100667 while (1) {
Max Reitz9c122ad2015-02-25 13:08:31 -0500668 int ret;
Vladimir Sementsov-Ogievskiy7f9039c2017-07-07 18:29:16 +0300669 uint32_t option, length;
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100670 uint64_t magic;
671
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300672 if (nbd_read(client->ioc, &magic, sizeof(magic), errp) < 0) {
673 error_prepend(errp, "read failed: ");
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100674 return -EINVAL;
675 }
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300676 magic = be64_to_cpu(magic);
677 trace_nbd_negotiate_options_check_magic(magic);
678 if (magic != NBD_OPTS_MAGIC) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300679 error_setg(errp, "Bad magic received");
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100680 return -EINVAL;
681 }
682
Vladimir Sementsov-Ogievskiy7f9039c2017-07-07 18:29:16 +0300683 if (nbd_read(client->ioc, &option,
684 sizeof(option), errp) < 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300685 error_prepend(errp, "read failed: ");
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100686 return -EINVAL;
687 }
Vladimir Sementsov-Ogievskiy7f9039c2017-07-07 18:29:16 +0300688 option = be32_to_cpu(option);
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600689 client->opt = option;
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100690
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300691 if (nbd_read(client->ioc, &length, sizeof(length), errp) < 0) {
692 error_prepend(errp, "read failed: ");
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100693 return -EINVAL;
694 }
695 length = be32_to_cpu(length);
Eric Blake894e0282018-01-10 17:08:24 -0600696 assert(!client->optlen);
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600697 client->optlen = length;
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100698
Eric Blakefdad35e2017-11-22 16:25:16 -0600699 if (length > NBD_MAX_BUFFER_SIZE) {
700 error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",
701 length, NBD_MAX_BUFFER_SIZE);
702 return -EINVAL;
703 }
704
Eric Blake3736cc52017-07-07 15:30:43 -0500705 trace_nbd_negotiate_options_check_option(option,
706 nbd_opt_lookup(option));
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000707 if (client->tlscreds &&
708 client->ioc == (QIOChannel *)client->sioc) {
709 QIOChannel *tioc;
710 if (!fixedNewstyle) {
Vladimir Sementsov-Ogievskiy7f9039c2017-07-07 18:29:16 +0300711 error_setg(errp, "Unsupported option 0x%" PRIx32, option);
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000712 return -EINVAL;
713 }
Vladimir Sementsov-Ogievskiy7f9039c2017-07-07 18:29:16 +0300714 switch (option) {
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000715 case NBD_OPT_STARTTLS:
Eric Blakee68c35c2017-10-27 12:40:31 +0200716 if (length) {
717 /* Unconditionally drop the connection if the client
718 * can't start a TLS negotiation correctly */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600719 return nbd_reject_length(client, true, errp);
Eric Blakee68c35c2017-10-27 12:40:31 +0200720 }
721 tioc = nbd_negotiate_handle_starttls(client, errp);
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000722 if (!tioc) {
723 return -EIO;
724 }
Eric Blake8cbee492017-10-27 12:40:30 +0200725 ret = 0;
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000726 object_unref(OBJECT(client->ioc));
727 client->ioc = QIO_CHANNEL(tioc);
728 break;
729
Eric Blaked1129a82016-04-14 16:02:23 -0600730 case NBD_OPT_EXPORT_NAME:
731 /* No way to return an error to client, so drop connection */
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300732 error_setg(errp, "Option 0x%x not permitted before TLS",
Vladimir Sementsov-Ogievskiy7f9039c2017-07-07 18:29:16 +0300733 option);
Eric Blaked1129a82016-04-14 16:02:23 -0600734 return -EINVAL;
735
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000736 default:
Eric Blake894e0282018-01-10 17:08:24 -0600737 ret = nbd_opt_drop(client, NBD_REP_ERR_TLS_REQD, errp,
738 "Option 0x%" PRIx32
739 "not permitted before TLS", option);
Eric Blake37ec36f2017-07-07 15:30:42 -0500740 /* Let the client keep trying, unless they asked to
741 * quit. In this mode, we've already sent an error, so
742 * we can't ack the abort. */
Vladimir Sementsov-Ogievskiy7f9039c2017-07-07 18:29:16 +0300743 if (option == NBD_OPT_ABORT) {
Vladimir Sementsov-Ogievskiy1e120ff2017-07-07 18:29:09 +0300744 return 1;
Eric Blakeb6f5d3b2016-10-14 13:33:16 -0500745 }
Eric Blaked1129a82016-04-14 16:02:23 -0600746 break;
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000747 }
748 } else if (fixedNewstyle) {
Vladimir Sementsov-Ogievskiy7f9039c2017-07-07 18:29:16 +0300749 switch (option) {
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000750 case NBD_OPT_LIST:
Eric Blakee68c35c2017-10-27 12:40:31 +0200751 if (length) {
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600752 ret = nbd_reject_length(client, false, errp);
Eric Blakee68c35c2017-10-27 12:40:31 +0200753 } else {
754 ret = nbd_negotiate_handle_list(client, errp);
755 }
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000756 break;
757
758 case NBD_OPT_ABORT:
Eric Blakeb6f5d3b2016-10-14 13:33:16 -0500759 /* NBD spec says we must try to reply before
760 * disconnecting, but that we must also tolerate
761 * guests that don't wait for our reply. */
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600762 nbd_negotiate_send_rep(client, NBD_REP_ACK, NULL);
Vladimir Sementsov-Ogievskiy1e120ff2017-07-07 18:29:09 +0300763 return 1;
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000764
765 case NBD_OPT_EXPORT_NAME:
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600766 return nbd_negotiate_handle_export_name(client,
Eric Blake23e099c2017-07-07 15:30:45 -0500767 myflags, no_zeroes,
768 errp);
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000769
Eric Blakef37708f2017-07-07 15:30:46 -0500770 case NBD_OPT_INFO:
771 case NBD_OPT_GO:
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600772 ret = nbd_negotiate_handle_info(client, myflags, errp);
Eric Blakef37708f2017-07-07 15:30:46 -0500773 if (ret == 1) {
774 assert(option == NBD_OPT_GO);
775 return 0;
776 }
Eric Blakef37708f2017-07-07 15:30:46 -0500777 break;
778
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000779 case NBD_OPT_STARTTLS:
Eric Blakee68c35c2017-10-27 12:40:31 +0200780 if (length) {
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600781 ret = nbd_reject_length(client, false, errp);
Eric Blakee68c35c2017-10-27 12:40:31 +0200782 } else if (client->tlscreds) {
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600783 ret = nbd_negotiate_send_rep_err(client,
784 NBD_REP_ERR_INVALID, errp,
Eric Blake36683282016-10-14 13:33:09 -0500785 "TLS already enabled");
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000786 } else {
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600787 ret = nbd_negotiate_send_rep_err(client,
788 NBD_REP_ERR_POLICY, errp,
Eric Blake36683282016-10-14 13:33:09 -0500789 "TLS not configured");
Eric Blake63d5ef82016-05-11 16:39:36 -0600790 }
Eric Blaked1129a82016-04-14 16:02:23 -0600791 break;
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +0200792
793 case NBD_OPT_STRUCTURED_REPLY:
794 if (length) {
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600795 ret = nbd_reject_length(client, false, errp);
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +0200796 } else if (client->structured_reply) {
797 ret = nbd_negotiate_send_rep_err(
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600798 client, NBD_REP_ERR_INVALID, errp,
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +0200799 "structured reply already negotiated");
800 } else {
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600801 ret = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +0200802 client->structured_reply = true;
803 myflags |= NBD_FLAG_SEND_DF;
804 }
805 break;
806
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000807 default:
Eric Blake894e0282018-01-10 17:08:24 -0600808 ret = nbd_opt_drop(client, NBD_REP_ERR_UNSUP, errp,
809 "Unsupported option 0x%" PRIx32 " (%s)",
810 option, nbd_opt_lookup(option));
Eric Blake156f6a12016-04-06 16:48:38 -0600811 break;
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100812 }
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000813 } else {
814 /*
815 * If broken new-style we should drop the connection
816 * for anything except NBD_OPT_EXPORT_NAME
817 */
Vladimir Sementsov-Ogievskiy7f9039c2017-07-07 18:29:16 +0300818 switch (option) {
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000819 case NBD_OPT_EXPORT_NAME:
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600820 return nbd_negotiate_handle_export_name(client,
Eric Blake23e099c2017-07-07 15:30:45 -0500821 myflags, no_zeroes,
822 errp);
Hani Benhabiles32d7d2e2014-06-07 01:32:32 +0100823
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000824 default:
Eric Blake3736cc52017-07-07 15:30:43 -0500825 error_setg(errp, "Unsupported option 0x%" PRIx32 " (%s)",
826 option, nbd_opt_lookup(option));
Daniel P. Berrange26afa862016-02-10 18:41:06 +0000827 return -EINVAL;
828 }
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100829 }
Eric Blake8cbee492017-10-27 12:40:30 +0200830 if (ret < 0) {
831 return ret;
832 }
Hani Benhabilesf5076b52014-06-07 01:32:31 +0100833 }
834}
835
Vladimir Sementsov-Ogievskiy1e120ff2017-07-07 18:29:09 +0300836/* nbd_negotiate
837 * Return:
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300838 * -errno on error, errp is set
839 * 0 on successful negotiation, errp is not set
840 * 1 if client sent NBD_OPT_ABORT, i.e. on valid disconnect,
841 * errp is not set
Vladimir Sementsov-Ogievskiy1e120ff2017-07-07 18:29:09 +0300842 */
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300843static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
bellard7a5ca862008-05-27 21:13:40 +0000844{
Eric Blake5f66d062017-07-17 14:26:35 -0500845 char buf[NBD_OLDSTYLE_NEGOTIATE_SIZE] = "";
Vladimir Sementsov-Ogievskiy2e5c9ad2017-06-02 18:01:49 +0300846 int ret;
Eric Blake7423f412016-07-21 13:34:46 -0600847 const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
Eric Blake1f4d6d12016-10-14 13:33:17 -0500848 NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
849 NBD_FLAG_SEND_WRITE_ZEROES);
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000850 bool oldStyle;
bellard7a5ca862008-05-27 21:13:40 +0000851
Eric Blake5f66d062017-07-17 14:26:35 -0500852 /* Old style negotiation header, no room for options
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200853 [ 0 .. 7] passwd ("NBDMAGIC")
854 [ 8 .. 15] magic (NBD_CLIENT_MAGIC)
Nick Thomasb2e3d872011-02-22 15:44:51 +0000855 [16 .. 23] size
Eric Blake5f66d062017-07-17 14:26:35 -0500856 [24 .. 27] export flags (zero-extended)
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200857 [28 .. 151] reserved (0)
858
Eric Blake5f66d062017-07-17 14:26:35 -0500859 New style negotiation header, client can send options
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200860 [ 0 .. 7] passwd ("NBDMAGIC")
861 [ 8 .. 15] magic (NBD_OPTS_MAGIC)
862 [16 .. 17] server flags (0)
Eric Blakef37708f2017-07-07 15:30:46 -0500863 ....options sent, ending in NBD_OPT_EXPORT_NAME or NBD_OPT_GO....
Nick Thomasb2e3d872011-02-22 15:44:51 +0000864 */
bellard7a5ca862008-05-27 21:13:40 +0000865
Daniel P. Berrange1c778ef2016-02-10 18:41:04 +0000866 qio_channel_set_blocking(client->ioc, false, NULL);
Paolo Bonzini185b4332012-03-05 08:56:10 +0100867
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300868 trace_nbd_negotiate_begin();
Nick Thomasb2e3d872011-02-22 15:44:51 +0000869 memcpy(buf, "NBDMAGIC", 8);
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000870
871 oldStyle = client->exp != NULL && !client->tlscreds;
872 if (oldStyle) {
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300873 trace_nbd_negotiate_old_style(client->exp->size,
874 client->exp->nbdflags | myflags);
John Snow667ad262016-02-04 11:27:55 +0100875 stq_be_p(buf + 8, NBD_CLIENT_MAGIC);
876 stq_be_p(buf + 16, client->exp->size);
Eric Blake5f66d062017-07-17 14:26:35 -0500877 stl_be_p(buf + 24, client->exp->nbdflags | myflags);
bellard7a5ca862008-05-27 21:13:40 +0000878
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300879 if (nbd_write(client->ioc, buf, sizeof(buf), errp) < 0) {
880 error_prepend(errp, "write failed: ");
Vladimir Sementsov-Ogievskiyd9faeed2017-06-02 18:01:48 +0300881 return -EINVAL;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200882 }
883 } else {
Vladimir Sementsov-Ogievskiy76ff0812017-07-07 18:29:10 +0300884 stq_be_p(buf + 8, NBD_OPTS_MAGIC);
885 stw_be_p(buf + 16, NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES);
886
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300887 if (nbd_write(client->ioc, buf, 18, errp) < 0) {
888 error_prepend(errp, "write failed: ");
Vladimir Sementsov-Ogievskiyd9faeed2017-06-02 18:01:48 +0300889 return -EINVAL;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200890 }
Eric Blake23e099c2017-07-07 15:30:45 -0500891 ret = nbd_negotiate_options(client, myflags, errp);
Vladimir Sementsov-Ogievskiy2e5c9ad2017-06-02 18:01:49 +0300892 if (ret != 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300893 if (ret < 0) {
894 error_prepend(errp, "option negotiation failed: ");
895 }
Vladimir Sementsov-Ogievskiy2e5c9ad2017-06-02 18:01:49 +0300896 return ret;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200897 }
Nick Thomasb2e3d872011-02-22 15:44:51 +0000898 }
bellard7a5ca862008-05-27 21:13:40 +0000899
Vladimir Sementsov-Ogievskiy0cfae922018-01-10 17:08:21 -0600900 assert(!client->optlen);
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300901 trace_nbd_negotiate_success();
Vladimir Sementsov-Ogievskiyd9faeed2017-06-02 18:01:48 +0300902
903 return 0;
bellard7a5ca862008-05-27 21:13:40 +0000904}
905
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300906static int nbd_receive_request(QIOChannel *ioc, NBDRequest *request,
907 Error **errp)
bellard7a5ca862008-05-27 21:13:40 +0000908{
Paolo Bonzinifa26c262012-08-22 15:13:30 +0200909 uint8_t buf[NBD_REQUEST_SIZE];
Nick Thomasb2e3d872011-02-22 15:44:51 +0000910 uint32_t magic;
Vladimir Sementsov-Ogievskiya0dc63a2017-06-02 18:01:42 +0300911 int ret;
bellard7a5ca862008-05-27 21:13:40 +0000912
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300913 ret = nbd_read(ioc, buf, sizeof(buf), errp);
Paolo Bonzini185b4332012-03-05 08:56:10 +0100914 if (ret < 0) {
915 return ret;
916 }
917
Nick Thomasb2e3d872011-02-22 15:44:51 +0000918 /* Request
919 [ 0 .. 3] magic (NBD_REQUEST_MAGIC)
Eric Blakeb626b512016-10-14 13:33:04 -0500920 [ 4 .. 5] flags (NBD_CMD_FLAG_FUA, ...)
921 [ 6 .. 7] type (NBD_CMD_READ, ...)
Nick Thomasb2e3d872011-02-22 15:44:51 +0000922 [ 8 .. 15] handle
923 [16 .. 23] from
924 [24 .. 27] len
925 */
bellard7a5ca862008-05-27 21:13:40 +0000926
Peter Maydell773dce32016-06-10 16:00:36 +0100927 magic = ldl_be_p(buf);
Eric Blakeb626b512016-10-14 13:33:04 -0500928 request->flags = lduw_be_p(buf + 4);
929 request->type = lduw_be_p(buf + 6);
Peter Maydell773dce32016-06-10 16:00:36 +0100930 request->handle = ldq_be_p(buf + 8);
931 request->from = ldq_be_p(buf + 16);
932 request->len = ldl_be_p(buf + 24);
bellard7a5ca862008-05-27 21:13:40 +0000933
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +0300934 trace_nbd_receive_request(magic, request->flags, request->type,
935 request->from, request->len);
bellard7a5ca862008-05-27 21:13:40 +0000936
Nick Thomasb2e3d872011-02-22 15:44:51 +0000937 if (magic != NBD_REQUEST_MAGIC) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +0300938 error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic);
Paolo Bonzini185b4332012-03-05 08:56:10 +0100939 return -EINVAL;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000940 }
941 return 0;
ths75818252008-07-03 13:41:03 +0000942}
bellard7a5ca862008-05-27 21:13:40 +0000943
Paolo Bonzini41996e32011-09-19 15:25:40 +0200944#define MAX_NBD_REQUESTS 16
945
Paolo Bonzinice339672012-09-18 13:17:52 +0200946void nbd_client_get(NBDClient *client)
Paolo Bonzini1743b512011-09-19 14:33:23 +0200947{
948 client->refcount++;
949}
950
Paolo Bonzinice339672012-09-18 13:17:52 +0200951void nbd_client_put(NBDClient *client)
Paolo Bonzini1743b512011-09-19 14:33:23 +0200952{
953 if (--client->refcount == 0) {
Paolo Bonziniff2b68a2012-08-22 18:45:12 +0200954 /* The last reference should be dropped by client->close,
Max Reitzf53a8292015-02-06 16:06:16 -0500955 * which is called by client_close.
Paolo Bonziniff2b68a2012-08-22 18:45:12 +0200956 */
957 assert(client->closing);
958
Paolo Bonziniff829112017-02-13 14:52:24 +0100959 qio_channel_detach_aio_context(client->ioc);
Daniel P. Berrange1c778ef2016-02-10 18:41:04 +0000960 object_unref(OBJECT(client->sioc));
961 object_unref(OBJECT(client->ioc));
Daniel P. Berrangef95910f2016-02-10 18:41:11 +0000962 if (client->tlscreds) {
963 object_unref(OBJECT(client->tlscreds));
964 }
965 g_free(client->tlsaclname);
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200966 if (client->exp) {
967 QTAILQ_REMOVE(&client->exp->clients, client, next);
968 nbd_export_put(client->exp);
969 }
Paolo Bonzini1743b512011-09-19 14:33:23 +0200970 g_free(client);
971 }
972}
973
Eric Blake0c9390d2017-06-08 17:26:17 -0500974static void client_close(NBDClient *client, bool negotiated)
Paolo Bonzini1743b512011-09-19 14:33:23 +0200975{
Paolo Bonziniff2b68a2012-08-22 18:45:12 +0200976 if (client->closing) {
977 return;
978 }
979
980 client->closing = true;
981
982 /* Force requests to finish. They will drop their own references,
983 * then we'll close the socket and free the NBDClient.
984 */
Daniel P. Berrange1c778ef2016-02-10 18:41:04 +0000985 qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH,
986 NULL);
Paolo Bonziniff2b68a2012-08-22 18:45:12 +0200987
988 /* Also tell the client, so that they release their reference. */
Eric Blake0c9390d2017-06-08 17:26:17 -0500989 if (client->close_fn) {
990 client->close_fn(client, negotiated);
Paolo Bonzini1743b512011-09-19 14:33:23 +0200991 }
Paolo Bonzini1743b512011-09-19 14:33:23 +0200992}
993
Eric Blake315f78a2016-10-14 13:33:05 -0500994static NBDRequestData *nbd_request_get(NBDClient *client)
Paolo Bonzinid9a73802011-09-19 14:18:33 +0200995{
Eric Blake315f78a2016-10-14 13:33:05 -0500996 NBDRequestData *req;
Paolo Bonzini72deddc2011-10-07 16:47:56 +0200997
Paolo Bonzini41996e32011-09-19 15:25:40 +0200998 assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
999 client->nb_requests++;
1000
Eric Blake315f78a2016-10-14 13:33:05 -05001001 req = g_new0(NBDRequestData, 1);
Paolo Bonzini72deddc2011-10-07 16:47:56 +02001002 nbd_client_get(client);
1003 req->client = client;
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001004 return req;
1005}
1006
Eric Blake315f78a2016-10-14 13:33:05 -05001007static void nbd_request_put(NBDRequestData *req)
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001008{
Paolo Bonzini72deddc2011-10-07 16:47:56 +02001009 NBDClient *client = req->client;
Stefan Hajnoczie1adb272013-05-02 14:23:07 +02001010
Stefan Hajnoczi2d821482013-05-02 14:23:08 +02001011 if (req->data) {
1012 qemu_vfree(req->data);
1013 }
Paolo Bonzini17294042015-10-01 12:59:08 +02001014 g_free(req);
Stefan Hajnoczie1adb272013-05-02 14:23:07 +02001015
Max Reitz958c7172014-06-20 21:57:32 +02001016 client->nb_requests--;
Paolo Bonziniff829112017-02-13 14:52:24 +01001017 nbd_client_receive_next_request(client);
1018
Paolo Bonzini72deddc2011-10-07 16:47:56 +02001019 nbd_client_put(client);
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001020}
1021
Max Reitzaadf99a2014-11-18 12:21:18 +01001022static void blk_aio_attached(AioContext *ctx, void *opaque)
Max Reitzf2149282014-06-20 21:57:34 +02001023{
1024 NBDExport *exp = opaque;
1025 NBDClient *client;
1026
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +03001027 trace_nbd_blk_aio_attached(exp->name, ctx);
Max Reitzf2149282014-06-20 21:57:34 +02001028
1029 exp->ctx = ctx;
1030
1031 QTAILQ_FOREACH(client, &exp->clients, next) {
Paolo Bonziniff829112017-02-13 14:52:24 +01001032 qio_channel_attach_aio_context(client->ioc, ctx);
1033 if (client->recv_coroutine) {
1034 aio_co_schedule(ctx, client->recv_coroutine);
1035 }
1036 if (client->send_coroutine) {
1037 aio_co_schedule(ctx, client->send_coroutine);
1038 }
Max Reitzf2149282014-06-20 21:57:34 +02001039 }
1040}
1041
Max Reitzaadf99a2014-11-18 12:21:18 +01001042static void blk_aio_detach(void *opaque)
Max Reitzf2149282014-06-20 21:57:34 +02001043{
1044 NBDExport *exp = opaque;
1045 NBDClient *client;
1046
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +03001047 trace_nbd_blk_aio_detach(exp->name, exp->ctx);
Max Reitzf2149282014-06-20 21:57:34 +02001048
1049 QTAILQ_FOREACH(client, &exp->clients, next) {
Paolo Bonziniff829112017-02-13 14:52:24 +01001050 qio_channel_detach_aio_context(client->ioc);
Max Reitzf2149282014-06-20 21:57:34 +02001051 }
1052
1053 exp->ctx = NULL;
1054}
1055
Max Reitz741cc432016-01-29 16:36:06 +01001056static void nbd_eject_notifier(Notifier *n, void *data)
1057{
1058 NBDExport *exp = container_of(n, NBDExport, eject_notifier);
1059 nbd_export_close(exp);
1060}
1061
Kevin Wolfcd7fca92016-07-06 11:22:39 +02001062NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
Eric Blake7423f412016-07-21 13:34:46 -06001063 uint16_t nbdflags, void (*close)(NBDExport *),
Kevin Wolfcd7fca92016-07-06 11:22:39 +02001064 bool writethrough, BlockBackend *on_eject_blk,
Max Reitz98f44bb2015-02-25 13:08:21 -05001065 Error **errp)
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001066{
Kevin Wolf3dff24f2017-08-15 21:07:38 +08001067 AioContext *ctx;
Kevin Wolfcd7fca92016-07-06 11:22:39 +02001068 BlockBackend *blk;
Marc-André Lureaue8d3eb72017-10-06 20:49:16 -03001069 NBDExport *exp = g_new0(NBDExport, 1);
Kevin Wolf8a7ce4f2017-02-09 15:43:38 +01001070 uint64_t perm;
Kevin Wolfd7086422017-01-13 19:02:32 +01001071 int ret;
Kevin Wolfcd7fca92016-07-06 11:22:39 +02001072
Kevin Wolf3dff24f2017-08-15 21:07:38 +08001073 /*
1074 * NBD exports are used for non-shared storage migration. Make sure
1075 * that BDRV_O_INACTIVE is cleared and the image is ready for write
1076 * access since the export could be available before migration handover.
1077 */
1078 ctx = bdrv_get_aio_context(bs);
1079 aio_context_acquire(ctx);
1080 bdrv_invalidate_cache(bs, NULL);
1081 aio_context_release(ctx);
1082
Kevin Wolf8a7ce4f2017-02-09 15:43:38 +01001083 /* Don't allow resize while the NBD server is running, otherwise we don't
1084 * care what happens with the node. */
1085 perm = BLK_PERM_CONSISTENT_READ;
1086 if ((nbdflags & NBD_FLAG_READ_ONLY) == 0) {
1087 perm |= BLK_PERM_WRITE;
1088 }
1089 blk = blk_new(perm, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
1090 BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD);
Kevin Wolfd7086422017-01-13 19:02:32 +01001091 ret = blk_insert_bs(blk, bs, errp);
1092 if (ret < 0) {
1093 goto fail;
1094 }
Kevin Wolfcd7fca92016-07-06 11:22:39 +02001095 blk_set_enable_write_cache(blk, !writethrough);
1096
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +02001097 exp->refcount = 1;
Paolo Bonzini4b9441f2012-09-18 13:58:25 +02001098 QTAILQ_INIT(&exp->clients);
Max Reitzaadf99a2014-11-18 12:21:18 +01001099 exp->blk = blk;
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001100 exp->dev_offset = dev_offset;
1101 exp->nbdflags = nbdflags;
Max Reitz98f44bb2015-02-25 13:08:21 -05001102 exp->size = size < 0 ? blk_getlength(blk) : size;
1103 if (exp->size < 0) {
1104 error_setg_errno(errp, -exp->size,
1105 "Failed to determine the NBD export's length");
1106 goto fail;
1107 }
1108 exp->size -= exp->size % BDRV_SECTOR_SIZE;
1109
Paolo Bonzini0ddf08d2012-09-18 13:59:03 +02001110 exp->close = close;
Max Reitzaadf99a2014-11-18 12:21:18 +01001111 exp->ctx = blk_get_aio_context(blk);
Max Reitzaadf99a2014-11-18 12:21:18 +01001112 blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
Max Reitz741cc432016-01-29 16:36:06 +01001113
Kevin Wolfcd7fca92016-07-06 11:22:39 +02001114 if (on_eject_blk) {
1115 blk_ref(on_eject_blk);
1116 exp->eject_notifier_blk = on_eject_blk;
1117 exp->eject_notifier.notify = nbd_eject_notifier;
1118 blk_add_remove_bs_notifier(on_eject_blk, &exp->eject_notifier);
1119 }
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001120 return exp;
Max Reitz98f44bb2015-02-25 13:08:21 -05001121
1122fail:
Kevin Wolfcd7fca92016-07-06 11:22:39 +02001123 blk_unref(blk);
Max Reitz98f44bb2015-02-25 13:08:21 -05001124 g_free(exp);
1125 return NULL;
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001126}
1127
Paolo Bonziniee0a19e2012-08-22 15:59:23 +02001128NBDExport *nbd_export_find(const char *name)
1129{
1130 NBDExport *exp;
1131 QTAILQ_FOREACH(exp, &exports, next) {
1132 if (strcmp(name, exp->name) == 0) {
1133 return exp;
1134 }
1135 }
1136
1137 return NULL;
1138}
1139
1140void nbd_export_set_name(NBDExport *exp, const char *name)
1141{
1142 if (exp->name == name) {
1143 return;
1144 }
1145
1146 nbd_export_get(exp);
1147 if (exp->name != NULL) {
1148 g_free(exp->name);
1149 exp->name = NULL;
1150 QTAILQ_REMOVE(&exports, exp, next);
1151 nbd_export_put(exp);
1152 }
1153 if (name != NULL) {
1154 nbd_export_get(exp);
1155 exp->name = g_strdup(name);
1156 QTAILQ_INSERT_TAIL(&exports, exp, next);
1157 }
1158 nbd_export_put(exp);
1159}
1160
Eric Blakeb1a75b32016-10-14 13:33:03 -05001161void nbd_export_set_description(NBDExport *exp, const char *description)
1162{
1163 g_free(exp->description);
1164 exp->description = g_strdup(description);
1165}
1166
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001167void nbd_export_close(NBDExport *exp)
1168{
Paolo Bonzini4b9441f2012-09-18 13:58:25 +02001169 NBDClient *client, *next;
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +02001170
Paolo Bonzini4b9441f2012-09-18 13:58:25 +02001171 nbd_export_get(exp);
1172 QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
Eric Blake0c9390d2017-06-08 17:26:17 -05001173 client_close(client, true);
Paolo Bonzini4b9441f2012-09-18 13:58:25 +02001174 }
Paolo Bonzini125afda2012-09-18 14:31:44 +02001175 nbd_export_set_name(exp, NULL);
Eric Blakeb1a75b32016-10-14 13:33:03 -05001176 nbd_export_set_description(exp, NULL);
Paolo Bonzini4b9441f2012-09-18 13:58:25 +02001177 nbd_export_put(exp);
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +02001178}
1179
1180void nbd_export_get(NBDExport *exp)
1181{
1182 assert(exp->refcount > 0);
1183 exp->refcount++;
1184}
1185
1186void nbd_export_put(NBDExport *exp)
1187{
1188 assert(exp->refcount > 0);
1189 if (exp->refcount == 1) {
1190 nbd_export_close(exp);
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001191 }
1192
Vladimir Sementsov-Ogievskiy91562452017-12-07 18:50:57 +03001193 /* nbd_export_close() may theoretically reduce refcount to 0. It may happen
1194 * if someone calls nbd_export_put() on named export not through
1195 * nbd_export_set_name() when refcount is 1. So, let's assert that
1196 * it is > 0.
1197 */
1198 assert(exp->refcount > 0);
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +02001199 if (--exp->refcount == 0) {
Paolo Bonziniee0a19e2012-08-22 15:59:23 +02001200 assert(exp->name == NULL);
Eric Blakeb1a75b32016-10-14 13:33:03 -05001201 assert(exp->description == NULL);
Paolo Bonziniee0a19e2012-08-22 15:59:23 +02001202
Paolo Bonzini0ddf08d2012-09-18 13:59:03 +02001203 if (exp->close) {
1204 exp->close(exp);
1205 }
1206
Wen Congyangd6268342015-09-16 16:35:46 +08001207 if (exp->blk) {
Kevin Wolfcd7fca92016-07-06 11:22:39 +02001208 if (exp->eject_notifier_blk) {
1209 notifier_remove(&exp->eject_notifier);
1210 blk_unref(exp->eject_notifier_blk);
1211 }
Wen Congyangd6268342015-09-16 16:35:46 +08001212 blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
1213 blk_aio_detach, exp);
1214 blk_unref(exp->blk);
1215 exp->blk = NULL;
1216 }
1217
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +02001218 g_free(exp);
1219 }
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001220}
1221
Max Reitze1401772014-11-18 12:21:17 +01001222BlockBackend *nbd_export_get_blockdev(NBDExport *exp)
Paolo Bonzini125afda2012-09-18 14:31:44 +02001223{
Max Reitzaadf99a2014-11-18 12:21:18 +01001224 return exp->blk;
Paolo Bonzini125afda2012-09-18 14:31:44 +02001225}
1226
Paolo Bonziniee0a19e2012-08-22 15:59:23 +02001227void nbd_export_close_all(void)
1228{
1229 NBDExport *exp, *next;
1230
1231 QTAILQ_FOREACH_SAFE(exp, &exports, next, next) {
1232 nbd_export_close(exp);
Paolo Bonziniee0a19e2012-08-22 15:59:23 +02001233 }
1234}
1235
Vladimir Sementsov-Ogievskiyde79bfc2017-10-12 17:29:00 -05001236static int coroutine_fn nbd_co_send_iov(NBDClient *client, struct iovec *iov,
1237 unsigned niov, Error **errp)
1238{
1239 int ret;
1240
1241 g_assert(qemu_in_coroutine());
1242 qemu_co_mutex_lock(&client->send_lock);
1243 client->send_coroutine = qemu_coroutine_self();
1244
1245 ret = qio_channel_writev_all(client->ioc, iov, niov, errp) < 0 ? -EIO : 0;
1246
1247 client->send_coroutine = NULL;
1248 qemu_co_mutex_unlock(&client->send_lock);
1249
1250 return ret;
1251}
1252
Vladimir Sementsov-Ogievskiycaad5382017-10-12 12:53:10 +03001253static inline void set_be_simple_reply(NBDSimpleReply *reply, uint64_t error,
1254 uint64_t handle)
1255{
1256 stl_be_p(&reply->magic, NBD_SIMPLE_REPLY_MAGIC);
1257 stl_be_p(&reply->error, error);
1258 stq_be_p(&reply->handle, handle);
1259}
1260
Vladimir Sementsov-Ogievskiy978df1b2017-10-12 12:53:12 +03001261static int nbd_co_send_simple_reply(NBDClient *client,
Vladimir Sementsov-Ogievskiy14cea412017-10-12 17:05:06 -05001262 uint64_t handle,
1263 uint32_t error,
Vladimir Sementsov-Ogievskiy978df1b2017-10-12 12:53:12 +03001264 void *data,
1265 size_t len,
1266 Error **errp)
Paolo Bonzini22045592011-09-19 14:25:30 +02001267{
Vladimir Sementsov-Ogievskiyde79bfc2017-10-12 17:29:00 -05001268 NBDSimpleReply reply;
Vladimir Sementsov-Ogievskiy14cea412017-10-12 17:05:06 -05001269 int nbd_err = system_errno_to_nbd_errno(error);
Vladimir Sementsov-Ogievskiyde79bfc2017-10-12 17:29:00 -05001270 struct iovec iov[] = {
1271 {.iov_base = &reply, .iov_len = sizeof(reply)},
1272 {.iov_base = data, .iov_len = len}
1273 };
Vladimir Sementsov-Ogievskiy6fb2b972017-07-07 18:29:17 +03001274
Eric Blakee7a78d02017-10-27 12:40:26 +02001275 trace_nbd_co_send_simple_reply(handle, nbd_err, nbd_err_lookup(nbd_err),
1276 len);
Vladimir Sementsov-Ogievskiyde79bfc2017-10-12 17:29:00 -05001277 set_be_simple_reply(&reply, nbd_err, handle);
Vladimir Sementsov-Ogievskiy6fb2b972017-07-07 18:29:17 +03001278
Vladimir Sementsov-Ogievskiyde79bfc2017-10-12 17:29:00 -05001279 return nbd_co_send_iov(client, iov, len ? 2 : 1, errp);
Paolo Bonzini22045592011-09-19 14:25:30 +02001280}
1281
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001282static inline void set_be_chunk(NBDStructuredReplyChunk *chunk, uint16_t flags,
1283 uint16_t type, uint64_t handle, uint32_t length)
1284{
1285 stl_be_p(&chunk->magic, NBD_STRUCTURED_REPLY_MAGIC);
1286 stw_be_p(&chunk->flags, flags);
1287 stw_be_p(&chunk->type, type);
1288 stq_be_p(&chunk->handle, handle);
1289 stl_be_p(&chunk->length, length);
1290}
1291
Eric Blakeef8c8872017-11-08 15:57:03 -06001292static int coroutine_fn nbd_co_send_structured_done(NBDClient *client,
1293 uint64_t handle,
1294 Error **errp)
1295{
1296 NBDStructuredReplyChunk chunk;
1297 struct iovec iov[] = {
1298 {.iov_base = &chunk, .iov_len = sizeof(chunk)},
1299 };
1300
1301 trace_nbd_co_send_structured_done(handle);
1302 set_be_chunk(&chunk, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_NONE, handle, 0);
1303
1304 return nbd_co_send_iov(client, iov, 1, errp);
1305}
1306
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001307static int coroutine_fn nbd_co_send_structured_read(NBDClient *client,
1308 uint64_t handle,
1309 uint64_t offset,
1310 void *data,
1311 size_t size,
Eric Blake418638d2017-11-06 21:09:11 -06001312 bool final,
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001313 Error **errp)
1314{
Eric Blakeefdc0c12017-11-08 15:57:00 -06001315 NBDStructuredReadData chunk;
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001316 struct iovec iov[] = {
1317 {.iov_base = &chunk, .iov_len = sizeof(chunk)},
1318 {.iov_base = data, .iov_len = size}
1319 };
1320
Eric Blakeef8c8872017-11-08 15:57:03 -06001321 assert(size);
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001322 trace_nbd_co_send_structured_read(handle, offset, data, size);
Eric Blake418638d2017-11-06 21:09:11 -06001323 set_be_chunk(&chunk.h, final ? NBD_REPLY_FLAG_DONE : 0,
1324 NBD_REPLY_TYPE_OFFSET_DATA, handle,
1325 sizeof(chunk) - sizeof(chunk.h) + size);
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001326 stq_be_p(&chunk.offset, offset);
1327
1328 return nbd_co_send_iov(client, iov, 2, errp);
1329}
1330
Eric Blake418638d2017-11-06 21:09:11 -06001331static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
1332 uint64_t handle,
1333 uint64_t offset,
1334 uint8_t *data,
1335 size_t size,
1336 Error **errp)
1337{
1338 int ret = 0;
1339 NBDExport *exp = client->exp;
1340 size_t progress = 0;
1341
1342 while (progress < size) {
1343 int64_t pnum;
1344 int status = bdrv_block_status_above(blk_bs(exp->blk), NULL,
1345 offset + progress,
1346 size - progress, &pnum, NULL,
1347 NULL);
Eric Blakee2de3252017-11-06 21:09:12 -06001348 bool final;
Eric Blake418638d2017-11-06 21:09:11 -06001349
1350 if (status < 0) {
1351 error_setg_errno(errp, -status, "unable to check for holes");
1352 return status;
1353 }
1354 assert(pnum && pnum <= size - progress);
Eric Blakee2de3252017-11-06 21:09:12 -06001355 final = progress + pnum == size;
Eric Blake418638d2017-11-06 21:09:11 -06001356 if (status & BDRV_BLOCK_ZERO) {
1357 NBDStructuredReadHole chunk;
1358 struct iovec iov[] = {
1359 {.iov_base = &chunk, .iov_len = sizeof(chunk)},
1360 };
1361
1362 trace_nbd_co_send_structured_read_hole(handle, offset + progress,
1363 pnum);
Eric Blakee2de3252017-11-06 21:09:12 -06001364 set_be_chunk(&chunk.h, final ? NBD_REPLY_FLAG_DONE : 0,
1365 NBD_REPLY_TYPE_OFFSET_HOLE,
Eric Blake418638d2017-11-06 21:09:11 -06001366 handle, sizeof(chunk) - sizeof(chunk.h));
1367 stq_be_p(&chunk.offset, offset + progress);
1368 stl_be_p(&chunk.length, pnum);
1369 ret = nbd_co_send_iov(client, iov, 1, errp);
1370 } else {
1371 ret = blk_pread(exp->blk, offset + progress + exp->dev_offset,
1372 data + progress, pnum);
1373 if (ret < 0) {
1374 error_setg_errno(errp, -ret, "reading from file failed");
1375 break;
1376 }
1377 ret = nbd_co_send_structured_read(client, handle, offset + progress,
Eric Blakee2de3252017-11-06 21:09:12 -06001378 data + progress, pnum, final,
Eric Blake418638d2017-11-06 21:09:11 -06001379 errp);
1380 }
1381
1382 if (ret < 0) {
1383 break;
1384 }
1385 progress += pnum;
1386 }
Eric Blake418638d2017-11-06 21:09:11 -06001387 return ret;
1388}
1389
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001390static int coroutine_fn nbd_co_send_structured_error(NBDClient *client,
1391 uint64_t handle,
1392 uint32_t error,
Eric Blakea57f6de2017-10-27 12:40:33 +02001393 const char *msg,
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001394 Error **errp)
1395{
1396 NBDStructuredError chunk;
1397 int nbd_err = system_errno_to_nbd_errno(error);
1398 struct iovec iov[] = {
1399 {.iov_base = &chunk, .iov_len = sizeof(chunk)},
Eric Blakea57f6de2017-10-27 12:40:33 +02001400 {.iov_base = (char *)msg, .iov_len = msg ? strlen(msg) : 0},
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001401 };
1402
1403 assert(nbd_err);
1404 trace_nbd_co_send_structured_error(handle, nbd_err,
Eric Blakea57f6de2017-10-27 12:40:33 +02001405 nbd_err_lookup(nbd_err), msg ? msg : "");
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001406 set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_ERROR, handle,
Eric Blakea57f6de2017-10-27 12:40:33 +02001407 sizeof(chunk) - sizeof(chunk.h) + iov[1].iov_len);
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001408 stl_be_p(&chunk.error, nbd_err);
Eric Blakea57f6de2017-10-27 12:40:33 +02001409 stw_be_p(&chunk.message_length, iov[1].iov_len);
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001410
Eric Blakea57f6de2017-10-27 12:40:33 +02001411 return nbd_co_send_iov(client, iov, 1 + !!iov[1].iov_len, errp);
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001412}
1413
Vladimir Sementsov-Ogievskiy2a6e1282017-06-02 18:01:44 +03001414/* nbd_co_receive_request
1415 * Collect a client request. Return 0 if request looks valid, -EIO to drop
1416 * connection right away, and any other negative value to report an error to
1417 * the client (although the caller may still need to disconnect after reporting
1418 * the error).
1419 */
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001420static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
1421 Error **errp)
Paolo Bonzinia030b342011-09-19 15:07:54 +02001422{
Paolo Bonzini72deddc2011-10-07 16:47:56 +02001423 NBDClient *client = req->client;
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001424 int valid_flags;
Paolo Bonzinia030b342011-09-19 15:07:54 +02001425
Daniel P. Berrange1c778ef2016-02-10 18:41:04 +00001426 g_assert(qemu_in_coroutine());
Paolo Bonziniff829112017-02-13 14:52:24 +01001427 assert(client->recv_coroutine == qemu_coroutine_self());
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001428 if (nbd_receive_request(client->ioc, request, errp) < 0) {
Vladimir Sementsov-Ogievskiyee898b82017-06-02 18:01:45 +03001429 return -EIO;
Paolo Bonzinia030b342011-09-19 15:07:54 +02001430 }
1431
Eric Blake3736cc52017-07-07 15:30:43 -05001432 trace_nbd_co_receive_request_decode_type(request->handle, request->type,
1433 nbd_cmd_lookup(request->type));
Eric Blake29b6c3b2016-05-11 16:39:37 -06001434
Eric Blakeb626b512016-10-14 13:33:04 -05001435 if (request->type != NBD_CMD_WRITE) {
Eric Blake29b6c3b2016-05-11 16:39:37 -06001436 /* No payload, we are ready to read the next request. */
1437 req->complete = true;
1438 }
1439
Eric Blakeb626b512016-10-14 13:33:04 -05001440 if (request->type == NBD_CMD_DISC) {
Eric Blake29b6c3b2016-05-11 16:39:37 -06001441 /* Special case: we're going to disconnect without a reply,
1442 * whether or not flags, from, or len are bogus */
Vladimir Sementsov-Ogievskiyee898b82017-06-02 18:01:45 +03001443 return -EIO;
Eric Blake29b6c3b2016-05-11 16:39:37 -06001444 }
1445
Eric Blakeb626b512016-10-14 13:33:04 -05001446 if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE) {
Paolo Bonzinieb38c3b2016-01-07 14:32:42 +01001447 if (request->len > NBD_MAX_BUFFER_SIZE) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001448 error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",
1449 request->len, NBD_MAX_BUFFER_SIZE);
Vladimir Sementsov-Ogievskiyee898b82017-06-02 18:01:45 +03001450 return -EINVAL;
Paolo Bonzinieb38c3b2016-01-07 14:32:42 +01001451 }
1452
Paolo Bonzinif1c17522016-01-07 14:34:13 +01001453 req->data = blk_try_blockalign(client->exp->blk, request->len);
1454 if (req->data == NULL) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001455 error_setg(errp, "No memory");
Vladimir Sementsov-Ogievskiyee898b82017-06-02 18:01:45 +03001456 return -ENOMEM;
Paolo Bonzinif1c17522016-01-07 14:34:13 +01001457 }
Stefan Hajnoczi2d821482013-05-02 14:23:08 +02001458 }
Eric Blakeb626b512016-10-14 13:33:04 -05001459 if (request->type == NBD_CMD_WRITE) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001460 if (nbd_read(client->ioc, req->data, request->len, errp) < 0) {
1461 error_prepend(errp, "reading from socket failed: ");
Vladimir Sementsov-Ogievskiyee898b82017-06-02 18:01:45 +03001462 return -EIO;
Paolo Bonzinia030b342011-09-19 15:07:54 +02001463 }
Eric Blake29b6c3b2016-05-11 16:39:37 -06001464 req->complete = true;
Vladimir Sementsov-Ogievskiy6fb2b972017-07-07 18:29:17 +03001465
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +03001466 trace_nbd_co_receive_request_payload_received(request->handle,
1467 request->len);
Paolo Bonzinia030b342011-09-19 15:07:54 +02001468 }
Eric Blake29b6c3b2016-05-11 16:39:37 -06001469
Eric Blakefed5f8f2017-11-15 15:35:56 -06001470 /* Sanity checks. */
1471 if (client->exp->nbdflags & NBD_FLAG_READ_ONLY &&
1472 (request->type == NBD_CMD_WRITE ||
1473 request->type == NBD_CMD_WRITE_ZEROES ||
1474 request->type == NBD_CMD_TRIM)) {
1475 error_setg(errp, "Export is read-only");
1476 return -EROFS;
1477 }
1478 if (request->from > client->exp->size ||
1479 request->from + request->len > client->exp->size) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001480 error_setg(errp, "operation past EOF; From: %" PRIu64 ", Len: %" PRIu32
1481 ", Size: %" PRIu64, request->from, request->len,
1482 (uint64_t)client->exp->size);
Eric Blakefed5f8f2017-11-15 15:35:56 -06001483 return (request->type == NBD_CMD_WRITE ||
1484 request->type == NBD_CMD_WRITE_ZEROES) ? -ENOSPC : -EINVAL;
Eric Blake29b6c3b2016-05-11 16:39:37 -06001485 }
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001486 valid_flags = NBD_CMD_FLAG_FUA;
1487 if (request->type == NBD_CMD_READ && client->structured_reply) {
1488 valid_flags |= NBD_CMD_FLAG_DF;
1489 } else if (request->type == NBD_CMD_WRITE_ZEROES) {
1490 valid_flags |= NBD_CMD_FLAG_NO_HOLE;
Eric Blakeab7c5482016-05-11 16:39:38 -06001491 }
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001492 if (request->flags & ~valid_flags) {
1493 error_setg(errp, "unsupported flags for command %s (got 0x%x)",
1494 nbd_cmd_lookup(request->type), request->flags);
Vladimir Sementsov-Ogievskiyee898b82017-06-02 18:01:45 +03001495 return -EINVAL;
Eric Blake1f4d6d12016-10-14 13:33:17 -05001496 }
Eric Blake29b6c3b2016-05-11 16:39:37 -06001497
Vladimir Sementsov-Ogievskiyee898b82017-06-02 18:01:45 +03001498 return 0;
Paolo Bonzinia030b342011-09-19 15:07:54 +02001499}
1500
Paolo Bonziniff829112017-02-13 14:52:24 +01001501/* Owns a reference to the NBDClient passed as opaque. */
1502static coroutine_fn void nbd_trip(void *opaque)
ths75818252008-07-03 13:41:03 +00001503{
Paolo Bonzini262db382011-09-19 15:19:27 +02001504 NBDClient *client = opaque;
Paolo Bonzini1743b512011-09-19 14:33:23 +02001505 NBDExport *exp = client->exp;
Eric Blake315f78a2016-10-14 13:33:05 -05001506 NBDRequestData *req;
Paolo Bonziniff829112017-02-13 14:52:24 +01001507 NBDRequest request = { 0 }; /* GCC thinks it can be used uninitialized */
Vladimir Sementsov-Ogievskiya0dc63a2017-06-02 18:01:42 +03001508 int ret;
Eric Blakea0c30362016-05-11 16:39:34 -06001509 int flags;
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001510 int reply_data_len = 0;
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001511 Error *local_err = NULL;
Eric Blakea57f6de2017-10-27 12:40:33 +02001512 char *msg = NULL;
ths75818252008-07-03 13:41:03 +00001513
Vladimir Sementsov-Ogievskiy95884632017-07-07 18:29:18 +03001514 trace_nbd_trip();
Paolo Bonziniff2b68a2012-08-22 18:45:12 +02001515 if (client->closing) {
Paolo Bonziniff829112017-02-13 14:52:24 +01001516 nbd_client_put(client);
Paolo Bonziniff2b68a2012-08-22 18:45:12 +02001517 return;
1518 }
ths75818252008-07-03 13:41:03 +00001519
Paolo Bonziniff2b68a2012-08-22 18:45:12 +02001520 req = nbd_request_get(client);
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001521 ret = nbd_co_receive_request(req, &request, &local_err);
Vladimir Sementsov-Ogievskiyee898b82017-06-02 18:01:45 +03001522 client->recv_coroutine = NULL;
1523 nbd_client_receive_next_request(client);
Paolo Bonzinia030b342011-09-19 15:07:54 +02001524 if (ret == -EIO) {
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001525 goto disconnect;
Paolo Bonzinia030b342011-09-19 15:07:54 +02001526 }
ths75818252008-07-03 13:41:03 +00001527
Paolo Bonzinia030b342011-09-19 15:07:54 +02001528 if (ret < 0) {
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001529 goto reply;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001530 }
bellard7a5ca862008-05-27 21:13:40 +00001531
Wen Congyangd6268342015-09-16 16:35:46 +08001532 if (client->closing) {
1533 /*
1534 * The client may be closed when we are blocked in
1535 * nbd_co_receive_request()
1536 */
1537 goto done;
1538 }
1539
Eric Blakeb626b512016-10-14 13:33:04 -05001540 switch (request.type) {
Nick Thomasb2e3d872011-02-22 15:44:51 +00001541 case NBD_CMD_READ:
Eric Blakeb626b512016-10-14 13:33:04 -05001542 /* XXX: NBD Protocol only documents use of FUA with WRITE */
1543 if (request.flags & NBD_CMD_FLAG_FUA) {
Max Reitzaadf99a2014-11-18 12:21:18 +01001544 ret = blk_co_flush(exp->blk);
Paolo Bonzinie25ceb72012-04-19 11:59:11 +02001545 if (ret < 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001546 error_setg_errno(&local_err, -ret, "flush failed");
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001547 break;
Paolo Bonzinie25ceb72012-04-19 11:59:11 +02001548 }
1549 }
1550
Eric Blakee2de3252017-11-06 21:09:12 -06001551 if (client->structured_reply && !(request.flags & NBD_CMD_FLAG_DF) &&
1552 request.len) {
Eric Blake418638d2017-11-06 21:09:11 -06001553 ret = nbd_co_send_sparse_read(req->client, request.handle,
1554 request.from, req->data, request.len,
1555 &local_err);
1556 if (ret < 0) {
1557 goto reply;
1558 }
1559 goto done;
1560 }
1561
Eric Blakedf7b97f2016-04-21 08:42:30 -06001562 ret = blk_pread(exp->blk, request.from + exp->dev_offset,
1563 req->data, request.len);
Paolo Bonziniadcf6302011-09-13 17:27:45 +02001564 if (ret < 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001565 error_setg_errno(&local_err, -ret, "reading from file failed");
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001566 break;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001567 }
bellard7a5ca862008-05-27 21:13:40 +00001568
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001569 reply_data_len = request.len;
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001570
Nick Thomasb2e3d872011-02-22 15:44:51 +00001571 break;
1572 case NBD_CMD_WRITE:
Eric Blakea0c30362016-05-11 16:39:34 -06001573 flags = 0;
Eric Blakeb626b512016-10-14 13:33:04 -05001574 if (request.flags & NBD_CMD_FLAG_FUA) {
Eric Blakea0c30362016-05-11 16:39:34 -06001575 flags |= BDRV_REQ_FUA;
1576 }
Eric Blakedf7b97f2016-04-21 08:42:30 -06001577 ret = blk_pwrite(exp->blk, request.from + exp->dev_offset,
Eric Blakea0c30362016-05-11 16:39:34 -06001578 req->data, request.len, flags);
Paolo Bonzinifae69412011-09-19 16:04:36 +02001579 if (ret < 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001580 error_setg_errno(&local_err, -ret, "writing to file failed");
Paolo Bonzinifae69412011-09-19 16:04:36 +02001581 }
1582
Nick Thomasb2e3d872011-02-22 15:44:51 +00001583 break;
Eric Blake1f4d6d12016-10-14 13:33:17 -05001584 case NBD_CMD_WRITE_ZEROES:
Eric Blake1f4d6d12016-10-14 13:33:17 -05001585 flags = 0;
1586 if (request.flags & NBD_CMD_FLAG_FUA) {
1587 flags |= BDRV_REQ_FUA;
1588 }
1589 if (!(request.flags & NBD_CMD_FLAG_NO_HOLE)) {
1590 flags |= BDRV_REQ_MAY_UNMAP;
1591 }
1592 ret = blk_pwrite_zeroes(exp->blk, request.from + exp->dev_offset,
1593 request.len, flags);
1594 if (ret < 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001595 error_setg_errno(&local_err, -ret, "writing to file failed");
Eric Blake1f4d6d12016-10-14 13:33:17 -05001596 }
1597
Eric Blake1f4d6d12016-10-14 13:33:17 -05001598 break;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001599 case NBD_CMD_DISC:
Eric Blake29b6c3b2016-05-11 16:39:37 -06001600 /* unreachable, thanks to special case in nbd_co_receive_request() */
1601 abort();
1602
Paolo Bonzini1486d042011-10-21 13:17:14 +02001603 case NBD_CMD_FLUSH:
Max Reitzaadf99a2014-11-18 12:21:18 +01001604 ret = blk_co_flush(exp->blk);
Paolo Bonzini1486d042011-10-21 13:17:14 +02001605 if (ret < 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001606 error_setg_errno(&local_err, -ret, "flush failed");
Paolo Bonzini1486d042011-10-21 13:17:14 +02001607 }
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001608
Paolo Bonzini1486d042011-10-21 13:17:14 +02001609 break;
Paolo Bonzini7a706632011-10-21 13:17:14 +02001610 case NBD_CMD_TRIM:
Eric Blake1c6c4bb2016-07-15 17:22:54 -06001611 ret = blk_co_pdiscard(exp->blk, request.from + exp->dev_offset,
1612 request.len);
1613 if (ret < 0) {
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001614 error_setg_errno(&local_err, -ret, "discard failed");
Paolo Bonzini7a706632011-10-21 13:17:14 +02001615 }
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001616
Paolo Bonzini7a706632011-10-21 13:17:14 +02001617 break;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001618 default:
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001619 error_setg(&local_err, "invalid request type (%" PRIu32 ") received",
1620 request.type);
Vladimir Sementsov-Ogievskiy14cea412017-10-12 17:05:06 -05001621 ret = -EINVAL;
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001622 }
1623
1624reply:
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001625 if (local_err) {
Vladimir Sementsov-Ogievskiy14cea412017-10-12 17:05:06 -05001626 /* If we get here, local_err was not a fatal error, and should be sent
1627 * to the client. */
Eric Blakea57f6de2017-10-27 12:40:33 +02001628 assert(ret < 0);
1629 msg = g_strdup(error_get_pretty(local_err));
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001630 error_report_err(local_err);
1631 local_err = NULL;
1632 }
1633
Eric Blakea57f6de2017-10-27 12:40:33 +02001634 if (client->structured_reply &&
1635 (ret < 0 || request.type == NBD_CMD_READ)) {
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001636 if (ret < 0) {
1637 ret = nbd_co_send_structured_error(req->client, request.handle,
Eric Blakea57f6de2017-10-27 12:40:33 +02001638 -ret, msg, &local_err);
Eric Blakeef8c8872017-11-08 15:57:03 -06001639 } else if (reply_data_len) {
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001640 ret = nbd_co_send_structured_read(req->client, request.handle,
1641 request.from, req->data,
Eric Blake418638d2017-11-06 21:09:11 -06001642 reply_data_len, true,
1643 &local_err);
Eric Blakeef8c8872017-11-08 15:57:03 -06001644 } else {
1645 ret = nbd_co_send_structured_done(req->client, request.handle,
1646 &local_err);
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001647 }
1648 } else {
1649 ret = nbd_co_send_simple_reply(req->client, request.handle,
1650 ret < 0 ? -ret : 0,
1651 req->data, reply_data_len, &local_err);
1652 }
Eric Blakea57f6de2017-10-27 12:40:33 +02001653 g_free(msg);
Vladimir Sementsov-Ogievskiy5c54e7f2017-10-27 12:40:32 +02001654 if (ret < 0) {
Vladimir Sementsov-Ogievskiyc7b97282017-07-07 18:29:12 +03001655 error_prepend(&local_err, "Failed to send reply: ");
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001656 goto disconnect;
1657 }
1658
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001659 /* We must disconnect after NBD_CMD_WRITE if we did not
1660 * read the payload.
1661 */
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001662 if (!req->complete) {
1663 error_setg(&local_err, "Request handling failed in intermediate state");
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001664 goto disconnect;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001665 }
bellard7a5ca862008-05-27 21:13:40 +00001666
Paolo Bonzini7fe7b682012-03-05 09:10:35 +01001667done:
Paolo Bonzini262db382011-09-19 15:19:27 +02001668 nbd_request_put(req);
Paolo Bonziniff829112017-02-13 14:52:24 +01001669 nbd_client_put(client);
Paolo Bonzini262db382011-09-19 15:19:27 +02001670 return;
1671
Vladimir Sementsov-Ogievskiy8c372a02017-06-02 18:01:50 +03001672disconnect:
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001673 if (local_err) {
1674 error_reportf_err(local_err, "Disconnect client, due to: ");
1675 }
Paolo Bonzini72deddc2011-10-07 16:47:56 +02001676 nbd_request_put(req);
Eric Blake0c9390d2017-06-08 17:26:17 -05001677 client_close(client, true);
Paolo Bonziniff829112017-02-13 14:52:24 +01001678 nbd_client_put(client);
bellard7a5ca862008-05-27 21:13:40 +00001679}
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001680
Paolo Bonziniff829112017-02-13 14:52:24 +01001681static void nbd_client_receive_next_request(NBDClient *client)
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001682{
Paolo Bonziniff829112017-02-13 14:52:24 +01001683 if (!client->recv_coroutine && client->nb_requests < MAX_NBD_REQUESTS) {
1684 nbd_client_get(client);
1685 client->recv_coroutine = qemu_coroutine_create(nbd_trip, client);
1686 aio_co_schedule(client->exp->ctx, client->recv_coroutine);
Max Reitz958c7172014-06-20 21:57:32 +02001687 }
1688}
1689
Fam Zheng1a6245a2016-01-14 16:41:03 +08001690static coroutine_fn void nbd_co_client_start(void *opaque)
Paolo Bonzini1743b512011-09-19 14:33:23 +02001691{
Vladimir Sementsov-Ogievskiyc84087f2017-06-02 18:01:46 +03001692 NBDClient *client = opaque;
Fam Zheng1a6245a2016-01-14 16:41:03 +08001693 NBDExport *exp = client->exp;
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001694 Error *local_err = NULL;
Fam Zheng1a6245a2016-01-14 16:41:03 +08001695
1696 if (exp) {
1697 nbd_export_get(exp);
Eric Blakedf8ad9f2017-05-26 22:04:21 -05001698 QTAILQ_INSERT_TAIL(&exp->clients, client, next);
Fam Zheng1a6245a2016-01-14 16:41:03 +08001699 }
Paolo Bonzini262db382011-09-19 15:19:27 +02001700 qemu_co_mutex_init(&client->send_lock);
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +02001701
Vladimir Sementsov-Ogievskiy2fd2c842017-07-07 18:29:11 +03001702 if (nbd_negotiate(client, &local_err)) {
1703 if (local_err) {
1704 error_report_err(local_err);
1705 }
Eric Blake0c9390d2017-06-08 17:26:17 -05001706 client_close(client, false);
Vladimir Sementsov-Ogievskiyc84087f2017-06-02 18:01:46 +03001707 return;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +02001708 }
Paolo Bonziniff829112017-02-13 14:52:24 +01001709
1710 nbd_client_receive_next_request(client);
Fam Zheng1a6245a2016-01-14 16:41:03 +08001711}
1712
Eric Blake0c9390d2017-06-08 17:26:17 -05001713/*
1714 * Create a new client listener on the given export @exp, using the
1715 * given channel @sioc. Begin servicing it in a coroutine. When the
1716 * connection closes, call @close_fn with an indication of whether the
1717 * client completed negotiation.
1718 */
Daniel P. Berrange1c778ef2016-02-10 18:41:04 +00001719void nbd_client_new(NBDExport *exp,
1720 QIOChannelSocket *sioc,
Daniel P. Berrangef95910f2016-02-10 18:41:11 +00001721 QCryptoTLSCreds *tlscreds,
1722 const char *tlsaclname,
Eric Blake0c9390d2017-06-08 17:26:17 -05001723 void (*close_fn)(NBDClient *, bool))
Fam Zheng1a6245a2016-01-14 16:41:03 +08001724{
1725 NBDClient *client;
Vladimir Sementsov-Ogievskiyc84087f2017-06-02 18:01:46 +03001726 Coroutine *co;
Fam Zheng1a6245a2016-01-14 16:41:03 +08001727
Marc-André Lureaue8d3eb72017-10-06 20:49:16 -03001728 client = g_new0(NBDClient, 1);
Fam Zheng1a6245a2016-01-14 16:41:03 +08001729 client->refcount = 1;
1730 client->exp = exp;
Daniel P. Berrangef95910f2016-02-10 18:41:11 +00001731 client->tlscreds = tlscreds;
1732 if (tlscreds) {
1733 object_ref(OBJECT(client->tlscreds));
1734 }
1735 client->tlsaclname = g_strdup(tlsaclname);
Daniel P. Berrange1c778ef2016-02-10 18:41:04 +00001736 client->sioc = sioc;
1737 object_ref(OBJECT(client->sioc));
1738 client->ioc = QIO_CHANNEL(sioc);
1739 object_ref(OBJECT(client->ioc));
Eric Blake0c9390d2017-06-08 17:26:17 -05001740 client->close_fn = close_fn;
Fam Zheng1a6245a2016-01-14 16:41:03 +08001741
Vladimir Sementsov-Ogievskiyc84087f2017-06-02 18:01:46 +03001742 co = qemu_coroutine_create(nbd_co_client_start, client);
1743 qemu_coroutine_enter(co);
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001744}