From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:42762) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R1gTk-0003A7-2Z for qemu-devel@nongnu.org; Thu, 08 Sep 2011 11:25:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R1gTd-0000pT-FS for qemu-devel@nongnu.org; Thu, 08 Sep 2011 11:25:23 -0400 Received: from mail-vw0-f53.google.com ([209.85.212.53]:39059) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R1gTd-0000ou-Aw for qemu-devel@nongnu.org; Thu, 08 Sep 2011 11:25:17 -0400 Received: by mail-vw0-f53.google.com with SMTP id 13so85560vws.12 for ; Thu, 08 Sep 2011 08:25:17 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Thu, 8 Sep 2011 17:24:54 +0200 Message-Id: <1315495505-28906-2-git-send-email-pbonzini@redhat.com> In-Reply-To: <1315495505-28906-1-git-send-email-pbonzini@redhat.com> References: <1315495505-28906-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 01/12] nbd: support feature negotiation List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org nbd supports writing flags in bytes 24...27 of the header, and uses that for the read-only flag. Add support for it in qemu-nbd. Signed-off-by: Paolo Bonzini --- block/nbd.c | 4 ++-- nbd.c | 32 +++++++++++++++++++++++++------- nbd.h | 9 ++++++--- qemu-nbd.c | 13 ++++++------- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/block/nbd.c b/block/nbd.c index 55cb2fd..ffc57a9 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -47,6 +47,7 @@ typedef struct BDRVNBDState { int sock; + uint32_t nbdflags; off_t size; size_t blocksize; char *export_name; /* An NBD server may export several devices */ @@ -110,7 +111,6 @@ static int nbd_establish_connection(BlockDriverState *bs) int ret; off_t size; size_t blocksize; - uint32_t nbdflags; if (s->host_spec[0] == '/') { sock = unix_socket_outgoing(s->host_spec); @@ -125,7 +125,7 @@ static int nbd_establish_connection(BlockDriverState *bs) } /* NBD handshake */ - ret = nbd_receive_negotiate(sock, s->export_name, &nbdflags, &size, + ret = nbd_receive_negotiate(sock, s->export_name, &s->nbdflags, &size, &blocksize); if (ret == -1) { logout("Failed to negotiate with the NBD server\n"); diff --git a/nbd.c b/nbd.c index e7a585d..07a8e53 100644 --- a/nbd.c +++ b/nbd.c @@ -29,6 +29,10 @@ #include #include +#ifdef __linux__ +#include +#endif + #include "qemu_socket.h" //#define DEBUG_NBD @@ -171,7 +175,7 @@ int unix_socket_outgoing(const char *path) Request (type == 2) */ -int nbd_negotiate(int csock, off_t size) +int nbd_negotiate(int csock, off_t size, uint32_t flags) { char buf[8 + 8 + 8 + 128]; @@ -179,14 +183,16 @@ int nbd_negotiate(int csock, off_t size) [ 0 .. 7] passwd ("NBDMAGIC") [ 8 .. 15] magic (0x00420281861253) [16 .. 23] size - [24 .. 151] reserved (0) + [24 .. 27] flags + [28 .. 151] reserved (0) */ TRACE("Beginning negotiation."); memcpy(buf, "NBDMAGIC", 8); cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL); cpu_to_be64w((uint64_t*)(buf + 16), size); - memset(buf + 24, 0, 128); + cpu_to_be32w((uint32_t*)(buf + 24), flags | NBD_FLAG_HAS_FLAGS); + memset(buf + 28, 0, 124); if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { LOG("write failed"); @@ -336,8 +342,8 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, return 0; } -#ifndef _WIN32 -int nbd_init(int fd, int csock, off_t size, size_t blocksize) +#ifdef __linux__ +int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize) { TRACE("Setting block size to %lu", (unsigned long)blocksize); @@ -357,6 +363,18 @@ int nbd_init(int fd, int csock, off_t size, size_t blocksize) return -1; } + if (flags & NBD_FLAG_READ_ONLY) { + int read_only = 1; + TRACE("Setting readonly attribute"); + + if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) { + int serrno = errno; + LOG("Failed setting read-only attribute"); + errno = serrno; + return -1; + } + } + TRACE("Clearing NBD socket"); if (ioctl(fd, NBD_CLEAR_SOCK) == -1) { @@ -547,7 +565,7 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply) } int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, - off_t *offset, bool readonly, uint8_t *data, int data_size) + off_t *offset, uint32_t nbdflags, uint8_t *data, int data_size) { struct nbd_request request; struct nbd_reply reply; @@ -631,7 +649,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, return -1; } - if (readonly) { + if (nbdflags & NBD_FLAG_READ_ONLY) { TRACE("Server is read-only, return error"); reply.error = 1; } else { diff --git a/nbd.h b/nbd.h index 96f77fe..938a021 100644 --- a/nbd.h +++ b/nbd.h @@ -39,6 +39,9 @@ struct nbd_reply { uint64_t handle; } QEMU_PACKED; +#define NBD_FLAG_HAS_FLAGS (1 << 0) /* Flags are there */ +#define NBD_FLAG_READ_ONLY (1 << 1) /* Device is read-only */ + enum { NBD_CMD_READ = 0, NBD_CMD_WRITE = 1, @@ -55,14 +58,14 @@ int tcp_socket_incoming_spec(const char *address_and_port); int unix_socket_outgoing(const char *path); int unix_socket_incoming(const char *path); -int nbd_negotiate(int csock, off_t size); +int nbd_negotiate(int csock, off_t size, uint32_t flags); int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, off_t *size, size_t *blocksize); -int nbd_init(int fd, int csock, off_t size, size_t blocksize); +int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize); int nbd_send_request(int csock, struct nbd_request *request); int nbd_receive_reply(int csock, struct nbd_reply *reply); int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, - off_t *offset, bool readonly, uint8_t *data, int data_size); + off_t *offset, uint32_t nbdflags, uint8_t *data, int data_size); int nbd_client(int fd); int nbd_disconnect(int fd); diff --git a/qemu-nbd.c b/qemu-nbd.c index 0b25a4d..58a3e16 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -185,7 +185,7 @@ int main(int argc, char **argv) BlockDriverState *bs; off_t dev_offset = 0; off_t offset = 0; - bool readonly = false; + uint32_t nbdflags = 0; bool disconnect = false; const char *bindto = "0.0.0.0"; int port = NBD_DEFAULT_PORT; @@ -230,7 +230,6 @@ int main(int argc, char **argv) int nb_fds = 0; int max_fd; int persistent = 0; - uint32_t nbdflags; while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { switch (ch) { @@ -263,7 +262,7 @@ int main(int argc, char **argv) } break; case 'r': - readonly = true; + nbdflags |= NBD_FLAG_READ_ONLY; flags &= ~BDRV_O_RDWR; break; case 'P': @@ -398,13 +397,13 @@ int main(int argc, char **argv) } ret = nbd_receive_negotiate(sock, NULL, &nbdflags, - &size, &blocksize); + &size, &blocksize); if (ret == -1) { ret = 1; goto out; } - ret = nbd_init(fd, sock, size, blocksize); + ret = nbd_init(fd, sock, nbdflags, size, blocksize); if (ret == -1) { ret = 1; goto out; @@ -463,7 +462,7 @@ int main(int argc, char **argv) for (i = 1; i < nb_fds && ret; i++) { if (FD_ISSET(sharing_fds[i], &fds)) { if (nbd_trip(bs, sharing_fds[i], fd_size, dev_offset, - &offset, readonly, data, NBD_BUFFER_SIZE) != 0) { + &offset, nbdflags, data, NBD_BUFFER_SIZE) != 0) { close(sharing_fds[i]); nb_fds--; sharing_fds[i] = sharing_fds[nb_fds]; @@ -479,7 +478,7 @@ int main(int argc, char **argv) (struct sockaddr *)&addr, &addr_len); if (sharing_fds[nb_fds] != -1 && - nbd_negotiate(sharing_fds[nb_fds], fd_size) != -1) { + nbd_negotiate(sharing_fds[nb_fds], fd_size, nbdflags) != -1) { if (sharing_fds[nb_fds] > max_fd) max_fd = sharing_fds[nb_fds]; nb_fds++; -- 1.7.6