From: Laurent Vivier <Laurent.Vivier@bull.net>
To: qemu-devel@nongnu.org
Cc: Anthony Liguori <aliguori@us.ibm.com>
Subject: [Qemu-devel] [PATCH][v2] Merge NBD client/server int qemu-nbd
Date: Thu, 19 Jun 2008 10:58:04 +0200 [thread overview]
Message-ID: <1213865884.3971.7.camel@frecb07144> (raw)
In-Reply-To: <1213551542.3806.13.camel@frecb07144>
[-- Attachment #1: Type: text/plain, Size: 1104 bytes --]
Hi,
this patch allows to connect directly a disk image file to an NBD
device. It introduces the use of a unix socket (instead of inet).
- To connect a file to a device:
# qemu-nbd --connect=/dev/nbd0 my_disk.qcow2
Then you can see directly your disk (no need of nbd-client):
# fdisk -l /dev/nbd0
Disk /dev/nbd0: 4294 MB, 4294967296 bytes
255 heads, 63 sectors/track, 522 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/nbd0p1 * 1 492 3951958+ 83 Linux
/dev/nbd0p2 493 522 240975 5 Extended
/dev/nbd0p5 493 522 240943+ 82 Linux swap /
Solaris
- To disconnect the file from the device:
# qemu-nbd --disconnect /dev/nbd0
Changelog:
- v2: call show_parts() from client and avoid the sleep(1). Thank you to
Avi and Anthony. Include my cleanup patch and comments from Carlo
Marcelo Arenas Belon.
Regards,
Laurent
--
------------- Laurent.Vivier@bull.net ---------------
"The best way to predict the future is to invent it."
- Alan Kay
[-- Attachment #2: qemu-nbd-local.patch --]
[-- Type: text/x-patch, Size: 7624 bytes --]
Index: qemu/nbd.c
===================================================================
--- qemu.orig/nbd.c 2008-06-18 17:05:46.000000000 +0200
+++ qemu/nbd.c 2008-06-19 10:47:46.000000000 +0200
@@ -25,6 +25,7 @@
#include <ctype.h>
#include <inttypes.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
@@ -183,6 +184,65 @@ error:
return -1;
}
+int unix_socket_incoming(const char *path)
+{
+ int s;
+ struct sockaddr_un addr;
+ int serrno;
+
+ s = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (s == -1) {
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ goto error;
+ }
+
+ if (listen(s, 128) == -1) {
+ goto error;
+ }
+
+ return s;
+error:
+ serrno = errno;
+ close(s);
+ errno = serrno;
+ return -1;
+}
+
+int unix_socket_outgoing(const char *path)
+{
+ int s;
+ struct sockaddr_un addr;
+ int serrno;
+
+ s = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (s == -1) {
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
+
+ if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ goto error;
+ }
+
+ return s;
+error:
+ serrno = errno;
+ close(s);
+ errno = serrno;
+ return -1;
+}
+
+
/* Basic flow
Server Client
@@ -388,8 +448,8 @@ int nbd_trip(BlockDriverState *bs, int c
}
if (len > sizeof(data)) {
- LOG("len (%u) is larger than max len (%u)",
- len, sizeof(data));
+ LOG("len (%u) is larger than max len (%lu)",
+ len, (unsigned long)sizeof(data));
errno = EINVAL;
return -1;
}
Index: qemu/nbd.h
===================================================================
--- qemu.orig/nbd.h 2008-06-18 17:05:46.000000000 +0200
+++ qemu/nbd.h 2008-06-19 10:47:46.000000000 +0200
@@ -27,6 +27,8 @@
#include "block_int.h"
int tcp_socket_incoming(const char *address, uint16_t port);
+int unix_socket_outgoing(const char *path);
+int unix_socket_incoming(const char *path);
int nbd_negotiate(BlockDriverState *bs, int csock, off_t size);
int nbd_receive_negotiate(int fd, int csock);
Index: qemu/qemu-nbd.c
===================================================================
--- qemu.orig/qemu-nbd.c 2008-06-18 17:05:46.000000000 +0200
+++ qemu/qemu-nbd.c 2008-06-19 10:48:49.000000000 +0200
@@ -21,15 +21,18 @@
#include "block_int.h"
#include "nbd.h"
-#include <malloc.h>
#include <stdarg.h>
#include <stdio.h>
#include <getopt.h>
#include <err.h>
+#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
+#include <signal.h>
+
+//#define DEBUG
int verbose;
@@ -44,6 +47,8 @@ static void usage(const char *name)
" -b, --bind=IFACE interface to bind to (default `0.0.0.0')\n"
" -r, --read-only export read-only\n"
" -P, --partition=NUM only expose partition NUM\n"
+" -c, --connect=DEV connect FILE to the local NBD device DEV\n"
+" -d, --disconnect disconnect the specified device\n"
" -v, --verbose display extra debugging information\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n"
@@ -145,19 +150,39 @@ static int find_partition(BlockDriverSta
return -1;
}
+static void show_parts(const char *device)
+{
+ if (fork() == 0) {
+ int nbd;
+
+ /* linux just needs an open() to trigger
+ * the partition table update
+ * but remember to load the module with max_part != 0 :
+ * modprobe nbd max_part=63
+ */
+ nbd = open(device, O_RDWR);
+ if (nbd != -1)
+ close(nbd);
+ exit(0);
+ }
+}
+
int main(int argc, char **argv)
{
BlockDriverState *bs;
off_t dev_offset = 0;
off_t offset = 0;
bool readonly = false;
+ bool disconnect = false;
const char *bindto = "0.0.0.0";
int port = 1024;
int sock, csock;
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
off_t fd_size;
- const char *sopt = "hVbo:p:rsP:v";
+ char *device;
+ char sockpath[128];
+ const char *sopt = "hVbo:p:rsP:c:dv?";
struct option lopt[] = {
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'V' },
@@ -166,8 +191,11 @@ int main(int argc, char **argv)
{ "offset", 1, 0, 'o' },
{ "read-only", 0, 0, 'r' },
{ "partition", 1, 0, 'P' },
+ { "connect", 1, 0, 'c' },
+ { "disconnect", 0, 0, 'd' },
{ "snapshot", 0, 0, 's' },
{ "verbose", 0, 0, 'v' },
+ { 0, 0, 0, 0 }
};
int ch;
int opt_ind = 0;
@@ -175,6 +203,8 @@ int main(int argc, char **argv)
char *end;
bool snapshot = false;
int partition = -1;
+ int fd;
+ int ret;
while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
switch (ch) {
@@ -213,6 +243,12 @@ int main(int argc, char **argv)
if (partition < 1 || partition > 8)
errx(EINVAL, "Invalid partition %d", partition);
break;
+ case 'd':
+ disconnect = true;
+ break;
+ case 'c':
+ device = optarg;
+ break;
case 'v':
verbose = 1;
break;
@@ -236,6 +272,20 @@ int main(int argc, char **argv)
argv[0]);
}
+ if (disconnect) {
+ fd = open(argv[optind], O_RDWR);
+ if (fd == -1)
+ errx(errno, "Cannot open %s", argv[optind]);
+
+ nbd_disconnect(fd);
+
+ close(fd);
+
+ printf("%s disconnected\n", argv[optind]);
+
+ return 0;
+ }
+
bdrv_init();
bs = bdrv_new("hda");
@@ -251,7 +301,60 @@ int main(int argc, char **argv)
find_partition(bs, partition, &dev_offset, &fd_size))
errx(errno, "Could not find partition %d", partition);
- sock = tcp_socket_incoming(bindto, port);
+ if (device) {
+ pid_t pid;
+ if (!verbose)
+ daemon(0, 0); /* detach client and server */
+
+ sprintf(sockpath, "/var/lock/qemu-img-%s", basename(device));
+
+ pid = fork();
+ if (pid < 0)
+ return 1;
+ if (pid != 0) {
+ ret = 0;
+ bdrv_close(bs);
+
+ do {
+ sock = unix_socket_outgoing(sockpath);
+ if (sock == -1) {
+ if (errno != ENOENT && errno != ECONNREFUSED)
+ goto exit;
+ sleep(1); /* wait children */
+ }
+ } while (sock == -1);
+
+ fd = open(device, O_RDWR);
+ if (fd == -1) {
+ ret = -1;
+ goto exit;
+ }
+
+ ret = nbd_receive_negotiate(fd, sock);
+ if (ret == -1)
+ goto exit;
+
+ printf("NBD device %s is now connected to file %s\n",
+ device, argv[optind]);
+
+ /* if supported, update partition table */
+
+ show_parts(device);
+
+ nbd_client(fd, sock);
+ close(fd);
+exit:
+ kill(pid, SIGTERM);
+ unlink(sockpath);
+
+ return ret;
+ }
+ /* children */
+ sock = unix_socket_incoming(sockpath);
+ } else {
+ sock = tcp_socket_incoming(bindto, port);
+ }
+
if (sock == -1)
return 1;
next prev parent reply other threads:[~2008-06-19 9:05 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-13 15:15 [Qemu-devel] [PATCH] Merge NBD client/server int qemu-nbd Laurent Vivier
2008-06-13 17:49 ` Anthony Liguori
2008-06-13 18:09 ` Avi Kivity
2008-06-13 18:39 ` Laurent Vivier
2008-06-14 15:12 ` Anthony Liguori
2008-06-14 18:47 ` Laurent Vivier
2008-06-14 17:18 ` Avi Kivity
2008-06-14 19:03 ` Laurent Vivier
2008-06-14 19:06 ` Avi Kivity
2008-06-14 19:21 ` Laurent Vivier
2008-06-14 19:35 ` Avi Kivity
2008-06-14 19:54 ` Laurent Vivier
2008-06-15 14:25 ` Anthony Liguori
2008-06-15 15:56 ` Laurent Vivier
2008-06-15 16:00 ` Avi Kivity
2008-06-15 17:39 ` Laurent Vivier
2008-06-19 8:58 ` Laurent Vivier [this message]
2008-06-19 9:18 ` [Qemu-devel] [PATCH][v2] " Laurent Vivier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1213865884.3971.7.camel@frecb07144 \
--to=laurent.vivier@bull.net \
--cc=aliguori@us.ibm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.