Statistics
| Branch: | Revision:

root / nbd.c @ a540f158

History | View | Annotate | Download (30.8 kB)

1 75818250 ths
/*
2 7a5ca864 bellard
 *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
3 7a5ca864 bellard
 *
4 7a5ca864 bellard
 *  Network Block Device
5 7a5ca864 bellard
 *
6 7a5ca864 bellard
 *  This program is free software; you can redistribute it and/or modify
7 7a5ca864 bellard
 *  it under the terms of the GNU General Public License as published by
8 7a5ca864 bellard
 *  the Free Software Foundation; under version 2 of the License.
9 7a5ca864 bellard
 *
10 7a5ca864 bellard
 *  This program is distributed in the hope that it will be useful,
11 7a5ca864 bellard
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 7a5ca864 bellard
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 7a5ca864 bellard
 *  GNU General Public License for more details.
14 7a5ca864 bellard
 *
15 7a5ca864 bellard
 *  You should have received a copy of the GNU General Public License
16 8167ee88 Blue Swirl
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
17 75818250 ths
 */
18 7a5ca864 bellard
19 737e150e Paolo Bonzini
#include "block/nbd.h"
20 737e150e Paolo Bonzini
#include "block/block.h"
21 7a5ca864 bellard
22 737e150e Paolo Bonzini
#include "block/coroutine.h"
23 262db388 Paolo Bonzini
24 7a5ca864 bellard
#include <errno.h>
25 7a5ca864 bellard
#include <string.h>
26 03ff3ca3 aliguori
#ifndef _WIN32
27 7a5ca864 bellard
#include <sys/ioctl.h>
28 03ff3ca3 aliguori
#endif
29 5dc2eec9 Andreas Färber
#if defined(__sun__) || defined(__HAIKU__)
30 7e00eb9b aliguori
#include <sys/ioccom.h>
31 7e00eb9b aliguori
#endif
32 7a5ca864 bellard
#include <ctype.h>
33 7a5ca864 bellard
#include <inttypes.h>
34 75818250 ths
35 b90fb4b8 Paolo Bonzini
#ifdef __linux__
36 b90fb4b8 Paolo Bonzini
#include <linux/fs.h>
37 b90fb4b8 Paolo Bonzini
#endif
38 b90fb4b8 Paolo Bonzini
39 1de7afc9 Paolo Bonzini
#include "qemu/sockets.h"
40 1de7afc9 Paolo Bonzini
#include "qemu/queue.h"
41 03ff3ca3 aliguori
42 03ff3ca3 aliguori
//#define DEBUG_NBD
43 03ff3ca3 aliguori
44 03ff3ca3 aliguori
#ifdef DEBUG_NBD
45 75818250 ths
#define TRACE(msg, ...) do { \
46 03ff3ca3 aliguori
    LOG(msg, ## __VA_ARGS__); \
47 75818250 ths
} while(0)
48 03ff3ca3 aliguori
#else
49 03ff3ca3 aliguori
#define TRACE(msg, ...) \
50 03ff3ca3 aliguori
    do { } while (0)
51 03ff3ca3 aliguori
#endif
52 7a5ca864 bellard
53 7a5ca864 bellard
#define LOG(msg, ...) do { \
54 7a5ca864 bellard
    fprintf(stderr, "%s:%s():L%d: " msg "\n", \
55 7a5ca864 bellard
            __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
56 7a5ca864 bellard
} while(0)
57 7a5ca864 bellard
58 7a5ca864 bellard
/* This is all part of the "official" NBD API */
59 7a5ca864 bellard
60 fa26c26b Paolo Bonzini
#define NBD_REQUEST_SIZE        (4 + 4 + 8 + 8 + 4)
61 b2e3d87f Nick Thomas
#define NBD_REPLY_SIZE          (4 + 4 + 8)
62 7a5ca864 bellard
#define NBD_REQUEST_MAGIC       0x25609513
63 7a5ca864 bellard
#define NBD_REPLY_MAGIC         0x67446698
64 fa26c26b Paolo Bonzini
#define NBD_OPTS_MAGIC          0x49484156454F5054LL
65 fa26c26b Paolo Bonzini
#define NBD_CLIENT_MAGIC        0x0000420281861253LL
66 7a5ca864 bellard
67 7a5ca864 bellard
#define NBD_SET_SOCK            _IO(0xab, 0)
68 7a5ca864 bellard
#define NBD_SET_BLKSIZE         _IO(0xab, 1)
69 7a5ca864 bellard
#define NBD_SET_SIZE            _IO(0xab, 2)
70 7a5ca864 bellard
#define NBD_DO_IT               _IO(0xab, 3)
71 7a5ca864 bellard
#define NBD_CLEAR_SOCK          _IO(0xab, 4)
72 7a5ca864 bellard
#define NBD_CLEAR_QUE           _IO(0xab, 5)
73 b2e3d87f Nick Thomas
#define NBD_PRINT_DEBUG         _IO(0xab, 6)
74 b2e3d87f Nick Thomas
#define NBD_SET_SIZE_BLOCKS     _IO(0xab, 7)
75 7a5ca864 bellard
#define NBD_DISCONNECT          _IO(0xab, 8)
76 bbb74edd Paolo Bonzini
#define NBD_SET_TIMEOUT         _IO(0xab, 9)
77 bbb74edd Paolo Bonzini
#define NBD_SET_FLAGS           _IO(0xab, 10)
78 7a5ca864 bellard
79 b2e3d87f Nick Thomas
#define NBD_OPT_EXPORT_NAME     (1 << 0)
80 1d45f8b5 Laurent Vivier
81 9a304d29 Paolo Bonzini
/* Definitions for opaque data types */
82 9a304d29 Paolo Bonzini
83 9a304d29 Paolo Bonzini
typedef struct NBDRequest NBDRequest;
84 9a304d29 Paolo Bonzini
85 9a304d29 Paolo Bonzini
struct NBDRequest {
86 9a304d29 Paolo Bonzini
    QSIMPLEQ_ENTRY(NBDRequest) entry;
87 9a304d29 Paolo Bonzini
    NBDClient *client;
88 9a304d29 Paolo Bonzini
    uint8_t *data;
89 9a304d29 Paolo Bonzini
};
90 9a304d29 Paolo Bonzini
91 9a304d29 Paolo Bonzini
struct NBDExport {
92 2c8d9f06 Paolo Bonzini
    int refcount;
93 0ddf08db Paolo Bonzini
    void (*close)(NBDExport *exp);
94 0ddf08db Paolo Bonzini
95 9a304d29 Paolo Bonzini
    BlockDriverState *bs;
96 ee0a19ec Paolo Bonzini
    char *name;
97 9a304d29 Paolo Bonzini
    off_t dev_offset;
98 9a304d29 Paolo Bonzini
    off_t size;
99 9a304d29 Paolo Bonzini
    uint32_t nbdflags;
100 4b9441f6 Paolo Bonzini
    QTAILQ_HEAD(, NBDClient) clients;
101 9a304d29 Paolo Bonzini
    QSIMPLEQ_HEAD(, NBDRequest) requests;
102 ee0a19ec Paolo Bonzini
    QTAILQ_ENTRY(NBDExport) next;
103 9a304d29 Paolo Bonzini
};
104 9a304d29 Paolo Bonzini
105 ee0a19ec Paolo Bonzini
static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
106 ee0a19ec Paolo Bonzini
107 9a304d29 Paolo Bonzini
struct NBDClient {
108 9a304d29 Paolo Bonzini
    int refcount;
109 9a304d29 Paolo Bonzini
    void (*close)(NBDClient *client);
110 9a304d29 Paolo Bonzini
111 9a304d29 Paolo Bonzini
    NBDExport *exp;
112 9a304d29 Paolo Bonzini
    int sock;
113 9a304d29 Paolo Bonzini
114 9a304d29 Paolo Bonzini
    Coroutine *recv_coroutine;
115 9a304d29 Paolo Bonzini
116 9a304d29 Paolo Bonzini
    CoMutex send_lock;
117 9a304d29 Paolo Bonzini
    Coroutine *send_coroutine;
118 9a304d29 Paolo Bonzini
119 4b9441f6 Paolo Bonzini
    QTAILQ_ENTRY(NBDClient) next;
120 9a304d29 Paolo Bonzini
    int nb_requests;
121 ff2b68aa Paolo Bonzini
    bool closing;
122 9a304d29 Paolo Bonzini
};
123 9a304d29 Paolo Bonzini
124 7a5ca864 bellard
/* That's all folks */
125 7a5ca864 bellard
126 185b4338 Paolo Bonzini
ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
127 7a5ca864 bellard
{
128 7a5ca864 bellard
    size_t offset = 0;
129 185b4338 Paolo Bonzini
    int err;
130 7a5ca864 bellard
131 ae255e52 Paolo Bonzini
    if (qemu_in_coroutine()) {
132 ae255e52 Paolo Bonzini
        if (do_read) {
133 ae255e52 Paolo Bonzini
            return qemu_co_recv(fd, buffer, size);
134 ae255e52 Paolo Bonzini
        } else {
135 ae255e52 Paolo Bonzini
            return qemu_co_send(fd, buffer, size);
136 ae255e52 Paolo Bonzini
        }
137 ae255e52 Paolo Bonzini
    }
138 ae255e52 Paolo Bonzini
139 7a5ca864 bellard
    while (offset < size) {
140 7a5ca864 bellard
        ssize_t len;
141 7a5ca864 bellard
142 7a5ca864 bellard
        if (do_read) {
143 00aa0040 Blue Swirl
            len = qemu_recv(fd, buffer + offset, size - offset, 0);
144 7a5ca864 bellard
        } else {
145 03ff3ca3 aliguori
            len = send(fd, buffer + offset, size - offset, 0);
146 7a5ca864 bellard
        }
147 7a5ca864 bellard
148 fc19f8a0 Paolo Bonzini
        if (len < 0) {
149 185b4338 Paolo Bonzini
            err = socket_error();
150 03ff3ca3 aliguori
151 fc19f8a0 Paolo Bonzini
            /* recoverable error */
152 7fe7b68b Paolo Bonzini
            if (err == EINTR || (offset > 0 && err == EAGAIN)) {
153 fc19f8a0 Paolo Bonzini
                continue;
154 fc19f8a0 Paolo Bonzini
            }
155 fc19f8a0 Paolo Bonzini
156 fc19f8a0 Paolo Bonzini
            /* unrecoverable error */
157 185b4338 Paolo Bonzini
            return -err;
158 7a5ca864 bellard
        }
159 7a5ca864 bellard
160 7a5ca864 bellard
        /* eof */
161 7a5ca864 bellard
        if (len == 0) {
162 7a5ca864 bellard
            break;
163 7a5ca864 bellard
        }
164 7a5ca864 bellard
165 7a5ca864 bellard
        offset += len;
166 7a5ca864 bellard
    }
167 7a5ca864 bellard
168 7a5ca864 bellard
    return offset;
169 7a5ca864 bellard
}
170 7a5ca864 bellard
171 7fe7b68b Paolo Bonzini
static ssize_t read_sync(int fd, void *buffer, size_t size)
172 7fe7b68b Paolo Bonzini
{
173 7fe7b68b Paolo Bonzini
    /* Sockets are kept in blocking mode in the negotiation phase.  After
174 7fe7b68b Paolo Bonzini
     * that, a non-readable socket simply means that another thread stole
175 7fe7b68b Paolo Bonzini
     * our request/reply.  Synchronization is done with recv_coroutine, so
176 7fe7b68b Paolo Bonzini
     * that this is coroutine-safe.
177 7fe7b68b Paolo Bonzini
     */
178 7fe7b68b Paolo Bonzini
    return nbd_wr_sync(fd, buffer, size, true);
179 7fe7b68b Paolo Bonzini
}
180 7fe7b68b Paolo Bonzini
181 7fe7b68b Paolo Bonzini
static ssize_t write_sync(int fd, void *buffer, size_t size)
182 7fe7b68b Paolo Bonzini
{
183 7fe7b68b Paolo Bonzini
    int ret;
184 7fe7b68b Paolo Bonzini
    do {
185 7fe7b68b Paolo Bonzini
        /* For writes, we do expect the socket to be writable.  */
186 7fe7b68b Paolo Bonzini
        ret = nbd_wr_sync(fd, buffer, size, false);
187 7fe7b68b Paolo Bonzini
    } while (ret == -EAGAIN);
188 7fe7b68b Paolo Bonzini
    return ret;
189 7fe7b68b Paolo Bonzini
}
190 7fe7b68b Paolo Bonzini
191 c12504ce Nick Thomas
static void combine_addr(char *buf, size_t len, const char* address,
192 c12504ce Nick Thomas
                         uint16_t port)
193 7a5ca864 bellard
{
194 c12504ce Nick Thomas
    /* If the address-part contains a colon, it's an IPv6 IP so needs [] */
195 c12504ce Nick Thomas
    if (strstr(address, ":")) {
196 c12504ce Nick Thomas
        snprintf(buf, len, "[%s]:%u", address, port);
197 c12504ce Nick Thomas
    } else {
198 c12504ce Nick Thomas
        snprintf(buf, len, "%s:%u", address, port);
199 7a5ca864 bellard
    }
200 7a5ca864 bellard
}
201 7a5ca864 bellard
202 f17c90be Kevin Wolf
int tcp_socket_outgoing_opts(QemuOpts *opts)
203 f17c90be Kevin Wolf
{
204 f17c90be Kevin Wolf
    Error *local_err = NULL;
205 f17c90be Kevin Wolf
    int fd = inet_connect_opts(opts, &local_err, NULL, NULL);
206 f17c90be Kevin Wolf
    if (local_err != NULL) {
207 f17c90be Kevin Wolf
        qerror_report_err(local_err);
208 f17c90be Kevin Wolf
        error_free(local_err);
209 f17c90be Kevin Wolf
    }
210 f17c90be Kevin Wolf
211 f17c90be Kevin Wolf
    return fd;
212 f17c90be Kevin Wolf
}
213 f17c90be Kevin Wolf
214 c12504ce Nick Thomas
int tcp_socket_incoming(const char *address, uint16_t port)
215 cd831bd7 ths
{
216 c12504ce Nick Thomas
    char address_and_port[128];
217 c12504ce Nick Thomas
    combine_addr(address_and_port, 128, address, port);
218 c12504ce Nick Thomas
    return tcp_socket_incoming_spec(address_and_port);
219 c12504ce Nick Thomas
}
220 cd831bd7 ths
221 c12504ce Nick Thomas
int tcp_socket_incoming_spec(const char *address_and_port)
222 c12504ce Nick Thomas
{
223 f8430e76 Paolo Bonzini
    Error *local_err = NULL;
224 f8430e76 Paolo Bonzini
    int fd = inet_listen(address_and_port, NULL, 0, SOCK_STREAM, 0, &local_err);
225 f8430e76 Paolo Bonzini
226 f8430e76 Paolo Bonzini
    if (local_err != NULL) {
227 f8430e76 Paolo Bonzini
        qerror_report_err(local_err);
228 f8430e76 Paolo Bonzini
        error_free(local_err);
229 f8430e76 Paolo Bonzini
    }
230 f8430e76 Paolo Bonzini
    return fd;
231 03ff3ca3 aliguori
}
232 c12504ce Nick Thomas
233 03ff3ca3 aliguori
int unix_socket_incoming(const char *path)
234 03ff3ca3 aliguori
{
235 f8430e76 Paolo Bonzini
    Error *local_err = NULL;
236 f8430e76 Paolo Bonzini
    int fd = unix_listen(path, NULL, 0, &local_err);
237 c12504ce Nick Thomas
238 f8430e76 Paolo Bonzini
    if (local_err != NULL) {
239 f8430e76 Paolo Bonzini
        qerror_report_err(local_err);
240 f8430e76 Paolo Bonzini
        error_free(local_err);
241 f8430e76 Paolo Bonzini
    }
242 f8430e76 Paolo Bonzini
    return fd;
243 cd831bd7 ths
}
244 cd831bd7 ths
245 03ff3ca3 aliguori
int unix_socket_outgoing(const char *path)
246 03ff3ca3 aliguori
{
247 f8430e76 Paolo Bonzini
    Error *local_err = NULL;
248 f8430e76 Paolo Bonzini
    int fd = unix_connect(path, &local_err);
249 f8430e76 Paolo Bonzini
250 f8430e76 Paolo Bonzini
    if (local_err != NULL) {
251 f8430e76 Paolo Bonzini
        qerror_report_err(local_err);
252 f8430e76 Paolo Bonzini
        error_free(local_err);
253 f8430e76 Paolo Bonzini
    }
254 f8430e76 Paolo Bonzini
    return fd;
255 03ff3ca3 aliguori
}
256 cd831bd7 ths
257 6b8c01e7 Paolo Bonzini
/* Basic flow for negotiation
258 7a5ca864 bellard

259 7a5ca864 bellard
   Server         Client
260 7a5ca864 bellard
   Negotiate
261 6b8c01e7 Paolo Bonzini

262 6b8c01e7 Paolo Bonzini
   or
263 6b8c01e7 Paolo Bonzini

264 6b8c01e7 Paolo Bonzini
   Server         Client
265 6b8c01e7 Paolo Bonzini
   Negotiate #1
266 6b8c01e7 Paolo Bonzini
                  Option
267 6b8c01e7 Paolo Bonzini
   Negotiate #2
268 6b8c01e7 Paolo Bonzini

269 6b8c01e7 Paolo Bonzini
   ----
270 6b8c01e7 Paolo Bonzini

271 6b8c01e7 Paolo Bonzini
   followed by
272 6b8c01e7 Paolo Bonzini

273 6b8c01e7 Paolo Bonzini
   Server         Client
274 7a5ca864 bellard
                  Request
275 7a5ca864 bellard
   Response
276 7a5ca864 bellard
                  Request
277 7a5ca864 bellard
   Response
278 7a5ca864 bellard
                  ...
279 7a5ca864 bellard
   ...
280 7a5ca864 bellard
                  Request (type == 2)
281 6b8c01e7 Paolo Bonzini

282 7a5ca864 bellard
*/
283 7a5ca864 bellard
284 6b8c01e7 Paolo Bonzini
static int nbd_receive_options(NBDClient *client)
285 6b8c01e7 Paolo Bonzini
{
286 6b8c01e7 Paolo Bonzini
    int csock = client->sock;
287 6b8c01e7 Paolo Bonzini
    char name[256];
288 6b8c01e7 Paolo Bonzini
    uint32_t tmp, length;
289 6b8c01e7 Paolo Bonzini
    uint64_t magic;
290 6b8c01e7 Paolo Bonzini
    int rc;
291 6b8c01e7 Paolo Bonzini
292 6b8c01e7 Paolo Bonzini
    /* Client sends:
293 6b8c01e7 Paolo Bonzini
        [ 0 ..   3]   reserved (0)
294 6b8c01e7 Paolo Bonzini
        [ 4 ..  11]   NBD_OPTS_MAGIC
295 6b8c01e7 Paolo Bonzini
        [12 ..  15]   NBD_OPT_EXPORT_NAME
296 6b8c01e7 Paolo Bonzini
        [16 ..  19]   length
297 6b8c01e7 Paolo Bonzini
        [20 ..  xx]   export name (length bytes)
298 6b8c01e7 Paolo Bonzini
     */
299 6b8c01e7 Paolo Bonzini
300 6b8c01e7 Paolo Bonzini
    rc = -EINVAL;
301 6b8c01e7 Paolo Bonzini
    if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
302 6b8c01e7 Paolo Bonzini
        LOG("read failed");
303 6b8c01e7 Paolo Bonzini
        goto fail;
304 6b8c01e7 Paolo Bonzini
    }
305 6b8c01e7 Paolo Bonzini
    TRACE("Checking reserved");
306 6b8c01e7 Paolo Bonzini
    if (tmp != 0) {
307 6b8c01e7 Paolo Bonzini
        LOG("Bad reserved received");
308 6b8c01e7 Paolo Bonzini
        goto fail;
309 6b8c01e7 Paolo Bonzini
    }
310 6b8c01e7 Paolo Bonzini
311 6b8c01e7 Paolo Bonzini
    if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
312 6b8c01e7 Paolo Bonzini
        LOG("read failed");
313 6b8c01e7 Paolo Bonzini
        goto fail;
314 6b8c01e7 Paolo Bonzini
    }
315 6b8c01e7 Paolo Bonzini
    TRACE("Checking reserved");
316 6b8c01e7 Paolo Bonzini
    if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) {
317 6b8c01e7 Paolo Bonzini
        LOG("Bad magic received");
318 6b8c01e7 Paolo Bonzini
        goto fail;
319 6b8c01e7 Paolo Bonzini
    }
320 6b8c01e7 Paolo Bonzini
321 6b8c01e7 Paolo Bonzini
    if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
322 6b8c01e7 Paolo Bonzini
        LOG("read failed");
323 6b8c01e7 Paolo Bonzini
        goto fail;
324 6b8c01e7 Paolo Bonzini
    }
325 6b8c01e7 Paolo Bonzini
    TRACE("Checking option");
326 6b8c01e7 Paolo Bonzini
    if (tmp != be32_to_cpu(NBD_OPT_EXPORT_NAME)) {
327 6b8c01e7 Paolo Bonzini
        LOG("Bad option received");
328 6b8c01e7 Paolo Bonzini
        goto fail;
329 6b8c01e7 Paolo Bonzini
    }
330 6b8c01e7 Paolo Bonzini
331 6b8c01e7 Paolo Bonzini
    if (read_sync(csock, &length, sizeof(length)) != sizeof(length)) {
332 6b8c01e7 Paolo Bonzini
        LOG("read failed");
333 6b8c01e7 Paolo Bonzini
        goto fail;
334 6b8c01e7 Paolo Bonzini
    }
335 6b8c01e7 Paolo Bonzini
    TRACE("Checking length");
336 6b8c01e7 Paolo Bonzini
    length = be32_to_cpu(length);
337 6b8c01e7 Paolo Bonzini
    if (length > 255) {
338 6b8c01e7 Paolo Bonzini
        LOG("Bad length received");
339 6b8c01e7 Paolo Bonzini
        goto fail;
340 6b8c01e7 Paolo Bonzini
    }
341 6b8c01e7 Paolo Bonzini
    if (read_sync(csock, name, length) != length) {
342 6b8c01e7 Paolo Bonzini
        LOG("read failed");
343 6b8c01e7 Paolo Bonzini
        goto fail;
344 6b8c01e7 Paolo Bonzini
    }
345 6b8c01e7 Paolo Bonzini
    name[length] = '\0';
346 6b8c01e7 Paolo Bonzini
347 6b8c01e7 Paolo Bonzini
    client->exp = nbd_export_find(name);
348 6b8c01e7 Paolo Bonzini
    if (!client->exp) {
349 6b8c01e7 Paolo Bonzini
        LOG("export not found");
350 6b8c01e7 Paolo Bonzini
        goto fail;
351 6b8c01e7 Paolo Bonzini
    }
352 6b8c01e7 Paolo Bonzini
353 6b8c01e7 Paolo Bonzini
    QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
354 6b8c01e7 Paolo Bonzini
    nbd_export_get(client->exp);
355 6b8c01e7 Paolo Bonzini
356 6b8c01e7 Paolo Bonzini
    TRACE("Option negotiation succeeded.");
357 6b8c01e7 Paolo Bonzini
    rc = 0;
358 6b8c01e7 Paolo Bonzini
fail:
359 6b8c01e7 Paolo Bonzini
    return rc;
360 6b8c01e7 Paolo Bonzini
}
361 6b8c01e7 Paolo Bonzini
362 9a304d29 Paolo Bonzini
static int nbd_send_negotiate(NBDClient *client)
363 7a5ca864 bellard
{
364 9a304d29 Paolo Bonzini
    int csock = client->sock;
365 b2e3d87f Nick Thomas
    char buf[8 + 8 + 8 + 128];
366 185b4338 Paolo Bonzini
    int rc;
367 6b8c01e7 Paolo Bonzini
    const int myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
368 6b8c01e7 Paolo Bonzini
                         NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
369 b2e3d87f Nick Thomas
370 6b8c01e7 Paolo Bonzini
    /* Negotiation header without options:
371 6b8c01e7 Paolo Bonzini
        [ 0 ..   7]   passwd       ("NBDMAGIC")
372 6b8c01e7 Paolo Bonzini
        [ 8 ..  15]   magic        (NBD_CLIENT_MAGIC)
373 b2e3d87f Nick Thomas
        [16 ..  23]   size
374 6b8c01e7 Paolo Bonzini
        [24 ..  25]   server flags (0)
375 6b8c01e7 Paolo Bonzini
        [24 ..  27]   export flags
376 6b8c01e7 Paolo Bonzini
        [28 .. 151]   reserved     (0)
377 6b8c01e7 Paolo Bonzini

378 6b8c01e7 Paolo Bonzini
       Negotiation header with options, part 1:
379 6b8c01e7 Paolo Bonzini
        [ 0 ..   7]   passwd       ("NBDMAGIC")
380 6b8c01e7 Paolo Bonzini
        [ 8 ..  15]   magic        (NBD_OPTS_MAGIC)
381 6b8c01e7 Paolo Bonzini
        [16 ..  17]   server flags (0)
382 6b8c01e7 Paolo Bonzini

383 6b8c01e7 Paolo Bonzini
       part 2 (after options are sent):
384 6b8c01e7 Paolo Bonzini
        [18 ..  25]   size
385 6b8c01e7 Paolo Bonzini
        [26 ..  27]   export flags
386 6b8c01e7 Paolo Bonzini
        [28 .. 151]   reserved     (0)
387 b2e3d87f Nick Thomas
     */
388 b2e3d87f Nick Thomas
389 f9e8cacc Stefan Hajnoczi
    qemu_set_block(csock);
390 185b4338 Paolo Bonzini
    rc = -EINVAL;
391 185b4338 Paolo Bonzini
392 b2e3d87f Nick Thomas
    TRACE("Beginning negotiation.");
393 8ffaaba0 Paolo Bonzini
    memset(buf, 0, sizeof(buf));
394 b2e3d87f Nick Thomas
    memcpy(buf, "NBDMAGIC", 8);
395 6b8c01e7 Paolo Bonzini
    if (client->exp) {
396 6b8c01e7 Paolo Bonzini
        assert ((client->exp->nbdflags & ~65535) == 0);
397 6b8c01e7 Paolo Bonzini
        cpu_to_be64w((uint64_t*)(buf + 8), NBD_CLIENT_MAGIC);
398 6b8c01e7 Paolo Bonzini
        cpu_to_be64w((uint64_t*)(buf + 16), client->exp->size);
399 6b8c01e7 Paolo Bonzini
        cpu_to_be16w((uint16_t*)(buf + 26), client->exp->nbdflags | myflags);
400 6b8c01e7 Paolo Bonzini
    } else {
401 6b8c01e7 Paolo Bonzini
        cpu_to_be64w((uint64_t*)(buf + 8), NBD_OPTS_MAGIC);
402 6b8c01e7 Paolo Bonzini
    }
403 b2e3d87f Nick Thomas
404 6b8c01e7 Paolo Bonzini
    if (client->exp) {
405 6b8c01e7 Paolo Bonzini
        if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
406 6b8c01e7 Paolo Bonzini
            LOG("write failed");
407 6b8c01e7 Paolo Bonzini
            goto fail;
408 6b8c01e7 Paolo Bonzini
        }
409 6b8c01e7 Paolo Bonzini
    } else {
410 6b8c01e7 Paolo Bonzini
        if (write_sync(csock, buf, 18) != 18) {
411 6b8c01e7 Paolo Bonzini
            LOG("write failed");
412 6b8c01e7 Paolo Bonzini
            goto fail;
413 6b8c01e7 Paolo Bonzini
        }
414 6b8c01e7 Paolo Bonzini
        rc = nbd_receive_options(client);
415 6b8c01e7 Paolo Bonzini
        if (rc < 0) {
416 6b8c01e7 Paolo Bonzini
            LOG("option negotiation failed");
417 6b8c01e7 Paolo Bonzini
            goto fail;
418 6b8c01e7 Paolo Bonzini
        }
419 6b8c01e7 Paolo Bonzini
420 6b8c01e7 Paolo Bonzini
        assert ((client->exp->nbdflags & ~65535) == 0);
421 6b8c01e7 Paolo Bonzini
        cpu_to_be64w((uint64_t*)(buf + 18), client->exp->size);
422 6b8c01e7 Paolo Bonzini
        cpu_to_be16w((uint16_t*)(buf + 26), client->exp->nbdflags | myflags);
423 6b8c01e7 Paolo Bonzini
        if (write_sync(csock, buf + 18, sizeof(buf) - 18) != sizeof(buf) - 18) {
424 6b8c01e7 Paolo Bonzini
            LOG("write failed");
425 6b8c01e7 Paolo Bonzini
            goto fail;
426 6b8c01e7 Paolo Bonzini
        }
427 b2e3d87f Nick Thomas
    }
428 b2e3d87f Nick Thomas
429 07f35073 Dong Xu Wang
    TRACE("Negotiation succeeded.");
430 185b4338 Paolo Bonzini
    rc = 0;
431 185b4338 Paolo Bonzini
fail:
432 f9e8cacc Stefan Hajnoczi
    qemu_set_nonblock(csock);
433 185b4338 Paolo Bonzini
    return rc;
434 7a5ca864 bellard
}
435 7a5ca864 bellard
436 1d45f8b5 Laurent Vivier
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
437 1d45f8b5 Laurent Vivier
                          off_t *size, size_t *blocksize)
438 7a5ca864 bellard
{
439 b2e3d87f Nick Thomas
    char buf[256];
440 b2e3d87f Nick Thomas
    uint64_t magic, s;
441 b2e3d87f Nick Thomas
    uint16_t tmp;
442 185b4338 Paolo Bonzini
    int rc;
443 b2e3d87f Nick Thomas
444 07f35073 Dong Xu Wang
    TRACE("Receiving negotiation.");
445 b2e3d87f Nick Thomas
446 f9e8cacc Stefan Hajnoczi
    qemu_set_block(csock);
447 185b4338 Paolo Bonzini
    rc = -EINVAL;
448 185b4338 Paolo Bonzini
449 b2e3d87f Nick Thomas
    if (read_sync(csock, buf, 8) != 8) {
450 b2e3d87f Nick Thomas
        LOG("read failed");
451 185b4338 Paolo Bonzini
        goto fail;
452 b2e3d87f Nick Thomas
    }
453 b2e3d87f Nick Thomas
454 b2e3d87f Nick Thomas
    buf[8] = '\0';
455 b2e3d87f Nick Thomas
    if (strlen(buf) == 0) {
456 b2e3d87f Nick Thomas
        LOG("server connection closed");
457 185b4338 Paolo Bonzini
        goto fail;
458 b2e3d87f Nick Thomas
    }
459 b2e3d87f Nick Thomas
460 b2e3d87f Nick Thomas
    TRACE("Magic is %c%c%c%c%c%c%c%c",
461 b2e3d87f Nick Thomas
          qemu_isprint(buf[0]) ? buf[0] : '.',
462 b2e3d87f Nick Thomas
          qemu_isprint(buf[1]) ? buf[1] : '.',
463 b2e3d87f Nick Thomas
          qemu_isprint(buf[2]) ? buf[2] : '.',
464 b2e3d87f Nick Thomas
          qemu_isprint(buf[3]) ? buf[3] : '.',
465 b2e3d87f Nick Thomas
          qemu_isprint(buf[4]) ? buf[4] : '.',
466 b2e3d87f Nick Thomas
          qemu_isprint(buf[5]) ? buf[5] : '.',
467 b2e3d87f Nick Thomas
          qemu_isprint(buf[6]) ? buf[6] : '.',
468 b2e3d87f Nick Thomas
          qemu_isprint(buf[7]) ? buf[7] : '.');
469 b2e3d87f Nick Thomas
470 b2e3d87f Nick Thomas
    if (memcmp(buf, "NBDMAGIC", 8) != 0) {
471 b2e3d87f Nick Thomas
        LOG("Invalid magic received");
472 185b4338 Paolo Bonzini
        goto fail;
473 b2e3d87f Nick Thomas
    }
474 b2e3d87f Nick Thomas
475 b2e3d87f Nick Thomas
    if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
476 b2e3d87f Nick Thomas
        LOG("read failed");
477 185b4338 Paolo Bonzini
        goto fail;
478 b2e3d87f Nick Thomas
    }
479 b2e3d87f Nick Thomas
    magic = be64_to_cpu(magic);
480 b2e3d87f Nick Thomas
    TRACE("Magic is 0x%" PRIx64, magic);
481 b2e3d87f Nick Thomas
482 b2e3d87f Nick Thomas
    if (name) {
483 b2e3d87f Nick Thomas
        uint32_t reserved = 0;
484 b2e3d87f Nick Thomas
        uint32_t opt;
485 b2e3d87f Nick Thomas
        uint32_t namesize;
486 b2e3d87f Nick Thomas
487 b2e3d87f Nick Thomas
        TRACE("Checking magic (opts_magic)");
488 fa26c26b Paolo Bonzini
        if (magic != NBD_OPTS_MAGIC) {
489 b2e3d87f Nick Thomas
            LOG("Bad magic received");
490 185b4338 Paolo Bonzini
            goto fail;
491 b2e3d87f Nick Thomas
        }
492 b2e3d87f Nick Thomas
        if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
493 b2e3d87f Nick Thomas
            LOG("flags read failed");
494 185b4338 Paolo Bonzini
            goto fail;
495 b2e3d87f Nick Thomas
        }
496 b2e3d87f Nick Thomas
        *flags = be16_to_cpu(tmp) << 16;
497 b2e3d87f Nick Thomas
        /* reserved for future use */
498 b2e3d87f Nick Thomas
        if (write_sync(csock, &reserved, sizeof(reserved)) !=
499 b2e3d87f Nick Thomas
            sizeof(reserved)) {
500 b2e3d87f Nick Thomas
            LOG("write failed (reserved)");
501 185b4338 Paolo Bonzini
            goto fail;
502 b2e3d87f Nick Thomas
        }
503 b2e3d87f Nick Thomas
        /* write the export name */
504 b2e3d87f Nick Thomas
        magic = cpu_to_be64(magic);
505 b2e3d87f Nick Thomas
        if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
506 b2e3d87f Nick Thomas
            LOG("write failed (magic)");
507 185b4338 Paolo Bonzini
            goto fail;
508 b2e3d87f Nick Thomas
        }
509 b2e3d87f Nick Thomas
        opt = cpu_to_be32(NBD_OPT_EXPORT_NAME);
510 b2e3d87f Nick Thomas
        if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) {
511 b2e3d87f Nick Thomas
            LOG("write failed (opt)");
512 185b4338 Paolo Bonzini
            goto fail;
513 b2e3d87f Nick Thomas
        }
514 b2e3d87f Nick Thomas
        namesize = cpu_to_be32(strlen(name));
515 b2e3d87f Nick Thomas
        if (write_sync(csock, &namesize, sizeof(namesize)) !=
516 b2e3d87f Nick Thomas
            sizeof(namesize)) {
517 b2e3d87f Nick Thomas
            LOG("write failed (namesize)");
518 185b4338 Paolo Bonzini
            goto fail;
519 b2e3d87f Nick Thomas
        }
520 b2e3d87f Nick Thomas
        if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) {
521 b2e3d87f Nick Thomas
            LOG("write failed (name)");
522 185b4338 Paolo Bonzini
            goto fail;
523 b2e3d87f Nick Thomas
        }
524 b2e3d87f Nick Thomas
    } else {
525 b2e3d87f Nick Thomas
        TRACE("Checking magic (cli_magic)");
526 b2e3d87f Nick Thomas
527 fa26c26b Paolo Bonzini
        if (magic != NBD_CLIENT_MAGIC) {
528 b2e3d87f Nick Thomas
            LOG("Bad magic received");
529 185b4338 Paolo Bonzini
            goto fail;
530 b2e3d87f Nick Thomas
        }
531 b2e3d87f Nick Thomas
    }
532 b2e3d87f Nick Thomas
533 b2e3d87f Nick Thomas
    if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) {
534 b2e3d87f Nick Thomas
        LOG("read failed");
535 185b4338 Paolo Bonzini
        goto fail;
536 b2e3d87f Nick Thomas
    }
537 b2e3d87f Nick Thomas
    *size = be64_to_cpu(s);
538 b2e3d87f Nick Thomas
    *blocksize = 1024;
539 b2e3d87f Nick Thomas
    TRACE("Size is %" PRIu64, *size);
540 b2e3d87f Nick Thomas
541 b2e3d87f Nick Thomas
    if (!name) {
542 b2e3d87f Nick Thomas
        if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) {
543 b2e3d87f Nick Thomas
            LOG("read failed (flags)");
544 185b4338 Paolo Bonzini
            goto fail;
545 b2e3d87f Nick Thomas
        }
546 b2e3d87f Nick Thomas
        *flags = be32_to_cpup(flags);
547 b2e3d87f Nick Thomas
    } else {
548 b2e3d87f Nick Thomas
        if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
549 b2e3d87f Nick Thomas
            LOG("read failed (tmp)");
550 185b4338 Paolo Bonzini
            goto fail;
551 b2e3d87f Nick Thomas
        }
552 b2e3d87f Nick Thomas
        *flags |= be32_to_cpu(tmp);
553 b2e3d87f Nick Thomas
    }
554 b2e3d87f Nick Thomas
    if (read_sync(csock, &buf, 124) != 124) {
555 b2e3d87f Nick Thomas
        LOG("read failed (buf)");
556 185b4338 Paolo Bonzini
        goto fail;
557 b2e3d87f Nick Thomas
    }
558 185b4338 Paolo Bonzini
    rc = 0;
559 185b4338 Paolo Bonzini
560 185b4338 Paolo Bonzini
fail:
561 f9e8cacc Stefan Hajnoczi
    qemu_set_nonblock(csock);
562 185b4338 Paolo Bonzini
    return rc;
563 cd831bd7 ths
}
564 7a5ca864 bellard
565 b90fb4b8 Paolo Bonzini
#ifdef __linux__
566 b90fb4b8 Paolo Bonzini
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
567 cd831bd7 ths
{
568 3e05c785 Chunyan Liu
    TRACE("Setting NBD socket");
569 3e05c785 Chunyan Liu
570 fc19f8a0 Paolo Bonzini
    if (ioctl(fd, NBD_SET_SOCK, csock) < 0) {
571 3e05c785 Chunyan Liu
        int serrno = errno;
572 3e05c785 Chunyan Liu
        LOG("Failed to set NBD socket");
573 185b4338 Paolo Bonzini
        return -serrno;
574 3e05c785 Chunyan Liu
    }
575 3e05c785 Chunyan Liu
576 b2e3d87f Nick Thomas
    TRACE("Setting block size to %lu", (unsigned long)blocksize);
577 7a5ca864 bellard
578 fc19f8a0 Paolo Bonzini
    if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) < 0) {
579 b2e3d87f Nick Thomas
        int serrno = errno;
580 b2e3d87f Nick Thomas
        LOG("Failed setting NBD block size");
581 185b4338 Paolo Bonzini
        return -serrno;
582 b2e3d87f Nick Thomas
    }
583 7a5ca864 bellard
584 0bfcd599 Blue Swirl
        TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize));
585 7a5ca864 bellard
586 fc19f8a0 Paolo Bonzini
    if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) < 0) {
587 b2e3d87f Nick Thomas
        int serrno = errno;
588 b2e3d87f Nick Thomas
        LOG("Failed setting size (in blocks)");
589 185b4338 Paolo Bonzini
        return -serrno;
590 b2e3d87f Nick Thomas
    }
591 7a5ca864 bellard
592 c8969ede Paolo Bonzini
    if (ioctl(fd, NBD_SET_FLAGS, flags) < 0) {
593 c8969ede Paolo Bonzini
        if (errno == ENOTTY) {
594 c8969ede Paolo Bonzini
            int read_only = (flags & NBD_FLAG_READ_ONLY) != 0;
595 c8969ede Paolo Bonzini
            TRACE("Setting readonly attribute");
596 c8969ede Paolo Bonzini
597 c8969ede Paolo Bonzini
            if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) {
598 c8969ede Paolo Bonzini
                int serrno = errno;
599 c8969ede Paolo Bonzini
                LOG("Failed setting read-only attribute");
600 c8969ede Paolo Bonzini
                return -serrno;
601 c8969ede Paolo Bonzini
            }
602 c8969ede Paolo Bonzini
        } else {
603 b90fb4b8 Paolo Bonzini
            int serrno = errno;
604 c8969ede Paolo Bonzini
            LOG("Failed setting flags");
605 185b4338 Paolo Bonzini
            return -serrno;
606 b90fb4b8 Paolo Bonzini
        }
607 b90fb4b8 Paolo Bonzini
    }
608 b90fb4b8 Paolo Bonzini
609 b2e3d87f Nick Thomas
    TRACE("Negotiation ended");
610 7a5ca864 bellard
611 b2e3d87f Nick Thomas
    return 0;
612 7a5ca864 bellard
}
613 7a5ca864 bellard
614 7a5ca864 bellard
int nbd_disconnect(int fd)
615 7a5ca864 bellard
{
616 b2e3d87f Nick Thomas
    ioctl(fd, NBD_CLEAR_QUE);
617 b2e3d87f Nick Thomas
    ioctl(fd, NBD_DISCONNECT);
618 b2e3d87f Nick Thomas
    ioctl(fd, NBD_CLEAR_SOCK);
619 b2e3d87f Nick Thomas
    return 0;
620 7a5ca864 bellard
}
621 7a5ca864 bellard
622 0a4eb864 Jes Sorensen
int nbd_client(int fd)
623 7a5ca864 bellard
{
624 b2e3d87f Nick Thomas
    int ret;
625 b2e3d87f Nick Thomas
    int serrno;
626 7a5ca864 bellard
627 b2e3d87f Nick Thomas
    TRACE("Doing NBD loop");
628 7a5ca864 bellard
629 b2e3d87f Nick Thomas
    ret = ioctl(fd, NBD_DO_IT);
630 fc19f8a0 Paolo Bonzini
    if (ret < 0 && errno == EPIPE) {
631 74624688 Paolo Bonzini
        /* NBD_DO_IT normally returns EPIPE when someone has disconnected
632 74624688 Paolo Bonzini
         * the socket via NBD_DISCONNECT.  We do not want to return 1 in
633 74624688 Paolo Bonzini
         * that case.
634 74624688 Paolo Bonzini
         */
635 74624688 Paolo Bonzini
        ret = 0;
636 74624688 Paolo Bonzini
    }
637 b2e3d87f Nick Thomas
    serrno = errno;
638 7a5ca864 bellard
639 b2e3d87f Nick Thomas
    TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
640 7a5ca864 bellard
641 b2e3d87f Nick Thomas
    TRACE("Clearing NBD queue");
642 b2e3d87f Nick Thomas
    ioctl(fd, NBD_CLEAR_QUE);
643 7a5ca864 bellard
644 b2e3d87f Nick Thomas
    TRACE("Clearing NBD socket");
645 b2e3d87f Nick Thomas
    ioctl(fd, NBD_CLEAR_SOCK);
646 7a5ca864 bellard
647 b2e3d87f Nick Thomas
    errno = serrno;
648 b2e3d87f Nick Thomas
    return ret;
649 7a5ca864 bellard
}
650 03ff3ca3 aliguori
#else
651 8e72506e Paolo Bonzini
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
652 03ff3ca3 aliguori
{
653 185b4338 Paolo Bonzini
    return -ENOTSUP;
654 03ff3ca3 aliguori
}
655 03ff3ca3 aliguori
656 03ff3ca3 aliguori
int nbd_disconnect(int fd)
657 03ff3ca3 aliguori
{
658 185b4338 Paolo Bonzini
    return -ENOTSUP;
659 03ff3ca3 aliguori
}
660 03ff3ca3 aliguori
661 0a4eb864 Jes Sorensen
int nbd_client(int fd)
662 03ff3ca3 aliguori
{
663 185b4338 Paolo Bonzini
    return -ENOTSUP;
664 03ff3ca3 aliguori
}
665 03ff3ca3 aliguori
#endif
666 7a5ca864 bellard
667 94e7340b Paolo Bonzini
ssize_t nbd_send_request(int csock, struct nbd_request *request)
668 7a5ca864 bellard
{
669 fa26c26b Paolo Bonzini
    uint8_t buf[NBD_REQUEST_SIZE];
670 185b4338 Paolo Bonzini
    ssize_t ret;
671 b2e3d87f Nick Thomas
672 b2e3d87f Nick Thomas
    cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
673 b2e3d87f Nick Thomas
    cpu_to_be32w((uint32_t*)(buf + 4), request->type);
674 b2e3d87f Nick Thomas
    cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
675 b2e3d87f Nick Thomas
    cpu_to_be64w((uint64_t*)(buf + 16), request->from);
676 b2e3d87f Nick Thomas
    cpu_to_be32w((uint32_t*)(buf + 24), request->len);
677 75818250 ths
678 b2e3d87f Nick Thomas
    TRACE("Sending request to client: "
679 b2e3d87f Nick Thomas
          "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}",
680 b2e3d87f Nick Thomas
          request->from, request->len, request->handle, request->type);
681 b2e3d87f Nick Thomas
682 185b4338 Paolo Bonzini
    ret = write_sync(csock, buf, sizeof(buf));
683 185b4338 Paolo Bonzini
    if (ret < 0) {
684 185b4338 Paolo Bonzini
        return ret;
685 185b4338 Paolo Bonzini
    }
686 185b4338 Paolo Bonzini
687 185b4338 Paolo Bonzini
    if (ret != sizeof(buf)) {
688 b2e3d87f Nick Thomas
        LOG("writing to socket failed");
689 185b4338 Paolo Bonzini
        return -EINVAL;
690 b2e3d87f Nick Thomas
    }
691 b2e3d87f Nick Thomas
    return 0;
692 b2e3d87f Nick Thomas
}
693 75818250 ths
694 94e7340b Paolo Bonzini
static ssize_t nbd_receive_request(int csock, struct nbd_request *request)
695 75818250 ths
{
696 fa26c26b Paolo Bonzini
    uint8_t buf[NBD_REQUEST_SIZE];
697 b2e3d87f Nick Thomas
    uint32_t magic;
698 185b4338 Paolo Bonzini
    ssize_t ret;
699 b2e3d87f Nick Thomas
700 185b4338 Paolo Bonzini
    ret = read_sync(csock, buf, sizeof(buf));
701 185b4338 Paolo Bonzini
    if (ret < 0) {
702 185b4338 Paolo Bonzini
        return ret;
703 185b4338 Paolo Bonzini
    }
704 185b4338 Paolo Bonzini
705 185b4338 Paolo Bonzini
    if (ret != sizeof(buf)) {
706 b2e3d87f Nick Thomas
        LOG("read failed");
707 185b4338 Paolo Bonzini
        return -EINVAL;
708 b2e3d87f Nick Thomas
    }
709 b2e3d87f Nick Thomas
710 b2e3d87f Nick Thomas
    /* Request
711 b2e3d87f Nick Thomas
       [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
712 b2e3d87f Nick Thomas
       [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
713 b2e3d87f Nick Thomas
       [ 8 .. 15]   handle
714 b2e3d87f Nick Thomas
       [16 .. 23]   from
715 b2e3d87f Nick Thomas
       [24 .. 27]   len
716 b2e3d87f Nick Thomas
     */
717 b2e3d87f Nick Thomas
718 b2e3d87f Nick Thomas
    magic = be32_to_cpup((uint32_t*)buf);
719 b2e3d87f Nick Thomas
    request->type  = be32_to_cpup((uint32_t*)(buf + 4));
720 b2e3d87f Nick Thomas
    request->handle = be64_to_cpup((uint64_t*)(buf + 8));
721 b2e3d87f Nick Thomas
    request->from  = be64_to_cpup((uint64_t*)(buf + 16));
722 b2e3d87f Nick Thomas
    request->len   = be32_to_cpup((uint32_t*)(buf + 24));
723 b2e3d87f Nick Thomas
724 b2e3d87f Nick Thomas
    TRACE("Got request: "
725 b2e3d87f Nick Thomas
          "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
726 b2e3d87f Nick Thomas
          magic, request->type, request->from, request->len);
727 b2e3d87f Nick Thomas
728 b2e3d87f Nick Thomas
    if (magic != NBD_REQUEST_MAGIC) {
729 b2e3d87f Nick Thomas
        LOG("invalid magic (got 0x%x)", magic);
730 185b4338 Paolo Bonzini
        return -EINVAL;
731 b2e3d87f Nick Thomas
    }
732 b2e3d87f Nick Thomas
    return 0;
733 75818250 ths
}
734 75818250 ths
735 94e7340b Paolo Bonzini
ssize_t nbd_receive_reply(int csock, struct nbd_reply *reply)
736 75818250 ths
{
737 b2e3d87f Nick Thomas
    uint8_t buf[NBD_REPLY_SIZE];
738 b2e3d87f Nick Thomas
    uint32_t magic;
739 185b4338 Paolo Bonzini
    ssize_t ret;
740 b2e3d87f Nick Thomas
741 185b4338 Paolo Bonzini
    ret = read_sync(csock, buf, sizeof(buf));
742 185b4338 Paolo Bonzini
    if (ret < 0) {
743 185b4338 Paolo Bonzini
        return ret;
744 185b4338 Paolo Bonzini
    }
745 185b4338 Paolo Bonzini
746 185b4338 Paolo Bonzini
    if (ret != sizeof(buf)) {
747 b2e3d87f Nick Thomas
        LOG("read failed");
748 185b4338 Paolo Bonzini
        return -EINVAL;
749 b2e3d87f Nick Thomas
    }
750 b2e3d87f Nick Thomas
751 b2e3d87f Nick Thomas
    /* Reply
752 b2e3d87f Nick Thomas
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
753 b2e3d87f Nick Thomas
       [ 4 ..  7]    error   (0 == no error)
754 b2e3d87f Nick Thomas
       [ 7 .. 15]    handle
755 b2e3d87f Nick Thomas
     */
756 b2e3d87f Nick Thomas
757 b2e3d87f Nick Thomas
    magic = be32_to_cpup((uint32_t*)buf);
758 b2e3d87f Nick Thomas
    reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
759 b2e3d87f Nick Thomas
    reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
760 b2e3d87f Nick Thomas
761 b2e3d87f Nick Thomas
    TRACE("Got reply: "
762 b2e3d87f Nick Thomas
          "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
763 b2e3d87f Nick Thomas
          magic, reply->error, reply->handle);
764 b2e3d87f Nick Thomas
765 b2e3d87f Nick Thomas
    if (magic != NBD_REPLY_MAGIC) {
766 b2e3d87f Nick Thomas
        LOG("invalid magic (got 0x%x)", magic);
767 185b4338 Paolo Bonzini
        return -EINVAL;
768 b2e3d87f Nick Thomas
    }
769 b2e3d87f Nick Thomas
    return 0;
770 75818250 ths
}
771 75818250 ths
772 94e7340b Paolo Bonzini
static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply)
773 75818250 ths
{
774 fa26c26b Paolo Bonzini
    uint8_t buf[NBD_REPLY_SIZE];
775 185b4338 Paolo Bonzini
    ssize_t ret;
776 b2e3d87f Nick Thomas
777 b2e3d87f Nick Thomas
    /* Reply
778 b2e3d87f Nick Thomas
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
779 b2e3d87f Nick Thomas
       [ 4 ..  7]    error   (0 == no error)
780 b2e3d87f Nick Thomas
       [ 7 .. 15]    handle
781 b2e3d87f Nick Thomas
     */
782 b2e3d87f Nick Thomas
    cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
783 b2e3d87f Nick Thomas
    cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
784 b2e3d87f Nick Thomas
    cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
785 b2e3d87f Nick Thomas
786 b2e3d87f Nick Thomas
    TRACE("Sending response to client");
787 b2e3d87f Nick Thomas
788 185b4338 Paolo Bonzini
    ret = write_sync(csock, buf, sizeof(buf));
789 185b4338 Paolo Bonzini
    if (ret < 0) {
790 185b4338 Paolo Bonzini
        return ret;
791 185b4338 Paolo Bonzini
    }
792 185b4338 Paolo Bonzini
793 185b4338 Paolo Bonzini
    if (ret != sizeof(buf)) {
794 b2e3d87f Nick Thomas
        LOG("writing to socket failed");
795 185b4338 Paolo Bonzini
        return -EINVAL;
796 b2e3d87f Nick Thomas
    }
797 b2e3d87f Nick Thomas
    return 0;
798 75818250 ths
}
799 7a5ca864 bellard
800 41996e38 Paolo Bonzini
#define MAX_NBD_REQUESTS 16
801 41996e38 Paolo Bonzini
802 ce33967a Paolo Bonzini
void nbd_client_get(NBDClient *client)
803 1743b515 Paolo Bonzini
{
804 1743b515 Paolo Bonzini
    client->refcount++;
805 1743b515 Paolo Bonzini
}
806 1743b515 Paolo Bonzini
807 ce33967a Paolo Bonzini
void nbd_client_put(NBDClient *client)
808 1743b515 Paolo Bonzini
{
809 1743b515 Paolo Bonzini
    if (--client->refcount == 0) {
810 ff2b68aa Paolo Bonzini
        /* The last reference should be dropped by client->close,
811 ff2b68aa Paolo Bonzini
         * which is called by nbd_client_close.
812 ff2b68aa Paolo Bonzini
         */
813 ff2b68aa Paolo Bonzini
        assert(client->closing);
814 ff2b68aa Paolo Bonzini
815 ff2b68aa Paolo Bonzini
        qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL);
816 ff2b68aa Paolo Bonzini
        close(client->sock);
817 ff2b68aa Paolo Bonzini
        client->sock = -1;
818 6b8c01e7 Paolo Bonzini
        if (client->exp) {
819 6b8c01e7 Paolo Bonzini
            QTAILQ_REMOVE(&client->exp->clients, client, next);
820 6b8c01e7 Paolo Bonzini
            nbd_export_put(client->exp);
821 6b8c01e7 Paolo Bonzini
        }
822 1743b515 Paolo Bonzini
        g_free(client);
823 1743b515 Paolo Bonzini
    }
824 1743b515 Paolo Bonzini
}
825 1743b515 Paolo Bonzini
826 ff2b68aa Paolo Bonzini
void nbd_client_close(NBDClient *client)
827 1743b515 Paolo Bonzini
{
828 ff2b68aa Paolo Bonzini
    if (client->closing) {
829 ff2b68aa Paolo Bonzini
        return;
830 ff2b68aa Paolo Bonzini
    }
831 ff2b68aa Paolo Bonzini
832 ff2b68aa Paolo Bonzini
    client->closing = true;
833 ff2b68aa Paolo Bonzini
834 ff2b68aa Paolo Bonzini
    /* Force requests to finish.  They will drop their own references,
835 ff2b68aa Paolo Bonzini
     * then we'll close the socket and free the NBDClient.
836 ff2b68aa Paolo Bonzini
     */
837 ff2b68aa Paolo Bonzini
    shutdown(client->sock, 2);
838 ff2b68aa Paolo Bonzini
839 ff2b68aa Paolo Bonzini
    /* Also tell the client, so that they release their reference.  */
840 1743b515 Paolo Bonzini
    if (client->close) {
841 1743b515 Paolo Bonzini
        client->close(client);
842 1743b515 Paolo Bonzini
    }
843 1743b515 Paolo Bonzini
}
844 1743b515 Paolo Bonzini
845 72deddc5 Paolo Bonzini
static NBDRequest *nbd_request_get(NBDClient *client)
846 d9a73806 Paolo Bonzini
{
847 d9a73806 Paolo Bonzini
    NBDRequest *req;
848 72deddc5 Paolo Bonzini
    NBDExport *exp = client->exp;
849 72deddc5 Paolo Bonzini
850 41996e38 Paolo Bonzini
    assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
851 41996e38 Paolo Bonzini
    client->nb_requests++;
852 41996e38 Paolo Bonzini
853 d9a73806 Paolo Bonzini
    if (QSIMPLEQ_EMPTY(&exp->requests)) {
854 d9a73806 Paolo Bonzini
        req = g_malloc0(sizeof(NBDRequest));
855 d9a73806 Paolo Bonzini
        req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
856 d9a73806 Paolo Bonzini
    } else {
857 d9a73806 Paolo Bonzini
        req = QSIMPLEQ_FIRST(&exp->requests);
858 d9a73806 Paolo Bonzini
        QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry);
859 d9a73806 Paolo Bonzini
    }
860 72deddc5 Paolo Bonzini
    nbd_client_get(client);
861 72deddc5 Paolo Bonzini
    req->client = client;
862 d9a73806 Paolo Bonzini
    return req;
863 d9a73806 Paolo Bonzini
}
864 d9a73806 Paolo Bonzini
865 72deddc5 Paolo Bonzini
static void nbd_request_put(NBDRequest *req)
866 d9a73806 Paolo Bonzini
{
867 72deddc5 Paolo Bonzini
    NBDClient *client = req->client;
868 72deddc5 Paolo Bonzini
    QSIMPLEQ_INSERT_HEAD(&client->exp->requests, req, entry);
869 41996e38 Paolo Bonzini
    if (client->nb_requests-- == MAX_NBD_REQUESTS) {
870 41996e38 Paolo Bonzini
        qemu_notify_event();
871 41996e38 Paolo Bonzini
    }
872 72deddc5 Paolo Bonzini
    nbd_client_put(client);
873 d9a73806 Paolo Bonzini
}
874 d9a73806 Paolo Bonzini
875 af49bbbe Paolo Bonzini
NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
876 0ddf08db Paolo Bonzini
                          off_t size, uint32_t nbdflags,
877 0ddf08db Paolo Bonzini
                          void (*close)(NBDExport *))
878 af49bbbe Paolo Bonzini
{
879 af49bbbe Paolo Bonzini
    NBDExport *exp = g_malloc0(sizeof(NBDExport));
880 d9a73806 Paolo Bonzini
    QSIMPLEQ_INIT(&exp->requests);
881 2c8d9f06 Paolo Bonzini
    exp->refcount = 1;
882 4b9441f6 Paolo Bonzini
    QTAILQ_INIT(&exp->clients);
883 af49bbbe Paolo Bonzini
    exp->bs = bs;
884 af49bbbe Paolo Bonzini
    exp->dev_offset = dev_offset;
885 af49bbbe Paolo Bonzini
    exp->nbdflags = nbdflags;
886 38ceff04 Paolo Bonzini
    exp->size = size == -1 ? bdrv_getlength(bs) : size;
887 0ddf08db Paolo Bonzini
    exp->close = close;
888 af49bbbe Paolo Bonzini
    return exp;
889 af49bbbe Paolo Bonzini
}
890 af49bbbe Paolo Bonzini
891 ee0a19ec Paolo Bonzini
NBDExport *nbd_export_find(const char *name)
892 ee0a19ec Paolo Bonzini
{
893 ee0a19ec Paolo Bonzini
    NBDExport *exp;
894 ee0a19ec Paolo Bonzini
    QTAILQ_FOREACH(exp, &exports, next) {
895 ee0a19ec Paolo Bonzini
        if (strcmp(name, exp->name) == 0) {
896 ee0a19ec Paolo Bonzini
            return exp;
897 ee0a19ec Paolo Bonzini
        }
898 ee0a19ec Paolo Bonzini
    }
899 ee0a19ec Paolo Bonzini
900 ee0a19ec Paolo Bonzini
    return NULL;
901 ee0a19ec Paolo Bonzini
}
902 ee0a19ec Paolo Bonzini
903 ee0a19ec Paolo Bonzini
void nbd_export_set_name(NBDExport *exp, const char *name)
904 ee0a19ec Paolo Bonzini
{
905 ee0a19ec Paolo Bonzini
    if (exp->name == name) {
906 ee0a19ec Paolo Bonzini
        return;
907 ee0a19ec Paolo Bonzini
    }
908 ee0a19ec Paolo Bonzini
909 ee0a19ec Paolo Bonzini
    nbd_export_get(exp);
910 ee0a19ec Paolo Bonzini
    if (exp->name != NULL) {
911 ee0a19ec Paolo Bonzini
        g_free(exp->name);
912 ee0a19ec Paolo Bonzini
        exp->name = NULL;
913 ee0a19ec Paolo Bonzini
        QTAILQ_REMOVE(&exports, exp, next);
914 ee0a19ec Paolo Bonzini
        nbd_export_put(exp);
915 ee0a19ec Paolo Bonzini
    }
916 ee0a19ec Paolo Bonzini
    if (name != NULL) {
917 ee0a19ec Paolo Bonzini
        nbd_export_get(exp);
918 ee0a19ec Paolo Bonzini
        exp->name = g_strdup(name);
919 ee0a19ec Paolo Bonzini
        QTAILQ_INSERT_TAIL(&exports, exp, next);
920 ee0a19ec Paolo Bonzini
    }
921 ee0a19ec Paolo Bonzini
    nbd_export_put(exp);
922 ee0a19ec Paolo Bonzini
}
923 ee0a19ec Paolo Bonzini
924 af49bbbe Paolo Bonzini
void nbd_export_close(NBDExport *exp)
925 af49bbbe Paolo Bonzini
{
926 4b9441f6 Paolo Bonzini
    NBDClient *client, *next;
927 2c8d9f06 Paolo Bonzini
928 4b9441f6 Paolo Bonzini
    nbd_export_get(exp);
929 4b9441f6 Paolo Bonzini
    QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
930 4b9441f6 Paolo Bonzini
        nbd_client_close(client);
931 4b9441f6 Paolo Bonzini
    }
932 125afda8 Paolo Bonzini
    nbd_export_set_name(exp, NULL);
933 4b9441f6 Paolo Bonzini
    nbd_export_put(exp);
934 2c8d9f06 Paolo Bonzini
}
935 2c8d9f06 Paolo Bonzini
936 2c8d9f06 Paolo Bonzini
void nbd_export_get(NBDExport *exp)
937 2c8d9f06 Paolo Bonzini
{
938 2c8d9f06 Paolo Bonzini
    assert(exp->refcount > 0);
939 2c8d9f06 Paolo Bonzini
    exp->refcount++;
940 2c8d9f06 Paolo Bonzini
}
941 2c8d9f06 Paolo Bonzini
942 2c8d9f06 Paolo Bonzini
void nbd_export_put(NBDExport *exp)
943 2c8d9f06 Paolo Bonzini
{
944 2c8d9f06 Paolo Bonzini
    assert(exp->refcount > 0);
945 2c8d9f06 Paolo Bonzini
    if (exp->refcount == 1) {
946 2c8d9f06 Paolo Bonzini
        nbd_export_close(exp);
947 d9a73806 Paolo Bonzini
    }
948 d9a73806 Paolo Bonzini
949 2c8d9f06 Paolo Bonzini
    if (--exp->refcount == 0) {
950 ee0a19ec Paolo Bonzini
        assert(exp->name == NULL);
951 ee0a19ec Paolo Bonzini
952 0ddf08db Paolo Bonzini
        if (exp->close) {
953 0ddf08db Paolo Bonzini
            exp->close(exp);
954 0ddf08db Paolo Bonzini
        }
955 0ddf08db Paolo Bonzini
956 2c8d9f06 Paolo Bonzini
        while (!QSIMPLEQ_EMPTY(&exp->requests)) {
957 2c8d9f06 Paolo Bonzini
            NBDRequest *first = QSIMPLEQ_FIRST(&exp->requests);
958 2c8d9f06 Paolo Bonzini
            QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry);
959 2c8d9f06 Paolo Bonzini
            qemu_vfree(first->data);
960 2c8d9f06 Paolo Bonzini
            g_free(first);
961 2c8d9f06 Paolo Bonzini
        }
962 2c8d9f06 Paolo Bonzini
963 2c8d9f06 Paolo Bonzini
        g_free(exp);
964 2c8d9f06 Paolo Bonzini
    }
965 af49bbbe Paolo Bonzini
}
966 af49bbbe Paolo Bonzini
967 125afda8 Paolo Bonzini
BlockDriverState *nbd_export_get_blockdev(NBDExport *exp)
968 125afda8 Paolo Bonzini
{
969 125afda8 Paolo Bonzini
    return exp->bs;
970 125afda8 Paolo Bonzini
}
971 125afda8 Paolo Bonzini
972 ee0a19ec Paolo Bonzini
void nbd_export_close_all(void)
973 ee0a19ec Paolo Bonzini
{
974 ee0a19ec Paolo Bonzini
    NBDExport *exp, *next;
975 ee0a19ec Paolo Bonzini
976 ee0a19ec Paolo Bonzini
    QTAILQ_FOREACH_SAFE(exp, &exports, next, next) {
977 ee0a19ec Paolo Bonzini
        nbd_export_close(exp);
978 ee0a19ec Paolo Bonzini
    }
979 ee0a19ec Paolo Bonzini
}
980 ee0a19ec Paolo Bonzini
981 41996e38 Paolo Bonzini
static int nbd_can_read(void *opaque);
982 262db388 Paolo Bonzini
static void nbd_read(void *opaque);
983 262db388 Paolo Bonzini
static void nbd_restart_write(void *opaque);
984 262db388 Paolo Bonzini
985 94e7340b Paolo Bonzini
static ssize_t nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply,
986 94e7340b Paolo Bonzini
                                 int len)
987 22045592 Paolo Bonzini
{
988 72deddc5 Paolo Bonzini
    NBDClient *client = req->client;
989 72deddc5 Paolo Bonzini
    int csock = client->sock;
990 94e7340b Paolo Bonzini
    ssize_t rc, ret;
991 22045592 Paolo Bonzini
992 262db388 Paolo Bonzini
    qemu_co_mutex_lock(&client->send_lock);
993 41996e38 Paolo Bonzini
    qemu_set_fd_handler2(csock, nbd_can_read, nbd_read,
994 41996e38 Paolo Bonzini
                         nbd_restart_write, client);
995 262db388 Paolo Bonzini
    client->send_coroutine = qemu_coroutine_self();
996 262db388 Paolo Bonzini
997 22045592 Paolo Bonzini
    if (!len) {
998 22045592 Paolo Bonzini
        rc = nbd_send_reply(csock, reply);
999 22045592 Paolo Bonzini
    } else {
1000 22045592 Paolo Bonzini
        socket_set_cork(csock, 1);
1001 22045592 Paolo Bonzini
        rc = nbd_send_reply(csock, reply);
1002 fc19f8a0 Paolo Bonzini
        if (rc >= 0) {
1003 262db388 Paolo Bonzini
            ret = qemu_co_send(csock, req->data, len);
1004 22045592 Paolo Bonzini
            if (ret != len) {
1005 185b4338 Paolo Bonzini
                rc = -EIO;
1006 22045592 Paolo Bonzini
            }
1007 22045592 Paolo Bonzini
        }
1008 22045592 Paolo Bonzini
        socket_set_cork(csock, 0);
1009 22045592 Paolo Bonzini
    }
1010 262db388 Paolo Bonzini
1011 262db388 Paolo Bonzini
    client->send_coroutine = NULL;
1012 41996e38 Paolo Bonzini
    qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client);
1013 262db388 Paolo Bonzini
    qemu_co_mutex_unlock(&client->send_lock);
1014 22045592 Paolo Bonzini
    return rc;
1015 22045592 Paolo Bonzini
}
1016 22045592 Paolo Bonzini
1017 94e7340b Paolo Bonzini
static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *request)
1018 a030b347 Paolo Bonzini
{
1019 72deddc5 Paolo Bonzini
    NBDClient *client = req->client;
1020 72deddc5 Paolo Bonzini
    int csock = client->sock;
1021 94e7340b Paolo Bonzini
    ssize_t rc;
1022 a030b347 Paolo Bonzini
1023 262db388 Paolo Bonzini
    client->recv_coroutine = qemu_coroutine_self();
1024 7fe7b68b Paolo Bonzini
    rc = nbd_receive_request(csock, request);
1025 7fe7b68b Paolo Bonzini
    if (rc < 0) {
1026 7fe7b68b Paolo Bonzini
        if (rc != -EAGAIN) {
1027 7fe7b68b Paolo Bonzini
            rc = -EIO;
1028 7fe7b68b Paolo Bonzini
        }
1029 a030b347 Paolo Bonzini
        goto out;
1030 a030b347 Paolo Bonzini
    }
1031 a030b347 Paolo Bonzini
1032 a030b347 Paolo Bonzini
    if (request->len > NBD_BUFFER_SIZE) {
1033 a030b347 Paolo Bonzini
        LOG("len (%u) is larger than max len (%u)",
1034 a030b347 Paolo Bonzini
            request->len, NBD_BUFFER_SIZE);
1035 a030b347 Paolo Bonzini
        rc = -EINVAL;
1036 a030b347 Paolo Bonzini
        goto out;
1037 a030b347 Paolo Bonzini
    }
1038 a030b347 Paolo Bonzini
1039 a030b347 Paolo Bonzini
    if ((request->from + request->len) < request->from) {
1040 a030b347 Paolo Bonzini
        LOG("integer overflow detected! "
1041 a030b347 Paolo Bonzini
            "you're probably being attacked");
1042 a030b347 Paolo Bonzini
        rc = -EINVAL;
1043 a030b347 Paolo Bonzini
        goto out;
1044 a030b347 Paolo Bonzini
    }
1045 a030b347 Paolo Bonzini
1046 a030b347 Paolo Bonzini
    TRACE("Decoding type");
1047 a030b347 Paolo Bonzini
1048 a030b347 Paolo Bonzini
    if ((request->type & NBD_CMD_MASK_COMMAND) == NBD_CMD_WRITE) {
1049 a030b347 Paolo Bonzini
        TRACE("Reading %u byte(s)", request->len);
1050 a030b347 Paolo Bonzini
1051 262db388 Paolo Bonzini
        if (qemu_co_recv(csock, req->data, request->len) != request->len) {
1052 a030b347 Paolo Bonzini
            LOG("reading from socket failed");
1053 a030b347 Paolo Bonzini
            rc = -EIO;
1054 a030b347 Paolo Bonzini
            goto out;
1055 a030b347 Paolo Bonzini
        }
1056 a030b347 Paolo Bonzini
    }
1057 a030b347 Paolo Bonzini
    rc = 0;
1058 a030b347 Paolo Bonzini
1059 a030b347 Paolo Bonzini
out:
1060 262db388 Paolo Bonzini
    client->recv_coroutine = NULL;
1061 a030b347 Paolo Bonzini
    return rc;
1062 a030b347 Paolo Bonzini
}
1063 a030b347 Paolo Bonzini
1064 262db388 Paolo Bonzini
static void nbd_trip(void *opaque)
1065 75818250 ths
{
1066 262db388 Paolo Bonzini
    NBDClient *client = opaque;
1067 1743b515 Paolo Bonzini
    NBDExport *exp = client->exp;
1068 ff2b68aa Paolo Bonzini
    NBDRequest *req;
1069 b2e3d87f Nick Thomas
    struct nbd_request request;
1070 b2e3d87f Nick Thomas
    struct nbd_reply reply;
1071 94e7340b Paolo Bonzini
    ssize_t ret;
1072 b2e3d87f Nick Thomas
1073 b2e3d87f Nick Thomas
    TRACE("Reading request.");
1074 ff2b68aa Paolo Bonzini
    if (client->closing) {
1075 ff2b68aa Paolo Bonzini
        return;
1076 ff2b68aa Paolo Bonzini
    }
1077 b2e3d87f Nick Thomas
1078 ff2b68aa Paolo Bonzini
    req = nbd_request_get(client);
1079 262db388 Paolo Bonzini
    ret = nbd_co_receive_request(req, &request);
1080 7fe7b68b Paolo Bonzini
    if (ret == -EAGAIN) {
1081 7fe7b68b Paolo Bonzini
        goto done;
1082 7fe7b68b Paolo Bonzini
    }
1083 a030b347 Paolo Bonzini
    if (ret == -EIO) {
1084 d9a73806 Paolo Bonzini
        goto out;
1085 a030b347 Paolo Bonzini
    }
1086 b2e3d87f Nick Thomas
1087 fae69416 Paolo Bonzini
    reply.handle = request.handle;
1088 fae69416 Paolo Bonzini
    reply.error = 0;
1089 fae69416 Paolo Bonzini
1090 a030b347 Paolo Bonzini
    if (ret < 0) {
1091 a030b347 Paolo Bonzini
        reply.error = -ret;
1092 a030b347 Paolo Bonzini
        goto error_reply;
1093 b2e3d87f Nick Thomas
    }
1094 b2e3d87f Nick Thomas
1095 af49bbbe Paolo Bonzini
    if ((request.from + request.len) > exp->size) {
1096 b2e3d87f Nick Thomas
            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
1097 b2e3d87f Nick Thomas
            ", Offset: %" PRIu64 "\n",
1098 af49bbbe Paolo Bonzini
                    request.from, request.len,
1099 0fee8f34 Stefan Weil
                    (uint64_t)exp->size, (uint64_t)exp->dev_offset);
1100 b2e3d87f Nick Thomas
        LOG("requested operation past EOF--bad client?");
1101 fae69416 Paolo Bonzini
        goto invalid_request;
1102 b2e3d87f Nick Thomas
    }
1103 b2e3d87f Nick Thomas
1104 2c7989a9 Paolo Bonzini
    switch (request.type & NBD_CMD_MASK_COMMAND) {
1105 b2e3d87f Nick Thomas
    case NBD_CMD_READ:
1106 b2e3d87f Nick Thomas
        TRACE("Request type is READ");
1107 b2e3d87f Nick Thomas
1108 e25ceb76 Paolo Bonzini
        if (request.type & NBD_CMD_FLAG_FUA) {
1109 e25ceb76 Paolo Bonzini
            ret = bdrv_co_flush(exp->bs);
1110 e25ceb76 Paolo Bonzini
            if (ret < 0) {
1111 e25ceb76 Paolo Bonzini
                LOG("flush failed");
1112 e25ceb76 Paolo Bonzini
                reply.error = -ret;
1113 e25ceb76 Paolo Bonzini
                goto error_reply;
1114 e25ceb76 Paolo Bonzini
            }
1115 e25ceb76 Paolo Bonzini
        }
1116 e25ceb76 Paolo Bonzini
1117 af49bbbe Paolo Bonzini
        ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512,
1118 d9a73806 Paolo Bonzini
                        req->data, request.len / 512);
1119 adcf6302 Paolo Bonzini
        if (ret < 0) {
1120 b2e3d87f Nick Thomas
            LOG("reading from file failed");
1121 adcf6302 Paolo Bonzini
            reply.error = -ret;
1122 fae69416 Paolo Bonzini
            goto error_reply;
1123 b2e3d87f Nick Thomas
        }
1124 b2e3d87f Nick Thomas
1125 b2e3d87f Nick Thomas
        TRACE("Read %u byte(s)", request.len);
1126 262db388 Paolo Bonzini
        if (nbd_co_send_reply(req, &reply, request.len) < 0)
1127 d9a73806 Paolo Bonzini
            goto out;
1128 b2e3d87f Nick Thomas
        break;
1129 b2e3d87f Nick Thomas
    case NBD_CMD_WRITE:
1130 b2e3d87f Nick Thomas
        TRACE("Request type is WRITE");
1131 b2e3d87f Nick Thomas
1132 af49bbbe Paolo Bonzini
        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
1133 b2e3d87f Nick Thomas
            TRACE("Server is read-only, return error");
1134 fae69416 Paolo Bonzini
            reply.error = EROFS;
1135 fae69416 Paolo Bonzini
            goto error_reply;
1136 fae69416 Paolo Bonzini
        }
1137 fae69416 Paolo Bonzini
1138 fae69416 Paolo Bonzini
        TRACE("Writing to device");
1139 fae69416 Paolo Bonzini
1140 af49bbbe Paolo Bonzini
        ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512,
1141 d9a73806 Paolo Bonzini
                         req->data, request.len / 512);
1142 fae69416 Paolo Bonzini
        if (ret < 0) {
1143 fae69416 Paolo Bonzini
            LOG("writing to file failed");
1144 fae69416 Paolo Bonzini
            reply.error = -ret;
1145 fae69416 Paolo Bonzini
            goto error_reply;
1146 fae69416 Paolo Bonzini
        }
1147 b2e3d87f Nick Thomas
1148 fae69416 Paolo Bonzini
        if (request.type & NBD_CMD_FLAG_FUA) {
1149 262db388 Paolo Bonzini
            ret = bdrv_co_flush(exp->bs);
1150 adcf6302 Paolo Bonzini
            if (ret < 0) {
1151 fae69416 Paolo Bonzini
                LOG("flush failed");
1152 adcf6302 Paolo Bonzini
                reply.error = -ret;
1153 fae69416 Paolo Bonzini
                goto error_reply;
1154 2c7989a9 Paolo Bonzini
            }
1155 b2e3d87f Nick Thomas
        }
1156 b2e3d87f Nick Thomas
1157 fc19f8a0 Paolo Bonzini
        if (nbd_co_send_reply(req, &reply, 0) < 0) {
1158 d9a73806 Paolo Bonzini
            goto out;
1159 fc19f8a0 Paolo Bonzini
        }
1160 b2e3d87f Nick Thomas
        break;
1161 b2e3d87f Nick Thomas
    case NBD_CMD_DISC:
1162 b2e3d87f Nick Thomas
        TRACE("Request type is DISCONNECT");
1163 b2e3d87f Nick Thomas
        errno = 0;
1164 262db388 Paolo Bonzini
        goto out;
1165 1486d04a Paolo Bonzini
    case NBD_CMD_FLUSH:
1166 1486d04a Paolo Bonzini
        TRACE("Request type is FLUSH");
1167 1486d04a Paolo Bonzini
1168 262db388 Paolo Bonzini
        ret = bdrv_co_flush(exp->bs);
1169 1486d04a Paolo Bonzini
        if (ret < 0) {
1170 1486d04a Paolo Bonzini
            LOG("flush failed");
1171 1486d04a Paolo Bonzini
            reply.error = -ret;
1172 1486d04a Paolo Bonzini
        }
1173 fc19f8a0 Paolo Bonzini
        if (nbd_co_send_reply(req, &reply, 0) < 0) {
1174 d9a73806 Paolo Bonzini
            goto out;
1175 fc19f8a0 Paolo Bonzini
        }
1176 1486d04a Paolo Bonzini
        break;
1177 7a706633 Paolo Bonzini
    case NBD_CMD_TRIM:
1178 7a706633 Paolo Bonzini
        TRACE("Request type is TRIM");
1179 262db388 Paolo Bonzini
        ret = bdrv_co_discard(exp->bs, (request.from + exp->dev_offset) / 512,
1180 262db388 Paolo Bonzini
                              request.len / 512);
1181 7a706633 Paolo Bonzini
        if (ret < 0) {
1182 7a706633 Paolo Bonzini
            LOG("discard failed");
1183 7a706633 Paolo Bonzini
            reply.error = -ret;
1184 7a706633 Paolo Bonzini
        }
1185 fc19f8a0 Paolo Bonzini
        if (nbd_co_send_reply(req, &reply, 0) < 0) {
1186 d9a73806 Paolo Bonzini
            goto out;
1187 fc19f8a0 Paolo Bonzini
        }
1188 7a706633 Paolo Bonzini
        break;
1189 b2e3d87f Nick Thomas
    default:
1190 b2e3d87f Nick Thomas
        LOG("invalid request type (%u) received", request.type);
1191 fae69416 Paolo Bonzini
    invalid_request:
1192 fae69416 Paolo Bonzini
        reply.error = -EINVAL;
1193 fae69416 Paolo Bonzini
    error_reply:
1194 fc19f8a0 Paolo Bonzini
        if (nbd_co_send_reply(req, &reply, 0) < 0) {
1195 d9a73806 Paolo Bonzini
            goto out;
1196 fc19f8a0 Paolo Bonzini
        }
1197 fae69416 Paolo Bonzini
        break;
1198 b2e3d87f Nick Thomas
    }
1199 b2e3d87f Nick Thomas
1200 b2e3d87f Nick Thomas
    TRACE("Request/Reply complete");
1201 b2e3d87f Nick Thomas
1202 7fe7b68b Paolo Bonzini
done:
1203 262db388 Paolo Bonzini
    nbd_request_put(req);
1204 262db388 Paolo Bonzini
    return;
1205 262db388 Paolo Bonzini
1206 d9a73806 Paolo Bonzini
out:
1207 72deddc5 Paolo Bonzini
    nbd_request_put(req);
1208 262db388 Paolo Bonzini
    nbd_client_close(client);
1209 7a5ca864 bellard
}
1210 af49bbbe Paolo Bonzini
1211 41996e38 Paolo Bonzini
static int nbd_can_read(void *opaque)
1212 41996e38 Paolo Bonzini
{
1213 41996e38 Paolo Bonzini
    NBDClient *client = opaque;
1214 41996e38 Paolo Bonzini
1215 41996e38 Paolo Bonzini
    return client->recv_coroutine || client->nb_requests < MAX_NBD_REQUESTS;
1216 41996e38 Paolo Bonzini
}
1217 41996e38 Paolo Bonzini
1218 1743b515 Paolo Bonzini
static void nbd_read(void *opaque)
1219 1743b515 Paolo Bonzini
{
1220 1743b515 Paolo Bonzini
    NBDClient *client = opaque;
1221 1743b515 Paolo Bonzini
1222 262db388 Paolo Bonzini
    if (client->recv_coroutine) {
1223 262db388 Paolo Bonzini
        qemu_coroutine_enter(client->recv_coroutine, NULL);
1224 262db388 Paolo Bonzini
    } else {
1225 262db388 Paolo Bonzini
        qemu_coroutine_enter(qemu_coroutine_create(nbd_trip), client);
1226 1743b515 Paolo Bonzini
    }
1227 1743b515 Paolo Bonzini
}
1228 1743b515 Paolo Bonzini
1229 262db388 Paolo Bonzini
static void nbd_restart_write(void *opaque)
1230 262db388 Paolo Bonzini
{
1231 262db388 Paolo Bonzini
    NBDClient *client = opaque;
1232 262db388 Paolo Bonzini
1233 262db388 Paolo Bonzini
    qemu_coroutine_enter(client->send_coroutine, NULL);
1234 262db388 Paolo Bonzini
}
1235 262db388 Paolo Bonzini
1236 1743b515 Paolo Bonzini
NBDClient *nbd_client_new(NBDExport *exp, int csock,
1237 1743b515 Paolo Bonzini
                          void (*close)(NBDClient *))
1238 af49bbbe Paolo Bonzini
{
1239 1743b515 Paolo Bonzini
    NBDClient *client;
1240 1743b515 Paolo Bonzini
    client = g_malloc0(sizeof(NBDClient));
1241 1743b515 Paolo Bonzini
    client->refcount = 1;
1242 1743b515 Paolo Bonzini
    client->exp = exp;
1243 1743b515 Paolo Bonzini
    client->sock = csock;
1244 9a304d29 Paolo Bonzini
    if (nbd_send_negotiate(client) < 0) {
1245 9a304d29 Paolo Bonzini
        g_free(client);
1246 9a304d29 Paolo Bonzini
        return NULL;
1247 9a304d29 Paolo Bonzini
    }
1248 1743b515 Paolo Bonzini
    client->close = close;
1249 262db388 Paolo Bonzini
    qemu_co_mutex_init(&client->send_lock);
1250 41996e38 Paolo Bonzini
    qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client);
1251 2c8d9f06 Paolo Bonzini
1252 6b8c01e7 Paolo Bonzini
    if (exp) {
1253 6b8c01e7 Paolo Bonzini
        QTAILQ_INSERT_TAIL(&exp->clients, client, next);
1254 6b8c01e7 Paolo Bonzini
        nbd_export_get(exp);
1255 6b8c01e7 Paolo Bonzini
    }
1256 1743b515 Paolo Bonzini
    return client;
1257 af49bbbe Paolo Bonzini
}