Revision b90fb4b8

b/block/nbd.c
48 48

  
49 49
typedef struct BDRVNBDState {
50 50
    int sock;
51
    uint32_t nbdflags;
51 52
    off_t size;
52 53
    size_t blocksize;
53 54
    char *export_name; /* An NBD server may export several devices */
......
111 112
    int ret;
112 113
    off_t size;
113 114
    size_t blocksize;
114
    uint32_t nbdflags;
115 115

  
116 116
    if (s->host_spec[0] == '/') {
117 117
        sock = unix_socket_outgoing(s->host_spec);
......
126 126
    }
127 127

  
128 128
    /* NBD handshake */
129
    ret = nbd_receive_negotiate(sock, s->export_name, &nbdflags, &size,
129
    ret = nbd_receive_negotiate(sock, s->export_name, &s->nbdflags, &size,
130 130
                                &blocksize);
131 131
    if (ret == -1) {
132 132
        logout("Failed to negotiate with the NBD server\n");
b/nbd.c
30 30
#include <ctype.h>
31 31
#include <inttypes.h>
32 32

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

  
33 37
#include "qemu_socket.h"
34 38

  
35 39
//#define DEBUG_NBD
......
172 176
                  Request (type == 2)
173 177
*/
174 178

  
175
int nbd_negotiate(int csock, off_t size)
179
int nbd_negotiate(int csock, off_t size, uint32_t flags)
176 180
{
177 181
    char buf[8 + 8 + 8 + 128];
178 182

  
......
180 184
        [ 0 ..   7]   passwd   ("NBDMAGIC")
181 185
        [ 8 ..  15]   magic    (0x00420281861253)
182 186
        [16 ..  23]   size
183
        [24 .. 151]   reserved (0)
187
        [24 ..  27]   flags
188
        [28 .. 151]   reserved (0)
184 189
     */
185 190

  
186 191
    TRACE("Beginning negotiation.");
187 192
    memcpy(buf, "NBDMAGIC", 8);
188 193
    cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
189 194
    cpu_to_be64w((uint64_t*)(buf + 16), size);
190
    memset(buf + 24, 0, 128);
195
    cpu_to_be32w((uint32_t*)(buf + 24), flags | NBD_FLAG_HAS_FLAGS);
196
    memset(buf + 28, 0, 124);
191 197

  
192 198
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
193 199
        LOG("write failed");
......
337 343
        return 0;
338 344
}
339 345

  
340
#ifndef _WIN32
341
int nbd_init(int fd, int csock, off_t size, size_t blocksize)
346
#ifdef __linux__
347
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
342 348
{
343 349
    TRACE("Setting block size to %lu", (unsigned long)blocksize);
344 350

  
......
358 364
        return -1;
359 365
    }
360 366

  
367
    if (flags & NBD_FLAG_READ_ONLY) {
368
        int read_only = 1;
369
        TRACE("Setting readonly attribute");
370

  
371
        if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) {
372
            int serrno = errno;
373
            LOG("Failed setting read-only attribute");
374
            errno = serrno;
375
            return -1;
376
        }
377
    }
378

  
361 379
    TRACE("Clearing NBD socket");
362 380

  
363 381
    if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
......
548 566
}
549 567

  
550 568
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
551
             off_t *offset, bool readonly, uint8_t *data, int data_size)
569
             off_t *offset, uint32_t nbdflags, uint8_t *data, int data_size)
552 570
{
553 571
    struct nbd_request request;
554 572
    struct nbd_reply reply;
......
632 650
            return -1;
633 651
        }
634 652

  
635
        if (readonly) {
653
        if (nbdflags & NBD_FLAG_READ_ONLY) {
636 654
            TRACE("Server is read-only, return error");
637 655
            reply.error = 1;
638 656
        } else {
b/nbd.h
37 37
    uint64_t handle;
38 38
} QEMU_PACKED;
39 39

  
40
#define NBD_FLAG_HAS_FLAGS      (1 << 0)        /* Flags are there */
41
#define NBD_FLAG_READ_ONLY      (1 << 1)        /* Device is read-only */
42

  
40 43
enum {
41 44
    NBD_CMD_READ = 0,
42 45
    NBD_CMD_WRITE = 1,
......
53 56
int unix_socket_outgoing(const char *path);
54 57
int unix_socket_incoming(const char *path);
55 58

  
56
int nbd_negotiate(int csock, off_t size);
59
int nbd_negotiate(int csock, off_t size, uint32_t flags);
57 60
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
58 61
                          off_t *size, size_t *blocksize);
59
int nbd_init(int fd, int csock, off_t size, size_t blocksize);
62
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize);
60 63
int nbd_send_request(int csock, struct nbd_request *request);
61 64
int nbd_receive_reply(int csock, struct nbd_reply *reply);
62 65
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
63
             off_t *offset, bool readonly, uint8_t *data, int data_size);
66
             off_t *offset, uint32_t nbdflags, uint8_t *data, int data_size);
64 67
int nbd_client(int fd);
65 68
int nbd_disconnect(int fd);
66 69

  
b/qemu-nbd.c
185 185
    BlockDriverState *bs;
186 186
    off_t dev_offset = 0;
187 187
    off_t offset = 0;
188
    bool readonly = false;
188
    uint32_t nbdflags = 0;
189 189
    bool disconnect = false;
190 190
    const char *bindto = "0.0.0.0";
191 191
    int port = NBD_DEFAULT_PORT;
......
230 230
    int nb_fds = 0;
231 231
    int max_fd;
232 232
    int persistent = 0;
233
    uint32_t nbdflags;
234 233

  
235 234
    while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
236 235
        switch (ch) {
......
263 262
            }
264 263
            break;
265 264
        case 'r':
266
            readonly = true;
265
            nbdflags |= NBD_FLAG_READ_ONLY;
267 266
            flags &= ~BDRV_O_RDWR;
268 267
            break;
269 268
        case 'P':
......
398 397
            }
399 398

  
400 399
            ret = nbd_receive_negotiate(sock, NULL, &nbdflags,
401
					&size, &blocksize);
400
                                        &size, &blocksize);
402 401
            if (ret == -1) {
403 402
                ret = 1;
404 403
                goto out;
405 404
            }
406 405

  
407
            ret = nbd_init(fd, sock, size, blocksize);
406
            ret = nbd_init(fd, sock, nbdflags, size, blocksize);
408 407
            if (ret == -1) {
409 408
                ret = 1;
410 409
                goto out;
......
463 462
        for (i = 1; i < nb_fds && ret; i++) {
464 463
            if (FD_ISSET(sharing_fds[i], &fds)) {
465 464
                if (nbd_trip(bs, sharing_fds[i], fd_size, dev_offset,
466
                    &offset, readonly, data, NBD_BUFFER_SIZE) != 0) {
465
                    &offset, nbdflags, data, NBD_BUFFER_SIZE) != 0) {
467 466
                    close(sharing_fds[i]);
468 467
                    nb_fds--;
469 468
                    sharing_fds[i] = sharing_fds[nb_fds];
......
479 478
                                             (struct sockaddr *)&addr,
480 479
                                             &addr_len);
481 480
                if (sharing_fds[nb_fds] != -1 &&
482
                    nbd_negotiate(sharing_fds[nb_fds], fd_size) != -1) {
481
                    nbd_negotiate(sharing_fds[nb_fds], fd_size, nbdflags) != -1) {
483 482
                        if (sharing_fds[nb_fds] > max_fd)
484 483
                            max_fd = sharing_fds[nb_fds];
485 484
                        nb_fds++;

Also available in: Unified diff