Statistics
| Branch: | Revision:

root / nbd.c @ a5c95808

History | View | Annotate | Download (31 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 c12504ce Nick Thomas
int tcp_socket_outgoing(const char *address, uint16_t port)
203 7a5ca864 bellard
{
204 c12504ce Nick Thomas
    char address_and_port[128];
205 c12504ce Nick Thomas
    combine_addr(address_and_port, 128, address, port);
206 c12504ce Nick Thomas
    return tcp_socket_outgoing_spec(address_and_port);
207 7a5ca864 bellard
}
208 7a5ca864 bellard
209 c12504ce Nick Thomas
int tcp_socket_outgoing_spec(const char *address_and_port)
210 cd831bd7 ths
{
211 f8430e76 Paolo Bonzini
    Error *local_err = NULL;
212 f8430e76 Paolo Bonzini
    int fd = inet_connect(address_and_port, &local_err);
213 f8430e76 Paolo Bonzini
214 f8430e76 Paolo Bonzini
    if (local_err != NULL) {
215 f8430e76 Paolo Bonzini
        qerror_report_err(local_err);
216 f8430e76 Paolo Bonzini
        error_free(local_err);
217 f8430e76 Paolo Bonzini
    }
218 f8430e76 Paolo Bonzini
    return fd;
219 cd831bd7 ths
}
220 cd831bd7 ths
221 c12504ce Nick Thomas
int tcp_socket_incoming(const char *address, uint16_t port)
222 cd831bd7 ths
{
223 c12504ce Nick Thomas
    char address_and_port[128];
224 c12504ce Nick Thomas
    combine_addr(address_and_port, 128, address, port);
225 c12504ce Nick Thomas
    return tcp_socket_incoming_spec(address_and_port);
226 c12504ce Nick Thomas
}
227 cd831bd7 ths
228 c12504ce Nick Thomas
int tcp_socket_incoming_spec(const char *address_and_port)
229 c12504ce Nick Thomas
{
230 f8430e76 Paolo Bonzini
    Error *local_err = NULL;
231 f8430e76 Paolo Bonzini
    int fd = inet_listen(address_and_port, NULL, 0, SOCK_STREAM, 0, &local_err);
232 f8430e76 Paolo Bonzini
233 f8430e76 Paolo Bonzini
    if (local_err != NULL) {
234 f8430e76 Paolo Bonzini
        qerror_report_err(local_err);
235 f8430e76 Paolo Bonzini
        error_free(local_err);
236 f8430e76 Paolo Bonzini
    }
237 f8430e76 Paolo Bonzini
    return fd;
238 03ff3ca3 aliguori
}
239 c12504ce Nick Thomas
240 03ff3ca3 aliguori
int unix_socket_incoming(const char *path)
241 03ff3ca3 aliguori
{
242 f8430e76 Paolo Bonzini
    Error *local_err = NULL;
243 f8430e76 Paolo Bonzini
    int fd = unix_listen(path, NULL, 0, &local_err);
244 c12504ce Nick Thomas
245 f8430e76 Paolo Bonzini
    if (local_err != NULL) {
246 f8430e76 Paolo Bonzini
        qerror_report_err(local_err);
247 f8430e76 Paolo Bonzini
        error_free(local_err);
248 f8430e76 Paolo Bonzini
    }
249 f8430e76 Paolo Bonzini
    return fd;
250 cd831bd7 ths
}
251 cd831bd7 ths
252 03ff3ca3 aliguori
int unix_socket_outgoing(const char *path)
253 03ff3ca3 aliguori
{
254 f8430e76 Paolo Bonzini
    Error *local_err = NULL;
255 f8430e76 Paolo Bonzini
    int fd = unix_connect(path, &local_err);
256 f8430e76 Paolo Bonzini
257 f8430e76 Paolo Bonzini
    if (local_err != NULL) {
258 f8430e76 Paolo Bonzini
        qerror_report_err(local_err);
259 f8430e76 Paolo Bonzini
        error_free(local_err);
260 f8430e76 Paolo Bonzini
    }
261 f8430e76 Paolo Bonzini
    return fd;
262 03ff3ca3 aliguori
}
263 cd831bd7 ths
264 6b8c01e7 Paolo Bonzini
/* Basic flow for negotiation
265 7a5ca864 bellard

266 7a5ca864 bellard
   Server         Client
267 7a5ca864 bellard
   Negotiate
268 6b8c01e7 Paolo Bonzini

269 6b8c01e7 Paolo Bonzini
   or
270 6b8c01e7 Paolo Bonzini

271 6b8c01e7 Paolo Bonzini
   Server         Client
272 6b8c01e7 Paolo Bonzini
   Negotiate #1
273 6b8c01e7 Paolo Bonzini
                  Option
274 6b8c01e7 Paolo Bonzini
   Negotiate #2
275 6b8c01e7 Paolo Bonzini

276 6b8c01e7 Paolo Bonzini
   ----
277 6b8c01e7 Paolo Bonzini

278 6b8c01e7 Paolo Bonzini
   followed by
279 6b8c01e7 Paolo Bonzini

280 6b8c01e7 Paolo Bonzini
   Server         Client
281 7a5ca864 bellard
                  Request
282 7a5ca864 bellard
   Response
283 7a5ca864 bellard
                  Request
284 7a5ca864 bellard
   Response
285 7a5ca864 bellard
                  ...
286 7a5ca864 bellard
   ...
287 7a5ca864 bellard
                  Request (type == 2)
288 6b8c01e7 Paolo Bonzini

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

385 6b8c01e7 Paolo Bonzini
       Negotiation header with options, part 1:
386 6b8c01e7 Paolo Bonzini
        [ 0 ..   7]   passwd       ("NBDMAGIC")
387 6b8c01e7 Paolo Bonzini
        [ 8 ..  15]   magic        (NBD_OPTS_MAGIC)
388 6b8c01e7 Paolo Bonzini
        [16 ..  17]   server flags (0)
389 6b8c01e7 Paolo Bonzini

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