blob: f847940f3edb8d8ecc00bf294a77f1e189abedff [file] [log] [blame]
ths75818252008-07-03 13:41:03 +00001/*
bellard7a5ca862008-05-27 21:13:40 +00002 * Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws>
3 *
4 * Network Block Device
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
Blue Swirl8167ee82009-07-16 20:47:01 +000016 * along with this program; if not, see <http://www.gnu.org/licenses/>.
ths75818252008-07-03 13:41:03 +000017 */
bellard7a5ca862008-05-27 21:13:40 +000018
Paolo Bonzini737e1502012-12-17 18:19:44 +010019#include "block/nbd.h"
20#include "block/block.h"
bellard7a5ca862008-05-27 21:13:40 +000021
Paolo Bonzini737e1502012-12-17 18:19:44 +010022#include "block/coroutine.h"
Paolo Bonzini262db382011-09-19 15:19:27 +020023
bellard7a5ca862008-05-27 21:13:40 +000024#include <errno.h>
25#include <string.h>
aliguori03ff3ca2008-09-15 15:51:35 +000026#ifndef _WIN32
bellard7a5ca862008-05-27 21:13:40 +000027#include <sys/ioctl.h>
aliguori03ff3ca2008-09-15 15:51:35 +000028#endif
Andreas Färber5dc2eec2010-09-20 00:50:46 +020029#if defined(__sun__) || defined(__HAIKU__)
aliguori7e00eb92008-08-02 01:57:02 +000030#include <sys/ioccom.h>
31#endif
bellard7a5ca862008-05-27 21:13:40 +000032#include <ctype.h>
33#include <inttypes.h>
bellard7a5ca862008-05-27 21:13:40 +000034
Paolo Bonzinib90fb4b2011-09-08 17:24:54 +020035#ifdef __linux__
36#include <linux/fs.h>
37#endif
38
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010039#include "qemu/sockets.h"
40#include "qemu/queue.h"
Alex Bligh6a1751b2013-08-21 16:02:47 +010041#include "qemu/main-loop.h"
ths75818252008-07-03 13:41:03 +000042
aliguori03ff3ca2008-09-15 15:51:35 +000043//#define DEBUG_NBD
44
45#ifdef DEBUG_NBD
ths75818252008-07-03 13:41:03 +000046#define TRACE(msg, ...) do { \
aliguori03ff3ca2008-09-15 15:51:35 +000047 LOG(msg, ## __VA_ARGS__); \
ths75818252008-07-03 13:41:03 +000048} while(0)
aliguori03ff3ca2008-09-15 15:51:35 +000049#else
50#define TRACE(msg, ...) \
51 do { } while (0)
52#endif
bellard7a5ca862008-05-27 21:13:40 +000053
54#define LOG(msg, ...) do { \
55 fprintf(stderr, "%s:%s():L%d: " msg "\n", \
56 __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
57} while(0)
58
bellard7a5ca862008-05-27 21:13:40 +000059/* This is all part of the "official" NBD API */
60
Paolo Bonzinifa26c262012-08-22 15:13:30 +020061#define NBD_REQUEST_SIZE (4 + 4 + 8 + 8 + 4)
Nick Thomasb2e3d872011-02-22 15:44:51 +000062#define NBD_REPLY_SIZE (4 + 4 + 8)
bellard7a5ca862008-05-27 21:13:40 +000063#define NBD_REQUEST_MAGIC 0x25609513
64#define NBD_REPLY_MAGIC 0x67446698
Paolo Bonzinifa26c262012-08-22 15:13:30 +020065#define NBD_OPTS_MAGIC 0x49484156454F5054LL
66#define NBD_CLIENT_MAGIC 0x0000420281861253LL
bellard7a5ca862008-05-27 21:13:40 +000067
68#define NBD_SET_SOCK _IO(0xab, 0)
69#define NBD_SET_BLKSIZE _IO(0xab, 1)
70#define NBD_SET_SIZE _IO(0xab, 2)
71#define NBD_DO_IT _IO(0xab, 3)
72#define NBD_CLEAR_SOCK _IO(0xab, 4)
73#define NBD_CLEAR_QUE _IO(0xab, 5)
Nick Thomasb2e3d872011-02-22 15:44:51 +000074#define NBD_PRINT_DEBUG _IO(0xab, 6)
75#define NBD_SET_SIZE_BLOCKS _IO(0xab, 7)
bellard7a5ca862008-05-27 21:13:40 +000076#define NBD_DISCONNECT _IO(0xab, 8)
Paolo Bonzinibbb74ed2011-09-08 17:24:55 +020077#define NBD_SET_TIMEOUT _IO(0xab, 9)
78#define NBD_SET_FLAGS _IO(0xab, 10)
bellard7a5ca862008-05-27 21:13:40 +000079
Nick Thomasb2e3d872011-02-22 15:44:51 +000080#define NBD_OPT_EXPORT_NAME (1 << 0)
Laurent Vivier1d45f8b2010-08-25 22:48:33 +020081
Paolo Bonzini9a304d22012-08-22 15:30:31 +020082/* Definitions for opaque data types */
83
84typedef struct NBDRequest NBDRequest;
85
86struct NBDRequest {
87 QSIMPLEQ_ENTRY(NBDRequest) entry;
88 NBDClient *client;
89 uint8_t *data;
90};
91
92struct NBDExport {
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +020093 int refcount;
Paolo Bonzini0ddf08d2012-09-18 13:59:03 +020094 void (*close)(NBDExport *exp);
95
Paolo Bonzini9a304d22012-08-22 15:30:31 +020096 BlockDriverState *bs;
Paolo Bonziniee0a19e2012-08-22 15:59:23 +020097 char *name;
Paolo Bonzini9a304d22012-08-22 15:30:31 +020098 off_t dev_offset;
99 off_t size;
100 uint32_t nbdflags;
Paolo Bonzini4b9441f2012-09-18 13:58:25 +0200101 QTAILQ_HEAD(, NBDClient) clients;
Paolo Bonziniee0a19e2012-08-22 15:59:23 +0200102 QTAILQ_ENTRY(NBDExport) next;
Paolo Bonzini9a304d22012-08-22 15:30:31 +0200103};
104
Paolo Bonziniee0a19e2012-08-22 15:59:23 +0200105static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
106
Paolo Bonzini9a304d22012-08-22 15:30:31 +0200107struct NBDClient {
108 int refcount;
109 void (*close)(NBDClient *client);
110
111 NBDExport *exp;
112 int sock;
113
114 Coroutine *recv_coroutine;
115
116 CoMutex send_lock;
117 Coroutine *send_coroutine;
118
Paolo Bonzini4b9441f2012-09-18 13:58:25 +0200119 QTAILQ_ENTRY(NBDClient) next;
Paolo Bonzini9a304d22012-08-22 15:30:31 +0200120 int nb_requests;
Paolo Bonziniff2b68a2012-08-22 18:45:12 +0200121 bool closing;
Paolo Bonzini9a304d22012-08-22 15:30:31 +0200122};
123
bellard7a5ca862008-05-27 21:13:40 +0000124/* That's all folks */
125
Paolo Bonzini185b4332012-03-05 08:56:10 +0100126ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
bellard7a5ca862008-05-27 21:13:40 +0000127{
128 size_t offset = 0;
Paolo Bonzini185b4332012-03-05 08:56:10 +0100129 int err;
bellard7a5ca862008-05-27 21:13:40 +0000130
Paolo Bonziniae255e52011-09-08 14:28:59 +0200131 if (qemu_in_coroutine()) {
132 if (do_read) {
133 return qemu_co_recv(fd, buffer, size);
134 } else {
135 return qemu_co_send(fd, buffer, size);
136 }
137 }
138
bellard7a5ca862008-05-27 21:13:40 +0000139 while (offset < size) {
140 ssize_t len;
141
142 if (do_read) {
Blue Swirl00aa0042011-07-23 20:04:29 +0000143 len = qemu_recv(fd, buffer + offset, size - offset, 0);
bellard7a5ca862008-05-27 21:13:40 +0000144 } else {
aliguori03ff3ca2008-09-15 15:51:35 +0000145 len = send(fd, buffer + offset, size - offset, 0);
bellard7a5ca862008-05-27 21:13:40 +0000146 }
147
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +0100148 if (len < 0) {
Paolo Bonzini185b4332012-03-05 08:56:10 +0100149 err = socket_error();
aliguori03ff3ca2008-09-15 15:51:35 +0000150
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +0100151 /* recoverable error */
Paolo Bonzini7fe7b682012-03-05 09:10:35 +0100152 if (err == EINTR || (offset > 0 && err == EAGAIN)) {
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +0100153 continue;
154 }
155
156 /* unrecoverable error */
Paolo Bonzini185b4332012-03-05 08:56:10 +0100157 return -err;
bellard7a5ca862008-05-27 21:13:40 +0000158 }
159
160 /* eof */
161 if (len == 0) {
162 break;
163 }
164
bellard7a5ca862008-05-27 21:13:40 +0000165 offset += len;
166 }
167
168 return offset;
169}
170
Paolo Bonzini7fe7b682012-03-05 09:10:35 +0100171static ssize_t read_sync(int fd, void *buffer, size_t size)
172{
173 /* Sockets are kept in blocking mode in the negotiation phase. After
174 * that, a non-readable socket simply means that another thread stole
175 * our request/reply. Synchronization is done with recv_coroutine, so
176 * that this is coroutine-safe.
177 */
178 return nbd_wr_sync(fd, buffer, size, true);
179}
180
181static ssize_t write_sync(int fd, void *buffer, size_t size)
182{
183 int ret;
184 do {
185 /* For writes, we do expect the socket to be writable. */
186 ret = nbd_wr_sync(fd, buffer, size, false);
187 } while (ret == -EAGAIN);
188 return ret;
189}
190
Nick Thomasc12504c2011-02-22 15:44:53 +0000191static void combine_addr(char *buf, size_t len, const char* address,
192 uint16_t port)
193{
194 /* If the address-part contains a colon, it's an IPv6 IP so needs [] */
195 if (strstr(address, ":")) {
196 snprintf(buf, len, "[%s]:%u", address, port);
197 } else {
198 snprintf(buf, len, "%s:%u", address, port);
199 }
200}
201
Kevin Wolff17c90b2013-03-15 11:55:29 +0100202int tcp_socket_outgoing_opts(QemuOpts *opts)
203{
204 Error *local_err = NULL;
205 int fd = inet_connect_opts(opts, &local_err, NULL, NULL);
206 if (local_err != NULL) {
207 qerror_report_err(local_err);
208 error_free(local_err);
209 }
210
211 return fd;
212}
213
bellard7a5ca862008-05-27 21:13:40 +0000214int tcp_socket_incoming(const char *address, uint16_t port)
215{
Nick Thomasc12504c2011-02-22 15:44:53 +0000216 char address_and_port[128];
217 combine_addr(address_and_port, 128, address, port);
218 return tcp_socket_incoming_spec(address_and_port);
bellard7a5ca862008-05-27 21:13:40 +0000219}
220
Nick Thomasc12504c2011-02-22 15:44:53 +0000221int tcp_socket_incoming_spec(const char *address_and_port)
222{
Paolo Bonzinif8430e72012-10-02 10:07:21 +0200223 Error *local_err = NULL;
224 int fd = inet_listen(address_and_port, NULL, 0, SOCK_STREAM, 0, &local_err);
225
226 if (local_err != NULL) {
227 qerror_report_err(local_err);
228 error_free(local_err);
229 }
230 return fd;
Nick Thomasc12504c2011-02-22 15:44:53 +0000231}
232
thscd831bd2008-07-03 10:23:51 +0000233int unix_socket_incoming(const char *path)
234{
Paolo Bonzinif8430e72012-10-02 10:07:21 +0200235 Error *local_err = NULL;
236 int fd = unix_listen(path, NULL, 0, &local_err);
thscd831bd2008-07-03 10:23:51 +0000237
Paolo Bonzinif8430e72012-10-02 10:07:21 +0200238 if (local_err != NULL) {
239 qerror_report_err(local_err);
240 error_free(local_err);
241 }
242 return fd;
thscd831bd2008-07-03 10:23:51 +0000243}
244
245int unix_socket_outgoing(const char *path)
246{
Paolo Bonzinif8430e72012-10-02 10:07:21 +0200247 Error *local_err = NULL;
248 int fd = unix_connect(path, &local_err);
249
250 if (local_err != NULL) {
251 qerror_report_err(local_err);
252 error_free(local_err);
253 }
254 return fd;
thscd831bd2008-07-03 10:23:51 +0000255}
thscd831bd2008-07-03 10:23:51 +0000256
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200257/* Basic flow for negotiation
bellard7a5ca862008-05-27 21:13:40 +0000258
259 Server Client
bellard7a5ca862008-05-27 21:13:40 +0000260 Negotiate
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200261
262 or
263
264 Server Client
265 Negotiate #1
266 Option
267 Negotiate #2
268
269 ----
270
271 followed by
272
273 Server Client
bellard7a5ca862008-05-27 21:13:40 +0000274 Request
275 Response
276 Request
277 Response
278 ...
279 ...
280 Request (type == 2)
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200281
bellard7a5ca862008-05-27 21:13:40 +0000282*/
283
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200284static int nbd_receive_options(NBDClient *client)
285{
286 int csock = client->sock;
287 char name[256];
288 uint32_t tmp, length;
289 uint64_t magic;
290 int rc;
291
292 /* Client sends:
293 [ 0 .. 3] reserved (0)
294 [ 4 .. 11] NBD_OPTS_MAGIC
295 [12 .. 15] NBD_OPT_EXPORT_NAME
296 [16 .. 19] length
297 [20 .. xx] export name (length bytes)
298 */
299
300 rc = -EINVAL;
301 if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
302 LOG("read failed");
303 goto fail;
304 }
305 TRACE("Checking reserved");
306 if (tmp != 0) {
307 LOG("Bad reserved received");
308 goto fail;
309 }
310
311 if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
312 LOG("read failed");
313 goto fail;
314 }
315 TRACE("Checking reserved");
316 if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) {
317 LOG("Bad magic received");
318 goto fail;
319 }
320
321 if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
322 LOG("read failed");
323 goto fail;
324 }
325 TRACE("Checking option");
326 if (tmp != be32_to_cpu(NBD_OPT_EXPORT_NAME)) {
327 LOG("Bad option received");
328 goto fail;
329 }
330
331 if (read_sync(csock, &length, sizeof(length)) != sizeof(length)) {
332 LOG("read failed");
333 goto fail;
334 }
335 TRACE("Checking length");
336 length = be32_to_cpu(length);
337 if (length > 255) {
338 LOG("Bad length received");
339 goto fail;
340 }
341 if (read_sync(csock, name, length) != length) {
342 LOG("read failed");
343 goto fail;
344 }
345 name[length] = '\0';
346
347 client->exp = nbd_export_find(name);
348 if (!client->exp) {
349 LOG("export not found");
350 goto fail;
351 }
352
353 QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
354 nbd_export_get(client->exp);
355
356 TRACE("Option negotiation succeeded.");
357 rc = 0;
358fail:
359 return rc;
360}
361
Paolo Bonzini9a304d22012-08-22 15:30:31 +0200362static int nbd_send_negotiate(NBDClient *client)
bellard7a5ca862008-05-27 21:13:40 +0000363{
Paolo Bonzini9a304d22012-08-22 15:30:31 +0200364 int csock = client->sock;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000365 char buf[8 + 8 + 8 + 128];
Paolo Bonzini185b4332012-03-05 08:56:10 +0100366 int rc;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200367 const int myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
368 NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
bellard7a5ca862008-05-27 21:13:40 +0000369
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200370 /* Negotiation header without options:
371 [ 0 .. 7] passwd ("NBDMAGIC")
372 [ 8 .. 15] magic (NBD_CLIENT_MAGIC)
Nick Thomasb2e3d872011-02-22 15:44:51 +0000373 [16 .. 23] size
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200374 [24 .. 25] server flags (0)
375 [24 .. 27] export flags
376 [28 .. 151] reserved (0)
377
378 Negotiation header with options, part 1:
379 [ 0 .. 7] passwd ("NBDMAGIC")
380 [ 8 .. 15] magic (NBD_OPTS_MAGIC)
381 [16 .. 17] server flags (0)
382
383 part 2 (after options are sent):
384 [18 .. 25] size
385 [26 .. 27] export flags
386 [28 .. 151] reserved (0)
Nick Thomasb2e3d872011-02-22 15:44:51 +0000387 */
bellard7a5ca862008-05-27 21:13:40 +0000388
Stefan Hajnoczif9e8cac2013-03-27 10:10:43 +0100389 qemu_set_block(csock);
Paolo Bonzini185b4332012-03-05 08:56:10 +0100390 rc = -EINVAL;
391
Nick Thomasb2e3d872011-02-22 15:44:51 +0000392 TRACE("Beginning negotiation.");
Paolo Bonzini8ffaaba2012-11-26 15:19:31 +0100393 memset(buf, 0, sizeof(buf));
Nick Thomasb2e3d872011-02-22 15:44:51 +0000394 memcpy(buf, "NBDMAGIC", 8);
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200395 if (client->exp) {
396 assert ((client->exp->nbdflags & ~65535) == 0);
397 cpu_to_be64w((uint64_t*)(buf + 8), NBD_CLIENT_MAGIC);
398 cpu_to_be64w((uint64_t*)(buf + 16), client->exp->size);
399 cpu_to_be16w((uint16_t*)(buf + 26), client->exp->nbdflags | myflags);
400 } else {
401 cpu_to_be64w((uint64_t*)(buf + 8), NBD_OPTS_MAGIC);
402 }
bellard7a5ca862008-05-27 21:13:40 +0000403
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200404 if (client->exp) {
405 if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
406 LOG("write failed");
407 goto fail;
408 }
409 } else {
410 if (write_sync(csock, buf, 18) != 18) {
411 LOG("write failed");
412 goto fail;
413 }
414 rc = nbd_receive_options(client);
415 if (rc < 0) {
416 LOG("option negotiation failed");
417 goto fail;
418 }
419
420 assert ((client->exp->nbdflags & ~65535) == 0);
421 cpu_to_be64w((uint64_t*)(buf + 18), client->exp->size);
422 cpu_to_be16w((uint16_t*)(buf + 26), client->exp->nbdflags | myflags);
423 if (write_sync(csock, buf + 18, sizeof(buf) - 18) != sizeof(buf) - 18) {
424 LOG("write failed");
425 goto fail;
426 }
Nick Thomasb2e3d872011-02-22 15:44:51 +0000427 }
bellard7a5ca862008-05-27 21:13:40 +0000428
Dong Xu Wang07f35072011-11-22 18:06:26 +0800429 TRACE("Negotiation succeeded.");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100430 rc = 0;
431fail:
Stefan Hajnoczif9e8cac2013-03-27 10:10:43 +0100432 qemu_set_nonblock(csock);
Paolo Bonzini185b4332012-03-05 08:56:10 +0100433 return rc;
bellard7a5ca862008-05-27 21:13:40 +0000434}
435
Laurent Vivier1d45f8b2010-08-25 22:48:33 +0200436int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
437 off_t *size, size_t *blocksize)
bellard7a5ca862008-05-27 21:13:40 +0000438{
Nick Thomasb2e3d872011-02-22 15:44:51 +0000439 char buf[256];
440 uint64_t magic, s;
441 uint16_t tmp;
Paolo Bonzini185b4332012-03-05 08:56:10 +0100442 int rc;
bellard7a5ca862008-05-27 21:13:40 +0000443
Dong Xu Wang07f35072011-11-22 18:06:26 +0800444 TRACE("Receiving negotiation.");
bellard7a5ca862008-05-27 21:13:40 +0000445
Stefan Hajnoczif9e8cac2013-03-27 10:10:43 +0100446 qemu_set_block(csock);
Paolo Bonzini185b4332012-03-05 08:56:10 +0100447 rc = -EINVAL;
448
Nick Thomasb2e3d872011-02-22 15:44:51 +0000449 if (read_sync(csock, buf, 8) != 8) {
450 LOG("read failed");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100451 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000452 }
bellard7a5ca862008-05-27 21:13:40 +0000453
Nick Thomasb2e3d872011-02-22 15:44:51 +0000454 buf[8] = '\0';
455 if (strlen(buf) == 0) {
456 LOG("server connection closed");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100457 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000458 }
bellard7a5ca862008-05-27 21:13:40 +0000459
Nick Thomasb2e3d872011-02-22 15:44:51 +0000460 TRACE("Magic is %c%c%c%c%c%c%c%c",
461 qemu_isprint(buf[0]) ? buf[0] : '.',
462 qemu_isprint(buf[1]) ? buf[1] : '.',
463 qemu_isprint(buf[2]) ? buf[2] : '.',
464 qemu_isprint(buf[3]) ? buf[3] : '.',
465 qemu_isprint(buf[4]) ? buf[4] : '.',
466 qemu_isprint(buf[5]) ? buf[5] : '.',
467 qemu_isprint(buf[6]) ? buf[6] : '.',
468 qemu_isprint(buf[7]) ? buf[7] : '.');
bellard7a5ca862008-05-27 21:13:40 +0000469
Nick Thomasb2e3d872011-02-22 15:44:51 +0000470 if (memcmp(buf, "NBDMAGIC", 8) != 0) {
471 LOG("Invalid magic received");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100472 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000473 }
bellard7a5ca862008-05-27 21:13:40 +0000474
Nick Thomasb2e3d872011-02-22 15:44:51 +0000475 if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
476 LOG("read failed");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100477 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000478 }
479 magic = be64_to_cpu(magic);
480 TRACE("Magic is 0x%" PRIx64, magic);
bellard7a5ca862008-05-27 21:13:40 +0000481
Nick Thomasb2e3d872011-02-22 15:44:51 +0000482 if (name) {
483 uint32_t reserved = 0;
484 uint32_t opt;
485 uint32_t namesize;
Laurent Vivier1d45f8b2010-08-25 22:48:33 +0200486
Nick Thomasb2e3d872011-02-22 15:44:51 +0000487 TRACE("Checking magic (opts_magic)");
Paolo Bonzinifa26c262012-08-22 15:13:30 +0200488 if (magic != NBD_OPTS_MAGIC) {
Nick Thomasb2e3d872011-02-22 15:44:51 +0000489 LOG("Bad magic received");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100490 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000491 }
492 if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
493 LOG("flags read failed");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100494 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000495 }
496 *flags = be16_to_cpu(tmp) << 16;
497 /* reserved for future use */
498 if (write_sync(csock, &reserved, sizeof(reserved)) !=
499 sizeof(reserved)) {
500 LOG("write failed (reserved)");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100501 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000502 }
503 /* write the export name */
504 magic = cpu_to_be64(magic);
505 if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
506 LOG("write failed (magic)");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100507 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000508 }
509 opt = cpu_to_be32(NBD_OPT_EXPORT_NAME);
510 if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) {
511 LOG("write failed (opt)");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100512 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000513 }
514 namesize = cpu_to_be32(strlen(name));
515 if (write_sync(csock, &namesize, sizeof(namesize)) !=
516 sizeof(namesize)) {
517 LOG("write failed (namesize)");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100518 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000519 }
520 if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) {
521 LOG("write failed (name)");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100522 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000523 }
524 } else {
525 TRACE("Checking magic (cli_magic)");
Laurent Vivier1d45f8b2010-08-25 22:48:33 +0200526
Paolo Bonzinifa26c262012-08-22 15:13:30 +0200527 if (magic != NBD_CLIENT_MAGIC) {
Nick Thomasb2e3d872011-02-22 15:44:51 +0000528 LOG("Bad magic received");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100529 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000530 }
531 }
Laurent Vivier1d45f8b2010-08-25 22:48:33 +0200532
Nick Thomasb2e3d872011-02-22 15:44:51 +0000533 if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) {
534 LOG("read failed");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100535 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000536 }
537 *size = be64_to_cpu(s);
538 *blocksize = 1024;
539 TRACE("Size is %" PRIu64, *size);
Laurent Vivier1d45f8b2010-08-25 22:48:33 +0200540
Nick Thomasb2e3d872011-02-22 15:44:51 +0000541 if (!name) {
542 if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) {
543 LOG("read failed (flags)");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100544 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000545 }
546 *flags = be32_to_cpup(flags);
547 } else {
548 if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
549 LOG("read failed (tmp)");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100550 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000551 }
552 *flags |= be32_to_cpu(tmp);
553 }
554 if (read_sync(csock, &buf, 124) != 124) {
555 LOG("read failed (buf)");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100556 goto fail;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000557 }
Paolo Bonzini185b4332012-03-05 08:56:10 +0100558 rc = 0;
559
560fail:
Stefan Hajnoczif9e8cac2013-03-27 10:10:43 +0100561 qemu_set_nonblock(csock);
Paolo Bonzini185b4332012-03-05 08:56:10 +0100562 return rc;
thscd831bd2008-07-03 10:23:51 +0000563}
bellard7a5ca862008-05-27 21:13:40 +0000564
Paolo Bonzinib90fb4b2011-09-08 17:24:54 +0200565#ifdef __linux__
566int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
thscd831bd2008-07-03 10:23:51 +0000567{
Chunyan Liu3e05c782011-12-02 23:27:54 +0800568 TRACE("Setting NBD socket");
569
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +0100570 if (ioctl(fd, NBD_SET_SOCK, csock) < 0) {
Chunyan Liu3e05c782011-12-02 23:27:54 +0800571 int serrno = errno;
572 LOG("Failed to set NBD socket");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100573 return -serrno;
Chunyan Liu3e05c782011-12-02 23:27:54 +0800574 }
575
Nick Thomasb2e3d872011-02-22 15:44:51 +0000576 TRACE("Setting block size to %lu", (unsigned long)blocksize);
bellard7a5ca862008-05-27 21:13:40 +0000577
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +0100578 if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) < 0) {
Nick Thomasb2e3d872011-02-22 15:44:51 +0000579 int serrno = errno;
580 LOG("Failed setting NBD block size");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100581 return -serrno;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000582 }
bellard7a5ca862008-05-27 21:13:40 +0000583
Blue Swirl0bfcd592010-05-22 08:02:12 +0000584 TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize));
bellard7a5ca862008-05-27 21:13:40 +0000585
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +0100586 if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) < 0) {
Nick Thomasb2e3d872011-02-22 15:44:51 +0000587 int serrno = errno;
588 LOG("Failed setting size (in blocks)");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100589 return -serrno;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000590 }
bellard7a5ca862008-05-27 21:13:40 +0000591
Paolo Bonzinic8969ed2012-11-13 10:34:17 +0100592 if (ioctl(fd, NBD_SET_FLAGS, flags) < 0) {
593 if (errno == ENOTTY) {
594 int read_only = (flags & NBD_FLAG_READ_ONLY) != 0;
595 TRACE("Setting readonly attribute");
Paolo Bonzinib90fb4b2011-09-08 17:24:54 +0200596
Paolo Bonzinic8969ed2012-11-13 10:34:17 +0100597 if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) {
598 int serrno = errno;
599 LOG("Failed setting read-only attribute");
600 return -serrno;
601 }
602 } else {
Paolo Bonzinib90fb4b2011-09-08 17:24:54 +0200603 int serrno = errno;
Paolo Bonzinic8969ed2012-11-13 10:34:17 +0100604 LOG("Failed setting flags");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100605 return -serrno;
Paolo Bonzinib90fb4b2011-09-08 17:24:54 +0200606 }
607 }
608
Nick Thomasb2e3d872011-02-22 15:44:51 +0000609 TRACE("Negotiation ended");
bellard7a5ca862008-05-27 21:13:40 +0000610
Nick Thomasb2e3d872011-02-22 15:44:51 +0000611 return 0;
bellard7a5ca862008-05-27 21:13:40 +0000612}
613
614int nbd_disconnect(int fd)
615{
Nick Thomasb2e3d872011-02-22 15:44:51 +0000616 ioctl(fd, NBD_CLEAR_QUE);
617 ioctl(fd, NBD_DISCONNECT);
618 ioctl(fd, NBD_CLEAR_SOCK);
619 return 0;
bellard7a5ca862008-05-27 21:13:40 +0000620}
621
Jes Sorensen0a4eb862010-08-31 09:30:33 +0200622int nbd_client(int fd)
bellard7a5ca862008-05-27 21:13:40 +0000623{
Nick Thomasb2e3d872011-02-22 15:44:51 +0000624 int ret;
625 int serrno;
bellard7a5ca862008-05-27 21:13:40 +0000626
Nick Thomasb2e3d872011-02-22 15:44:51 +0000627 TRACE("Doing NBD loop");
bellard7a5ca862008-05-27 21:13:40 +0000628
Nick Thomasb2e3d872011-02-22 15:44:51 +0000629 ret = ioctl(fd, NBD_DO_IT);
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +0100630 if (ret < 0 && errno == EPIPE) {
Paolo Bonzini74624682011-11-04 15:51:18 +0100631 /* NBD_DO_IT normally returns EPIPE when someone has disconnected
632 * the socket via NBD_DISCONNECT. We do not want to return 1 in
633 * that case.
634 */
635 ret = 0;
636 }
Nick Thomasb2e3d872011-02-22 15:44:51 +0000637 serrno = errno;
bellard7a5ca862008-05-27 21:13:40 +0000638
Nick Thomasb2e3d872011-02-22 15:44:51 +0000639 TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
bellard7a5ca862008-05-27 21:13:40 +0000640
Nick Thomasb2e3d872011-02-22 15:44:51 +0000641 TRACE("Clearing NBD queue");
642 ioctl(fd, NBD_CLEAR_QUE);
bellard7a5ca862008-05-27 21:13:40 +0000643
Nick Thomasb2e3d872011-02-22 15:44:51 +0000644 TRACE("Clearing NBD socket");
645 ioctl(fd, NBD_CLEAR_SOCK);
bellard7a5ca862008-05-27 21:13:40 +0000646
Nick Thomasb2e3d872011-02-22 15:44:51 +0000647 errno = serrno;
648 return ret;
bellard7a5ca862008-05-27 21:13:40 +0000649}
aliguori03ff3ca2008-09-15 15:51:35 +0000650#else
Paolo Bonzini8e725062011-09-21 09:34:12 +0200651int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
aliguori03ff3ca2008-09-15 15:51:35 +0000652{
Paolo Bonzini185b4332012-03-05 08:56:10 +0100653 return -ENOTSUP;
aliguori03ff3ca2008-09-15 15:51:35 +0000654}
655
656int nbd_disconnect(int fd)
657{
Paolo Bonzini185b4332012-03-05 08:56:10 +0100658 return -ENOTSUP;
aliguori03ff3ca2008-09-15 15:51:35 +0000659}
660
Jes Sorensen0a4eb862010-08-31 09:30:33 +0200661int nbd_client(int fd)
aliguori03ff3ca2008-09-15 15:51:35 +0000662{
Paolo Bonzini185b4332012-03-05 08:56:10 +0100663 return -ENOTSUP;
aliguori03ff3ca2008-09-15 15:51:35 +0000664}
665#endif
bellard7a5ca862008-05-27 21:13:40 +0000666
Paolo Bonzini94e73402012-03-07 11:25:01 +0100667ssize_t nbd_send_request(int csock, struct nbd_request *request)
ths75818252008-07-03 13:41:03 +0000668{
Paolo Bonzinifa26c262012-08-22 15:13:30 +0200669 uint8_t buf[NBD_REQUEST_SIZE];
Paolo Bonzini185b4332012-03-05 08:56:10 +0100670 ssize_t ret;
ths75818252008-07-03 13:41:03 +0000671
Nick Thomasb2e3d872011-02-22 15:44:51 +0000672 cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
673 cpu_to_be32w((uint32_t*)(buf + 4), request->type);
674 cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
675 cpu_to_be64w((uint64_t*)(buf + 16), request->from);
676 cpu_to_be32w((uint32_t*)(buf + 24), request->len);
ths75818252008-07-03 13:41:03 +0000677
Nick Thomasb2e3d872011-02-22 15:44:51 +0000678 TRACE("Sending request to client: "
679 "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}",
680 request->from, request->len, request->handle, request->type);
ths75818252008-07-03 13:41:03 +0000681
Paolo Bonzini185b4332012-03-05 08:56:10 +0100682 ret = write_sync(csock, buf, sizeof(buf));
683 if (ret < 0) {
684 return ret;
685 }
686
687 if (ret != sizeof(buf)) {
Nick Thomasb2e3d872011-02-22 15:44:51 +0000688 LOG("writing to socket failed");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100689 return -EINVAL;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000690 }
691 return 0;
ths75818252008-07-03 13:41:03 +0000692}
693
Paolo Bonzini94e73402012-03-07 11:25:01 +0100694static ssize_t nbd_receive_request(int csock, struct nbd_request *request)
bellard7a5ca862008-05-27 21:13:40 +0000695{
Paolo Bonzinifa26c262012-08-22 15:13:30 +0200696 uint8_t buf[NBD_REQUEST_SIZE];
Nick Thomasb2e3d872011-02-22 15:44:51 +0000697 uint32_t magic;
Paolo Bonzini185b4332012-03-05 08:56:10 +0100698 ssize_t ret;
bellard7a5ca862008-05-27 21:13:40 +0000699
Paolo Bonzini185b4332012-03-05 08:56:10 +0100700 ret = read_sync(csock, buf, sizeof(buf));
701 if (ret < 0) {
702 return ret;
703 }
704
705 if (ret != sizeof(buf)) {
Nick Thomasb2e3d872011-02-22 15:44:51 +0000706 LOG("read failed");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100707 return -EINVAL;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000708 }
bellard7a5ca862008-05-27 21:13:40 +0000709
Nick Thomasb2e3d872011-02-22 15:44:51 +0000710 /* Request
711 [ 0 .. 3] magic (NBD_REQUEST_MAGIC)
712 [ 4 .. 7] type (0 == READ, 1 == WRITE)
713 [ 8 .. 15] handle
714 [16 .. 23] from
715 [24 .. 27] len
716 */
bellard7a5ca862008-05-27 21:13:40 +0000717
Nick Thomasb2e3d872011-02-22 15:44:51 +0000718 magic = be32_to_cpup((uint32_t*)buf);
719 request->type = be32_to_cpup((uint32_t*)(buf + 4));
720 request->handle = be64_to_cpup((uint64_t*)(buf + 8));
721 request->from = be64_to_cpup((uint64_t*)(buf + 16));
722 request->len = be32_to_cpup((uint32_t*)(buf + 24));
bellard7a5ca862008-05-27 21:13:40 +0000723
Nick Thomasb2e3d872011-02-22 15:44:51 +0000724 TRACE("Got request: "
725 "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
726 magic, request->type, request->from, request->len);
bellard7a5ca862008-05-27 21:13:40 +0000727
Nick Thomasb2e3d872011-02-22 15:44:51 +0000728 if (magic != NBD_REQUEST_MAGIC) {
729 LOG("invalid magic (got 0x%x)", magic);
Paolo Bonzini185b4332012-03-05 08:56:10 +0100730 return -EINVAL;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000731 }
732 return 0;
ths75818252008-07-03 13:41:03 +0000733}
bellard7a5ca862008-05-27 21:13:40 +0000734
Paolo Bonzini94e73402012-03-07 11:25:01 +0100735ssize_t nbd_receive_reply(int csock, struct nbd_reply *reply)
ths75818252008-07-03 13:41:03 +0000736{
Nick Thomasb2e3d872011-02-22 15:44:51 +0000737 uint8_t buf[NBD_REPLY_SIZE];
738 uint32_t magic;
Paolo Bonzini185b4332012-03-05 08:56:10 +0100739 ssize_t ret;
ths75818252008-07-03 13:41:03 +0000740
Paolo Bonzini185b4332012-03-05 08:56:10 +0100741 ret = read_sync(csock, buf, sizeof(buf));
742 if (ret < 0) {
743 return ret;
744 }
745
746 if (ret != sizeof(buf)) {
Nick Thomasb2e3d872011-02-22 15:44:51 +0000747 LOG("read failed");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100748 return -EINVAL;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000749 }
bellard7a5ca862008-05-27 21:13:40 +0000750
Nick Thomasb2e3d872011-02-22 15:44:51 +0000751 /* Reply
752 [ 0 .. 3] magic (NBD_REPLY_MAGIC)
753 [ 4 .. 7] error (0 == no error)
754 [ 7 .. 15] handle
755 */
ths75818252008-07-03 13:41:03 +0000756
Nick Thomasb2e3d872011-02-22 15:44:51 +0000757 magic = be32_to_cpup((uint32_t*)buf);
758 reply->error = be32_to_cpup((uint32_t*)(buf + 4));
759 reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
ths75818252008-07-03 13:41:03 +0000760
Nick Thomasb2e3d872011-02-22 15:44:51 +0000761 TRACE("Got reply: "
762 "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
763 magic, reply->error, reply->handle);
ths75818252008-07-03 13:41:03 +0000764
Nick Thomasb2e3d872011-02-22 15:44:51 +0000765 if (magic != NBD_REPLY_MAGIC) {
766 LOG("invalid magic (got 0x%x)", magic);
Paolo Bonzini185b4332012-03-05 08:56:10 +0100767 return -EINVAL;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000768 }
769 return 0;
ths75818252008-07-03 13:41:03 +0000770}
771
Paolo Bonzini94e73402012-03-07 11:25:01 +0100772static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply)
ths75818252008-07-03 13:41:03 +0000773{
Paolo Bonzinifa26c262012-08-22 15:13:30 +0200774 uint8_t buf[NBD_REPLY_SIZE];
Paolo Bonzini185b4332012-03-05 08:56:10 +0100775 ssize_t ret;
ths75818252008-07-03 13:41:03 +0000776
Nick Thomasb2e3d872011-02-22 15:44:51 +0000777 /* Reply
778 [ 0 .. 3] magic (NBD_REPLY_MAGIC)
779 [ 4 .. 7] error (0 == no error)
780 [ 7 .. 15] handle
781 */
782 cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
783 cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
784 cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
ths75818252008-07-03 13:41:03 +0000785
Nick Thomasb2e3d872011-02-22 15:44:51 +0000786 TRACE("Sending response to client");
ths75818252008-07-03 13:41:03 +0000787
Paolo Bonzini185b4332012-03-05 08:56:10 +0100788 ret = write_sync(csock, buf, sizeof(buf));
789 if (ret < 0) {
790 return ret;
791 }
792
793 if (ret != sizeof(buf)) {
Nick Thomasb2e3d872011-02-22 15:44:51 +0000794 LOG("writing to socket failed");
Paolo Bonzini185b4332012-03-05 08:56:10 +0100795 return -EINVAL;
Nick Thomasb2e3d872011-02-22 15:44:51 +0000796 }
797 return 0;
ths75818252008-07-03 13:41:03 +0000798}
799
Paolo Bonzini41996e32011-09-19 15:25:40 +0200800#define MAX_NBD_REQUESTS 16
801
Paolo Bonzinice339672012-09-18 13:17:52 +0200802void nbd_client_get(NBDClient *client)
Paolo Bonzini1743b512011-09-19 14:33:23 +0200803{
804 client->refcount++;
805}
806
Paolo Bonzinice339672012-09-18 13:17:52 +0200807void nbd_client_put(NBDClient *client)
Paolo Bonzini1743b512011-09-19 14:33:23 +0200808{
809 if (--client->refcount == 0) {
Paolo Bonziniff2b68a2012-08-22 18:45:12 +0200810 /* The last reference should be dropped by client->close,
811 * which is called by nbd_client_close.
812 */
813 assert(client->closing);
814
815 qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL);
816 close(client->sock);
817 client->sock = -1;
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +0200818 if (client->exp) {
819 QTAILQ_REMOVE(&client->exp->clients, client, next);
820 nbd_export_put(client->exp);
821 }
Paolo Bonzini1743b512011-09-19 14:33:23 +0200822 g_free(client);
823 }
824}
825
Paolo Bonziniff2b68a2012-08-22 18:45:12 +0200826void nbd_client_close(NBDClient *client)
Paolo Bonzini1743b512011-09-19 14:33:23 +0200827{
Paolo Bonziniff2b68a2012-08-22 18:45:12 +0200828 if (client->closing) {
829 return;
830 }
831
832 client->closing = true;
833
834 /* Force requests to finish. They will drop their own references,
835 * then we'll close the socket and free the NBDClient.
836 */
837 shutdown(client->sock, 2);
838
839 /* Also tell the client, so that they release their reference. */
Paolo Bonzini1743b512011-09-19 14:33:23 +0200840 if (client->close) {
841 client->close(client);
842 }
Paolo Bonzini1743b512011-09-19 14:33:23 +0200843}
844
Paolo Bonzini72deddc2011-10-07 16:47:56 +0200845static NBDRequest *nbd_request_get(NBDClient *client)
Paolo Bonzinid9a73802011-09-19 14:18:33 +0200846{
847 NBDRequest *req;
Paolo Bonzini72deddc2011-10-07 16:47:56 +0200848
Paolo Bonzini41996e32011-09-19 15:25:40 +0200849 assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
850 client->nb_requests++;
851
Stefan Hajnoczie1adb272013-05-02 14:23:07 +0200852 req = g_slice_new0(NBDRequest);
Paolo Bonzini72deddc2011-10-07 16:47:56 +0200853 nbd_client_get(client);
854 req->client = client;
Paolo Bonzinid9a73802011-09-19 14:18:33 +0200855 return req;
856}
857
Paolo Bonzini72deddc2011-10-07 16:47:56 +0200858static void nbd_request_put(NBDRequest *req)
Paolo Bonzinid9a73802011-09-19 14:18:33 +0200859{
Paolo Bonzini72deddc2011-10-07 16:47:56 +0200860 NBDClient *client = req->client;
Stefan Hajnoczie1adb272013-05-02 14:23:07 +0200861
Stefan Hajnoczi2d821482013-05-02 14:23:08 +0200862 if (req->data) {
863 qemu_vfree(req->data);
864 }
Stefan Hajnoczie1adb272013-05-02 14:23:07 +0200865 g_slice_free(NBDRequest, req);
866
Paolo Bonzini41996e32011-09-19 15:25:40 +0200867 if (client->nb_requests-- == MAX_NBD_REQUESTS) {
868 qemu_notify_event();
869 }
Paolo Bonzini72deddc2011-10-07 16:47:56 +0200870 nbd_client_put(client);
Paolo Bonzinid9a73802011-09-19 14:18:33 +0200871}
872
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +0200873NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
Paolo Bonzini0ddf08d2012-09-18 13:59:03 +0200874 off_t size, uint32_t nbdflags,
875 void (*close)(NBDExport *))
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +0200876{
877 NBDExport *exp = g_malloc0(sizeof(NBDExport));
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +0200878 exp->refcount = 1;
Paolo Bonzini4b9441f2012-09-18 13:58:25 +0200879 QTAILQ_INIT(&exp->clients);
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +0200880 exp->bs = bs;
881 exp->dev_offset = dev_offset;
882 exp->nbdflags = nbdflags;
Paolo Bonzini38ceff02012-03-12 16:17:27 +0100883 exp->size = size == -1 ? bdrv_getlength(bs) : size;
Paolo Bonzini0ddf08d2012-09-18 13:59:03 +0200884 exp->close = close;
Fam Zheng38b54b62013-08-23 09:14:50 +0800885 bdrv_ref(bs);
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +0200886 return exp;
887}
888
Paolo Bonziniee0a19e2012-08-22 15:59:23 +0200889NBDExport *nbd_export_find(const char *name)
890{
891 NBDExport *exp;
892 QTAILQ_FOREACH(exp, &exports, next) {
893 if (strcmp(name, exp->name) == 0) {
894 return exp;
895 }
896 }
897
898 return NULL;
899}
900
901void nbd_export_set_name(NBDExport *exp, const char *name)
902{
903 if (exp->name == name) {
904 return;
905 }
906
907 nbd_export_get(exp);
908 if (exp->name != NULL) {
909 g_free(exp->name);
910 exp->name = NULL;
911 QTAILQ_REMOVE(&exports, exp, next);
912 nbd_export_put(exp);
913 }
914 if (name != NULL) {
915 nbd_export_get(exp);
916 exp->name = g_strdup(name);
917 QTAILQ_INSERT_TAIL(&exports, exp, next);
918 }
919 nbd_export_put(exp);
920}
921
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +0200922void nbd_export_close(NBDExport *exp)
923{
Paolo Bonzini4b9441f2012-09-18 13:58:25 +0200924 NBDClient *client, *next;
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +0200925
Paolo Bonzini4b9441f2012-09-18 13:58:25 +0200926 nbd_export_get(exp);
927 QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
928 nbd_client_close(client);
929 }
Paolo Bonzini125afda2012-09-18 14:31:44 +0200930 nbd_export_set_name(exp, NULL);
Paolo Bonzini4b9441f2012-09-18 13:58:25 +0200931 nbd_export_put(exp);
Fam Zheng38b54b62013-08-23 09:14:50 +0800932 if (exp->bs) {
933 bdrv_unref(exp->bs);
934 exp->bs = NULL;
935 }
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +0200936}
937
938void nbd_export_get(NBDExport *exp)
939{
940 assert(exp->refcount > 0);
941 exp->refcount++;
942}
943
944void nbd_export_put(NBDExport *exp)
945{
946 assert(exp->refcount > 0);
947 if (exp->refcount == 1) {
948 nbd_export_close(exp);
Paolo Bonzinid9a73802011-09-19 14:18:33 +0200949 }
950
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +0200951 if (--exp->refcount == 0) {
Paolo Bonziniee0a19e2012-08-22 15:59:23 +0200952 assert(exp->name == NULL);
953
Paolo Bonzini0ddf08d2012-09-18 13:59:03 +0200954 if (exp->close) {
955 exp->close(exp);
956 }
957
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +0200958 g_free(exp);
959 }
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +0200960}
961
Paolo Bonzini125afda2012-09-18 14:31:44 +0200962BlockDriverState *nbd_export_get_blockdev(NBDExport *exp)
963{
964 return exp->bs;
965}
966
Paolo Bonziniee0a19e2012-08-22 15:59:23 +0200967void nbd_export_close_all(void)
968{
969 NBDExport *exp, *next;
970
971 QTAILQ_FOREACH_SAFE(exp, &exports, next, next) {
972 nbd_export_close(exp);
Paolo Bonziniee0a19e2012-08-22 15:59:23 +0200973 }
974}
975
Paolo Bonzini41996e32011-09-19 15:25:40 +0200976static int nbd_can_read(void *opaque);
Paolo Bonzini262db382011-09-19 15:19:27 +0200977static void nbd_read(void *opaque);
978static void nbd_restart_write(void *opaque);
979
Paolo Bonzini94e73402012-03-07 11:25:01 +0100980static ssize_t nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply,
981 int len)
Paolo Bonzini22045592011-09-19 14:25:30 +0200982{
Paolo Bonzini72deddc2011-10-07 16:47:56 +0200983 NBDClient *client = req->client;
984 int csock = client->sock;
Paolo Bonzini94e73402012-03-07 11:25:01 +0100985 ssize_t rc, ret;
Paolo Bonzini22045592011-09-19 14:25:30 +0200986
Paolo Bonzini262db382011-09-19 15:19:27 +0200987 qemu_co_mutex_lock(&client->send_lock);
Paolo Bonzini41996e32011-09-19 15:25:40 +0200988 qemu_set_fd_handler2(csock, nbd_can_read, nbd_read,
989 nbd_restart_write, client);
Paolo Bonzini262db382011-09-19 15:19:27 +0200990 client->send_coroutine = qemu_coroutine_self();
991
Paolo Bonzini22045592011-09-19 14:25:30 +0200992 if (!len) {
993 rc = nbd_send_reply(csock, reply);
Paolo Bonzini22045592011-09-19 14:25:30 +0200994 } else {
995 socket_set_cork(csock, 1);
996 rc = nbd_send_reply(csock, reply);
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +0100997 if (rc >= 0) {
Paolo Bonzini262db382011-09-19 15:19:27 +0200998 ret = qemu_co_send(csock, req->data, len);
Paolo Bonzini22045592011-09-19 14:25:30 +0200999 if (ret != len) {
Paolo Bonzini185b4332012-03-05 08:56:10 +01001000 rc = -EIO;
Paolo Bonzini22045592011-09-19 14:25:30 +02001001 }
1002 }
Paolo Bonzini22045592011-09-19 14:25:30 +02001003 socket_set_cork(csock, 0);
1004 }
Paolo Bonzini262db382011-09-19 15:19:27 +02001005
1006 client->send_coroutine = NULL;
Paolo Bonzini41996e32011-09-19 15:25:40 +02001007 qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client);
Paolo Bonzini262db382011-09-19 15:19:27 +02001008 qemu_co_mutex_unlock(&client->send_lock);
Paolo Bonzini22045592011-09-19 14:25:30 +02001009 return rc;
1010}
1011
Paolo Bonzini94e73402012-03-07 11:25:01 +01001012static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *request)
Paolo Bonzinia030b342011-09-19 15:07:54 +02001013{
Paolo Bonzini72deddc2011-10-07 16:47:56 +02001014 NBDClient *client = req->client;
1015 int csock = client->sock;
Stefan Hajnoczi2d821482013-05-02 14:23:08 +02001016 uint32_t command;
Paolo Bonzini94e73402012-03-07 11:25:01 +01001017 ssize_t rc;
Paolo Bonzinia030b342011-09-19 15:07:54 +02001018
Paolo Bonzini262db382011-09-19 15:19:27 +02001019 client->recv_coroutine = qemu_coroutine_self();
Paolo Bonzini7fe7b682012-03-05 09:10:35 +01001020 rc = nbd_receive_request(csock, request);
1021 if (rc < 0) {
1022 if (rc != -EAGAIN) {
1023 rc = -EIO;
1024 }
Paolo Bonzinia030b342011-09-19 15:07:54 +02001025 goto out;
1026 }
1027
Stefan Hajnoczi2d821482013-05-02 14:23:08 +02001028 if (request->len > NBD_MAX_BUFFER_SIZE) {
Paolo Bonzinia030b342011-09-19 15:07:54 +02001029 LOG("len (%u) is larger than max len (%u)",
Stefan Hajnoczi2d821482013-05-02 14:23:08 +02001030 request->len, NBD_MAX_BUFFER_SIZE);
Paolo Bonzinia030b342011-09-19 15:07:54 +02001031 rc = -EINVAL;
1032 goto out;
1033 }
1034
1035 if ((request->from + request->len) < request->from) {
1036 LOG("integer overflow detected! "
1037 "you're probably being attacked");
1038 rc = -EINVAL;
1039 goto out;
1040 }
1041
1042 TRACE("Decoding type");
1043
Stefan Hajnoczi2d821482013-05-02 14:23:08 +02001044 command = request->type & NBD_CMD_MASK_COMMAND;
1045 if (command == NBD_CMD_READ || command == NBD_CMD_WRITE) {
1046 req->data = qemu_blockalign(client->exp->bs, request->len);
1047 }
1048 if (command == NBD_CMD_WRITE) {
Paolo Bonzinia030b342011-09-19 15:07:54 +02001049 TRACE("Reading %u byte(s)", request->len);
1050
Paolo Bonzini262db382011-09-19 15:19:27 +02001051 if (qemu_co_recv(csock, req->data, request->len) != request->len) {
Paolo Bonzinia030b342011-09-19 15:07:54 +02001052 LOG("reading from socket failed");
1053 rc = -EIO;
1054 goto out;
1055 }
1056 }
1057 rc = 0;
1058
1059out:
Paolo Bonzini262db382011-09-19 15:19:27 +02001060 client->recv_coroutine = NULL;
Paolo Bonzinia030b342011-09-19 15:07:54 +02001061 return rc;
1062}
1063
Paolo Bonzini262db382011-09-19 15:19:27 +02001064static void nbd_trip(void *opaque)
ths75818252008-07-03 13:41:03 +00001065{
Paolo Bonzini262db382011-09-19 15:19:27 +02001066 NBDClient *client = opaque;
Paolo Bonzini1743b512011-09-19 14:33:23 +02001067 NBDExport *exp = client->exp;
Paolo Bonziniff2b68a2012-08-22 18:45:12 +02001068 NBDRequest *req;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001069 struct nbd_request request;
1070 struct nbd_reply reply;
Paolo Bonzini94e73402012-03-07 11:25:01 +01001071 ssize_t ret;
ths75818252008-07-03 13:41:03 +00001072
Nick Thomasb2e3d872011-02-22 15:44:51 +00001073 TRACE("Reading request.");
Paolo Bonziniff2b68a2012-08-22 18:45:12 +02001074 if (client->closing) {
1075 return;
1076 }
ths75818252008-07-03 13:41:03 +00001077
Paolo Bonziniff2b68a2012-08-22 18:45:12 +02001078 req = nbd_request_get(client);
Paolo Bonzini262db382011-09-19 15:19:27 +02001079 ret = nbd_co_receive_request(req, &request);
Paolo Bonzini7fe7b682012-03-05 09:10:35 +01001080 if (ret == -EAGAIN) {
1081 goto done;
1082 }
Paolo Bonzinia030b342011-09-19 15:07:54 +02001083 if (ret == -EIO) {
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001084 goto out;
Paolo Bonzinia030b342011-09-19 15:07:54 +02001085 }
ths75818252008-07-03 13:41:03 +00001086
Paolo Bonzinifae69412011-09-19 16:04:36 +02001087 reply.handle = request.handle;
1088 reply.error = 0;
1089
Paolo Bonzinia030b342011-09-19 15:07:54 +02001090 if (ret < 0) {
1091 reply.error = -ret;
1092 goto error_reply;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001093 }
bellard7a5ca862008-05-27 21:13:40 +00001094
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001095 if ((request.from + request.len) > exp->size) {
Nick Thomasb2e3d872011-02-22 15:44:51 +00001096 LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
1097 ", Offset: %" PRIu64 "\n",
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001098 request.from, request.len,
Stefan Weil0fee8f32012-04-12 22:30:16 +02001099 (uint64_t)exp->size, (uint64_t)exp->dev_offset);
Nick Thomasb2e3d872011-02-22 15:44:51 +00001100 LOG("requested operation past EOF--bad client?");
Paolo Bonzinifae69412011-09-19 16:04:36 +02001101 goto invalid_request;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001102 }
bellard7a5ca862008-05-27 21:13:40 +00001103
Paolo Bonzini2c7989a2011-10-21 13:16:28 +02001104 switch (request.type & NBD_CMD_MASK_COMMAND) {
Nick Thomasb2e3d872011-02-22 15:44:51 +00001105 case NBD_CMD_READ:
1106 TRACE("Request type is READ");
bellard7a5ca862008-05-27 21:13:40 +00001107
Paolo Bonzinie25ceb72012-04-19 11:59:11 +02001108 if (request.type & NBD_CMD_FLAG_FUA) {
1109 ret = bdrv_co_flush(exp->bs);
1110 if (ret < 0) {
1111 LOG("flush failed");
1112 reply.error = -ret;
1113 goto error_reply;
1114 }
1115 }
1116
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001117 ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512,
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001118 req->data, request.len / 512);
Paolo Bonziniadcf6302011-09-13 17:27:45 +02001119 if (ret < 0) {
Nick Thomasb2e3d872011-02-22 15:44:51 +00001120 LOG("reading from file failed");
Paolo Bonziniadcf6302011-09-13 17:27:45 +02001121 reply.error = -ret;
Paolo Bonzinifae69412011-09-19 16:04:36 +02001122 goto error_reply;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001123 }
bellard7a5ca862008-05-27 21:13:40 +00001124
Nick Thomasb2e3d872011-02-22 15:44:51 +00001125 TRACE("Read %u byte(s)", request.len);
Paolo Bonzini262db382011-09-19 15:19:27 +02001126 if (nbd_co_send_reply(req, &reply, request.len) < 0)
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001127 goto out;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001128 break;
1129 case NBD_CMD_WRITE:
1130 TRACE("Request type is WRITE");
bellard7a5ca862008-05-27 21:13:40 +00001131
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001132 if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
Nick Thomasb2e3d872011-02-22 15:44:51 +00001133 TRACE("Server is read-only, return error");
Paolo Bonzinifae69412011-09-19 16:04:36 +02001134 reply.error = EROFS;
1135 goto error_reply;
1136 }
bellard7a5ca862008-05-27 21:13:40 +00001137
Paolo Bonzinifae69412011-09-19 16:04:36 +02001138 TRACE("Writing to device");
1139
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001140 ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512,
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001141 req->data, request.len / 512);
Paolo Bonzinifae69412011-09-19 16:04:36 +02001142 if (ret < 0) {
1143 LOG("writing to file failed");
1144 reply.error = -ret;
1145 goto error_reply;
1146 }
1147
1148 if (request.type & NBD_CMD_FLAG_FUA) {
Paolo Bonzini262db382011-09-19 15:19:27 +02001149 ret = bdrv_co_flush(exp->bs);
Paolo Bonziniadcf6302011-09-13 17:27:45 +02001150 if (ret < 0) {
Paolo Bonzinifae69412011-09-19 16:04:36 +02001151 LOG("flush failed");
Paolo Bonziniadcf6302011-09-13 17:27:45 +02001152 reply.error = -ret;
Paolo Bonzinifae69412011-09-19 16:04:36 +02001153 goto error_reply;
Paolo Bonzini2c7989a2011-10-21 13:16:28 +02001154 }
Nick Thomasb2e3d872011-02-22 15:44:51 +00001155 }
bellard7a5ca862008-05-27 21:13:40 +00001156
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +01001157 if (nbd_co_send_reply(req, &reply, 0) < 0) {
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001158 goto out;
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +01001159 }
Nick Thomasb2e3d872011-02-22 15:44:51 +00001160 break;
1161 case NBD_CMD_DISC:
1162 TRACE("Request type is DISCONNECT");
1163 errno = 0;
Paolo Bonzini262db382011-09-19 15:19:27 +02001164 goto out;
Paolo Bonzini1486d042011-10-21 13:17:14 +02001165 case NBD_CMD_FLUSH:
1166 TRACE("Request type is FLUSH");
1167
Paolo Bonzini262db382011-09-19 15:19:27 +02001168 ret = bdrv_co_flush(exp->bs);
Paolo Bonzini1486d042011-10-21 13:17:14 +02001169 if (ret < 0) {
1170 LOG("flush failed");
1171 reply.error = -ret;
1172 }
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +01001173 if (nbd_co_send_reply(req, &reply, 0) < 0) {
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001174 goto out;
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +01001175 }
Paolo Bonzini1486d042011-10-21 13:17:14 +02001176 break;
Paolo Bonzini7a706632011-10-21 13:17:14 +02001177 case NBD_CMD_TRIM:
1178 TRACE("Request type is TRIM");
Paolo Bonzini262db382011-09-19 15:19:27 +02001179 ret = bdrv_co_discard(exp->bs, (request.from + exp->dev_offset) / 512,
1180 request.len / 512);
Paolo Bonzini7a706632011-10-21 13:17:14 +02001181 if (ret < 0) {
1182 LOG("discard failed");
1183 reply.error = -ret;
1184 }
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +01001185 if (nbd_co_send_reply(req, &reply, 0) < 0) {
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001186 goto out;
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +01001187 }
Paolo Bonzini7a706632011-10-21 13:17:14 +02001188 break;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001189 default:
1190 LOG("invalid request type (%u) received", request.type);
Paolo Bonzinifae69412011-09-19 16:04:36 +02001191 invalid_request:
1192 reply.error = -EINVAL;
1193 error_reply:
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +01001194 if (nbd_co_send_reply(req, &reply, 0) < 0) {
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001195 goto out;
Paolo Bonzinifc19f8a2012-03-07 11:05:34 +01001196 }
Paolo Bonzinifae69412011-09-19 16:04:36 +02001197 break;
Nick Thomasb2e3d872011-02-22 15:44:51 +00001198 }
bellard7a5ca862008-05-27 21:13:40 +00001199
Nick Thomasb2e3d872011-02-22 15:44:51 +00001200 TRACE("Request/Reply complete");
bellard7a5ca862008-05-27 21:13:40 +00001201
Paolo Bonzini7fe7b682012-03-05 09:10:35 +01001202done:
Paolo Bonzini262db382011-09-19 15:19:27 +02001203 nbd_request_put(req);
1204 return;
1205
Paolo Bonzinid9a73802011-09-19 14:18:33 +02001206out:
Paolo Bonzini72deddc2011-10-07 16:47:56 +02001207 nbd_request_put(req);
Paolo Bonzini262db382011-09-19 15:19:27 +02001208 nbd_client_close(client);
bellard7a5ca862008-05-27 21:13:40 +00001209}
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001210
Paolo Bonzini41996e32011-09-19 15:25:40 +02001211static int nbd_can_read(void *opaque)
1212{
1213 NBDClient *client = opaque;
1214
1215 return client->recv_coroutine || client->nb_requests < MAX_NBD_REQUESTS;
1216}
1217
Paolo Bonzini1743b512011-09-19 14:33:23 +02001218static void nbd_read(void *opaque)
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001219{
Paolo Bonzini1743b512011-09-19 14:33:23 +02001220 NBDClient *client = opaque;
1221
Paolo Bonzini262db382011-09-19 15:19:27 +02001222 if (client->recv_coroutine) {
1223 qemu_coroutine_enter(client->recv_coroutine, NULL);
1224 } else {
1225 qemu_coroutine_enter(qemu_coroutine_create(nbd_trip), client);
Paolo Bonzini1743b512011-09-19 14:33:23 +02001226 }
Paolo Bonzini1743b512011-09-19 14:33:23 +02001227}
1228
Paolo Bonzini262db382011-09-19 15:19:27 +02001229static void nbd_restart_write(void *opaque)
1230{
1231 NBDClient *client = opaque;
1232
1233 qemu_coroutine_enter(client->send_coroutine, NULL);
1234}
1235
Paolo Bonzini1743b512011-09-19 14:33:23 +02001236NBDClient *nbd_client_new(NBDExport *exp, int csock,
1237 void (*close)(NBDClient *))
1238{
1239 NBDClient *client;
Paolo Bonzini1743b512011-09-19 14:33:23 +02001240 client = g_malloc0(sizeof(NBDClient));
1241 client->refcount = 1;
1242 client->exp = exp;
1243 client->sock = csock;
Paolo Bonzini9a304d22012-08-22 15:30:31 +02001244 if (nbd_send_negotiate(client) < 0) {
1245 g_free(client);
1246 return NULL;
1247 }
Paolo Bonzini1743b512011-09-19 14:33:23 +02001248 client->close = close;
Paolo Bonzini262db382011-09-19 15:19:27 +02001249 qemu_co_mutex_init(&client->send_lock);
Paolo Bonzini41996e32011-09-19 15:25:40 +02001250 qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client);
Paolo Bonzini2c8d9f02012-09-18 13:26:25 +02001251
Paolo Bonzini6b8c01e2012-08-23 14:57:11 +02001252 if (exp) {
1253 QTAILQ_INSERT_TAIL(&exp->clients, client, next);
1254 nbd_export_get(exp);
1255 }
Paolo Bonzini1743b512011-09-19 14:33:23 +02001256 return client;
Paolo Bonziniaf49bbb2011-09-19 14:03:37 +02001257}