Statistics
| Branch: | Revision:

root / nbd.c @ 3777b09f

History | View | Annotate | Download (18.9 kB)

1
/*
2
 *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
3
 *
4
 *  Network Block Device
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; under version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
17
 */
18

    
19
#include "nbd.h"
20
#include "block.h"
21

    
22
#include <errno.h>
23
#include <string.h>
24
#ifndef _WIN32
25
#include <sys/ioctl.h>
26
#endif
27
#if defined(__sun__) || defined(__HAIKU__)
28
#include <sys/ioccom.h>
29
#endif
30
#include <ctype.h>
31
#include <inttypes.h>
32

    
33
#ifdef __linux__
34
#include <linux/fs.h>
35
#endif
36

    
37
#include "qemu_socket.h"
38

    
39
//#define DEBUG_NBD
40

    
41
#ifdef DEBUG_NBD
42
#define TRACE(msg, ...) do { \
43
    LOG(msg, ## __VA_ARGS__); \
44
} while(0)
45
#else
46
#define TRACE(msg, ...) \
47
    do { } while (0)
48
#endif
49

    
50
#define LOG(msg, ...) do { \
51
    fprintf(stderr, "%s:%s():L%d: " msg "\n", \
52
            __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
53
} while(0)
54

    
55
/* This is all part of the "official" NBD API */
56

    
57
#define NBD_REPLY_SIZE          (4 + 4 + 8)
58
#define NBD_REQUEST_MAGIC       0x25609513
59
#define NBD_REPLY_MAGIC         0x67446698
60

    
61
#define NBD_SET_SOCK            _IO(0xab, 0)
62
#define NBD_SET_BLKSIZE         _IO(0xab, 1)
63
#define NBD_SET_SIZE            _IO(0xab, 2)
64
#define NBD_DO_IT               _IO(0xab, 3)
65
#define NBD_CLEAR_SOCK          _IO(0xab, 4)
66
#define NBD_CLEAR_QUE           _IO(0xab, 5)
67
#define NBD_PRINT_DEBUG         _IO(0xab, 6)
68
#define NBD_SET_SIZE_BLOCKS     _IO(0xab, 7)
69
#define NBD_DISCONNECT          _IO(0xab, 8)
70
#define NBD_SET_TIMEOUT         _IO(0xab, 9)
71
#define NBD_SET_FLAGS           _IO(0xab, 10)
72

    
73
#define NBD_OPT_EXPORT_NAME     (1 << 0)
74

    
75
/* That's all folks */
76

    
77
#define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true)
78
#define write_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, false)
79

    
80
size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
81
{
82
    size_t offset = 0;
83

    
84
    if (qemu_in_coroutine()) {
85
        if (do_read) {
86
            return qemu_co_recv(fd, buffer, size);
87
        } else {
88
            return qemu_co_send(fd, buffer, size);
89
        }
90
    }
91

    
92
    while (offset < size) {
93
        ssize_t len;
94

    
95
        if (do_read) {
96
            len = qemu_recv(fd, buffer + offset, size - offset, 0);
97
        } else {
98
            len = send(fd, buffer + offset, size - offset, 0);
99
        }
100

    
101
        if (len == -1)
102
            errno = socket_error();
103

    
104
        /* recoverable error */
105
        if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
106
            continue;
107
        }
108

    
109
        /* eof */
110
        if (len == 0) {
111
            break;
112
        }
113

    
114
        /* unrecoverable error */
115
        if (len == -1) {
116
            return 0;
117
        }
118

    
119
        offset += len;
120
    }
121

    
122
    return offset;
123
}
124

    
125
static void combine_addr(char *buf, size_t len, const char* address,
126
                         uint16_t port)
127
{
128
    /* If the address-part contains a colon, it's an IPv6 IP so needs [] */
129
    if (strstr(address, ":")) {
130
        snprintf(buf, len, "[%s]:%u", address, port);
131
    } else {
132
        snprintf(buf, len, "%s:%u", address, port);
133
    }
134
}
135

    
136
int tcp_socket_outgoing(const char *address, uint16_t port)
137
{
138
    char address_and_port[128];
139
    combine_addr(address_and_port, 128, address, port);
140
    return tcp_socket_outgoing_spec(address_and_port);
141
}
142

    
143
int tcp_socket_outgoing_spec(const char *address_and_port)
144
{
145
    return inet_connect(address_and_port, SOCK_STREAM);
146
}
147

    
148
int tcp_socket_incoming(const char *address, uint16_t port)
149
{
150
    char address_and_port[128];
151
    combine_addr(address_and_port, 128, address, port);
152
    return tcp_socket_incoming_spec(address_and_port);
153
}
154

    
155
int tcp_socket_incoming_spec(const char *address_and_port)
156
{
157
    char *ostr  = NULL;
158
    int olen = 0;
159
    return inet_listen(address_and_port, ostr, olen, SOCK_STREAM, 0);
160
}
161

    
162
int unix_socket_incoming(const char *path)
163
{
164
    char *ostr = NULL;
165
    int olen = 0;
166

    
167
    return unix_listen(path, ostr, olen);
168
}
169

    
170
int unix_socket_outgoing(const char *path)
171
{
172
    return unix_connect(path);
173
}
174

    
175
/* Basic flow
176

177
   Server         Client
178

179
   Negotiate
180
                  Request
181
   Response
182
                  Request
183
   Response
184
                  ...
185
   ...
186
                  Request (type == 2)
187
*/
188

    
189
int nbd_negotiate(int csock, off_t size, uint32_t flags)
190
{
191
    char buf[8 + 8 + 8 + 128];
192

    
193
    /* Negotiate
194
        [ 0 ..   7]   passwd   ("NBDMAGIC")
195
        [ 8 ..  15]   magic    (0x00420281861253)
196
        [16 ..  23]   size
197
        [24 ..  27]   flags
198
        [28 .. 151]   reserved (0)
199
     */
200

    
201
    TRACE("Beginning negotiation.");
202
    memcpy(buf, "NBDMAGIC", 8);
203
    cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
204
    cpu_to_be64w((uint64_t*)(buf + 16), size);
205
    cpu_to_be32w((uint32_t*)(buf + 24),
206
                 flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
207
                 NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
208
    memset(buf + 28, 0, 124);
209

    
210
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
211
        LOG("write failed");
212
        errno = EINVAL;
213
        return -1;
214
    }
215

    
216
    TRACE("Negotiation succeeded.");
217

    
218
    return 0;
219
}
220

    
221
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
222
                          off_t *size, size_t *blocksize)
223
{
224
    char buf[256];
225
    uint64_t magic, s;
226
    uint16_t tmp;
227

    
228
    TRACE("Receiving negotiation.");
229

    
230
    if (read_sync(csock, buf, 8) != 8) {
231
        LOG("read failed");
232
        errno = EINVAL;
233
        return -1;
234
    }
235

    
236
    buf[8] = '\0';
237
    if (strlen(buf) == 0) {
238
        LOG("server connection closed");
239
        errno = EINVAL;
240
        return -1;
241
    }
242

    
243
    TRACE("Magic is %c%c%c%c%c%c%c%c",
244
          qemu_isprint(buf[0]) ? buf[0] : '.',
245
          qemu_isprint(buf[1]) ? buf[1] : '.',
246
          qemu_isprint(buf[2]) ? buf[2] : '.',
247
          qemu_isprint(buf[3]) ? buf[3] : '.',
248
          qemu_isprint(buf[4]) ? buf[4] : '.',
249
          qemu_isprint(buf[5]) ? buf[5] : '.',
250
          qemu_isprint(buf[6]) ? buf[6] : '.',
251
          qemu_isprint(buf[7]) ? buf[7] : '.');
252

    
253
    if (memcmp(buf, "NBDMAGIC", 8) != 0) {
254
        LOG("Invalid magic received");
255
        errno = EINVAL;
256
        return -1;
257
    }
258

    
259
    if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
260
        LOG("read failed");
261
        errno = EINVAL;
262
        return -1;
263
    }
264
    magic = be64_to_cpu(magic);
265
    TRACE("Magic is 0x%" PRIx64, magic);
266

    
267
    if (name) {
268
        uint32_t reserved = 0;
269
        uint32_t opt;
270
        uint32_t namesize;
271

    
272
        TRACE("Checking magic (opts_magic)");
273
        if (magic != 0x49484156454F5054LL) {
274
            LOG("Bad magic received");
275
            errno = EINVAL;
276
            return -1;
277
        }
278
        if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
279
            LOG("flags read failed");
280
            errno = EINVAL;
281
            return -1;
282
        }
283
        *flags = be16_to_cpu(tmp) << 16;
284
        /* reserved for future use */
285
        if (write_sync(csock, &reserved, sizeof(reserved)) !=
286
            sizeof(reserved)) {
287
            LOG("write failed (reserved)");
288
            errno = EINVAL;
289
            return -1;
290
        }
291
        /* write the export name */
292
        magic = cpu_to_be64(magic);
293
        if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
294
            LOG("write failed (magic)");
295
            errno = EINVAL;
296
            return -1;
297
        }
298
        opt = cpu_to_be32(NBD_OPT_EXPORT_NAME);
299
        if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) {
300
            LOG("write failed (opt)");
301
            errno = EINVAL;
302
            return -1;
303
        }
304
        namesize = cpu_to_be32(strlen(name));
305
        if (write_sync(csock, &namesize, sizeof(namesize)) !=
306
            sizeof(namesize)) {
307
            LOG("write failed (namesize)");
308
            errno = EINVAL;
309
            return -1;
310
        }
311
        if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) {
312
            LOG("write failed (name)");
313
            errno = EINVAL;
314
            return -1;
315
        }
316
    } else {
317
        TRACE("Checking magic (cli_magic)");
318

    
319
        if (magic != 0x00420281861253LL) {
320
            LOG("Bad magic received");
321
            errno = EINVAL;
322
            return -1;
323
        }
324
    }
325

    
326
    if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) {
327
        LOG("read failed");
328
        errno = EINVAL;
329
        return -1;
330
    }
331
    *size = be64_to_cpu(s);
332
    *blocksize = 1024;
333
    TRACE("Size is %" PRIu64, *size);
334

    
335
    if (!name) {
336
        if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) {
337
            LOG("read failed (flags)");
338
            errno = EINVAL;
339
            return -1;
340
        }
341
        *flags = be32_to_cpup(flags);
342
    } else {
343
        if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
344
            LOG("read failed (tmp)");
345
            errno = EINVAL;
346
            return -1;
347
        }
348
        *flags |= be32_to_cpu(tmp);
349
    }
350
    if (read_sync(csock, &buf, 124) != 124) {
351
        LOG("read failed (buf)");
352
        errno = EINVAL;
353
        return -1;
354
    }
355
        return 0;
356
}
357

    
358
#ifdef __linux__
359
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
360
{
361
    TRACE("Setting NBD socket");
362

    
363
    if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
364
        int serrno = errno;
365
        LOG("Failed to set NBD socket");
366
        errno = serrno;
367
        return -1;
368
    }
369

    
370
    TRACE("Setting block size to %lu", (unsigned long)blocksize);
371

    
372
    if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
373
        int serrno = errno;
374
        LOG("Failed setting NBD block size");
375
        errno = serrno;
376
        return -1;
377
    }
378

    
379
        TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize));
380

    
381
    if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
382
        int serrno = errno;
383
        LOG("Failed setting size (in blocks)");
384
        errno = serrno;
385
        return -1;
386
    }
387

    
388
    if (flags & NBD_FLAG_READ_ONLY) {
389
        int read_only = 1;
390
        TRACE("Setting readonly attribute");
391

    
392
        if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) {
393
            int serrno = errno;
394
            LOG("Failed setting read-only attribute");
395
            errno = serrno;
396
            return -1;
397
        }
398
    }
399

    
400
    if (ioctl(fd, NBD_SET_FLAGS, flags) < 0
401
        && errno != ENOTTY) {
402
        int serrno = errno;
403
        LOG("Failed setting flags");
404
        errno = serrno;
405
        return -1;
406
    }
407

    
408
    TRACE("Negotiation ended");
409

    
410
    return 0;
411
}
412

    
413
int nbd_disconnect(int fd)
414
{
415
    ioctl(fd, NBD_CLEAR_QUE);
416
    ioctl(fd, NBD_DISCONNECT);
417
    ioctl(fd, NBD_CLEAR_SOCK);
418
    return 0;
419
}
420

    
421
int nbd_client(int fd)
422
{
423
    int ret;
424
    int serrno;
425

    
426
    TRACE("Doing NBD loop");
427

    
428
    ret = ioctl(fd, NBD_DO_IT);
429
    if (ret == -1 && errno == EPIPE) {
430
        /* NBD_DO_IT normally returns EPIPE when someone has disconnected
431
         * the socket via NBD_DISCONNECT.  We do not want to return 1 in
432
         * that case.
433
         */
434
        ret = 0;
435
    }
436
    serrno = errno;
437

    
438
    TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
439

    
440
    TRACE("Clearing NBD queue");
441
    ioctl(fd, NBD_CLEAR_QUE);
442

    
443
    TRACE("Clearing NBD socket");
444
    ioctl(fd, NBD_CLEAR_SOCK);
445

    
446
    errno = serrno;
447
    return ret;
448
}
449
#else
450
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
451
{
452
    errno = ENOTSUP;
453
    return -1;
454
}
455

    
456
int nbd_disconnect(int fd)
457
{
458
    errno = ENOTSUP;
459
    return -1;
460
}
461

    
462
int nbd_client(int fd)
463
{
464
    errno = ENOTSUP;
465
    return -1;
466
}
467
#endif
468

    
469
int nbd_send_request(int csock, struct nbd_request *request)
470
{
471
    uint8_t buf[4 + 4 + 8 + 8 + 4];
472

    
473
    cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
474
    cpu_to_be32w((uint32_t*)(buf + 4), request->type);
475
    cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
476
    cpu_to_be64w((uint64_t*)(buf + 16), request->from);
477
    cpu_to_be32w((uint32_t*)(buf + 24), request->len);
478

    
479
    TRACE("Sending request to client: "
480
          "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}",
481
          request->from, request->len, request->handle, request->type);
482

    
483
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
484
        LOG("writing to socket failed");
485
        errno = EINVAL;
486
        return -1;
487
    }
488
    return 0;
489
}
490

    
491
static int nbd_receive_request(int csock, struct nbd_request *request)
492
{
493
    uint8_t buf[4 + 4 + 8 + 8 + 4];
494
    uint32_t magic;
495

    
496
    if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
497
        LOG("read failed");
498
        errno = EINVAL;
499
        return -1;
500
    }
501

    
502
    /* Request
503
       [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
504
       [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
505
       [ 8 .. 15]   handle
506
       [16 .. 23]   from
507
       [24 .. 27]   len
508
     */
509

    
510
    magic = be32_to_cpup((uint32_t*)buf);
511
    request->type  = be32_to_cpup((uint32_t*)(buf + 4));
512
    request->handle = be64_to_cpup((uint64_t*)(buf + 8));
513
    request->from  = be64_to_cpup((uint64_t*)(buf + 16));
514
    request->len   = be32_to_cpup((uint32_t*)(buf + 24));
515

    
516
    TRACE("Got request: "
517
          "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
518
          magic, request->type, request->from, request->len);
519

    
520
    if (magic != NBD_REQUEST_MAGIC) {
521
        LOG("invalid magic (got 0x%x)", magic);
522
        errno = EINVAL;
523
        return -1;
524
    }
525
    return 0;
526
}
527

    
528
int nbd_receive_reply(int csock, struct nbd_reply *reply)
529
{
530
    uint8_t buf[NBD_REPLY_SIZE];
531
    uint32_t magic;
532

    
533
    memset(buf, 0xAA, sizeof(buf));
534

    
535
    if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
536
        LOG("read failed");
537
        errno = EINVAL;
538
        return -1;
539
    }
540

    
541
    /* Reply
542
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
543
       [ 4 ..  7]    error   (0 == no error)
544
       [ 7 .. 15]    handle
545
     */
546

    
547
    magic = be32_to_cpup((uint32_t*)buf);
548
    reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
549
    reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
550

    
551
    TRACE("Got reply: "
552
          "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
553
          magic, reply->error, reply->handle);
554

    
555
    if (magic != NBD_REPLY_MAGIC) {
556
        LOG("invalid magic (got 0x%x)", magic);
557
        errno = EINVAL;
558
        return -1;
559
    }
560
    return 0;
561
}
562

    
563
static int nbd_send_reply(int csock, struct nbd_reply *reply)
564
{
565
    uint8_t buf[4 + 4 + 8];
566

    
567
    /* Reply
568
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
569
       [ 4 ..  7]    error   (0 == no error)
570
       [ 7 .. 15]    handle
571
     */
572
    cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
573
    cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
574
    cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
575

    
576
    TRACE("Sending response to client");
577

    
578
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
579
        LOG("writing to socket failed");
580
        errno = EINVAL;
581
        return -1;
582
    }
583
    return 0;
584
}
585

    
586
int nbd_trip(BlockDriverState *bs, int csock, off_t size,
587
             uint64_t dev_offset, uint32_t nbdflags,
588
             uint8_t *data)
589
{
590
    struct nbd_request request;
591
    struct nbd_reply reply;
592
    int ret;
593

    
594
    TRACE("Reading request.");
595

    
596
    if (nbd_receive_request(csock, &request) == -1)
597
        return -1;
598

    
599
    if (request.len + NBD_REPLY_SIZE > NBD_BUFFER_SIZE) {
600
        LOG("len (%u) is larger than max len (%u)",
601
            request.len + NBD_REPLY_SIZE, NBD_BUFFER_SIZE);
602
        errno = EINVAL;
603
        return -1;
604
    }
605

    
606
    if ((request.from + request.len) < request.from) {
607
        LOG("integer overflow detected! "
608
            "you're probably being attacked");
609
        errno = EINVAL;
610
        return -1;
611
    }
612

    
613
    if ((request.from + request.len) > size) {
614
            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
615
            ", Offset: %" PRIu64 "\n",
616
                    request.from, request.len, (uint64_t)size, dev_offset);
617
        LOG("requested operation past EOF--bad client?");
618
        errno = EINVAL;
619
        return -1;
620
    }
621

    
622
    TRACE("Decoding type");
623

    
624
    reply.handle = request.handle;
625
    reply.error = 0;
626

    
627
    switch (request.type & NBD_CMD_MASK_COMMAND) {
628
    case NBD_CMD_READ:
629
        TRACE("Request type is READ");
630

    
631
        ret = bdrv_read(bs, (request.from + dev_offset) / 512,
632
                        data + NBD_REPLY_SIZE,
633
                        request.len / 512);
634
        if (ret < 0) {
635
            LOG("reading from file failed");
636
            reply.error = -ret;
637
            request.len = 0;
638
        }
639

    
640
        TRACE("Read %u byte(s)", request.len);
641

    
642
        /* Reply
643
           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
644
           [ 4 ..  7]    error   (0 == no error)
645
           [ 7 .. 15]    handle
646
         */
647

    
648
        cpu_to_be32w((uint32_t*)data, NBD_REPLY_MAGIC);
649
        cpu_to_be32w((uint32_t*)(data + 4), reply.error);
650
        cpu_to_be64w((uint64_t*)(data + 8), reply.handle);
651

    
652
        TRACE("Sending data to client");
653

    
654
        if (write_sync(csock, data,
655
                   request.len + NBD_REPLY_SIZE) !=
656
                   request.len + NBD_REPLY_SIZE) {
657
            LOG("writing to socket failed");
658
            errno = EINVAL;
659
            return -1;
660
        }
661
        break;
662
    case NBD_CMD_WRITE:
663
        TRACE("Request type is WRITE");
664

    
665
        TRACE("Reading %u byte(s)", request.len);
666

    
667
        if (read_sync(csock, data, request.len) != request.len) {
668
            LOG("reading from socket failed");
669
            errno = EINVAL;
670
            return -1;
671
        }
672

    
673
        if (nbdflags & NBD_FLAG_READ_ONLY) {
674
            TRACE("Server is read-only, return error");
675
            reply.error = 1;
676
        } else {
677
            TRACE("Writing to device");
678

    
679
            ret = bdrv_write(bs, (request.from + dev_offset) / 512,
680
                             data, request.len / 512);
681
            if (ret < 0) {
682
                LOG("writing to file failed");
683
                reply.error = -ret;
684
                request.len = 0;
685
            }
686

    
687
            if (request.type & NBD_CMD_FLAG_FUA) {
688
                ret = bdrv_flush(bs);
689
                if (ret < 0) {
690
                    LOG("flush failed");
691
                    reply.error = -ret;
692
                }
693
            }
694
        }
695

    
696
        if (nbd_send_reply(csock, &reply) == -1)
697
            return -1;
698
        break;
699
    case NBD_CMD_DISC:
700
        TRACE("Request type is DISCONNECT");
701
        errno = 0;
702
        return 1;
703
    case NBD_CMD_FLUSH:
704
        TRACE("Request type is FLUSH");
705

    
706
        ret = bdrv_flush(bs);
707
        if (ret < 0) {
708
            LOG("flush failed");
709
            reply.error = -ret;
710
        }
711

    
712
        if (nbd_send_reply(csock, &reply) == -1)
713
            return -1;
714
        break;
715
    case NBD_CMD_TRIM:
716
        TRACE("Request type is TRIM");
717
        ret = bdrv_discard(bs, (request.from + dev_offset) / 512,
718
                           request.len / 512);
719
        if (ret < 0) {
720
            LOG("discard failed");
721
            reply.error = -ret;
722
        }
723
        if (nbd_send_reply(csock, &reply) == -1)
724
            return -1;
725
        break;
726
    default:
727
        LOG("invalid request type (%u) received", request.type);
728
        errno = EINVAL;
729
        return -1;
730
    }
731

    
732
    TRACE("Request/Reply complete");
733

    
734
    return 0;
735
}