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