All of lore.kernel.org
 help / color / mirror / Atom feed
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;
 

  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.