* [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).