qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH][RFC] qemu-nbd:multiple files server
@ 2008-09-08  9:47 Laurent Vivier
  2008-09-10 15:27 ` Anthony Liguori
  0 siblings, 1 reply; 2+ messages in thread
From: Laurent Vivier @ 2008-09-08  9:47 UTC (permalink / raw)
  To: qemu-devel@nongnu.org

[-- Attachment #1: Type: text/plain, Size: 1381 bytes --]

This patch allows the NBD client to select the file to use.

It modifies the NBD protocol to allow the client to provide a filename
if the NBD server reports a disk size of 0.

Example:

# add in /etc/services

nbd	1024/tcp

# add in /etc/inetd.conf

nbd		stream	tcp	nowait root /usr/local/bin/qemu-nbd /usr/local/bin/qemu-nbd --nocache --read-only --port 0 --directory /ISO

In /ISO, there are:

debian-31r0a-amd64-netinst.iso   openSUSE-10.3-GM-x86_64-mini.iso
debian-40r0-i386-netinst.iso     ubuntu-6.06-desktop-amd64.iso
debian-40r0-i386-xfce-CD-1.iso   ubuntu-7.10-desktop-amd64.iso
debian-40r1-amd64-netinst.iso    ubuntu-8.04-desktop-i386.iso
debian-40r1-powerpc-netinst.iso  winxp_64.iso

Then I can start qemu with:

x86_64-softmmu/qemu-system-x86_64 -net nic -net tap -hda new_disk.qcow2 -cdrom nbd:my_nbd_server:1024:ubuntu-6.06-desktop-amd64.iso -boot d

or

x86_64-softmmu/qemu-system-x86_64 -net nic -net tap -hda new_disk.qcow2 -cdrom nbd:my_nbd_server:1024:winxp_64.iso -boot d

My goal is to be able to provide an install CD server, without
configuring BOOTD/DHCP/TFTP server.

Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
-- 
----------------- Laurent.Vivier@bull.net  ------------------
  "La perfection est atteinte non quand il ne reste rien à
ajouter mais quand il ne reste rien à enlever." Saint Exupéry

[-- Attachment #2: nbd-directory.patch --]
[-- Type: text/x-vhdl, Size: 7410 bytes --]

---
 block-nbd.c |   16 ++++++++++++++
 nbd.c       |   47 +++++++++++++++++++++++++++++++++++++++++
 nbd.h       |    2 +
 qemu-nbd.c  |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 4 files changed, 124 insertions(+), 9 deletions(-)

Index: qemu/nbd.c
===================================================================
--- qemu.orig/nbd.c	2008-09-08 09:43:45.000000000 +0200
+++ qemu/nbd.c	2008-09-08 09:53:05.000000000 +0200
@@ -337,6 +337,53 @@ int nbd_receive_negotiate(int csock, off
         return 0;
 }
 
+int nbd_filename(int csock, const char *filename)
+{
+    uint8_t len;
+
+    if (!filename || strlen(filename) > 254) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    len = strlen(filename) + 1;
+    if (write_sync(csock, &len, sizeof(uint8_t)) !=
+                    sizeof(uint8_t)) {
+        LOG("read failed");
+        errno = EINVAL;
+        return -1;
+    }
+    if (len && write_sync(csock, (char*)filename, len) != len) {
+        LOG("read failed");
+        errno = EINVAL;
+        return -1;
+    }
+    return 0;
+}
+
+int nbd_receive_filename(int csock, char *filename)
+{
+    uint8_t len;
+    filename[0] = '\0';
+    if (read_sync(csock, &len, sizeof(uint8_t)) != sizeof(uint8_t)) {
+        LOG("read failed");
+        errno = EINVAL;
+        return -1;
+    }
+    if (len == 0) {
+        LOG("read failed");
+        errno = EINVAL;
+        return -1;
+    }
+    if (read_sync(csock, filename, len) != len) {
+        LOG("read failed");
+        errno = EINVAL;
+        return -1;
+    }
+    filename[len] = 0;
+    return 0;
+}
+
 int nbd_init(int fd, int csock, off_t size, size_t blocksize)
 {
 	TRACE("Setting block size to %lu", (unsigned long)blocksize);
Index: qemu/nbd.h
===================================================================
--- qemu.orig/nbd.h	2008-09-08 09:43:45.000000000 +0200
+++ qemu/nbd.h	2008-09-08 09:53:05.000000000 +0200
@@ -52,6 +52,8 @@ int unix_socket_incoming(const char *pat
 
 int nbd_negotiate(int csock, off_t size);
 int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize);
+int nbd_filename(int csock, const char *filename);
+int nbd_receive_filename(int csock, char *filename);
 int nbd_init(int fd, int csock, 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);
Index: qemu/block-nbd.c
===================================================================
--- qemu.orig/block-nbd.c	2008-09-08 09:31:04.000000000 +0200
+++ qemu/block-nbd.c	2008-09-08 09:53:05.000000000 +0200
@@ -47,6 +47,7 @@ static int nbd_open(BlockDriverState *bs
     off_t size;
     size_t blocksize;
     int ret;
+    const char *name = NULL;
 
     if ((flags & BDRV_O_CREAT))
         return -EINVAL;
@@ -79,6 +80,10 @@ static int nbd_open(BlockDriverState *bs
         if (r == p)
             return -EINVAL;
         sock = tcp_socket_outgoing(hostname, port);
+        if (*r == ':') {
+            r++;
+            name = r;
+        }
     }
 
     if (sock == -1)
@@ -88,6 +93,17 @@ static int nbd_open(BlockDriverState *bs
     if (ret == -1)
         return -errno;
 
+    if (size == 0) {
+        if (name == NULL)
+            return -EINVAL;
+        ret = nbd_filename(sock, name);
+        if (ret == -1)
+            return -errno;
+        ret = nbd_receive_negotiate(sock, &size, &blocksize);
+        if (ret == -1)
+            return -errno;
+    }
+
     s->sock = sock;
     s->size = size;
     s->blocksize = blocksize;
Index: qemu/qemu-nbd.c
===================================================================
--- qemu.orig/qemu-nbd.c	2008-09-08 09:49:06.000000000 +0200
+++ qemu/qemu-nbd.c	2008-09-08 10:23:37.000000000 +0200
@@ -158,6 +158,42 @@ static int find_partition(BlockDriverSta
     return -1;
 }
 
+static int negotiate_filename(int csock, BlockDriverState *bs, int flags,
+                              const char *directory, off_t *fd_size)
+{
+    char filename[255];
+    char path[PATH_MAX];
+    const char *name;
+    int ret;
+
+    ret = nbd_negotiate(csock, *fd_size);
+    if (ret == -1)
+        return -1;
+
+    if (*fd_size)
+        return 0;
+
+    if (directory == NULL)
+        return -1;
+
+    if (nbd_receive_filename(csock, filename) == -1)
+        return -1;
+
+    name = basename(filename);
+    if (strlen(directory) + strlen(name) + 1 > PATH_MAX)
+        return -1;
+
+    sprintf(path, "%s/%s", directory, name);
+    if (bdrv_open(bs, path, flags) == -1)
+        return -1;
+
+    *fd_size = bs->total_sectors * 512;
+
+    ret = nbd_negotiate(csock, *fd_size);
+
+    return ret;
+}
+
 static void show_parts(const char *device)
 {
     if (fork() == 0) {
@@ -189,8 +225,9 @@ int main(int argc, char **argv)
     off_t fd_size;
     char *device = NULL;
     char *socket = NULL;
+    char *directory = NULL;
     char sockpath[128];
-    const char *sopt = "hVbo:p:rsnP:c:dvk:e:t";
+    const char *sopt = "hVbo:p:rsnP:c:dvk:e:ti:";
     struct option lopt[] = {
         { "help", 0, 0, 'h' },
         { "version", 0, 0, 'V' },
@@ -207,6 +244,7 @@ int main(int argc, char **argv)
         { "shared", 1, 0, 'e' },
         { "persistent", 0, 0, 't' },
         { "verbose", 0, 0, 'v' },
+        { "directory", 1, 0, 'i' },
         { NULL, 0, 0, 0 }
     };
     int ch;
@@ -300,13 +338,16 @@ int main(int argc, char **argv)
             usage(argv[0]);
             exit(0);
             break;
+        case 'i':
+            directory = optarg;
+            break;
         case '?':
             errx(EINVAL, "Try `%s --help' for more information.",
                  argv[0]);
         }
     }
 
-    if ((argc - optind) != 1) {
+    if (directory == NULL && (argc - optind) != 1) {
         errx(EINVAL, "Invalid number of argument.\n"
              "Try `%s --help' for more information.",
              argv[0]);
@@ -330,20 +371,28 @@ int main(int argc, char **argv)
         errx(EINVAL, "You cannot set port to 0 and use shared");
     }
 
+    if (directory && port) {
+        errx(EINVAL, "--directory can only be used with --port=0");
+    }
+
     bdrv_init();
 
     bs = bdrv_new("hda");
     if (bs == NULL)
         return 1;
 
-    if (bdrv_open(bs, argv[optind], flags) == -1)
-        return 1;
+    if (directory) {
+        fd_size = 0;
+    } else {
+        if (bdrv_open(bs, argv[optind], flags) == -1)
+            return 1;
 
-    fd_size = bs->total_sectors * 512;
+        fd_size = bs->total_sectors * 512;
 
-    if (partition != -1 &&
-        find_partition(bs, partition, &dev_offset, &fd_size))
-        errx(errno, "Could not find partition %d", partition);
+        if (partition != -1 &&
+            find_partition(bs, partition, &dev_offset, &fd_size))
+            errx(errno, "Could not find partition %d", partition);
+    }
 
     if (device) {
         pid_t pid;
@@ -425,7 +474,8 @@ int main(int argc, char **argv)
     } else {
         if (port == 0) {
             /* read and write on stdin/stdout */
-            ret = nbd_negotiate(STDIN_FILENO, fd_size);
+            ret = negotiate_filename(STDIN_FILENO, bs, flags, directory,
+                                     &fd_size);
             while (ret != -1) {
                 ret = nbd_trip(bs, STDIN_FILENO, fd_size, dev_offset,
                                &offset, readonly, data, NBD_BUFFER_SIZE);

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Qemu-devel] [PATCH][RFC] qemu-nbd:multiple files server
  2008-09-08  9:47 [Qemu-devel] [PATCH][RFC] qemu-nbd:multiple files server Laurent Vivier
@ 2008-09-10 15:27 ` Anthony Liguori
  0 siblings, 0 replies; 2+ messages in thread
From: Anthony Liguori @ 2008-09-10 15:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier, Paul.Clements

Laurent Vivier wrote:
> This patch allows the NBD client to select the file to use.
>
> It modifies the NBD protocol to allow the client to provide a filename
> if the NBD server reports a disk size of 0.
>   

I don't have a problem with it from a client/server perspective, but we 
need to make sure that we're extending the NBD protocol in a way that's 
compatible with other implementations.

So please make sure Paul is on board with how you're extending the protocol.

Regards,

Anthony Liguori

> Example:
>
> # add in /etc/services
>
> nbd	1024/tcp
>
> # add in /etc/inetd.conf
>
> nbd		stream	tcp	nowait root /usr/local/bin/qemu-nbd /usr/local/bin/qemu-nbd --nocache --read-only --port 0 --directory /ISO
>
> In /ISO, there are:
>
> debian-31r0a-amd64-netinst.iso   openSUSE-10.3-GM-x86_64-mini.iso
> debian-40r0-i386-netinst.iso     ubuntu-6.06-desktop-amd64.iso
> debian-40r0-i386-xfce-CD-1.iso   ubuntu-7.10-desktop-amd64.iso
> debian-40r1-amd64-netinst.iso    ubuntu-8.04-desktop-i386.iso
> debian-40r1-powerpc-netinst.iso  winxp_64.iso
>
> Then I can start qemu with:
>
> x86_64-softmmu/qemu-system-x86_64 -net nic -net tap -hda new_disk.qcow2 -cdrom nbd:my_nbd_server:1024:ubuntu-6.06-desktop-amd64.iso -boot d
>
> or
>
> x86_64-softmmu/qemu-system-x86_64 -net nic -net tap -hda new_disk.qcow2 -cdrom nbd:my_nbd_server:1024:winxp_64.iso -boot d
>
> My goal is to be able to provide an install CD server, without
> configuring BOOTD/DHCP/TFTP server.
>
> Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
>   

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-09-10 15:28 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-08  9:47 [Qemu-devel] [PATCH][RFC] qemu-nbd:multiple files server Laurent Vivier
2008-09-10 15:27 ` Anthony Liguori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).