xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library
@ 2010-06-07 21:54 Daniel Stodden
  2010-06-07 21:54 ` [PATCH 1 of 7] blktap2: Remove tapdisk-ipc module Daniel Stodden
                   ` (7 more replies)
  0 siblings, 8 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-07 21:54 UTC (permalink / raw)
  To: Xen


Hi.

Apart from removing some dead code and tidying up tapdisk-vbd a
little, the bigger introduces our new tap-ctl utility code.

The code aims to be a complete replacement for the original blktap2
control path, run through sysfs. Fully implemented in userspace, all
tapdisks now gained a small IPC layer on top of Unix domain sockets.

Sample usage:

# tap-ctl allocate
/dev/xen/blktap-2/tapdev0

# tap-ctl spawn
tapdisk spawned with pid 4168

# tap-ctl list
    4168  -    -          - -
       -  0    -          - -

# tap-ctl attach -p 4168 -m 0
# tap-ctl list
    4168  0    0          - -

# tap-ctl open -p 4168 -m 0 -a aio:/var/tmp/lenny.ext

# tap-ctl list
    4168  0    0        aio /var/tmp/lenny.ext

# tap-ctl close -p 4168 -m 0
# tap-ctl detach -p 4168 -m 0
# tap-ctl free -m 0

The above example is a bit noisy, because it's mediating between minor
number (block devices), tapdisks and tapdisk VBDs (the tapdisk I/O
queue running a bdev) in detail. 

There are shortcuts. At the same time, the low-level interface should
be general enough to stay extensible, and help accomodate some of the
more esoteric features, like shared images and/or multiple VBDs
sharing the same tapdisk.

Cheers,
Daniel

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

* [PATCH 1 of 7] blktap2: Remove tapdisk-ipc module
  2010-06-07 21:54 [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
@ 2010-06-07 21:54 ` Daniel Stodden
  2010-06-07 21:54 ` [PATCH 2 of 7] blktap2: Remove LVM hacks Daniel Stodden
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-07 21:54 UTC (permalink / raw)
  To: Xen

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

Obsoleted with blktapctrl.

Signed-off-by: Jake Wires <jake.wires@citrix.com>
Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>



[-- Attachment #2: remove-tapdisk-ipc.diff --]
[-- Type: text/x-patch, Size: 20566 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1275947595 25200
# Node ID 0156cca51013424068a563705b0d5689292b5c36
# Parent  4ab68bf4c37e4c97e12efe7aced616ce6946578f
blktap2: Remove tapdisk-ipc module.

Obsoleted with blktapctrl.

Signed-off-by: Jake Wires <jake.wires@citrix.com>
Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>

diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/Makefile
--- a/tools/blktap2/drivers/Makefile	Thu Jun 03 07:30:54 2010 +0100
+++ b/tools/blktap2/drivers/Makefile	Mon Jun 07 14:53:15 2010 -0700
@@ -74,7 +74,6 @@
 PORTABLE-OBJS-$(CONFIG_NetBSD) += blk_netbsd.o
 
 TAP-OBJS-y  := scheduler.o
-TAP-OBJS-y  += tapdisk-ipc.o
 TAP-OBJS-y  += tapdisk-vbd.o
 TAP-OBJS-y  += tapdisk-image.o
 TAP-OBJS-y  += tapdisk-driver.o
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/img2qcow.c
--- a/tools/blktap2/drivers/img2qcow.c	Thu Jun 03 07:30:54 2010 +0100
+++ b/tools/blktap2/drivers/img2qcow.c	Mon Jun 07 14:53:15 2010 -0700
@@ -201,13 +201,13 @@
 			(uint64_t)info.size);
 	
         /* Open Qcow image*/
-        err = tapdisk_server_initialize(NULL, NULL);
+        err = tapdisk_server_initialize();
         if( err ) {
           DPRINTF("qcow2raw Couldn't initialize server instance.\n");
           return err;
         }
 
-        err=tapdisk_vbd_initialize(-1,-1, QCOW_VBD);
+        err=tapdisk_vbd_initialize(QCOW_VBD);
         if( err ) {
           DPRINTF("qcow2raw Couldn't initialize qcow vbd.\n");
           return err;
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/qcow2raw.c
--- a/tools/blktap2/drivers/qcow2raw.c	Thu Jun 03 07:30:54 2010 +0100
+++ b/tools/blktap2/drivers/qcow2raw.c	Mon Jun 07 14:53:15 2010 -0700
@@ -217,13 +217,13 @@
 		exit(-1);
 	}
 
-        err = tapdisk_server_initialize(NULL, NULL);
+        err = tapdisk_server_initialize();
         if( err ) {
           DPRINTF("qcow2raw Couldn't initialize server instance.\n");
           return err;
         }
 
-        err=tapdisk_vbd_initialize(-1,-1, QCOW_VBD);
+        err=tapdisk_vbd_initialize(QCOW_VBD);
         if( err ) {
           DPRINTF("qcow2raw Couldn't initialize qcow vbd.\n");
           return err;
@@ -335,7 +335,7 @@
 	}
 
         //Now the output file should be there, reopen it as an aio VBD
-        err=tapdisk_vbd_initialize(-1,-1, AIO_VBD);
+        err=tapdisk_vbd_initialize(AIO_VBD);
         if( err ) {
           DPRINTF("qcow2raw Couldn't initialize aio vbd.\n");
           return err;
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/tapdisk-diff.c
--- a/tools/blktap2/drivers/tapdisk-diff.c	Thu Jun 03 07:30:54 2010 +0100
+++ b/tools/blktap2/drivers/tapdisk-diff.c	Mon Jun 07 14:53:15 2010 -0700
@@ -540,7 +540,7 @@
 
 	s->id = tapdisk_stream_count++;
 
-	err = tapdisk_vbd_initialize(-1, -1, s->id);
+	err = tapdisk_vbd_initialize(s->id);
 	if (err)
 		goto out;
 
@@ -755,7 +755,7 @@
 
 	tapdisk_start_logging("tapdisk-diff");
 
-	err = tapdisk_server_initialize(NULL, NULL);
+	err = tapdisk_server_initialize();
 	if (err)
 		goto out;
 
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/tapdisk-ipc.c
--- a/tools/blktap2/drivers/tapdisk-ipc.c	Thu Jun 03 07:30:54 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,353 +0,0 @@
-/* 
- * Copyright (c) 2008, XenSource Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of XenSource Inc. nor the names of its contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-
-#include "tapdisk.h"
-#include "tapdisk-ipc.h"
-#include "tapdisk-vbd.h"
-#include "tapdisk-server.h"
-
-static void
-tapdisk_ipc_read_event(event_id_t id, char mode, void *private)
-{
-	td_ipc_t *ipc = private;
-	tapdisk_ipc_read(ipc);
-}
-
-static void
-__tapdisk_ipc_init(td_ipc_t *ipc)
-{
-	ipc->rfd = -1;
-	ipc->wfd = -1;
-	ipc->rfd_event = -1;
-}
-
-int
-tapdisk_ipc_open(td_ipc_t *ipc, const char *read, const char *write)
-{
-	int err;
-
-	memset(ipc, 0, sizeof(td_ipc_t));
-	__tapdisk_ipc_init(ipc);
-
-	if (read) {
-		ipc->rfd = open(read, O_RDWR | O_NONBLOCK);
-		if (ipc->rfd < 0) {
-			err = -errno;
-			EPRINTF("FD open failed %s: %d\n", read, err);
-			goto fail;
-		}
-
-		ipc->rfd_event = 
-			tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
-						      ipc->rfd, 0,
-						      tapdisk_ipc_read_event,
-						      ipc);
-		if (ipc->rfd_event < 0) {
-			err = ipc->rfd_event;
-			goto fail;
-		}
-	}
-
-	if (write) {
-		ipc->wfd = open(write, O_RDWR | O_NONBLOCK);
-		if (ipc->wfd < 0) {
-			err = -errno;
-			EPRINTF("FD open failed %s, %d\n", write, err);
-			goto fail;
-		}
-	}
-
-	return 0;
-
-fail:
-	tapdisk_ipc_close(ipc);
-	return err;
-}
-
-void
-tapdisk_ipc_close(td_ipc_t *ipc)
-{
-	if (ipc->rfd > 0)
-		close(ipc->rfd);
-
-	if (ipc->wfd > 0)
-		close(ipc->wfd);
-
-	if (ipc->rfd_event >= 0)
-		tapdisk_server_unregister_event(ipc->rfd_event);
-
-	__tapdisk_ipc_init(ipc);
-}
-
-static int
-tapdisk_ipc_write_message(int fd, tapdisk_message_t *message, int timeout)
-{
-	fd_set writefds;
-	int ret, len, offset;
-	struct timeval tv, *t;
-
-	t      = NULL;
-	offset = 0;
-	len    = sizeof(tapdisk_message_t);
-
-	if (timeout) {
-		tv.tv_sec  = timeout;
-		tv.tv_usec = 0;
-		t = &tv;
-	}
-
-	DPRINTF("sending '%s' message (uuid = %u)\n",
-		tapdisk_message_name(message->type), message->cookie);
-
-	while (offset < len) {
-		FD_ZERO(&writefds);
-		FD_SET(fd, &writefds);
-
-		/* we don't bother reinitializing tv. at worst, it will wait a
-		 * bit more time than expected. */
-
-		ret = select(fd + 1, NULL, &writefds, NULL, t);
-		if (ret == -1)
-			break;
-		else if (FD_ISSET(fd, &writefds)) {
-			ret = write(fd, message + offset, len - offset);
-			if (ret <= 0)
-				break;
-			offset += ret;
-		} else
-			break;
-	}
-
-	if (offset != len) {
-		EPRINTF("failure writing message\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-int
-tapdisk_ipc_write(td_ipc_t *ipc, int type)
-{
-	tapdisk_message_t message;
-
-	if (ipc->wfd == -1)
-		return 0;
-
-	memset(&message, 0, sizeof(tapdisk_message_t));
-	message.type   = type;
-	message.cookie = ipc->uuid;
-
-	return tapdisk_ipc_write_message(ipc->wfd, &message, 2);
-}
-
-int
-tapdisk_ipc_write_error(td_ipc_t *ipc, const char *text)
-{
-	tapdisk_message_t message;
-
-	memset(&message, 0, sizeof(message));
-	message.type   = TAPDISK_MESSAGE_RUNTIME_ERROR;
-	message.cookie = ipc->uuid;
-	snprintf(message.u.string.text, sizeof(message.u.string.text), "%s", text);
-
-	return tapdisk_ipc_write_message(ipc->wfd, &message, 2);
-}
-
-static int
-tapdisk_ipc_read_message(int fd, tapdisk_message_t *message, int timeout)
-{
-	fd_set readfds;
-	int ret, len, offset;
-	struct timeval tv, *t;
-
-	t      = NULL;
-	offset = 0;
-	len    = sizeof(tapdisk_message_t);
-
-	if (timeout) {
-		tv.tv_sec  = timeout;
-		tv.tv_usec = 0;
-		t = &tv;
-	}
-
-	memset(message, 0, sizeof(tapdisk_message_t));
-
-	while (offset < len) {
-		FD_ZERO(&readfds);
-		FD_SET(fd, &readfds);
-
-		/* we don't bother reinitializing tv. at worst, it will wait a
-		 * bit more time than expected. */
-
-		ret = select(fd + 1, &readfds, NULL, NULL, t);
-		if (ret == -1)
-			break;
-		else if (FD_ISSET(fd, &readfds)) {
-			ret = read(fd, message + offset, len - offset);
-			if (ret <= 0)
-				break;
-			offset += ret;
-		} else
-			break;
-	}
-
-	if (offset != len) {
-		EPRINTF("failure reading message\n");
-		return -EIO;
-	}
-
-	DPRINTF("received '%s' message (uuid = %u)\n",
-		tapdisk_message_name(message->type), message->cookie);
-
-	return 0;
-}
-
-int
-tapdisk_ipc_read(td_ipc_t *ipc)
-{
-	int err;
-	td_vbd_t *vbd;
-	td_uuid_t uuid;
-	tapdisk_message_t message;
-
-	err = tapdisk_ipc_read_message(ipc->rfd, &message, 2);
-	if (err) {
-		tapdisk_server_check_state();
-		return err;
-	}
-
-	uuid = message.cookie;
-	vbd  = tapdisk_server_get_vbd(uuid);
-
-	if (!vbd && message.type != TAPDISK_MESSAGE_PID) {
-		EPRINTF("received message for non-existing vbd: %u\n", uuid);
-		err = -EINVAL;
-		goto fail;
-	}
-
-	switch (message.type) {
-	case TAPDISK_MESSAGE_PID:
-		err = tapdisk_vbd_initialize(ipc->rfd, ipc->wfd, uuid);
-
-		memset(&message, 0, sizeof(tapdisk_message_t));
-		message.cookie = uuid;
-
-		if (!err) {
-			message.type          = TAPDISK_MESSAGE_PID_RSP;
-			message.u.tapdisk_pid = getpid();
-		} else
-			message.type          = TAPDISK_MESSAGE_ERROR;
-
-		return tapdisk_ipc_write_message(ipc->wfd, &message, 0);
-
-	case TAPDISK_MESSAGE_OPEN:
-	{
-		image_t image;
-		char *devname;
-		td_flag_t flags;
-
-		flags = 0;
-
-		if (message.u.params.flags & TAPDISK_MESSAGE_FLAG_RDONLY)
-			flags |= TD_OPEN_RDONLY;
-		if (message.u.params.flags & TAPDISK_MESSAGE_FLAG_SHARED)
-			flags |= TD_OPEN_SHAREABLE;
-		if (message.u.params.flags & TAPDISK_MESSAGE_FLAG_ADD_CACHE)
-			flags |= TD_OPEN_ADD_CACHE;
-		if (message.u.params.flags & TAPDISK_MESSAGE_FLAG_VHD_INDEX)
-			flags |= TD_OPEN_VHD_INDEX;
-		if (message.u.params.flags & TAPDISK_MESSAGE_FLAG_LOG_DIRTY)
-			flags |= TD_OPEN_LOG_DIRTY;
-
-		err   = asprintf(&devname, "%s/%s%d",
-				 BLKTAP_DEV_DIR, BLKTAP_DEV_NAME,
-				 message.u.params.devnum);
-		if (err == -1)
-			goto fail;
-
-		err   = tapdisk_vbd_open(vbd,
-					 message.u.params.path,
-					 message.drivertype,
-					 message.u.params.storage,
-					 devname, flags);
-		free(devname);
-		if (err)
-			goto fail;
-
-		err   = tapdisk_vbd_get_image_info(vbd, &image);
-		if (err)
-			goto fail;
-
-		memset(&message, 0, sizeof(tapdisk_message_t));
-		message.cookie              = uuid;
-		message.u.image.sectors     = image.size;
-		message.u.image.sector_size = image.secsize;
-		message.u.image.info        = image.info;
-		message.type                = TAPDISK_MESSAGE_OPEN_RSP;
-
-		return tapdisk_ipc_write_message(ipc->wfd, &message, 0);
-	}
-
-	case TAPDISK_MESSAGE_PAUSE:
-		tapdisk_vbd_pause(vbd);
-		return 0; /* response written asynchronously */
-
-	case TAPDISK_MESSAGE_RESUME:
-		tapdisk_vbd_resume(vbd,
-				   message.u.params.path,
-				   message.drivertype);
-		return 0; /* response written asynchronously */
-
-	case TAPDISK_MESSAGE_CLOSE:
-		tapdisk_vbd_close(vbd);
-		return 0; /* response written asynchronously */
-
-	case TAPDISK_MESSAGE_EXIT:
-		return 0;
-	}
-
-	err = -EINVAL;
-	EPRINTF("received unrecognized message %s, uuid = %d\n",
-		tapdisk_message_name(message.type), uuid);
-
-fail:
-	memset(&message, 0, sizeof(tapdisk_message_t));
-	message.cookie = uuid;
-	message.type   = TAPDISK_MESSAGE_ERROR;
-	tapdisk_ipc_write_message(ipc->wfd, &message, 2);
-	tapdisk_server_check_state();
-
-	return -err;
-}
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/tapdisk-ipc.h
--- a/tools/blktap2/drivers/tapdisk-ipc.h	Thu Jun 03 07:30:54 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/* 
- * Copyright (c) 2008, XenSource Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of XenSource Inc. nor the names of its contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _TAPDISK_IPC_H_
-#define _TAPDISK_IPC_H_
-
-#include "tapdisk-message.h"
-#include "scheduler.h"
-
-typedef struct td_ipc_handle {
-	int                         rfd;
-	int                         wfd;
-	event_id_t		    rfd_event;
-	td_uuid_t                   uuid;
-} td_ipc_t;
-
-int tapdisk_ipc_open(td_ipc_t *ipc, const char *read, const char *write);
-void tapdisk_ipc_close(td_ipc_t *ipc);
-int tapdisk_ipc_read(td_ipc_t *ipc);
-int tapdisk_ipc_write(td_ipc_t *ipc, int type);
-int tapdisk_ipc_write_error(td_ipc_t *ipc, const char *message);
-
-#endif
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/tapdisk-server.c
--- a/tools/blktap2/drivers/tapdisk-server.c	Thu Jun 03 07:30:54 2010 +0100
+++ b/tools/blktap2/drivers/tapdisk-server.c	Mon Jun 07 14:53:15 2010 -0700
@@ -212,27 +212,6 @@
 		tapdisk_vbd_kill_queue(vbd);
 }
 
-static void
-tapdisk_server_send_error(const char *message)
-{
-	td_vbd_t *vbd, *tmp;
-
-	tapdisk_server_for_each_vbd(vbd, tmp)
-		tapdisk_ipc_write_error(&vbd->ipc, message);
-}
-
-static int
-tapdisk_server_init_ipc(const char *read, const char *write)
-{
-	return tapdisk_ipc_open(&server.ipc, read, write);
-}
-
-static void
-tapdisk_server_close_ipc(void)
-{
-	tapdisk_ipc_close(&server.ipc);
-}
-
 static int
 tapdisk_server_init_aio(void)
 {
@@ -250,7 +229,6 @@
 tapdisk_server_close(void)
 {
 	tapdisk_server_close_aio();
-	tapdisk_server_close_ipc();
 }
 
 static void
@@ -292,7 +270,6 @@
 		if (xfsz_error_sent)
 			break;
 
-		tapdisk_server_send_error("received SIGXFSZ, closing queues");
 		xfsz_error_sent = 1;
 		break;
 
@@ -303,7 +280,7 @@
 }
 
 int
-tapdisk_server_initialize(const char *read, const char *write)
+tapdisk_server_initialize(void)
 {
 	int err;
 
@@ -312,21 +289,13 @@
 
 	scheduler_initialize(&server.scheduler);
 
-	err = tapdisk_server_init_ipc(read, write);
-	if (err)
-		goto fail;
-
 	err = tapdisk_server_init_aio();
 	if (err)
-		goto fail;
+		return err;
 
 	server.run = 1;
 
 	return 0;
-
-fail:
-	tapdisk_server_close_ipc();
-	return err;
 }
 
 int
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/tapdisk-server.h
--- a/tools/blktap2/drivers/tapdisk-server.h	Thu Jun 03 07:30:54 2010 +0100
+++ b/tools/blktap2/drivers/tapdisk-server.h	Mon Jun 07 14:53:15 2010 -0700
@@ -47,14 +47,13 @@
 void tapdisk_server_unregister_event(event_id_t);
 void tapdisk_server_set_max_timeout(int);
 
-int tapdisk_server_initialize(const char *, const char *);
+int tapdisk_server_initialize(void);
 int tapdisk_server_run(void);
 
 #define TAPDISK_TIOCBS              (TAPDISK_DATA_REQUESTS + 50)
 
 typedef struct tapdisk_server {
 	int                          run;
-	td_ipc_t                     ipc;
 	struct list_head             vbds;
 	scheduler_t                  scheduler;
 	struct tqueue                aio_queue;
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/tapdisk-stream.c
--- a/tools/blktap2/drivers/tapdisk-stream.c	Thu Jun 03 07:30:54 2010 +0100
+++ b/tools/blktap2/drivers/tapdisk-stream.c	Mon Jun 07 14:53:15 2010 -0700
@@ -333,11 +333,11 @@
 
 	s->id = tapdisk_stream_count++;
 
-	err = tapdisk_server_initialize(NULL, NULL);
+	err = tapdisk_server_initialize();
 	if (err)
 		goto out;
 
-	err = tapdisk_vbd_initialize(-1, -1, s->id);
+	err = tapdisk_vbd_initialize(s->id);
 	if (err)
 		goto out;
 
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/tapdisk-vbd.c
--- a/tools/blktap2/drivers/tapdisk-vbd.c	Thu Jun 03 07:30:54 2010 +0100
+++ b/tools/blktap2/drivers/tapdisk-vbd.c	Mon Jun 07 14:53:15 2010 -0700
@@ -82,7 +82,7 @@
 }
 
 int
-tapdisk_vbd_initialize(int rfd, int wfd, uint16_t uuid)
+tapdisk_vbd_initialize(uint16_t uuid)
 {
 	int i;
 	td_vbd_t *vbd;
@@ -100,9 +100,6 @@
 	}
 
 	vbd->uuid     = uuid;
-	vbd->ipc.rfd  = rfd;
-	vbd->ipc.wfd  = wfd;
-	vbd->ipc.uuid = uuid;
 	vbd->ring.fd  = -1;
 
 	/* default blktap ring completion */
@@ -995,7 +992,6 @@
 		vbd->kicked);
 
 	tapdisk_vbd_close_vdi(vbd);
-	tapdisk_ipc_write(&vbd->ipc, TAPDISK_MESSAGE_CLOSE_RSP);
 	tapdisk_vbd_unregister_events(vbd);
 	tapdisk_vbd_unmap_device(vbd);
 	tapdisk_server_remove_vbd(vbd);
@@ -1196,7 +1192,6 @@
 
 	td_flag_clear(vbd->state, TD_VBD_PAUSE_REQUESTED);
 	td_flag_set(vbd->state, TD_VBD_PAUSED);
-	tapdisk_ipc_write(&vbd->ipc, TAPDISK_MESSAGE_PAUSE_RSP);
 
 	return 0;
 }
@@ -1208,7 +1203,6 @@
 
 	if (!td_flag_test(vbd->state, TD_VBD_PAUSED)) {
 		EPRINTF("resume request for unpaused vbd %s\n", vbd->name);
-		tapdisk_ipc_write(&vbd->ipc, TAPDISK_MESSAGE_ERROR);
 		return -EINVAL;
 	}
 
@@ -1216,7 +1210,6 @@
 	vbd->name = strdup(path);
 	if (!vbd->name) {
 		EPRINTF("copying new vbd %s name failed\n", path);
-		tapdisk_ipc_write(&vbd->ipc, TAPDISK_MESSAGE_ERROR);
 		return -EINVAL;
 	}
 	vbd->type = drivertype;
@@ -1241,15 +1234,12 @@
 		sleep(TD_VBD_EIO_SLEEP);
 	}
 
-	if (err) {
-		tapdisk_ipc_write(&vbd->ipc, TAPDISK_MESSAGE_ERROR);
+	if (err)
 		return err;
-	}
 
 	tapdisk_vbd_start_queue(vbd);
 	td_flag_clear(vbd->state, TD_VBD_PAUSED);
 	td_flag_clear(vbd->state, TD_VBD_PAUSE_REQUESTED);
-	tapdisk_ipc_write(&vbd->ipc, TAPDISK_MESSAGE_RESUME_RSP);
 
 	return 0;
 }
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/tapdisk-vbd.h
--- a/tools/blktap2/drivers/tapdisk-vbd.h	Thu Jun 03 07:30:54 2010 +0100
+++ b/tools/blktap2/drivers/tapdisk-vbd.h	Mon Jun 07 14:53:15 2010 -0700
@@ -34,7 +34,6 @@
 
 #include "tapdisk.h"
 #include "scheduler.h"
-#include "tapdisk-ipc.h"
 #include "tapdisk-image.h"
 
 #define TD_VBD_MAX_RETRIES          100
@@ -101,8 +100,6 @@
 	td_flag_t                   flags;
 	td_flag_t                   state;
 
-	td_ipc_t                    ipc;
-
 	struct list_head            images;
 
 	struct list_head            new_requests;
@@ -171,7 +168,7 @@
 	return list_entry(image->next.next, td_image_t, next);
 }
 
-int tapdisk_vbd_initialize(int, int, td_uuid_t);
+int tapdisk_vbd_initialize(td_uuid_t);
 void tapdisk_vbd_set_callback(td_vbd_t *, td_vbd_cb_t, void *);
 int tapdisk_vbd_parse_stack(td_vbd_t *vbd, const char *path);
 int tapdisk_vbd_open(td_vbd_t *, const char *, uint16_t,
diff -r 4ab68bf4c37e -r 0156cca51013 tools/blktap2/drivers/tapdisk2.c
--- a/tools/blktap2/drivers/tapdisk2.c	Thu Jun 03 07:30:54 2010 +0100
+++ b/tools/blktap2/drivers/tapdisk2.c	Mon Jun 07 14:53:15 2010 -0700
@@ -249,7 +249,7 @@
 	char *devname;
 	struct blktap2_params params;
 
-	err = tapdisk_vbd_initialize(-1, -1, TAPDISK2_VBD);
+	err = tapdisk_vbd_initialize(TAPDISK2_VBD);
 	if (err)
 		return err;
 
@@ -349,7 +349,7 @@
 	if (err)
 		goto out;
 
-	err = tapdisk_server_initialize(NULL, NULL);
+	err = tapdisk_server_initialize();
 	if (err)
 		goto fail;
 

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* [PATCH 2 of 7] blktap2: Remove LVM hacks
  2010-06-07 21:54 [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
  2010-06-07 21:54 ` [PATCH 1 of 7] blktap2: Remove tapdisk-ipc module Daniel Stodden
@ 2010-06-07 21:54 ` Daniel Stodden
  2010-06-07 21:54 ` [PATCH 3 of 7] blktap2: Fix tapdisk disktype issues Daniel Stodden
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-07 21:54 UTC (permalink / raw)
  To: Xen

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

These only mattered for XCP's LVHD with blktap1.

Signed-off-by: Jake Wires <jake.wires@citrix.com>
Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>



[-- Attachment #2: remove-tapdisk-lvm.diff --]
[-- Type: text/x-patch, Size: 7376 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1275947595 25200
# Node ID eb39271223ce6600cb81cf0dab8167a382d1393a
# Parent  0156cca51013424068a563705b0d5689292b5c36
blktap2: Remove LVM hacks.

These only mattered for XCP's LVHD with blktap1.

Signed-off-by: Jake Wires <jake.wires@citrix.com>
Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>

diff -r 0156cca51013 -r eb39271223ce tools/blktap2/drivers/tapdisk-vbd.c
--- a/tools/blktap2/drivers/tapdisk-vbd.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-vbd.c	Mon Jun 07 14:53:15 2010 -0700
@@ -280,272 +280,6 @@
 	return err;
 }
 
-/*
- * LVHD hack: have to rescan LVM metadata on pool
- * slaves to register lvchanges made on master.  FIXME.
- */
-static int
-tapdisk_vbd_reactivate_volume(const char *name)
-{
-	int err;
-	char *cmd;
-
-	DPRINTF("reactivating %s\n", name);
-
-	err = asprintf(&cmd, "lvchange -an %s", name);
-	if (err == - 1) {
-		EPRINTF("failed to deactivate %s\n", name);
-		return -errno;
-	}
-
-	err = system(cmd);
-	if (err) {
-		/* 
-		 * Assume that LV deactivation failed because the LV is open, 
-		 * in which case the LVM information should be up-to-date and 
-		 * we don't need this step anyways (so ignore the error). If 
-		 * the failure is due to a non-existent LV, the next command 
-		 * (lvchange -ay) will catch it.
-		 * If we want to be more prudent/paranoid, we can instead check 
-		 * whether the LV is currently open (a bit more work).
-		 */
-	}
-
-	free(cmd);
-	err = asprintf(&cmd, "lvchange -ay --refresh %s", name);
-	if (err == - 1) {
-		EPRINTF("failed to activate %s\n", name);
-		return -errno;
-	}
-
-	err = system(cmd);
-	if (err)
-		EPRINTF("%s failed: %d\n", cmd, err);
-	free(cmd);
-	return err;
-}
-
-static int
-tapdisk_vbd_reactivate_volumes(td_vbd_t *vbd, int resume)
-{
-	int i, cnt, err;
-	char *name, *new;
-	vhd_context_t vhd;
-	vhd_parent_locator_t *loc;
-
-	new  = NULL;
-	name = NULL;
-
-	if (vbd->storage != TAPDISK_STORAGE_TYPE_LVM)
-		return 0;
-
-	if (!resume && vbd->reactivated)
-		return 0;
-
-	name = strdup(vbd->name);
-	if (!name) {
-		EPRINTF("%s: nomem\n", vbd->name);
-		return -ENOMEM;
-	}
-
-	for (cnt = 0; 1; cnt++) {
-
-		/* only need to reactivate child and parent during resume */
-		if (resume && cnt == 2)
-			break;
-
-		err = tapdisk_vbd_reactivate_volume(name);
-		if (err)
-			goto fail;
-
-		if (!strstr(name, "VHD"))
-			break;
-
-		for (i = 0; i < TD_VBD_EIO_RETRIES; i++) {
-			err = vhd_open(&vhd, name, VHD_OPEN_RDONLY);
-			if (!err)
-				break;
-
-			libvhd_set_log_level(1);
-			sleep(TD_VBD_EIO_SLEEP);
-		}
-		libvhd_set_log_level(0);
-		if (err)
-			goto fail;
-
-		if (vhd.footer.type != HD_TYPE_DIFF) {
-			vhd_close(&vhd);
-			break;
-		}
-
-		loc = NULL;
-		for (i = 0; i < 8; i++)
-			if (vhd.header.loc[i].code == PLAT_CODE_MACX) {
-				loc = vhd.header.loc + i;
-				break;
-			}
-
-		if (!loc) {
-			vhd_close(&vhd);
-			err = -EINVAL;
-			goto fail;
-		}
-
-		free(name);
-		err = vhd_parent_locator_read(&vhd, loc, &name);
-		vhd_close(&vhd);
-
-		if (err) {
-			name = NULL;
-			goto fail;
-		}
-
-		/*
-		 * vhd_parent_locator_read returns path relative to child:
-		 * ./VG_XenStorage--<sr-uuid>-VHD--<vdi-uuid>
-		 * we have to convert this to absolute path for lvm
-		 */
-		err = asprintf(&new, "/dev/mapper/%s", name + 2);
-		if (err == -1) {
-			err  = -errno;
-			goto fail;
-		}
-
-		free(name);
-		name = new;
-	}
-
-	err = 0;
-	vbd->reactivated = 1;
-
-out:
-	free(name);
-	return err;
-
-fail:
-	EPRINTF("failed to reactivate %s: %d\n", vbd->name, err);
-	goto out;
-}
-
-/*
- * LVHD hack: 
- * raw volumes are named /dev/<sr-vg-name>-<sr-uuid>/LV-<sr-uuid>
- * vhd volumes are named /dev/<sr-vg-name>-<sr-uuid>/VHD-<sr-uuid>
- *
- * a live snapshot of a raw volume will result in the writeable volume's
- * name changing from the raw to vhd format, but this change will not be
- * reflected by xenstore.  hence this mess.
- */
-static int
-tapdisk_vbd_check_file(td_vbd_t *vbd)
-{
-	int i, err;
-	regex_t re;
-	size_t len, max;
-	regmatch_t matches[4];
-	char *new, *src, *dst, error[256];
-
-	if (vbd->storage != TAPDISK_STORAGE_TYPE_LVM)
-		return 0;
-
-	err = tapdisk_vbd_reactivate_volume(vbd->name);
-	if (!err)
-		return 0;
-	else
-		DPRINTF("reactivating %s failed\n", vbd->name);
-
-#define HEX   "[A-Za-z0-9]"
-#define UUID  HEX"\\{8\\}-"HEX"\\{4\\}-"HEX"\\{4\\}-"HEX"\\{4\\}-"HEX"\\{12\\}"
-#define VG    "VG_"HEX"\\+"
-#define TYPE  "\\(LV\\|VHD\\)"
-#define RE    "\\(/dev/"VG"-"UUID"/\\)"TYPE"\\(-"UUID"\\)"
-
-	err = regcomp(&re, RE, 0);
-	if (err)
-		goto regerr;
-
-#undef HEX
-#undef UUID
-#undef VG
-#undef TYPE
-#undef RE
-
-	err = regexec(&re, vbd->name, 4, matches, 0);
-	if (err)
-		goto regerr;
-
-	max = strlen("VHD") + 1;
-	for (i = 1; i < 4; i++) {
-		if (matches[i].rm_so == -1 || matches[i].rm_eo == -1) {
-			EPRINTF("%s: failed to tokenize name\n", vbd->name);
-			err = -EINVAL;
-			goto out;
-		}
-
-		max += matches[i].rm_eo - matches[i].rm_so;
-	}
-
-	new = malloc(max);
-	if (!new) {
-		EPRINTF("%s: failed to allocate new name\n", vbd->name);
-		err = -ENOMEM;
-		goto out;
-	}
-
-	src = new;
-	for (i = 1; i < 4; i++) {
-		dst = vbd->name + matches[i].rm_so;
-		len = matches[i].rm_eo - matches[i].rm_so;
-
-		if (i == 2) {
-			if (memcmp(dst, "LV", len)) {
-				EPRINTF("%s: bad name format\n", vbd->name);
-				free(new);
-				err = -EINVAL;
-				goto out;
-			}
-
-			src += sprintf(src, "VHD");
-			continue;
-		}
-
-		memcpy(src, dst, len + 1);
-		src += len;
-	}
-
-	*src = '\0';
-
-	err = tapdisk_vbd_reactivate_volume(new);
-	if (err)
-		DPRINTF("reactivating %s failed\n", new);
-
-	err = access(new, F_OK);
-	if (err == -1) {
-		EPRINTF("neither %s nor %s accessible\n",
-			vbd->name, new);
-		err = -errno;
-		free(new);
-		goto out;
-	}
-
-	DPRINTF("couldn't find %s, trying %s\n", vbd->name, new);
-
-	err = 0;
-	free(vbd->name);
-	vbd->name = new;
-	vbd->type = DISK_TYPE_VHD;
-
-out:
-	regfree(&re);
-	return err;
-
-regerr:
-	regerror(err, &re, error, sizeof(error));
-	EPRINTF("%s: regex failed: %s\n", vbd->name, error);
-	err = -EINVAL;
-	goto out;
-}
-
 /* TODO: ugh, lets not call it parent info... */
 static struct list_head *
 tapdisk_vbd_open_level(td_vbd_t *vbd, char* params, int driver_type, td_disk_info_t *parent_info, td_flag_t flags)
@@ -658,10 +392,6 @@
 	struct list_head *images;
 	td_disk_info_t *parent_info = NULL;
 
-	err = tapdisk_vbd_reactivate_volumes(vbd, 0);
-	if (err)
-		return err;
-
 	flags = (vbd->flags & ~TD_OPEN_SHAREABLE) | extra_flags;
 
 	/* loop on each user specified driver.
@@ -1215,22 +945,10 @@
 	vbd->type = drivertype;
 
 	for (i = 0; i < TD_VBD_EIO_RETRIES; i++) {
-		err = tapdisk_vbd_check_file(vbd);
-		if (err)
-			goto sleep;
-
-		err = tapdisk_vbd_reactivate_volumes(vbd, 1);
-		if (err) {
-			EPRINTF("failed to reactivate %s: %d\n",
-				vbd->name, err);
-			goto sleep;
-		}
-
 		err = __tapdisk_vbd_open_vdi(vbd, TD_OPEN_STRICT);
 		if (!err)
 			break;
 
-	sleep:
 		sleep(TD_VBD_EIO_SLEEP);
 	}
 
@@ -1887,12 +1605,6 @@
 
 	tapdisk_vbd_start_queue(vbd);
 
-	err = tapdisk_vbd_reactivate_volumes(vbd, 1);
-	if (err) {
-		EPRINTF("failed to reactivate %s, %d\n", vbd->name, err);
-		goto out;
-	}
-
 	for (i = 0; i < TD_VBD_EIO_RETRIES; i++) {
 		err = __tapdisk_vbd_open_vdi(vbd, TD_OPEN_STRICT);
 		if (err != -EIO)

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* [PATCH 3 of 7] blktap2: Fix tapdisk disktype issues
  2010-06-07 21:54 [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
  2010-06-07 21:54 ` [PATCH 1 of 7] blktap2: Remove tapdisk-ipc module Daniel Stodden
  2010-06-07 21:54 ` [PATCH 2 of 7] blktap2: Remove LVM hacks Daniel Stodden
@ 2010-06-07 21:54 ` Daniel Stodden
  2010-06-07 21:54 ` [PATCH 4 of 7] blktap2: Fix E/DPRINTF defs all around the driver/ subdir Daniel Stodden
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-07 21:54 UTC (permalink / raw)
  To: Xen

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

Stop coercing drivers/disktype code into the tool stack. Make both
blktapctrl and tap-ctl transfer type/path pairs as "<type>:<path>"
strings. Remove the message.disktype integer altogether.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
Signed-off-by: Jake Wires <jake.wires@citrix.com>



[-- Attachment #2: disktypes.diff --]
[-- Type: text/x-patch, Size: 27672 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1275947595 25200
# Node ID 5f2119204138ad484ad7ffe0a8eff5c0d70d3f52
# Parent  eb39271223ce6600cb81cf0dab8167a382d1393a
blktap2: Fix tapdisk disktype issues.

Stop coercing drivers/disktype code into the tool stack. Make both
blktapctrl and tap-ctl transfer type/path pairs as "<type>:<path>"
strings. Remove the message.disktype integer altogether.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
Signed-off-by: Jake Wires <jake.wires@citrix.com>

diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/Makefile
--- a/tools/blktap2/drivers/Makefile	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/Makefile	Mon Jun 07 14:53:15 2010 -0700
@@ -77,6 +77,7 @@
 TAP-OBJS-y  += tapdisk-vbd.o
 TAP-OBJS-y  += tapdisk-image.o
 TAP-OBJS-y  += tapdisk-driver.o
+TAP-OBJS-y  += tapdisk-disktype.o
 TAP-OBJS-y  += tapdisk-interface.o
 TAP-OBJS-y  += tapdisk-server.o
 TAP-OBJS-y  += tapdisk-queue.o
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/block-qcow.c
--- a/tools/blktap2/drivers/block-qcow.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/block-qcow.c	Mon Jun 07 14:53:15 2010 -0700
@@ -41,6 +41,7 @@
 #include "tapdisk.h"
 #include "tapdisk-driver.h"
 #include "tapdisk-interface.h"
+#include "tapdisk-disktype.h"
 #include "qcow.h"
 #include "blk.h"
 #include "atomicio.h"
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/block-remus.c
--- a/tools/blktap2/drivers/block-remus.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/block-remus.c	Mon Jun 07 14:53:15 2010 -0700
@@ -98,6 +98,7 @@
  */
 td_vbd_t *device_vbd = NULL;
 td_image_t *remus_image = NULL;
+struct tap_disk tapdisk_remus;
 
 struct ramdisk {
 	size_t sector_size;
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/block-vhd.c
--- a/tools/blktap2/drivers/block-vhd.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/block-vhd.c	Mon Jun 07 14:53:15 2010 -0700
@@ -58,6 +58,7 @@
 #include "tapdisk.h"
 #include "tapdisk-driver.h"
 #include "tapdisk-interface.h"
+#include "tapdisk-disktype.h"
 
 unsigned int SPB;
 
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/disktypes.h
--- a/tools/blktap2/drivers/disktypes.h	Mon Jun 07 14:53:15 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/* 
- * Copyright (c) 2007, XenSource Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of XenSource Inc. nor the names of its contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __DISKTYPES_H__
-#define __DISKTYPES_H__
-
-typedef struct disk_info {
-       int  idnum;
-       char name[50];       /* e.g. "RAMDISK" */
-       char handle[10];     /* xend handle, e.g. 'ram' */
-       int  single_handler; /* is there a single controller for all */
-                            /* instances of disk type? */
-#ifdef TAPDISK
-       struct tap_disk *drv;
-#endif
-} disk_info_t;
-
-extern struct tap_disk tapdisk_aio;
-/* extern struct tap_disk tapdisk_sync;    */
-/* extern struct tap_disk tapdisk_vmdk;    */
-/* extern struct tap_disk tapdisk_vhdsync; */
-extern struct tap_disk tapdisk_vhd;
-extern struct tap_disk tapdisk_ram;
- extern struct tap_disk tapdisk_qcow; 
-extern struct tap_disk tapdisk_block_cache;
-extern struct tap_disk tapdisk_log;
-extern struct tap_disk tapdisk_remus;
-
-#define MAX_DISK_TYPES        20
-
-#define DISK_TYPE_AIO         0
-#define DISK_TYPE_SYNC        1
-#define DISK_TYPE_VMDK        2
-#define DISK_TYPE_VHDSYNC     3
-#define DISK_TYPE_VHD         4
-#define DISK_TYPE_RAM         5
-#define DISK_TYPE_QCOW        6
-#define DISK_TYPE_BLOCK_CACHE 7
-#define DISK_TYPE_LOG         9
-#define DISK_TYPE_REMUS       10
-
-/*Define Individual Disk Parameters here */
-static disk_info_t null_disk = {
-       -1,
-       "null disk",
-       "null",
-       0,
-#ifdef TAPDISK
-       0,
-#endif
-};
-
-static disk_info_t aio_disk = {
-       DISK_TYPE_AIO,
-       "raw image (aio)",
-       "aio",
-       0,
-#ifdef TAPDISK
-       &tapdisk_aio,
-#endif
-};
-/*
-static disk_info_t sync_disk = {
-       DISK_TYPE_SYNC,
-       "raw image (sync)",
-       "sync",
-       0,
-#ifdef TAPDISK
-       &tapdisk_sync,
-#endif
-};
-
-static disk_info_t vmdk_disk = {
-       DISK_TYPE_VMDK,
-       "vmware image (vmdk)",
-       "vmdk",
-       1,
-#ifdef TAPDISK
-       &tapdisk_vmdk,
-#endif
-};
-
-static disk_info_t vhdsync_disk = {
-       DISK_TYPE_VHDSYNC,
-       "virtual server image (vhd) - synchronous",
-       "vhdsync",
-       1,
-#ifdef TAPDISK
-       &tapdisk_vhdsync,
-#endif
-};
-*/
-
-static disk_info_t vhd_disk = {
-       DISK_TYPE_VHD,
-       "virtual server image (vhd)",
-       "vhd",
-       0,
-#ifdef TAPDISK
-       &tapdisk_vhd,
-#endif
-};
-
-
-static disk_info_t ram_disk = {
-       DISK_TYPE_RAM,
-       "ramdisk image (ram)",
-       "ram",
-       1,
-#ifdef TAPDISK
-       &tapdisk_ram,
-#endif
-};
-
-
-static disk_info_t qcow_disk = {
-       DISK_TYPE_QCOW,
-       "qcow disk (qcow)",
-       "qcow",
-       0,
-#ifdef TAPDISK
-       &tapdisk_qcow,
-#endif
-};
-
-
-static disk_info_t block_cache_disk = {
-       DISK_TYPE_BLOCK_CACHE,
-       "block cache image (bc)",
-       "bc",
-       1,
-#ifdef TAPDISK
-       &tapdisk_block_cache,
-#endif
-};
-
-static disk_info_t log_disk = {
-	DISK_TYPE_LOG,
-	"write logger (log)",
-	"log",
-	0,
-#ifdef TAPDISK
-	&tapdisk_log,
-#endif
-};
-
-static disk_info_t remus_disk = {
-       DISK_TYPE_REMUS,
-       "remus disk replicator (remus)",
-       "remus",
-       0,
-#ifdef TAPDISK
-       &tapdisk_remus,
-#endif
-};
-
-/*Main disk info array */
-static disk_info_t *dtypes[] = {
-       &aio_disk,
-       &null_disk, /* &sync_disk, */
-       &null_disk, /* &vmdk_disk, */
-        &null_disk, /* &vhdsync_disk, */
-       &vhd_disk,
-       &ram_disk,
-       &qcow_disk,
-       &block_cache_disk,
-       &null_disk,
-       &log_disk,
-       &remus_disk,
-};
-
-#endif
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/img2qcow.c
--- a/tools/blktap2/drivers/img2qcow.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/img2qcow.c	Mon Jun 07 14:53:15 2010 -0700
@@ -49,6 +49,7 @@
 #include "tapdisk-server.h"
 #include "tapdisk-driver.h"
 #include "tapdisk-interface.h"
+#include "tapdisk-disktype.h"
 #include "qcow.h"
 #include "blk.h"
 
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/qcow2raw.c
--- a/tools/blktap2/drivers/qcow2raw.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/qcow2raw.c	Mon Jun 07 14:53:15 2010 -0700
@@ -47,6 +47,7 @@
 #include "tapdisk-server.h"
 #include "tapdisk-driver.h"
 #include "tapdisk-interface.h"
+#include "tapdisk-disktype.h"
 #include "qcow.h"
 
 #if 1
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-diff.c
--- a/tools/blktap2/drivers/tapdisk-diff.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-diff.c	Mon Jun 07 14:53:15 2010 -0700
@@ -38,6 +38,7 @@
 #include "scheduler.h"
 #include "tapdisk-vbd.h"
 #include "tapdisk-server.h"
+#include "tapdisk-disktype.h"
 #include "libvhd.h"
 
 #define POLL_READ                        0
@@ -670,11 +671,11 @@
 tapdisk_stream_open(struct tapdisk_stream *s, const char *arg)
 {
 	int err, type;
-	char *path;
+	const char *path;
 
-	err = tapdisk_parse_disk_type(arg, &path, &type);
-	if (err)
-		return err;
+	type = tapdisk_disktype_parse_params(arg, &path);
+	if (type < 0)
+		return type;
 
 	tapdisk_stream_initialize(s);
 
@@ -716,7 +717,8 @@
 {
 	int c, err, type1;
 	const char *arg1 = NULL, *arg2 = NULL;
-	char *path1;
+	const disk_info_t *info;
+	const char *path1;
 
 	err    = 0;
 
@@ -741,9 +743,10 @@
 	if (!arg1 || !arg2)
 		goto fail_usage;
 
-	err = tapdisk_parse_disk_type(arg1, &path1, &type1);
-	if (err)
-		return err;
+	type1 = tapdisk_disktype_parse_params(arg1, &path1);
+	if (type1 < 0)
+		return type1;
+
 	if (type1 != DISK_TYPE_VHD) {
 		printf("error: first VDI is not VHD\n");
 		return EINVAL;
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-disktype.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/drivers/tapdisk-disktype.c	Mon Jun 07 14:53:15 2010 -0700
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2007, 2010, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+
+#include "tapdisk-disktype.h"
+#include "tapdisk-message.h"
+
+static const disk_info_t aio_disk = {
+       "aio",
+       "raw image (aio)",
+       0,
+};
+
+static const disk_info_t sync_disk = {
+       "sync",
+       "raw image (sync)",
+       0,
+};
+
+static const disk_info_t vmdk_disk = {
+       "vmdk",
+       "vmware image (vmdk)",
+       1,
+};
+
+static const disk_info_t vhdsync_disk = {
+       "vhdsync",
+       "virtual server image (vhd) - synchronous",
+       1,
+};
+
+static const disk_info_t vhd_disk = {
+       "vhd",
+       "virtual server image (vhd)",
+       0,
+};
+
+
+static const disk_info_t ram_disk = {
+       "ram",
+       "ramdisk image (ram)",
+       1,
+};
+
+static const disk_info_t qcow_disk = {
+       "qcow",
+       "qcow disk (qcow)",
+       0,
+};
+
+static const disk_info_t block_cache_disk = {
+       "bc",
+       "block cache image (bc)",
+       1,
+};
+
+static const disk_info_t vhd_index_disk = {
+       "vhdi",
+       "vhd index image (vhdi)",
+       1,
+};
+
+static const disk_info_t log_disk = {
+	"log",
+	"write logger (log)",
+	0,
+};
+
+static disk_info_t remus_disk = {
+       "remus disk replicator (remus)",
+       "remus",
+       0,
+};
+
+const disk_info_t *tapdisk_disk_types[] = {
+	[DISK_TYPE_AIO]	= &aio_disk,
+	[DISK_TYPE_SYNC]	= &sync_disk,
+	[DISK_TYPE_VMDK]	= &vmdk_disk,
+	[DISK_TYPE_VHDSYNC]	= &vhdsync_disk,
+	[DISK_TYPE_VHD]	= &vhd_disk,
+	[DISK_TYPE_RAM]	= &ram_disk,
+	[DISK_TYPE_QCOW]	= &qcow_disk,
+	[DISK_TYPE_BLOCK_CACHE] = &block_cache_disk,
+	[DISK_TYPE_LOG]	= &log_disk,
+	[DISK_TYPE_VINDEX]	= &vhd_index_disk,
+	[DISK_TYPE_REMUS]	= &remus_disk,
+	0,
+};
+
+extern struct tap_disk tapdisk_aio;
+extern struct tap_disk tapdisk_sync;
+extern struct tap_disk tapdisk_vmdk;
+extern struct tap_disk tapdisk_vhdsync;
+extern struct tap_disk tapdisk_vhd;
+extern struct tap_disk tapdisk_ram;
+extern struct tap_disk tapdisk_qcow;
+extern struct tap_disk tapdisk_block_cache;
+extern struct tap_disk tapdisk_vhd_index;
+extern struct tap_disk tapdisk_log;
+extern struct tap_disk tapdisk_remus;
+
+const struct tap_disk *tapdisk_disk_drivers[] = {
+	[DISK_TYPE_AIO]         = &tapdisk_aio,
+#if 0
+	[DISK_TYPE_SYNC]        = &tapdisk_sync,
+	[DISK_TYPE_VMDK]        = &tapdisk_vmdk,
+#endif
+	[DISK_TYPE_VHD]         = &tapdisk_vhd,
+	[DISK_TYPE_RAM]         = &tapdisk_ram,
+	[DISK_TYPE_QCOW]        = &tapdisk_qcow,
+	[DISK_TYPE_BLOCK_CACHE] = &tapdisk_block_cache,
+	[DISK_TYPE_VINDEX]      = &tapdisk_vhd_index,
+	[DISK_TYPE_LOG]         = &tapdisk_log,
+	[DISK_TYPE_REMUS]       = &tapdisk_remus,
+	0,
+};
+
+int
+tapdisk_disktype_find(const char *name)
+{
+	const disk_info_t *info;
+	int i;
+
+	for (i = 0; info = tapdisk_disk_types[i], info != NULL; ++i) {
+		if (strcmp(name, info->name))
+			continue;
+
+		if (!tapdisk_disk_drivers[i])
+			return -ENOSYS;
+
+		return i;
+	}
+
+	return -ENOENT;
+}
+
+int
+tapdisk_disktype_parse_params(const char *params, const char **_path)
+{
+	char name[DISK_TYPE_NAME_MAX], *ptr;
+	size_t len;
+	int type;
+
+	ptr = strchr(params, ':');
+	if (!ptr)
+		return -EINVAL;
+
+	len = ptr - params;
+
+	if (len > sizeof(name) - 1)
+		return -ENAMETOOLONG;
+
+	memset(name, 0, sizeof(name));
+	strncpy(name, params, len);
+
+	type = tapdisk_disktype_find(name);
+
+	if (type >= 0)
+		*_path = params + len + 1;
+
+	return type;
+}
+
+int
+tapdisk_parse_disk_type(const char *params, const char **_path, int *_type)
+{
+	int type;
+
+	type = tapdisk_disktype_parse_params(params, _path);
+	if (type < 0)
+		return type;
+
+	*_type = type;
+
+	return 0;
+}
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-disktype.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/drivers/tapdisk-disktype.h	Mon Jun 07 14:53:15 2010 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007, 2010, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DISKTYPES_H__
+#define __DISKTYPES_H__
+
+#define DISK_TYPE_AIO         0
+#define DISK_TYPE_SYNC        1
+#define DISK_TYPE_VMDK        2
+#define DISK_TYPE_VHDSYNC     3
+#define DISK_TYPE_VHD         4
+#define DISK_TYPE_RAM         5
+#define DISK_TYPE_QCOW        6
+#define DISK_TYPE_BLOCK_CACHE 7
+#define DISK_TYPE_LOG         9
+#define DISK_TYPE_REMUS       10
+#define DISK_TYPE_VINDEX      11
+
+#define DISK_TYPE_NAME_MAX    32
+
+typedef struct disk_info {
+	const char     *name; /* driver name, e.g. 'aio' */
+	char           *desc;  /* e.g. "raw image" */
+	unsigned int    flags; 
+} disk_info_t;
+
+extern const disk_info_t     *tapdisk_disk_types[];
+extern const struct tap_disk *tapdisk_disk_drivers[];
+
+/* one single controller for all instances of disk type */
+#define DISK_TYPE_SINGLE_CONTROLLER (1<<0)
+
+int tapdisk_disktype_find(const char *name);
+int tapdisk_disktype_parse_params(const char *params, const char **_path);
+int tapdisk_parse_disk_type(const char *, const char **, int *);
+
+#endif
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-driver.c
--- a/tools/blktap2/drivers/tapdisk-driver.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-driver.c	Mon Jun 07 14:53:15 2010 -0700
@@ -29,15 +29,16 @@
 
 #include "tapdisk-driver.h"
 #include "tapdisk-server.h"
+#include "tapdisk-disktype.h"
 
 td_driver_t *
 tapdisk_driver_allocate(int type, char *name, td_flag_t flags, int storage)
 {
 	int err;
 	td_driver_t *driver;
-	struct tap_disk *ops;
+	const struct tap_disk *ops;
 
-	ops = tapdisk_server_find_driver_interface(type);
+	ops = tapdisk_disk_drivers[type];
 	if (!ops)
 		return NULL;
 
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-driver.h
--- a/tools/blktap2/drivers/tapdisk-driver.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-driver.h	Mon Jun 07 14:53:15 2010 -0700
@@ -47,7 +47,7 @@
 	td_disk_info_t               info;
 
 	void                        *data;
-	struct tap_disk             *ops;
+	const struct tap_disk       *ops;
 
 	struct list_head             next;
 };
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-image.c
--- a/tools/blktap2/drivers/tapdisk-image.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-image.c	Mon Jun 07 14:53:15 2010 -0700
@@ -39,7 +39,7 @@
 #define ERR(_err, _f, _a...) tlog_error(_err, _f, ##_a)
 
 td_image_t *
-tapdisk_image_allocate(char *file, int type, int storage,
+tapdisk_image_allocate(const char *file, int type, int storage,
 		       td_flag_t flags, void *private)
 {
 	int err;
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-image.h
--- a/tools/blktap2/drivers/tapdisk-image.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-image.h	Mon Jun 07 14:53:15 2010 -0700
@@ -47,7 +47,7 @@
 	struct list_head             next;
 };
 
-td_image_t *tapdisk_image_allocate(char *, int, int, td_flag_t, void *);
+td_image_t *tapdisk_image_allocate(const char *, int, int, td_flag_t, void *);
 void tapdisk_image_free(td_image_t *);
 
 int tapdisk_image_check_td_request(td_image_t *, td_request_t);
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-server.c
--- a/tools/blktap2/drivers/tapdisk-server.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-server.c	Mon Jun 07 14:53:15 2010 -0700
@@ -32,7 +32,6 @@
 #include <sys/ioctl.h>
 #include <sys/signal.h>
 
-#define TAPDISK
 #include "tapdisk-utils.h"
 #include "tapdisk-server.h"
 #include "tapdisk-driver.h"
@@ -46,18 +45,6 @@
 #define tapdisk_server_for_each_vbd(vbd, tmp)			        \
 	list_for_each_entry_safe(vbd, tmp, &server.vbds, next)
 
-struct tap_disk *
-tapdisk_server_find_driver_interface(int type)
-{
-	int n;
-
-	n = sizeof(dtypes) / sizeof(struct disk_info_t *);
-	if (type >= n)
-		return NULL;
-
-	return dtypes[type]->drv;
-}
-
 td_image_t *
 tapdisk_server_get_shared_image(td_image_t *image)
 {
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-stream.c
--- a/tools/blktap2/drivers/tapdisk-stream.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-stream.c	Mon Jun 07 14:53:15 2010 -0700
@@ -37,6 +37,7 @@
 #include "scheduler.h"
 #include "tapdisk-vbd.h"
 #include "tapdisk-server.h"
+#include "tapdisk-disktype.h"
 
 #define POLL_READ                        0
 #define POLL_WRITE                       1
@@ -545,7 +546,9 @@
 main(int argc, char *argv[])
 {
 	int c, err, type;
-	char *params, *path;
+	const char *params;
+	const disk_info_t *info;
+	const char *path;
 	uint64_t count, skip;
 	struct tapdisk_stream stream;
 
@@ -575,8 +578,9 @@
 	if (!params)
 		usage(argv[0], EINVAL);
 
-	err = tapdisk_parse_disk_type(params, &path, &type);
-	if (err) {
+	type = tapdisk_disktype_parse_params(params, &path);
+	if (type < 0) {
+		err = type;
 		fprintf(stderr, "invalid argument %s: %d\n", params, err);
 		return err;
 	}
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-utils.c
--- a/tools/blktap2/drivers/tapdisk-utils.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-utils.c	Mon Jun 07 14:53:15 2010 -0700
@@ -40,7 +40,6 @@
 
 #include "blk.h"
 #include "tapdisk.h"
-#include "disktypes.h"
 #include "blktaplib.h"
 #include "tapdisk-log.h"
 #include "tapdisk-utils.h"
@@ -108,45 +107,6 @@
 	return 0;
 }
 
-int
-tapdisk_parse_disk_type(const char *params, char **_path, int *_type)
-{
-        int i, err, size, handle_len;
-	char *ptr, *path, handle[10];
-
-	if (strlen(params) + 1 >= MAX_NAME_LEN)
-		return -ENAMETOOLONG;
-
-	ptr = strchr(params, ':');
-	if (!ptr)
-		return -EINVAL;
-
-	path = ptr + 1;
-
-        handle_len = ptr - params;
-        if (handle_len > sizeof(handle))
-          return -ENAMETOOLONG;
-        
-        memcpy(handle, params, handle_len);
-        handle[handle_len] = '\0';
-               
-	size = sizeof(dtypes) / sizeof(disk_info_t *);
-	for (i = 0; i < size; i++) {
-          if (strncmp(handle, dtypes[i]->handle, handle_len))
-			continue;
-
-		if (dtypes[i]->idnum == -1)
-			return -ENODEV;
-
-		*_type = dtypes[i]->idnum;
-		*_path = path;
-
-		return 0;
-	}
-
-	return -ENODEV;
-}
-
 /*Get Image size, secsize*/
 int
 tapdisk_get_image_size(int fd, uint64_t *_sectors, uint32_t *_sector_size)
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-utils.h
--- a/tools/blktap2/drivers/tapdisk-utils.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-utils.h	Mon Jun 07 14:53:15 2010 -0700
@@ -36,7 +36,6 @@
 void tapdisk_stop_logging(void);
 int tapdisk_set_resource_limits(void);
 int tapdisk_namedup(char **, const char *);
-int tapdisk_parse_disk_type(const char *, char **, int *);
 int tapdisk_get_image_size(int, uint64_t *, uint32_t *);
 int tapdisk_linux_version(void);
 
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-vbd.c
--- a/tools/blktap2/drivers/tapdisk-vbd.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-vbd.c	Mon Jun 07 14:53:15 2010 -0700
@@ -43,6 +43,7 @@
 #include "tapdisk-driver.h"
 #include "tapdisk-server.h"
 #include "tapdisk-interface.h"
+#include "tapdisk-disktype.h"
 #include "tapdisk-vbd.h"
 #include "blktap2.h"
 
@@ -282,9 +283,9 @@
 
 /* TODO: ugh, lets not call it parent info... */
 static struct list_head *
-tapdisk_vbd_open_level(td_vbd_t *vbd, char* params, int driver_type, td_disk_info_t *parent_info, td_flag_t flags)
+tapdisk_vbd_open_level(td_vbd_t *vbd, const char* params, int driver_type, td_disk_info_t *parent_info, td_flag_t flags)
 {
-	char *name;
+	const char *name;
 	int type, err;
 	td_image_t *image;
 	td_disk_id_t id;
@@ -294,19 +295,16 @@
 	images = calloc(1, sizeof(struct list_head));
 	INIT_LIST_HEAD(images);
 
-	name   = params;
-	type   = driver_type;
+	name    = params;
+	id.name = NULL;
+	type    = driver_type;
 
 	for (;;) {
 		err   = -ENOMEM;
 		image = tapdisk_image_allocate(name, type,
 					       vbd->storage, flags, vbd);
 
-		/* free 'name' if it was created by td_get_parent_id() */
-		if (name != params) {
-			free(name);
-			name = NULL;
-		}
+		free(id.name);
 
 		if (!image)
 			return NULL;
@@ -382,7 +380,7 @@
 static int
 __tapdisk_vbd_open_vdi(td_vbd_t *vbd, td_flag_t extra_flags)
 {
-	char *file;
+	const char *file;
 	int err, type;
 	td_flag_t flags;
 	td_disk_id_t id;
@@ -524,9 +522,9 @@
 		     uint16_t drivertype, uint16_t storage, td_flag_t flags)
 {
 	int i, err;
-	struct tap_disk *ops;
+	const struct tap_disk *ops;
 
-	ops = tapdisk_server_find_driver_interface(drivertype);
+	ops = tapdisk_disk_drivers[drivertype];
 	if (!ops)
 		return -EINVAL;
 	DPRINTF("Loaded %s driver for vbd %u %s 0x%08x\n",
@@ -1573,7 +1571,8 @@
 tapdisk_vbd_resume_ring(td_vbd_t *vbd)
 {
 	int i, err, type;
-	char *path, message[BLKTAP2_MAX_MESSAGE_LEN];
+	char message[BLKTAP2_MAX_MESSAGE_LEN];
+	const char *path;
 
 	memset(message, 0, sizeof(message));
 
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk-vbd.h
--- a/tools/blktap2/drivers/tapdisk-vbd.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-vbd.h	Mon Jun 07 14:53:15 2010 -0700
@@ -80,7 +80,7 @@
 };
 
 struct td_vbd_driver_info {
-	char                       *params;
+	const char                 *params;
 	int                         type;
 	struct list_head            next;
 };
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk.h
--- a/tools/blktap2/drivers/tapdisk.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk.h	Mon Jun 07 14:53:15 2010 -0700
@@ -61,7 +61,6 @@
 
 #include "list.h"
 #include "blktaplib.h"
-#include "disktypes.h"
 #include "tapdisk-log.h"
 #include "tapdisk-utils.h"
 
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/drivers/tapdisk2.c
--- a/tools/blktap2/drivers/tapdisk2.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk2.c	Mon Jun 07 14:53:15 2010 -0700
@@ -43,6 +43,7 @@
 #include "tapdisk-vbd.h"
 #include "tapdisk-utils.h"
 #include "tapdisk-server.h"
+#include "tapdisk-disktype.h"
 
 #define TAPDISK2_VBD 0
 
@@ -327,7 +328,7 @@
 static int
 tapdisk2_create_device(const char *params)
 {
-	char *path;
+	const char *path;
 	int err, type;
 
 	chdir("/");
diff -r eb39271223ce -r 5f2119204138 tools/blktap2/include/tapdisk-message.h
--- a/tools/blktap2/include/tapdisk-message.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/include/tapdisk-message.h	Mon Jun 07 14:53:15 2010 -0700
@@ -28,6 +28,7 @@
 #define _TAPDISK_MESSAGE_H_
 
 #include <inttypes.h>
+#include <sys/types.h>
 
 #define TAPDISK_MESSAGE_MAX_PATH_LENGTH  256
 #define TAPDISK_MESSAGE_STRING_LENGTH    256
@@ -67,7 +68,6 @@
 struct tapdisk_message {
 	uint16_t                         type;
 	uint16_t                         cookie;
-	uint16_t                         drivertype;
 
 	union {
 		pid_t                    tapdisk_pid;

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* [PATCH 4 of 7] blktap2: Fix E/DPRINTF defs all around the driver/ subdir
  2010-06-07 21:54 [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
                   ` (2 preceding siblings ...)
  2010-06-07 21:54 ` [PATCH 3 of 7] blktap2: Fix tapdisk disktype issues Daniel Stodden
@ 2010-06-07 21:54 ` Daniel Stodden
  2010-06-07 21:54 ` [PATCH 5 of 7] blktap2: Cleanup vdi stacking code Daniel Stodden
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-07 21:54 UTC (permalink / raw)
  To: Xen

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

This is just to avoid macro madness among subdirs sharing blktaplib.h.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
Signed-off-by: Jake Wires <jake.wires@citrix.com>



[-- Attachment #2: dprintf.diff --]
[-- Type: text/x-patch, Size: 2926 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1275947595 25200
# Node ID d8393489b4c4d93944203f62578f8cf2721ce961
# Parent  5f2119204138ad484ad7ffe0a8eff5c0d70d3f52
blktap2: Fix E/DPRINTF defs all around the driver/ subdir.

This is just to avoid macro madness among subdirs sharing blktaplib.h.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
Signed-off-by: Jake Wires <jake.wires@citrix.com>

diff -r 5f2119204138 -r d8393489b4c4 tools/blktap2/drivers/block-remus.c
--- a/tools/blktap2/drivers/block-remus.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/block-remus.c	Mon Jun 07 14:53:15 2010 -0700
@@ -33,7 +33,6 @@
 
 /* due to architectural choices in tapdisk, block-buffer is forced to
  * reimplement some code which is meant to be private */
-#define TAPDISK
 #include "tapdisk.h"
 #include "tapdisk-server.h"
 #include "tapdisk-driver.h"
diff -r 5f2119204138 -r d8393489b4c4 tools/blktap2/drivers/img2qcow.c
--- a/tools/blktap2/drivers/img2qcow.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/img2qcow.c	Mon Jun 07 14:53:15 2010 -0700
@@ -65,8 +65,6 @@
 #define O_LARGEFILE	0
 #endif
 
-
-#define TAPDISK 1
 #define BLOCK_PROCESSSZ 4096
 #define QCOW_VBD 0
 #define PROGRESS_QUANT 2
diff -r 5f2119204138 -r d8393489b4c4 tools/blktap2/drivers/qcow2raw.c
--- a/tools/blktap2/drivers/qcow2raw.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/qcow2raw.c	Mon Jun 07 14:53:15 2010 -0700
@@ -62,7 +62,6 @@
 #define O_LARGEFILE 0
 #endif
 
-#define TAPDISK 1
 #define BLOCK_PROCESSSZ 4096
 #define QCOW_VBD 0
 #define AIO_VBD 1
diff -r 5f2119204138 -r d8393489b4c4 tools/blktap2/drivers/tapdisk.h
--- a/tools/blktap2/drivers/tapdisk.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk.h	Mon Jun 07 14:53:15 2010 -0700
@@ -64,6 +64,10 @@
 #include "tapdisk-log.h"
 #include "tapdisk-utils.h"
 
+#define DPRINTF(_f, _a...)           syslog(LOG_INFO, _f, ##_a)
+#define EPRINTF(_f, _a...)           syslog(LOG_ERR, "tap-err:%s: " _f, __func__, ##_a)
+#define PERROR(_f, _a...)            EPRINTF(_f ": %s", ##_a, strerror(errno))
+
 #define MAX_SEGMENTS_PER_REQ         11
 #define SECTOR_SHIFT                 9
 #define DEFAULT_SECTOR_SIZE          512
diff -r 5f2119204138 -r d8393489b4c4 tools/blktap2/include/blktaplib.h
--- a/tools/blktap2/include/blktaplib.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/include/blktaplib.h	Mon Jun 07 14:53:15 2010 -0700
@@ -36,15 +36,6 @@
 #include <xenctrl.h>
 #include <xen/io/blkif.h>
 
-#if 1
-#define DPRINTF(_f, _a...) syslog(LOG_INFO, _f, ##_a)
-#else
-#define DPRINTF(_f, _a...) ((void)0)
-#endif
-
-#define EPRINTF(_f, _a...) syslog(LOG_ERR, "tap-err:%s: " _f, __func__, ##_a)
-#define PERROR(_f, _a...)  EPRINTF(_f ": %s", ##_a, strerror(errno))
-
 #define BLK_RING_SIZE __CONST_RING_SIZE(blkif, XC_PAGE_SIZE)
 
 /* size of the extra VMA area to map in attached pages. */

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* [PATCH 5 of 7] blktap2: Cleanup vdi stacking code
  2010-06-07 21:54 [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
                   ` (3 preceding siblings ...)
  2010-06-07 21:54 ` [PATCH 4 of 7] blktap2: Fix E/DPRINTF defs all around the driver/ subdir Daniel Stodden
@ 2010-06-07 21:54 ` Daniel Stodden
  2010-06-07 21:54 ` [PATCH 6 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-07 21:54 UTC (permalink / raw)
  To: Xen

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

Removes some rough edges, memory leakage (?), fixes __list_splice, ...

Signed-off-by: Jake Wires <jake.wires@citrix.com>
Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>



[-- Attachment #2: stack-cleanup.diff --]
[-- Type: text/x-patch, Size: 11108 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1275947595 25200
# Node ID 3ea1751e3fe79c53acec392ee060b34491925235
# Parent  d8393489b4c4d93944203f62578f8cf2721ce961
blktap2: Cleanup vdi stacking code.

Removes some rough edges, memory leakage (?), fixes __list_splice, ...

Signed-off-by: Jake Wires <jake.wires@citrix.com>
Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>

diff -r d8393489b4c4 -r 3ea1751e3fe7 tools/blktap2/drivers/tapdisk-interface.c
--- a/tools/blktap2/drivers/tapdisk-interface.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-interface.c	Mon Jun 07 14:53:15 2010 -0700
@@ -59,7 +59,7 @@
 }
 
 int
-td_open(td_image_t *image)
+__td_open(td_image_t *image, td_disk_info_t *info)
 {
 	int err;
 	td_driver_t *driver;
@@ -72,6 +72,9 @@
 						 image->storage);
 		if (!driver)
 			return -ENOMEM;
+
+		if (info) /* pre-seed driver->info for virtual drivers */
+			driver->info = *info;
 	}
 
 	if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
@@ -95,6 +98,12 @@
 }
 
 int
+td_open(td_image_t *image)
+{
+	return __td_open(image, NULL);
+}
+
+int
 td_close(td_image_t *image)
 {
 	td_driver_t *driver;
diff -r d8393489b4c4 -r 3ea1751e3fe7 tools/blktap2/drivers/tapdisk-interface.h
--- a/tools/blktap2/drivers/tapdisk-interface.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-interface.h	Mon Jun 07 14:53:15 2010 -0700
@@ -32,6 +32,7 @@
 #include "tapdisk-queue.h"
 
 int td_open(td_image_t *);
+int __td_open(td_image_t *, td_disk_info_t *);
 int td_load(td_image_t *);
 int td_close(td_image_t *);
 int td_get_parent_id(td_image_t *, td_disk_id_t *);
diff -r d8393489b4c4 -r 3ea1751e3fe7 tools/blktap2/drivers/tapdisk-vbd.c
--- a/tools/blktap2/drivers/tapdisk-vbd.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-vbd.c	Mon Jun 07 14:53:15 2010 -0700
@@ -82,6 +82,17 @@
 	INIT_LIST_HEAD(&vreq->next);
 }
 
+void
+tapdisk_vbd_free(td_vbd_t *vbd)
+{
+	if (vbd) {
+		tapdisk_vbd_free_stack(vbd);
+		list_del_init(&vbd->next);
+		free(vbd->name);
+		free(vbd);
+	}
+}
+
 int
 tapdisk_vbd_initialize(uint16_t uuid)
 {
@@ -281,23 +292,21 @@
 	return err;
 }
 
-/* TODO: ugh, lets not call it parent info... */
-static struct list_head *
-tapdisk_vbd_open_level(td_vbd_t *vbd, const char* params, int driver_type, td_disk_info_t *parent_info, td_flag_t flags)
+static int
+tapdisk_vbd_open_level(td_vbd_t *vbd, struct list_head *head,
+		       const char *params, int driver_type,
+		       td_disk_info_t *driver_info, td_flag_t flags)
 {
 	const char *name;
 	int type, err;
 	td_image_t *image;
 	td_disk_id_t id;
-	struct  list_head *images;
 	td_driver_t *driver;
 
-	images = calloc(1, sizeof(struct list_head));
-	INIT_LIST_HEAD(images);
-
 	name    = params;
 	id.name = NULL;
 	type    = driver_type;
+	INIT_LIST_HEAD(head);
 
 	for (;;) {
 		err   = -ENOMEM;
@@ -307,42 +316,13 @@
 		free(id.name);
 
 		if (!image)
-			return NULL;
+			goto out;
 
 
-		/* We have to do this to set the driver info for child drivers.  this conflicts with td_open */
-		driver = image->driver;
-		if (!driver) {
-			driver = tapdisk_driver_allocate(image->type,
-							 image->name,
-							 image->flags,
-							 image->storage);
-			if (!driver)
-				return NULL;
-		}
-		/* the image has a driver, set the info and driver */
-		image->driver = driver;
-		image->info = driver->info;
-
-		/* XXX: we don't touch driver->refcount, broken? */
-		/* XXX: we've replicated about 90% of td_open() gross! */
-		/* XXX: this breaks if a driver modifies its info within a layer */
-
-		/* if the parent info is set, pass it to the child */
-		if(parent_info)
-		{
-			image->driver->info = *parent_info;
-		}
-
-		err = td_load(image);
-		if (err) {
-			if (err != -ENODEV)
-				return NULL;
-
-			err = td_open(image);
-			if (err)
-				return NULL;
-		}
+		/* this breaks if a driver modifies its info within a layer */
+		err = __td_open(image, driver_info);
+		if (err)
+			goto out;
 
 		/* TODO: non-sink drivers that don't care about their child
 		 * currently return EINVAL. Could return TD_PARENT_OK or
@@ -351,60 +331,73 @@
 		err = td_get_parent_id(image, &id);
 		if (err && (err != TD_NO_PARENT && err != -EINVAL)) {
 			td_close(image);
-			return NULL;
+			goto out;
 		}
 
-		if (!image->storage)
-			image->storage = vbd->storage;
-
 		/* add this image to the end of the list */
-		list_add_tail(&image->next, images);
-
+		list_add_tail(&image->next, head);
 		image = NULL;
 
 		/* if the image does not have a parent we return the
 		 * list of images generated by this level of the stack */
-		if (err == TD_NO_PARENT || err == -EINVAL)
-			break;
+		if (err == TD_NO_PARENT || err == -EINVAL) {
+			err = 0;
+			goto out;
+		}
 
 		name   = id.name;
 		type   = id.drivertype;
-#if 0
-		/* catch this by validate, not here */
+
 		flags |= (TD_OPEN_RDONLY | TD_OPEN_SHAREABLE);
-#endif
 	}
-	return images;
+
+out:
+	if (err) {
+		if (image) {
+			td_close(image);
+			tapdisk_image_free(image);
+		}
+		while (!list_empty(head)) {
+			image = list_entry(&head->next, td_image_t, next);
+			td_close(image);
+			tapdisk_image_free(image);
+		}
+	}
+
+	return err;
 }
 
 static int
 __tapdisk_vbd_open_vdi(td_vbd_t *vbd, td_flag_t extra_flags)
 {
-	const char *file;
-	int err, type;
+	int err;
 	td_flag_t flags;
-	td_disk_id_t id;
 	td_image_t *tmp;
-	struct tfilter *filter = NULL;
 	td_vbd_driver_info_t *driver_info;
 	struct list_head *images;
 	td_disk_info_t *parent_info = NULL;
 
+	if (list_empty(&vbd->driver_stack))
+		return -ENOENT;
+
 	flags = (vbd->flags & ~TD_OPEN_SHAREABLE) | extra_flags;
 
 	/* loop on each user specified driver.
 	 * NOTE: driver_info is in reverse order. That is, the first
 	 * item is the 'parent' or 'sink' driver */
 	list_for_each_entry(driver_info, &vbd->driver_stack, next) {
-		file = driver_info->params;
-		type = driver_info->type;
-		images = tapdisk_vbd_open_level(vbd, file, type, parent_info, flags);
-		if (!images)
-			return -EINVAL;
+		LIST_HEAD(images);
 
-		/* after each loop, append the created stack to the result stack */
-		list_splice(images, &vbd->images);
-		free(images);
+		err = tapdisk_vbd_open_level(vbd, &images,
+					     driver_info->params,
+					     driver_info->type,
+					     parent_info, flags);
+		if (err)
+			goto fail;
+
+		/* after each loop, 
+		 * append the created stack to the result stack */
+		list_splice(&images, &vbd->images);
 
 		/* set the parent_info to the first diskinfo on the stack */
 		tmp = tapdisk_vbd_first_image(vbd);
@@ -421,7 +414,7 @@
 		err = tapdisk_vbd_add_block_cache(vbd);
 		if (err)
 			goto fail;
-	}		
+	}
 
 	err = tapdisk_vbd_validate_chain(vbd);
 	if (err)
@@ -432,16 +425,7 @@
 	return 0;
 
 fail:
-
-/* TODO: loop over vbd to free images? maybe do that in vbd_close_vdi */
-#if 0
-	if (image)
-		tapdisk_image_free(image);
-#endif
-
-	/* TODO: handle partial stack creation? */
 	tapdisk_vbd_close_vdi(vbd);
-
 	return err;
 }
 
@@ -453,47 +437,71 @@
 	char *params, *driver_str;
 	td_vbd_driver_info_t *driver;
 
-	/* make a copy of path */
-	/* TODO: check against MAX_NAME_LEM ? */
 	err = tapdisk_namedup(&params, path);
-	if(err)
-		goto error;
-
+	if (err)
+		return err;
 
 	/* tokenize params based on pipe '|' */
 	driver_str = strtok(params, "|");
-	while(driver_str != NULL)
-	{
+	while (driver_str != NULL) {
+		const char *path;
+		int type;
+
 		/* parse driver info and add to vbd */
 		driver = calloc(1, sizeof(td_vbd_driver_info_t));
+		if (!driver) {
+			PERROR("malloc");
+			err = -errno;
+			goto out;
+		}
 		INIT_LIST_HEAD(&driver->next);
-		err = tapdisk_parse_disk_type(driver_str, &driver->params, &driver->type);
-		if(err)
-			goto error;
 
-		/* build the list backwards as the last driver will be the first
-		 * driver to open in the stack */
+		err = tapdisk_parse_disk_type(driver_str, &path, &type);
+		if (err) {
+			free(driver);
+			goto out;
+		}
+
+		driver->type   = type;
+		driver->params = strdup(path);
+		if (!driver->params) {
+			err = -ENOMEM;
+			free(driver);
+			goto out;
+		}
+
+		/* build the list backwards as the last driver will be the
+		 * first driver to open in the stack */
 		list_add(&driver->next, &vbd->driver_stack);
 
 		/* get next driver string */
 		driver_str = strtok(NULL, "|");
 	}
 
-	return 0;
-
-	/* error: free any driver_info's and params */
- error:
-	while(!list_empty(&vbd->driver_stack)) {
-		driver = list_entry(vbd->driver_stack.next, td_vbd_driver_info_t, next);
-		list_del(&driver->next);
-		free(driver);
-	}
+out:
+	free(params);
+	if (err)
+		tapdisk_vbd_free_stack(vbd);
 
 	return err;
 }
 
+void
+tapdisk_vbd_free_stack(td_vbd_t *vbd)
+{
+	td_vbd_driver_info_t *driver;
+
+	while (!list_empty(&vbd->driver_stack)) {
+		driver = list_entry(vbd->driver_stack.next,
+				    td_vbd_driver_info_t, next);
+		list_del(&driver->next);
+		free(driver->params);
+		free(driver);
+	}
+}
+
 /* NOTE: driver type, etc. must be set */
-static int
+int
 tapdisk_vbd_open_stack(td_vbd_t *vbd, uint16_t storage, td_flag_t flags)
 {
 	int i, err;
@@ -536,7 +544,6 @@
 
 	vbd->flags   = flags;
 	vbd->storage = storage;
-	vbd->type    = drivertype;
 
 	for (i = 0; i < TD_VBD_EIO_RETRIES; i++) {
 		err = __tapdisk_vbd_open_vdi(vbd, 0);
diff -r d8393489b4c4 -r 3ea1751e3fe7 tools/blktap2/drivers/tapdisk-vbd.h
--- a/tools/blktap2/drivers/tapdisk-vbd.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-vbd.h	Mon Jun 07 14:53:15 2010 -0700
@@ -80,7 +80,7 @@
 };
 
 struct td_vbd_driver_info {
-	const char                 *params;
+	char                       *params;
 	int                         type;
 	struct list_head            next;
 };
@@ -174,6 +174,7 @@
 int tapdisk_vbd_open(td_vbd_t *, const char *, uint16_t,
 		     uint16_t, const char *, td_flag_t);
 int tapdisk_vbd_close(td_vbd_t *);
+void tapdisk_vbd_free_stack(td_vbd_t *);
 
 int tapdisk_vbd_open_vdi(td_vbd_t *, const char *,
 			 uint16_t, uint16_t, td_flag_t);
diff -r d8393489b4c4 -r 3ea1751e3fe7 tools/blktap2/include/list.h
--- a/tools/blktap2/include/list.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/include/list.h	Mon Jun 07 14:53:15 2010 -0700
@@ -87,24 +87,25 @@
 	return list->next == head;
 }
 
-static inline void __list_splice(struct list_head *list,
-				 struct list_head *head)
+static inline void __list_splice(const struct list_head *list,
+				 struct list_head *prev,
+				 struct list_head *next)
 {
 	struct list_head *first = list->next;
 	struct list_head *last = list->prev;
-	struct list_head *at = head->next;
 
-	first->prev = head;
-	head->next = first;
+	first->prev = prev;
+	prev->next = first;
 
-	last->next = at;
-	at->prev = last;
+	last->next = next;
+	next->prev = last;
 }
 
-static inline void list_splice(struct list_head *list, struct list_head *head)
+static inline void list_splice(const struct list_head *list,
+			       struct list_head *head)
 {
 	if (!list_empty(list))
-		__list_splice(list, head);
+		__list_splice(list, head, head->next);
 }
 
 #define list_entry(ptr, type, member)                                   \

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* [PATCH 6 of 7] blktap2: The tap-ctl userspace control utility and library
  2010-06-07 21:54 [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
                   ` (4 preceding siblings ...)
  2010-06-07 21:54 ` [PATCH 5 of 7] blktap2: Cleanup vdi stacking code Daniel Stodden
@ 2010-06-07 21:54 ` Daniel Stodden
  2010-06-07 21:54 ` [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface Daniel Stodden
  2010-08-03 19:14 ` [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Łukasz Oleś
  7 siblings, 0 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-07 21:54 UTC (permalink / raw)
  To: Xen

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

Tapdisk control in userspace, a replacement for the original blktap2
control stack, which had to pass a kernel space interface based on
sysfs nodes.

All tapdisk processes listen for commands on a unix stream socket. The
control library supports scanning the socket namespace for running
tapdisks, VBD minors allocated, associated images and state inquiry.

Control operations include allocating/releasing devices, spawning
tapdisks, opening/closing images, attaching disk images to
devices. disk pause/resume operations and runtime switching of disk
images.

Signed-off-by: Jake Wires <jake.wires@citrix.com>
Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>



[-- Attachment #2: tap-ctl.diff --]
[-- Type: text/x-patch, Size: 126743 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1275947596 25200
# Node ID ccef87cf5f4125061e46c7eb0d1483e6f369fb77
# Parent  3ea1751e3fe79c53acec392ee060b34491925235
blktap2: The tap-ctl userspace control utility and library.

Tapdisk control in userspace, a replacement for the original blktap2
control stack, which had to pass a kernel space interface based on
sysfs nodes.

All tapdisk processes listen for commands on a unix stream socket. The
control library supports scanning the socket namespace for running
tapdisks, VBD minors allocated, associated images and state inquiry.

Control operations include allocating/releasing devices, spawning
tapdisks, opening/closing images, attaching disk images to
devices. disk pause/resume operations and runtime switching of disk
images.

Signed-off-by: Jake Wires <jake.wires@citrix.com>
Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>

diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/Makefile
--- a/tools/blktap2/Makefile	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/Makefile	Mon Jun 07 14:53:16 2010 -0700
@@ -9,6 +9,7 @@
 SUBDIRS-y += lvm
 SUBDIRS-y += vhd
 SUBDIRS-y += drivers
+SUBDIRS-y += control
 
 clean:
 	rm -rf *.a *.so *.o *.rpm $(LIB) *~ $(DEPS) TAGS
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/Makefile	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,57 @@
+XEN_ROOT := ../../../
+include $(XEN_ROOT)/tools/Rules.mk
+
+IBIN               = tap-ctl
+INST_DIR           = /usr/sbin
+
+CFLAGS            += -Werror
+CFLAGS            += -Wno-unused
+CFLAGS            += -I../include -I../drivers
+CFLAGS            += -I$(XEN_INCLUDE) -I$(XEN_LIBXC)
+CFLAGS            += -D_GNU_SOURCE
+CFLAGS            += -DTAPCTL
+
+# Get gcc to generate the dependencies for us.
+CFLAGS            += -Wp,-MD,.$(@F).d
+DEPS               = .*.d
+
+CTL_OBJS  := tap-ctl-ipc.o
+CTL_OBJS  += tap-ctl-list.o
+CTL_OBJS  += tap-ctl-allocate.o
+CTL_OBJS  += tap-ctl-free.o
+CTL_OBJS  += tap-ctl-create.o
+CTL_OBJS  += tap-ctl-destroy.o
+CTL_OBJS  += tap-ctl-spawn.o
+CTL_OBJS  += tap-ctl-attach.o
+CTL_OBJS  += tap-ctl-detach.o
+CTL_OBJS  += tap-ctl-open.o
+CTL_OBJS  += tap-ctl-close.o
+CTL_OBJS  += tap-ctl-pause.o
+CTL_OBJS  += tap-ctl-unpause.o
+CTL_OBJS  += tap-ctl-major.o
+CTL_OBJS  += tap-ctl-check.o
+
+OBJS = $(CTL_OBJS)
+LIBS = libblktapctl.a
+
+all: build
+
+build: $(IBIN)
+
+tap-ctl: tap-ctl.o libblktapctl.a
+	$(CC) $(CFLAGS) -o $@ $^
+
+libblktapctl.a: $(CTL_OBJS)
+	ar r $@ $^
+
+install: all
+	$(INSTALL_DIR) -p $(DESTDIR)$(INST_DIR)
+	$(INSTALL_PROG) $(IBIN) $(DESTDIR)$(INST_DIR)
+
+clean:
+	rm -f $(OBJS) $(DEPS) $(IBIN) $(LIBS)
+	rm -f *~
+
+.PHONY: all build clean install
+
+-include $(DEPS)
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-allocate.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-allocate.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <linux/major.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+static int
+tap_ctl_prepare_directory(const char *dir)
+{
+	int err;
+	char *ptr, *name, *start;
+
+	err = access(dir, W_OK | R_OK);
+	if (!err)
+		return 0;
+
+	name = strdup(dir);
+	if (!name)
+		return ENOMEM;
+
+	start = name;
+
+	for (;;) {
+		ptr = strchr(start + 1, '/');
+		if (ptr)
+			*ptr = '\0';
+
+		err = mkdir(name, 0755);
+		if (err && errno != EEXIST) {
+			PERROR("mkdir %s", name);
+			err = errno;
+			break;
+		}
+
+		if (!ptr)
+			break;
+		else {
+			*ptr = '/';
+			start = ptr + 1;
+		}
+	}
+
+	free(name);
+	return err;
+}
+
+static int
+tap_ctl_make_device(const char *devname, const int major,
+		    const int minor, const int perm)
+{
+	int err;
+	char *copy, *dir;
+
+	copy = strdup(devname);
+	if (!copy)
+		return ENOMEM;
+
+	dir = dirname(copy);
+
+	err = tap_ctl_prepare_directory(dir);
+	free(copy);
+
+	if (err)
+		return err;
+
+	if (!access(devname, F_OK))
+		if (unlink(devname)) {
+			PERROR("unlink %s", devname);
+			return errno;
+		}
+
+	err = mknod(devname, perm, makedev(major, minor));
+	if (err) {
+		PERROR("mknod %s", devname);
+		return errno;
+	}
+
+	return 0;
+}
+
+static int
+tap_ctl_check_environment(void)
+{
+	FILE *f;
+	int err, minor;
+	char name[256];
+
+	err = tap_ctl_prepare_directory(BLKTAP2_CONTROL_DIR);
+	if (err)
+		return err;
+
+	if (!access(BLKTAP2_CONTROL_DEVICE, R_OK | W_OK))
+		return 0;
+
+	memset(name, 0, sizeof(name));
+
+	f = fopen("/proc/misc", "r");
+	if (!f) {
+		EPRINTF("failed to open /proc/misc: %d\n", errno);
+		return errno;
+	}
+
+	while (fscanf(f, "%d %256s", &minor, name) == 2)
+		if (!strcmp(name, BLKTAP2_CONTROL_NAME)) {
+			err = tap_ctl_make_device(BLKTAP2_CONTROL_DEVICE,
+						  MISC_MAJOR,
+						  minor, S_IFCHR | 0600);
+			goto out;
+		}
+
+	err = ENOSYS;
+	EPRINTF("didn't find %s in /proc/misc\n", BLKTAP2_CONTROL_NAME);
+
+out:
+	fclose(f);
+	return err;
+}
+
+static int
+tap_ctl_allocate_device(int *minor, char **devname)
+{
+	char *name;
+	int fd, err;
+	struct blktap2_handle handle;
+
+	*minor = -1;
+	if (!devname)
+		return EINVAL;
+
+	fd = open(BLKTAP2_CONTROL_DEVICE, O_RDONLY);
+	if (fd == -1) {
+		EPRINTF("failed to open control device: %d\n", errno);
+		return errno;
+	}
+
+	err = ioctl(fd, BLKTAP2_IOCTL_ALLOC_TAP, &handle);
+	close(fd);
+	if (err == -1) {
+		EPRINTF("failed to allocate new device: %d\n", errno);
+		return errno;
+	}
+
+	err = asprintf(&name, "%s%d", BLKTAP2_RING_DEVICE, handle.minor);
+	if (err == -1) {
+		err = ENOMEM;
+		goto fail;
+	}
+
+	err = tap_ctl_make_device(name, handle.ring,
+				  handle.minor, S_IFCHR | 0600);
+	free(name);
+	if (err) {
+		EPRINTF("creating ring device for %d failed: %d\n",
+			handle.minor, err);
+		goto fail;
+	}
+
+	if (*devname)
+		name = *devname;
+	else {
+		err = asprintf(&name, "%s%d",
+			       BLKTAP2_IO_DEVICE, handle.minor);
+		if (err == -1) {
+			err = ENOMEM;
+			goto fail;
+		}
+		*devname = name;
+	}
+
+	err = tap_ctl_make_device(name, handle.device,
+				  handle.minor, S_IFBLK | 0600);
+	if (err) {
+		EPRINTF("creating IO device for %d failed: %d\n",
+			handle.minor, err);
+		goto fail;
+	}
+
+	DBG("new interface: ring: %u, device: %u, minor: %u\n",
+	    handle.ring, handle.device, handle.minor);
+
+	*minor = handle.minor;
+	return 0;
+
+fail:
+	tap_ctl_free(handle.minor);
+	return err;
+}
+
+int
+tap_ctl_allocate(int *minor, char **devname)
+{
+	int err;
+
+	*minor = -1;
+
+	err = tap_ctl_check_environment();
+	if (err)
+		return err;
+
+	err = tap_ctl_allocate_device(minor, devname);
+	if (err)
+		return err;
+
+	return 0;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-attach.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-attach.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+
+int
+tap_ctl_attach(const int id, const int minor)
+{
+	int err;
+	tapdisk_message_t message;
+
+	memset(&message, 0, sizeof(message));
+	message.type = TAPDISK_MESSAGE_ATTACH;
+	message.cookie = minor;
+
+	err = tap_ctl_connect_send_and_receive(id, &message, 5);
+	if (err)
+		return err;
+
+	if (message.type == TAPDISK_MESSAGE_ATTACH_RSP) {
+		err = message.u.response.error;
+		if (err)
+			EPRINTF("attach failed: %d\n", err);
+	} else {
+		EPRINTF("got unexpected result '%s' from %d\n",
+			tapdisk_message_name(message.type), id);
+		err = EINVAL;
+	}
+
+	return err;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-check.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-check.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int
+tap_ctl_check_blktap(const char **msg)
+{
+	FILE *f;
+	int err = 0, minor;
+	char name[32];
+
+	memset(name, 0, sizeof(name));
+
+	f = fopen("/proc/misc", "r");
+	if (!f) {
+		*msg = "failed to open /proc/misc";
+		return -errno;
+	}
+
+	while (fscanf(f, "%d %32s", &minor, name) == 2) {
+		if (!strcmp(name, BLKTAP2_CONTROL_NAME))
+			goto out;
+	}
+
+	err = -ENOSYS;
+	*msg = "blktap kernel module not installed";
+
+out:
+	fclose(f);
+	return err;
+}
+
+int
+tap_ctl_check(const char **msg)
+{
+	int err;
+	uid_t uid;
+
+	err = tap_ctl_check_blktap(msg);
+	if (err)
+		goto out;
+
+	err  = 0;
+	*msg = "ok";
+
+out:
+	return err;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-close.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-close.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+
+static int
+__tap_ctl_close(const int id, const int minor, const int force)
+{
+	int err;
+	tapdisk_message_t message;
+
+	memset(&message, 0, sizeof(message));
+	message.type = TAPDISK_MESSAGE_CLOSE;
+	if (force)
+		message.type = TAPDISK_MESSAGE_FORCE_SHUTDOWN;
+	message.cookie = minor;
+
+	err = tap_ctl_connect_send_and_receive(id, &message, 5);
+	if (err)
+		return err;
+
+	if (message.type == TAPDISK_MESSAGE_CLOSE_RSP) {
+		err = message.u.response.error;
+		if (err)
+			EPRINTF("close failed: %d\n", err);
+	} else {
+		EPRINTF("got unexpected result '%s' from %d\n",
+			tapdisk_message_name(message.type), id);
+		err = EINVAL;
+	}
+
+	return err;
+}
+
+int
+tap_ctl_close(const int id, const int minor, const int force)
+{
+	int i, err;
+
+	for (i = 0; i < 20; i++) {
+		err = __tap_ctl_close(id, minor, force);
+		if (!err)
+			return 0;
+
+		err = (err < 0 ? -err : err);
+		if (err != EAGAIN) {
+			EPRINTF("close failed: %d\n", err);
+			return err;
+		}
+
+		usleep(1000);
+	}
+
+	EPRINTF("close timed out\n");
+	return EIO;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-create.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-create.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int
+tap_ctl_create(const char *params, char **devname)
+{
+	int err, id, minor;
+
+	err = tap_ctl_allocate(&minor, devname);
+	if (err)
+		return err;
+
+	id = tap_ctl_spawn();
+	if (id < 0)
+		goto destroy;
+
+	err = tap_ctl_attach(id, minor);
+	if (err)
+		goto destroy;
+
+	err = tap_ctl_open(id, minor, params);
+	if (err)
+		goto detach;
+
+	return 0;
+
+detach:
+	tap_ctl_detach(id, minor);
+destroy:
+	tap_ctl_free(minor);
+	return err;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-destroy.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-destroy.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int
+tap_ctl_destroy(const int id, const int minor)
+{
+	int err;
+
+	err = tap_ctl_close(id, minor, 0);
+	if (err)
+		return err;
+
+	err = tap_ctl_detach(id, minor);
+	if (err)
+		return err;
+
+	err = tap_ctl_free(minor);
+	if (err)
+		return err;
+
+	return 0;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-detach.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-detach.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+
+int
+tap_ctl_detach(const int id, const int minor)
+{
+	int err;
+	tapdisk_message_t message;
+
+	memset(&message, 0, sizeof(message));
+	message.type = TAPDISK_MESSAGE_DETACH;
+	message.cookie = minor;
+
+	err = tap_ctl_connect_send_and_receive(id, &message, 5);
+	if (err)
+		return err;
+
+	if (message.type == TAPDISK_MESSAGE_DETACH_RSP) {
+		err = message.u.response.error;
+		if (err < 0)
+			printf("detach failed: %d\n", err);
+	} else {
+		printf("got unexpected result '%s' from %d\n",
+		       tapdisk_message_name(message.type), id);
+		err = EINVAL;
+	}
+
+	return err;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-free.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-free.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int
+tap_ctl_free(const int minor)
+{
+	int fd, err;
+
+	fd = open(BLKTAP2_CONTROL_DEVICE, O_RDONLY);
+	if (fd == -1) {
+		EPRINTF("failed to open control device: %d\n", errno);
+		return errno;
+	}
+
+	err = ioctl(fd, BLKTAP2_IOCTL_FREE_TAP, minor);
+	close(fd);
+
+	return err;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-ipc.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-ipc.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int tap_ctl_debug = 0;
+
+int
+tap_ctl_read_message(int fd, tapdisk_message_t *message, int timeout)
+{
+	fd_set readfds;
+	int ret, len, offset;
+	struct timeval tv, *t;
+
+	t      = NULL;
+	offset = 0;
+	len    = sizeof(tapdisk_message_t);
+
+	if (timeout) {
+		tv.tv_sec  = timeout;
+		tv.tv_usec = 0;
+		t = &tv;
+	}
+
+	memset(message, 0, sizeof(tapdisk_message_t));
+
+	while (offset < len) {
+		FD_ZERO(&readfds);
+		FD_SET(fd, &readfds);
+
+		ret = select(fd + 1, &readfds, NULL, NULL, t);
+		if (ret == -1)
+			break;
+		else if (FD_ISSET(fd, &readfds)) {
+			ret = read(fd, message + offset, len - offset);
+			if (ret <= 0)
+				break;
+			offset += ret;
+		} else
+			break;
+	}
+
+	if (offset != len) {
+		EPRINTF("failure reading message\n");
+		return -EIO;
+	}
+
+	DBG("received '%s' message (uuid = %u)\n",
+	    tapdisk_message_name(message->type), message->cookie);
+
+	return 0;
+}
+
+int
+tap_ctl_write_message(int fd, tapdisk_message_t *message, int timeout)
+{
+	fd_set writefds;
+	int ret, len, offset;
+	struct timeval tv, *t;
+
+	t      = NULL;
+	offset = 0;
+	len    = sizeof(tapdisk_message_t);
+
+	if (timeout) {
+		tv.tv_sec  = timeout;
+		tv.tv_usec = 0;
+		t = &tv;
+	}
+
+	DBG("sending '%s' message (uuid = %u)\n",
+	    tapdisk_message_name(message->type), message->cookie);
+
+	while (offset < len) {
+		FD_ZERO(&writefds);
+		FD_SET(fd, &writefds);
+
+		/* we don't bother reinitializing tv. at worst, it will wait a
+		 * bit more time than expected. */
+
+		ret = select(fd + 1, NULL, &writefds, NULL, t);
+		if (ret == -1)
+			break;
+		else if (FD_ISSET(fd, &writefds)) {
+			ret = write(fd, message + offset, len - offset);
+			if (ret <= 0)
+				break;
+			offset += ret;
+		} else
+			break;
+	}
+
+	if (offset != len) {
+		EPRINTF("failure writing message\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
+tap_ctl_send_and_receive(int sfd, tapdisk_message_t *message, int timeout)
+{
+	int err;
+
+	err = tap_ctl_write_message(sfd, message, timeout);
+	if (err) {
+		EPRINTF("failed to send '%s' message\n",
+			tapdisk_message_name(message->type));
+		return err;
+	}
+
+	err = tap_ctl_read_message(sfd, message, timeout);
+	if (err) {
+		EPRINTF("failed to receive '%s' message\n",
+			tapdisk_message_name(message->type));
+		return err;
+	}
+
+	return 0;
+}
+
+char *
+tap_ctl_socket_name(int id)
+{
+	char *name;
+
+	if (asprintf(&name, "%s/%s%d",
+		     BLKTAP2_CONTROL_DIR, BLKTAP2_CONTROL_SOCKET, id) == -1)
+		return NULL;
+
+	return name;
+}
+
+int
+tap_ctl_connect(const char *name, int *sfd)
+{
+	int fd, err;
+	struct sockaddr_un saddr;
+
+	*sfd = -1;
+
+	fd = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (fd == -1) {
+		EPRINTF("couldn't create socket for %s: %d\n", name, errno);
+		return -errno;
+	}
+
+	memset(&saddr, 0, sizeof(saddr));
+	saddr.sun_family = AF_UNIX;
+	strcpy(saddr.sun_path, name);
+
+	err = connect(fd, (const struct sockaddr *)&saddr, sizeof(saddr));
+	if (err) {
+		EPRINTF("couldn't connect to %s: %d\n", name, errno);
+		close(fd);
+		return -errno;
+	}
+
+	*sfd = fd;
+	return 0;
+}
+
+int
+tap_ctl_connect_id(int id, int *sfd)
+{
+	int err;
+	char *name;
+
+	*sfd = -1;
+
+	if (id < 0) {
+		EPRINTF("invalid id %d\n", id);
+		return -EINVAL;
+	}
+
+	name = tap_ctl_socket_name(id);
+	if (!name) {
+		EPRINTF("couldn't name socket for %d\n", id);
+		return -ENOMEM;
+	}
+
+	err = tap_ctl_connect(name, sfd);
+	free(name);
+
+	return err;
+}
+
+int
+tap_ctl_connect_send_and_receive(int id, tapdisk_message_t *message, int timeout)
+{
+	int err, sfd;
+
+	err = tap_ctl_connect_id(id, &sfd);
+	if (err)
+		return err;
+
+	err = tap_ctl_send_and_receive(sfd, message, timeout);
+
+	close(sfd);
+	return err;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-list.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-list.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <glob.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+#include "list.h"
+
+static void
+free_list(tap_list_t *entry)
+{
+	if (entry->type) {
+		free(entry->type);
+		entry->type = NULL;
+	}
+
+	if (entry->path) {
+		free(entry->path);
+		entry->path = NULL;
+	}
+
+	free(entry);
+}
+
+int
+_parse_params(const char *params, char **type, char **path)
+{
+	char *ptr;
+	size_t len;
+
+	ptr = strchr(params, ':');
+	if (!ptr)
+		return -EINVAL;
+
+	len = ptr - params;
+
+	*type = strndup(params, len);
+	*path =  strdup(params + len + 1);
+
+	if (!*type || !*path) {
+		free(*type);
+		*type = NULL;
+
+		free(*path);
+		*path = NULL;
+
+		return -errno;
+	}
+
+	return 0;
+}
+
+static int
+init_list(tap_list_t *entry,
+	  int tap_id, pid_t tap_pid, int vbd_minor, int vbd_state,
+	  const char *params)
+{
+	int err = 0;
+
+	entry->id     = tap_id;
+	entry->pid    = tap_pid;
+	entry->minor  = vbd_minor;
+	entry->state  = vbd_state;
+
+	if (params)
+		err = _parse_params(params, &entry->type, &entry->path);
+
+	return err;
+}
+
+void
+tap_ctl_free_list(tap_list_t **list)
+{
+	tap_list_t **_entry;
+
+	for (_entry = list; *_entry != NULL; ++_entry)
+		free_list(*_entry);
+
+	free(list);
+}
+
+static tap_list_t**
+tap_ctl_alloc_list(int n)
+{
+	tap_list_t **list, *entry;
+	size_t size;
+	int i;
+
+	size = sizeof(tap_list_t*) * (n+1);
+	list = malloc(size);
+	if (!list)
+		goto fail;
+
+	memset(list, 0, size);
+
+	for (i = 0; i < n; ++i) {
+		tap_list_t *entry;
+
+		entry = malloc(sizeof(tap_list_t));
+		if (!entry)
+			goto fail;
+
+		memset(entry, 0, sizeof(tap_list_t));
+
+		list[i] = entry;
+	}
+
+	return list;
+
+fail:
+	if (list)
+		tap_ctl_free_list(list);
+
+	return NULL;
+}
+
+static int
+tap_ctl_list_length(const tap_list_t **list)
+{
+	const tap_list_t **_entry;
+	int n;
+
+	n = 0;
+	for (_entry = list; *_entry != NULL; ++_entry)
+		n++;
+
+	return n;
+}
+
+static int
+_tap_minor_cmp(const void *a, const void *b)
+{
+	return *(int*)a - *(int*)b;
+}
+
+int
+_tap_ctl_find_minors(int **_minorv)
+{
+	glob_t glbuf = { 0 };
+	const char *pattern, *format;
+	int *minorv = NULL, n_minors = 0;
+	int err, i;
+
+	pattern = BLKTAP2_SYSFS_DIR"/blktap*";
+	format  = BLKTAP2_SYSFS_DIR"/blktap%d";
+
+	n_minors = 0;
+	minorv   = NULL;
+
+	err = glob(pattern, 0, NULL, &glbuf);
+	switch (err) {
+	case GLOB_NOMATCH:
+		goto done;
+
+	case GLOB_ABORTED:
+	case GLOB_NOSPACE:
+		err = -errno;
+		EPRINTF("%s: glob failed, err %d", pattern, err);
+		goto fail;
+	}
+
+	minorv = malloc(sizeof(int) * glbuf.gl_pathc);
+	if (!minorv) {
+		err = -errno;
+		goto fail;
+	}
+
+	for (i = 0; i < glbuf.gl_pathc; ++i) {
+		int n;
+
+		n = sscanf(glbuf.gl_pathv[i], format, &minorv[n_minors]);
+		if (n != 1)
+			continue;
+
+		n_minors++;
+	}
+
+	qsort(minorv, n_minors, sizeof(int), _tap_minor_cmp);
+
+done:
+	*_minorv = minorv;
+	err = 0;
+
+out:
+	if (glbuf.gl_pathv)
+		globfree(&glbuf);
+
+	return err ? : n_minors;
+
+fail:
+	if (minorv)
+		free(minorv);
+
+	goto out;
+}
+
+struct tapdisk {
+	int    id;
+	pid_t  pid;
+	struct list_head list;
+};
+
+static int
+_tap_tapdisk_cmp(const void *a, const void *b)
+{
+	return ((struct tapdisk*)a)->id - ((struct tapdisk*)b)->id;
+}
+
+int
+_tap_ctl_find_tapdisks(struct tapdisk **_tapv)
+{
+	glob_t glbuf = { 0 };
+	const char *pattern, *format;
+	struct tapdisk *tapv = NULL;
+	int err, i, n_taps = 0;
+
+	pattern = BLKTAP2_CONTROL_DIR"/"BLKTAP2_CONTROL_SOCKET"*";
+	format  = BLKTAP2_CONTROL_DIR"/"BLKTAP2_CONTROL_SOCKET"%d";
+
+	n_taps = 0;
+	tapv   = NULL;
+
+	err = glob(pattern, 0, NULL, &glbuf);
+	switch (err) {
+	case GLOB_NOMATCH:
+		goto done;
+
+	case GLOB_ABORTED:
+	case GLOB_NOSPACE:
+		err = -errno;
+		EPRINTF("%s: glob failed, err %d", pattern, err);
+		goto fail;
+	}
+
+	tapv = malloc(sizeof(struct tapdisk) * glbuf.gl_pathc);
+	if (!tapv) {
+		err = -errno;
+		goto fail;
+	}
+
+	for (i = 0; i < glbuf.gl_pathc; ++i) {
+		struct tapdisk *tap;
+		int n;
+
+		tap = &tapv[n_taps];
+
+		err = sscanf(glbuf.gl_pathv[i], format, &tap->id);
+		if (err != 1)
+			continue;
+
+		tap->pid = tap_ctl_get_pid(tap->id);
+		if (tap->pid < 0)
+			continue;
+
+		n_taps++;
+	}
+
+	qsort(tapv, n_taps, sizeof(struct tapdisk), _tap_tapdisk_cmp);
+
+	for (i = 0; i < n_taps; ++i)
+		INIT_LIST_HEAD(&tapv[i].list);
+
+done:
+	*_tapv = tapv;
+	err = 0;
+
+out:
+	if (glbuf.gl_pathv)
+		globfree(&glbuf);
+
+	return err ? : n_taps;
+
+fail:
+	if (tapv)
+		free(tapv);
+
+	goto out;
+}
+
+struct tapdisk_list {
+	int  minor;
+	int  state;
+	char *params;
+	struct list_head entry;
+};
+
+int
+_tap_ctl_list_tapdisk(int id, struct list_head *_list)
+{
+	tapdisk_message_t message;
+	struct list_head list;
+	struct tapdisk_list *tl, *next;
+	int err, sfd;
+
+	err = tap_ctl_connect_id(id, &sfd);
+	if (err)
+		return err;
+
+	memset(&message, 0, sizeof(message));
+	message.type   = TAPDISK_MESSAGE_LIST;
+	message.cookie = -1;
+
+	err = tap_ctl_write_message(sfd, &message, 2);
+	if (err)
+		return err;
+
+	INIT_LIST_HEAD(&list);
+	do {
+		err = tap_ctl_read_message(sfd, &message, 2);
+		if (err) {
+			err = -EPROTO;
+			break;
+		}
+
+		if (message.u.list.count == 0)
+			break;
+
+		tl = malloc(sizeof(struct tapdisk_list));
+		if (!tl) {
+			err = -ENOMEM;
+			break;
+		}
+
+		tl->minor  = message.u.list.minor;
+		tl->state  = message.u.list.state;
+		if (message.u.list.path[0] != 0) {
+			tl->params = strndup(message.u.list.path,
+					     sizeof(message.u.list.path));
+			if (!tl->params) {
+				err = -errno;
+				break;
+			}
+		} else
+			tl->params = NULL;
+
+		list_add(&tl->entry, &list);
+	} while (1);
+
+	if (err)
+		list_for_each_entry_safe(tl, next, &list, entry) {
+			list_del(&tl->entry);
+			free(tl->params);
+			free(tl);
+		}
+
+	close(sfd);
+	list_splice(&list, _list);
+	return err;
+}
+
+void
+_tap_ctl_free_tapdisks(struct tapdisk *tapv, int n_taps)
+{
+	struct tapdisk *tap;
+
+	for (tap = tapv; tap < &tapv[n_taps]; ++tap) {
+		struct tapdisk_list *tl;
+
+		list_for_each_entry(tl, &tap->list, entry) {
+			free(tl->params);
+			free(tl);
+		}
+	}
+
+	free(tapv);
+}
+
+int
+_tap_list_join3(int n_minors, int *minorv, int n_taps, struct tapdisk *tapv,
+		tap_list_t ***_list)
+{
+	tap_list_t **list, **_entry, *entry;
+	int i, _m, err;
+
+	list = tap_ctl_alloc_list(n_minors + n_taps);
+	if (!list) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	_entry = list;
+
+	for (i = 0; i < n_taps; ++i) {
+		struct tapdisk *tap = &tapv[i];
+		struct tapdisk_list *tl;
+
+		/* orphaned tapdisk */
+		if (list_empty(&tap->list)) {
+			err = init_list(*_entry++, tap->id, tap->pid, -1, -1, NULL);
+			if (err)
+				goto fail;
+			continue;
+		}
+
+		list_for_each_entry(tl, &tap->list, entry) {
+
+			err = init_list(*_entry++,
+					tap->id, tap->pid,
+					tl->minor, tl->state, tl->params);
+			if (err)
+				goto fail;
+
+			if (tl->minor >= 0) {
+				/* clear minor */
+				for (_m = 0; _m < n_minors; ++_m) {
+					if (minorv[_m] == tl->minor) {
+						minorv[_m] = -1;
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	/* orphaned minors */
+	for (_m = 0; _m < n_minors; ++_m) {
+		int minor = minorv[_m];
+		if (minor >= 0) {
+			err = init_list(*_entry++, -1, -1, minor, -1, NULL);
+			if (err)
+				goto fail;
+		}
+	}
+
+	/* free extraneous list entries */
+	for (; *_entry != NULL; ++entry) {
+		free_list(*_entry);
+		*_entry = NULL;
+	}
+
+	*_list = list;
+
+	return 0;
+
+fail:
+	if (list)
+		tap_ctl_free_list(list);
+
+	return err;
+}
+
+int
+tap_ctl_list(tap_list_t ***list)
+{
+	int n_taps, n_minors, err, *minorv;
+	struct tapdisk *tapv, *tap;
+
+	n_taps   = -1;
+	n_minors = -1;
+
+	err = n_minors = _tap_ctl_find_minors(&minorv);
+	if (err < 0)
+		goto out;
+
+	err = n_taps = _tap_ctl_find_tapdisks(&tapv);
+	if (err < 0)
+		goto out;
+
+	for (tap = tapv; tap < &tapv[n_taps]; ++tap) {
+		err = _tap_ctl_list_tapdisk(tap->id, &tap->list);
+		if (err)
+			goto out;
+	}
+
+	err = _tap_list_join3(n_minors, minorv, n_taps, tapv, list);
+
+out:
+	if (n_taps > 0)
+		_tap_ctl_free_tapdisks(tapv, n_taps);
+
+	if (n_minors > 0)
+		free(minorv);
+
+	return err;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-major.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-major.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "tap-ctl.h"
+
+int
+tap_ctl_blk_major(void)
+{
+	FILE *devices;
+	int rv, major;
+
+	devices = fopen("/proc/devices", "r");
+	if (!devices) {
+		rv = -errno;
+		goto out;
+	}
+
+	do {
+		char buf[32], *s;
+		int n, offset;
+
+		s = fgets(buf, sizeof(buf), devices);
+		if (!s)
+			break;
+
+		major  = -ENODEV;
+		offset = 0;
+
+		n = sscanf(buf, "%d tapdev%n", &major, &offset);
+		if (n == 1 && offset)
+			break;
+	} while (1);
+
+	rv = major;
+
+out:
+	if (devices)
+		fclose(devices);
+
+	return rv;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-open.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-open.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+#include "blktaplib.h"
+
+int
+tap_ctl_open(const int id, const int minor, const char *params)
+{
+	int err;
+	tapdisk_message_t message;
+
+	memset(&message, 0, sizeof(message));
+	message.type = TAPDISK_MESSAGE_OPEN;
+	message.cookie = minor;
+	message.u.params.storage = TAPDISK_STORAGE_TYPE_DEFAULT;
+	message.u.params.devnum = minor;
+
+	err = snprintf(message.u.params.path,
+		       sizeof(message.u.params.path) - 1, "%s", params);
+	if (err >= sizeof(message.u.params.path)) {
+		EPRINTF("name too long\n");
+		return ENAMETOOLONG;
+	}
+
+	err = tap_ctl_connect_send_and_receive(id, &message, 5);
+	if (err)
+		return err;
+
+	switch (message.type) {
+	case TAPDISK_MESSAGE_OPEN_RSP:
+		break;
+	case TAPDISK_MESSAGE_ERROR:
+		err = -message.u.response.error;
+		EPRINTF("open failed, err %d\n", err);
+		break;
+	default:
+		EPRINTF("got unexpected result '%s' from %d\n",
+			tapdisk_message_name(message.type), id);
+		err = EINVAL;
+	}
+
+	return err;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-pause.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-pause.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "tap-ctl.h"
+
+int
+tap_ctl_pause(const int id, const int minor)
+{
+	int err;
+	tapdisk_message_t message;
+
+	memset(&message, 0, sizeof(message));
+	message.type = TAPDISK_MESSAGE_PAUSE;
+	message.cookie = minor;
+
+	err = tap_ctl_connect_send_and_receive(id, &message, 5);
+	if (err)
+		return err;
+
+	if (message.type == TAPDISK_MESSAGE_PAUSE_RSP)
+		err = message.u.response.error;
+	else {
+		err = EINVAL;
+		EPRINTF("got unexpected result '%s' from %d\n",
+			tapdisk_message_name(message.type), id);
+	}
+
+	return err;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-spawn.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-spawn.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+static pid_t
+__tap_ctl_spawn(int *readfd)
+{
+	int err, child, channel[2];
+	char *tapdisk;
+
+	if (pipe(channel)) {
+		EPRINTF("pipe failed: %d\n", errno);
+		return -errno;
+	}
+
+	if ((child = fork()) == -1) {
+		EPRINTF("fork failed: %d\n", errno);
+		return -errno;
+	}
+
+	if (child) {
+		close(channel[1]);
+		*readfd = channel[0];
+		return child;
+	}
+
+	if (dup2(channel[1], STDOUT_FILENO) == -1) {
+		EPRINTF("dup2 failed: %d\n", errno);
+		exit(errno);
+	}
+
+	if (dup2(channel[1], STDERR_FILENO) == -1) {
+		EPRINTF("dup2 failed: %d\n", errno);
+		exit(errno);
+	}
+
+	close(channel[0]);
+	close(channel[1]);
+
+	tapdisk = getenv("TAPDISK2");
+	if (!tapdisk)
+		tapdisk = "tapdisk2";
+
+	execlp(tapdisk, tapdisk, NULL);
+
+	EPRINTF("exec failed\n");
+	exit(1);
+}
+
+pid_t
+tap_ctl_get_pid(const int id)
+{
+	int err;
+	tapdisk_message_t message;
+
+	memset(&message, 0, sizeof(message));
+	message.type = TAPDISK_MESSAGE_PID;
+
+	err = tap_ctl_connect_send_and_receive(id, &message, 2);
+	if (err)
+		return err;
+
+	return message.u.tapdisk_pid;
+}
+
+static int
+tap_ctl_wait(pid_t child)
+{
+	pid_t pid;
+	int status;
+
+	pid = waitpid(child, &status, 0);
+	if (pid < 0) {
+		EPRINTF("wait(%d) failed, err %d\n", child, errno);
+		return -errno;
+	}
+
+	if (WIFEXITED(status)) {
+		int code = WEXITSTATUS(status);
+		if (code)
+			EPRINTF("tapdisk2[%d] failed, status %d\n", child, code);
+		return -code;
+	}
+
+	if (WIFSIGNALED(status)) {
+		int signo = WTERMSIG(status);
+		EPRINTF("tapdisk2[%d] killed by signal %d\n", child, signo);
+		return -EINTR;
+	}
+
+	EPRINTF("tapdisk2[%d]: unexpected status %#x\n", child, status);
+	return -EAGAIN;
+}
+
+static int
+tap_ctl_get_child_id(int readfd)
+{
+	int id;
+	FILE *f;
+
+	f = fdopen(readfd, "r");
+	if (!f) {
+		EPRINTF("fdopen failed: %d\n", errno);
+		return -1;
+	}
+
+	errno = 0;
+	if (fscanf(f, BLKTAP2_CONTROL_DIR"/"
+		   BLKTAP2_CONTROL_SOCKET"%d", &id) != 1) {
+		errno = (errno ? : EINVAL);
+		EPRINTF("parsing id failed: %d\n", errno);
+		id = -1;
+	}
+
+	fclose(f);
+	return id;
+}
+
+int
+tap_ctl_spawn(void)
+{
+	pid_t child;
+	int err, id, readfd;
+
+	readfd = -1;
+
+	child = __tap_ctl_spawn(&readfd);
+	if (child < 0)
+		return child;
+
+	err = tap_ctl_wait(child);
+	if (err)
+		return err;
+
+	id = tap_ctl_get_child_id(readfd);
+	if (id < 0)
+		EPRINTF("get_id failed, child %d err %d\n", child, errno);
+
+	return id;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl-unpause.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl-unpause.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+
+int
+tap_ctl_unpause(const int id, const int minor, const char *params)
+{
+	int err;
+	tapdisk_message_t message;
+
+	memset(&message, 0, sizeof(message));
+	message.type = TAPDISK_MESSAGE_RESUME;
+	message.cookie = minor;
+
+	if (params)
+		strncpy(message.u.params.path, params,
+			sizeof(message.u.params.path) - 1);
+
+	err = tap_ctl_connect_send_and_receive(id, &message, 15);
+	if (err)
+		return err;
+
+	if (message.type == TAPDISK_MESSAGE_RESUME_RSP)
+		err = message.u.response.error;
+	else {
+		err = EINVAL;
+		EPRINTF("got unexpected result '%s' from %d\n",
+			tapdisk_message_name(message.type), id);
+	}
+
+	return err;
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,815 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+
+typedef int (*tap_ctl_func_t) (int, char **);
+
+struct command {
+	char                     *name;
+	tap_ctl_func_t            func;
+};
+
+static void
+tap_cli_list_usage(FILE *stream)
+{
+	fprintf(stream,
+		"usage: list [-h] [-p pid] [-m minor] [-t type] [-f file]\n");
+}
+
+static void
+tap_ctl_list_row(tap_list_t *entry)
+{
+	char minor_str[10] = "-";
+	char state_str[10] = "-";
+	char pid_str[10]   = "-";
+
+	if (entry->pid != -1)
+		sprintf(pid_str, "%d", entry->pid);
+
+	if (entry->minor != -1)
+		sprintf(minor_str, "%d", entry->minor);
+
+	if (entry->state != -1)
+		sprintf(state_str, "%x", entry->state);
+
+	printf("%8s %2s %4s %10s %s\n",
+	       pid_str, minor_str, state_str,
+	       entry->type ? : "-", entry->path ? : "-");
+}
+
+static void
+tap_ctl_list_dict(tap_list_t *entry)
+{
+	int d = 0;
+
+	if (entry->pid != -1) {
+		if (d) putc(' ', stdout);
+		d = printf("pid=%d", entry->pid);
+	}
+
+	if (entry->minor != -1) {
+		if (d) putc(' ', stdout);
+		d = printf("minor=%d", entry->minor);
+	}
+
+	if (entry->state != -1) {
+		if (d) putc(' ', stdout);
+		d = printf("state=%d", entry->state);
+	}
+
+	if (entry->type && entry->path) {
+		if (d) putc(' ', stdout);
+		d = printf("args=%s:%s", entry->type, entry->path);
+	}
+
+	putc('\n', stdout);
+}
+
+int
+tap_cli_list(int argc, char **argv)
+{
+	tap_list_t **list, **_entry;
+	int c, minor, tty, err;
+	const char *type, *file;
+	pid_t pid;
+
+	err = tap_ctl_list(&list);
+	if (err)
+		return -err;
+
+	pid   = -1;
+	minor = -1;
+	type  = NULL;
+	file  = NULL;
+
+	while ((c = getopt(argc, argv, "m:p:t:f:h")) != -1) {
+		switch (c) {
+		case 'm':
+			minor = atoi(optarg);
+			break;
+		case 'p':
+			pid = atoi(optarg);
+			break;
+		case 't':
+			type = optarg;
+			break;
+		case 'f':
+			file = optarg;
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_list_usage(stdout);
+			return 0;
+		}
+	}
+
+	tty = isatty(STDOUT_FILENO);
+
+	for (_entry = list; *_entry != NULL; ++_entry) {
+		tap_list_t *entry  = *_entry;
+
+		if (minor >= 0 && entry->minor != minor)
+			continue;
+
+		if (pid >= 0 && entry->pid != pid)
+			continue;
+
+		if (type && entry->type && strcmp(entry->type, type))
+			continue;
+
+		if (file && entry->path && strcmp(entry->path, file))
+			continue;
+
+		if (tty)
+			tap_ctl_list_row(entry);
+		else
+			tap_ctl_list_dict(entry);
+	}
+
+	tap_ctl_free_list(list);
+
+	return 0;
+
+usage:
+	tap_cli_list_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_allocate_usage(FILE *stream)
+{
+	fprintf(stream, "usage: allocate [-d device name]>\n");
+}
+
+static int
+tap_cli_allocate(int argc, char **argv)
+{
+	char *devname;
+	int c, minor, err;
+
+	devname = NULL;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "d:h")) != -1) {
+		switch (c) {
+		case 'd':
+			devname = optarg;
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_allocate_usage(stdout);
+			return 0;
+		}
+	}
+
+	err = tap_ctl_allocate(&minor, &devname);
+	if (!err)
+		printf("%s\n", devname);
+
+	return err;
+
+usage:
+	tap_cli_allocate_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_free_usage(FILE *stream)
+{
+	fprintf(stream, "usage: free <-m minor>\n");
+}
+
+static int
+tap_cli_free(int argc, char **argv)
+{
+	int c, minor;
+
+	minor = -1;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "m:h")) != -1) {
+		switch (c) {
+		case 'm':
+			minor = atoi(optarg);
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_free_usage(stdout);
+			return 0;
+		}
+	}
+
+	if (minor == -1)
+		goto usage;
+
+	return tap_ctl_free(minor);
+
+usage:
+	tap_cli_free_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_create_usage(FILE *stream)
+{
+	fprintf(stream, "usage: create <-a args> [-d device name]\n");
+}
+
+static int
+tap_cli_create(int argc, char **argv)
+{
+	int c, err;
+	char *args, *devname;
+
+	args    = NULL;
+	devname = NULL;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "a:d:h")) != -1) {
+		switch (c) {
+		case 'a':
+			args = optarg;
+			break;
+		case 'd':
+			devname = optarg;
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_create_usage(stdout);
+			return 0;
+		}
+	}
+
+	if (!args)
+		goto usage;
+
+	err = tap_ctl_create(args, &devname);
+	if (!err)
+		printf("%s\n", devname);
+
+	return err;
+
+usage:
+	tap_cli_create_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_destroy_usage(FILE *stream)
+{
+	fprintf(stream, "usage: destroy <-p pid> <-m minor>\n");
+}
+
+static int
+tap_cli_destroy(int argc, char **argv)
+{
+	int c, pid, minor;
+
+	pid   = -1;
+	minor = -1;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "p:m:h")) != -1) {
+		switch (c) {
+		case 'p':
+			pid = atoi(optarg);
+			break;
+		case 'm':
+			minor = atoi(optarg);
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_destroy_usage(stdout);
+			return 0;
+		}
+	}
+
+	if (pid == -1 || minor == -1)
+		goto usage;
+
+	return tap_ctl_destroy(pid, minor);
+
+usage:
+	tap_cli_destroy_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_spawn_usage(FILE *stream)
+{
+	fprintf(stream, "usage: spawn\n");
+}
+
+static int
+tap_cli_spawn(int argc, char **argv)
+{
+	int c;
+	pid_t task;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "h")) != -1) {
+		switch (c) {
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_spawn_usage(stdout);
+			return 0;
+		}
+	}
+
+	task = tap_ctl_spawn();
+	if (task < 0) {
+		printf("spawn failed: %d\n", errno);
+		return task;
+	}
+
+	printf("tapdisk spawned with pid %d\n", task);
+	return 0;
+
+usage:
+	tap_cli_spawn_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_attach_usage(FILE *stream)
+{
+	fprintf(stream, "usage: attach <-p pid> <-m minor>\n");
+}
+
+static int
+tap_cli_attach(int argc, char **argv)
+{
+	int c, pid, minor;
+
+	pid   = -1;
+	minor = -1;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "p:m:h")) != -1) {
+		switch (c) {
+		case 'p':
+			pid = atoi(optarg);
+			break;
+		case 'm':
+			minor = atoi(optarg);
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_attach_usage(stderr);
+			return 0;
+		}
+	}
+
+	if (pid == -1 || minor == -1)
+		goto usage;
+
+	return tap_ctl_attach(pid, minor);
+
+usage:
+	tap_cli_attach_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_detach_usage(FILE *stream)
+{
+	fprintf(stream, "usage: detach <-p pid> <-m minor>\n");
+}
+
+static int
+tap_cli_detach(int argc, char **argv)
+{
+	int c, pid, minor;
+
+	pid   = -1;
+	minor = -1;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "p:m:h")) != -1) {
+		switch (c) {
+		case 'p':
+			pid = atoi(optarg);
+			break;
+		case 'm':
+			minor = atoi(optarg);
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_detach_usage(stdout);
+			return 0;
+		}
+	}
+
+	if (pid == -1 || minor == -1)
+		goto usage;
+
+	return tap_ctl_detach(pid, minor);
+
+usage:
+	tap_cli_detach_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_close_usage(FILE *stream)
+{
+	fprintf(stream, "usage: close <-p pid> <-m minor> [-f force]\n");
+}
+
+static int
+tap_cli_close(int argc, char **argv)
+{
+	int c, pid, minor, force;
+
+	pid   = -1;
+	minor = -1;
+	force = 0;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "p:m:fh")) != -1) {
+		switch (c) {
+		case 'p':
+			pid = atoi(optarg);
+			break;
+		case 'm':
+			minor = atoi(optarg);
+			break;
+		case 'f':
+			force = -1;
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_close_usage(stdout);
+			return 0;
+		}
+	}
+
+	if (pid == -1 || minor == -1)
+		goto usage;
+
+	return tap_ctl_close(pid, minor, force);
+
+usage:
+	tap_cli_close_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_pause_usage(FILE *stream)
+{
+	fprintf(stream, "usage: pause <-p pid> <-m minor>\n");
+}
+
+static int
+tap_cli_pause(int argc, char **argv)
+{
+	int c, pid, minor;
+
+	pid   = -1;
+	minor = -1;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "p:m:h")) != -1) {
+		switch (c) {
+		case 'p':
+			pid = atoi(optarg);
+			break;
+		case 'm':
+			minor = atoi(optarg);
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_pause_usage(stdout);
+			return 0;
+		}
+	}
+
+	if (pid == -1 || minor == -1)
+		goto usage;
+
+	return tap_ctl_pause(pid, minor);
+
+usage:
+	tap_cli_pause_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_unpause_usage(FILE *stream)
+{
+	fprintf(stream, "usage: unpause <-p pid> <-m minor> [-a args]\n");
+}
+
+int
+tap_cli_unpause(int argc, char **argv)
+{
+	const char *args;
+	int c, pid, minor;
+
+	pid   = -1;
+	minor = -1;
+	args  = NULL;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "p:m:a:h")) != -1) {
+		switch (c) {
+		case 'p':
+			pid = atoi(optarg);
+			break;
+		case 'm':
+			minor = atoi(optarg);
+			break;
+		case 'a':
+			args = optarg;
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_unpause_usage(stdout);
+			return 0;
+		}
+	}
+
+	if (pid == -1 || minor == -1)
+		goto usage;
+
+	return tap_ctl_unpause(pid, minor, args);
+
+usage:
+	tap_cli_unpause_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_major_usage(FILE *stream)
+{
+	fprintf(stream, "usage: major [-h]\n");
+}
+
+static int
+tap_cli_major(int argc, char **argv)
+{
+	int c, chr, major;
+
+	chr = 0;
+
+	while ((c = getopt(argc, argv, "bch")) != -1) {
+		switch (c) {
+		case 'b':
+			chr = 0;
+			break;
+		case 'c':
+			chr = 1;
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_major_usage(stdout);
+			return 0;
+		default:
+			goto usage;
+		}
+	}
+
+	if (chr)
+		major = -EINVAL;
+	else
+		major = tap_ctl_blk_major();
+
+	if (major < 0)
+		return -major;
+
+	printf("%d\n", major);
+
+	return 0;
+
+usage:
+	tap_cli_major_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_open_usage(FILE *stream)
+{
+	fprintf(stream, "usage: open <-p pid> <-m minor> <-a args>\n");
+}
+
+static int
+tap_cli_open(int argc, char **argv)
+{
+	const char *args;
+	int c, pid, minor;
+
+	pid   = -1;
+	minor = -1;
+	args  = NULL;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "a:m:p:h")) != -1) {
+		switch (c) {
+		case 'p':
+			pid = atoi(optarg);
+			break;
+		case 'm':
+			minor = atoi(optarg);
+			break;
+		case 'a':
+			args = optarg;
+			break;
+		case '?':
+			goto usage;
+		case 'h':
+			tap_cli_open_usage(stdout);
+			return 0;
+		}
+	}
+
+	if (pid == -1 || minor == -1 || !args)
+		goto usage;
+
+	return tap_ctl_open(pid, minor, args);
+
+usage:
+	tap_cli_open_usage(stderr);
+	return EINVAL;
+}
+
+static void
+tap_cli_check_usage(FILE *stream)
+{
+	fprintf(stream, "usage: check\n"
+		"(checks whether environment is suitable for tapdisk2)\n");
+}
+
+static int
+tap_cli_check(int argc, char **argv)
+{
+	int err;
+	const char *msg;
+
+	if (argc != 1)
+		goto usage;
+
+	err = tap_ctl_check(&msg);
+	printf("%s\n", msg);
+
+	return err;
+
+usage:
+	tap_cli_check_usage(stderr);
+	return EINVAL;
+}
+
+struct command commands[] = {
+	{ .name = "list",         .func = tap_cli_list          },
+	{ .name = "allocate",     .func = tap_cli_allocate      },
+	{ .name = "free",         .func = tap_cli_free          },
+	{ .name = "create",       .func = tap_cli_create        },
+	{ .name = "destroy",      .func = tap_cli_destroy       },
+	{ .name = "spawn",        .func = tap_cli_spawn         },
+	{ .name = "attach",       .func = tap_cli_attach        },
+	{ .name = "detach",       .func = tap_cli_detach        },
+	{ .name = "open",         .func = tap_cli_open          },
+	{ .name = "close",        .func = tap_cli_close         },
+	{ .name = "pause",        .func = tap_cli_pause         },
+	{ .name = "unpause",      .func = tap_cli_unpause       },
+	{ .name = "major",        .func = tap_cli_major         },
+	{ .name = "check",        .func = tap_cli_check         },
+};
+
+#define print_commands()					\
+	do {							\
+		int i, n;					\
+		n = sizeof(commands) / sizeof(struct command);	\
+		printf("COMMAND := { ");			\
+		printf("%s", commands[0].name);			\
+		for (i = 1; i < n; i++)				\
+			printf(" | %s", commands[i].name);	\
+		printf(" }\n");					\
+	} while (0)
+
+void
+help(void)
+{
+	printf("usage: tap-ctl COMMAND [OPTIONS]\n");
+	print_commands();
+	exit(0);
+}
+
+struct command *
+get_command(char *command)
+{
+	int i, n;
+
+	if (strnlen(command, 25) >= 25)
+		return NULL;
+
+	n = sizeof(commands) / sizeof (struct command);
+
+	for (i = 0; i < n; i++)
+		if (!strcmp(command, commands[i].name))
+			return &commands[i];
+
+	return NULL;
+}
+
+int
+main(int argc, char *argv[])
+{
+	char **cargv;
+	const char *msg;
+	struct command *cmd;
+	int cargc, i, cnt, ret;
+
+#ifdef CORE_DUMP
+	#include <sys/resource.h>
+	struct rlimit rlim;
+	rlim.rlim_cur = RLIM_INFINITY;
+	rlim.rlim_max = RLIM_INFINITY;
+	if (setrlimit(RLIMIT_CORE, &rlim) < 0)
+		PERROR("setrlimit failed");
+#endif
+
+	ret = 0;
+
+	if (argc < 2)
+		help();
+
+	cargc = argc - 1;
+	cmd   = get_command(argv[1]);
+	if (!cmd) {
+		EPRINTF("invalid COMMAND %s", argv[1]);
+		help();
+	}
+
+	ret = tap_ctl_check(&msg);
+	if (ret) {
+		printf("%s\n", msg);
+		return ret;
+	}
+
+	cargv = malloc(sizeof(char *) * cargc);
+	if (!cargv)
+		exit(ENOMEM);
+
+	cnt      = 1;
+	cargv[0] = cmd->name;
+	for (i = 1; i < cargc; i++) {
+		char *arg = argv[i + (argc - cargc)];
+
+		if (!strcmp(arg, "--debug")) {
+			tap_ctl_debug = 1;
+			continue;
+		}
+
+		cargv[cnt++] = arg;
+	}
+
+	ret = cmd->func(cnt, cargv);
+
+	free(cargv);
+
+	return (ret >= 0 ? ret : -ret);
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/control/tap-ctl.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/control/tap-ctl.h	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __TAP_CTL_H__
+#define __TAP_CTL_H__
+
+#include <syslog.h>
+#include <errno.h>
+
+#include "tapdisk-message.h"
+
+extern int tap_ctl_debug;
+
+#ifdef TAPCTL
+#define DBG(_f, _a...)				\
+	do {					\
+		if (tap_ctl_debug)		\
+			printf(_f, ##_a);	\
+	} while (0)
+
+#define DPRINTF(_f, _a...) syslog(LOG_INFO, _f, ##_a)
+#define EPRINTF(_f, _a...) syslog(LOG_ERR, "tap-err:%s: " _f, __func__, ##_a)
+#define  PERROR(_f, _a...) syslog(LOG_ERR, "tap-err:%s: " _f ": %s", __func__, ##_a, \
+				  strerror(errno))
+#endif
+
+void tap_ctl_version(int *major, int *minor);
+int tap_ctl_kernel_version(int *major, int *minor);
+
+int tap_ctl_check_blktap(const char **message);
+int tap_ctl_check_version(const char **message);
+int tap_ctl_check(const char **message);
+
+int tap_ctl_connect(const char *path, int *socket);
+int tap_ctl_connect_id(int id, int *socket);
+int tap_ctl_read_message(int fd, tapdisk_message_t *message, int timeout);
+int tap_ctl_write_message(int fd, tapdisk_message_t *message, int timeout);
+int tap_ctl_send_and_receive(int fd, tapdisk_message_t *message, int timeout);
+int tap_ctl_connect_send_and_receive(int id,
+				     tapdisk_message_t *message, int timeout);
+char *tap_ctl_socket_name(int id);
+
+typedef struct {
+	int         id;
+	pid_t       pid;
+	int         minor;
+	int         state;
+	char       *type;
+	char       *path;
+} tap_list_t;
+
+int tap_ctl_get_driver_id(const char *handle);
+
+int tap_ctl_list(tap_list_t ***list);
+void tap_ctl_free_list(tap_list_t **list);
+
+int tap_ctl_allocate(int *minor, char **devname);
+int tap_ctl_free(const int minor);
+
+int tap_ctl_create(const char *params, char **devname);
+int tap_ctl_destroy(const int id, const int minor);
+
+int tap_ctl_spawn(void);
+pid_t tap_ctl_get_pid(const int id);
+
+int tap_ctl_attach(const int id, const int minor);
+int tap_ctl_detach(const int id, const int minor);
+
+int tap_ctl_open(const int id, const int minor, const char *params);
+int tap_ctl_close(const int id, const int minor, const int force);
+
+int tap_ctl_pause(const int id, const int minor);
+int tap_ctl_unpause(const int id, const int minor, const char *params);
+
+int tap_ctl_blk_major(void);
+
+#endif
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/drivers/Makefile
--- a/tools/blktap2/drivers/Makefile	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/Makefile	Mon Jun 07 14:53:16 2010 -0700
@@ -12,8 +12,7 @@
 CFLAGS    += -Werror -g -O0
 CFLAGS    += -Wno-unused
 CFLAGS    += -fno-strict-aliasing
-CFLAGS    += -I../lib -I../../libxc
-CFLAGS    += -I../include -I../../include
+CFLAGS    += -I$(BLKTAP_ROOT)/include -I$(BLKTAP_ROOT)/drivers
 CFLAGS    += $(CFLAGS_libxenctrl)
 CFLAGS    += -I $(LIBAIO_DIR)
 CFLAGS    += -I $(MEMSHR_DIR)
@@ -75,6 +74,7 @@
 
 TAP-OBJS-y  := scheduler.o
 TAP-OBJS-y  += tapdisk-vbd.o
+TAP-OBJS-y  += tapdisk-control.o
 TAP-OBJS-y  += tapdisk-image.o
 TAP-OBJS-y  += tapdisk-driver.o
 TAP-OBJS-y  += tapdisk-disktype.o
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/drivers/blktap2.h
--- a/tools/blktap2/drivers/blktap2.h	Mon Jun 07 14:53:15 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2008, XenSource Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of XenSource Inc. nor the names of its contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _BLKTAP_2_H_
-#define _BLKTAP_2_H_
-
-#define MISC_MAJOR_NUMBER              10
-
-#define BLKTAP2_MAX_MESSAGE_LEN        256
-
-#define BLKTAP2_RING_MESSAGE_PAUSE     1
-#define BLKTAP2_RING_MESSAGE_RESUME    2
-#define BLKTAP2_RING_MESSAGE_CLOSE     3
-
-#define BLKTAP2_IOCTL_KICK_FE          1
-#define BLKTAP2_IOCTL_ALLOC_TAP        200
-#define BLKTAP2_IOCTL_FREE_TAP         201
-#define BLKTAP2_IOCTL_CREATE_DEVICE    202
-#define BLKTAP2_IOCTL_SET_PARAMS       203
-#define BLKTAP2_IOCTL_PAUSE            204
-#define BLKTAP2_IOCTL_REOPEN           205
-#define BLKTAP2_IOCTL_RESUME           206
-
-#define BLKTAP2_CONTROL_NAME           "blktap-control"
-#define BLKTAP2_DIRECTORY              "/dev/xen/blktap-2"
-#define BLKTAP2_CONTROL_DEVICE         BLKTAP2_DIRECTORY"/control"
-#define BLKTAP2_RING_DEVICE            BLKTAP2_DIRECTORY"/blktap"
-#define BLKTAP2_IO_DEVICE              BLKTAP2_DIRECTORY"/tapdev"
-
-struct blktap2_handle {
-	unsigned int                   ring;
-	unsigned int                   device;
-	unsigned int                   minor;
-};
-
-struct blktap2_params {
-	char                           name[BLKTAP2_MAX_MESSAGE_LEN];
-	unsigned long long             capacity;
-	unsigned long                  sector_size;
-};
-
-#endif
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/drivers/tapdisk-control.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/drivers/tapdisk-control.c	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,836 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include "list.h"
+#include "tapdisk.h"
+#include "blktap2.h"
+#include "blktaplib.h"
+#include "tapdisk-vbd.h"
+#include "tapdisk-utils.h"
+#include "tapdisk-server.h"
+#include "tapdisk-message.h"
+#include "tapdisk-disktype.h"
+
+struct tapdisk_control {
+	char              *path;
+	int                socket;
+	int                event_id;
+};
+
+struct tapdisk_control_connection {
+	int                socket;
+	event_id_t         event_id;
+};
+
+static struct tapdisk_control td_control;
+
+static void
+tapdisk_control_initialize(void)
+{
+	td_control.socket   = -1;
+	td_control.event_id = -1;
+
+	signal(SIGPIPE, SIG_IGN);
+}
+
+void
+tapdisk_control_close(void)
+{
+	if (td_control.path) {
+		unlink(td_control.path);
+		free(td_control.path);
+		td_control.path = NULL;
+	}
+
+	if (td_control.socket != -1) {
+		close(td_control.socket);
+		td_control.socket = -1;
+	}
+}
+
+static struct tapdisk_control_connection *
+tapdisk_control_allocate_connection(int fd)
+{
+	struct tapdisk_control_connection *connection;
+	size_t sz;
+
+	connection = calloc(1, sizeof(*connection));
+	if (!connection) {
+		EPRINTF("calloc");
+		return NULL;
+	}
+
+	connection->socket = fd;
+	return connection;
+}
+
+static void
+tapdisk_control_close_connection(struct tapdisk_control_connection *connection)
+{
+	tapdisk_server_unregister_event(connection->event_id);
+	close(connection->socket);
+	free(connection);
+}
+
+static int
+tapdisk_control_read_message(int fd, tapdisk_message_t *message, int timeout)
+{
+	fd_set readfds;
+	int ret, len, offset;
+	struct timeval tv, *t;
+
+	t      = NULL;
+	offset = 0;
+	len    = sizeof(tapdisk_message_t);
+
+	if (timeout) {
+		tv.tv_sec  = timeout;
+		tv.tv_usec = 0;
+		t = &tv;
+	}
+
+	memset(message, 0, sizeof(tapdisk_message_t));
+
+	while (offset < len) {
+		FD_ZERO(&readfds);
+		FD_SET(fd, &readfds);
+
+		ret = select(fd + 1, &readfds, NULL, NULL, t);
+		if (ret == -1)
+			break;
+		else if (FD_ISSET(fd, &readfds)) {
+			ret = read(fd, message + offset, len - offset);
+			if (ret <= 0)
+				break;
+			offset += ret;
+		} else
+			break;
+	}
+
+	if (offset != len) {
+		EPRINTF("failure reading message (wanted %d but got %d)\n",
+			len, offset);
+		return -EIO;
+	}
+
+	DPRINTF("received '%s' message (uuid = %u)\n",
+		tapdisk_message_name(message->type), message->cookie);
+
+	return 0;
+}
+
+static int
+tapdisk_control_write_message(int fd, tapdisk_message_t *message, int timeout)
+{
+	fd_set writefds;
+	int ret, len, offset;
+	struct timeval tv, *t;
+
+	t      = NULL;
+	offset = 0;
+	len    = sizeof(tapdisk_message_t);
+
+	if (timeout) {
+		tv.tv_sec  = timeout;
+		tv.tv_usec = 0;
+		t = &tv;
+	}
+
+	DPRINTF("sending '%s' message (uuid = %u)\n",
+		tapdisk_message_name(message->type), message->cookie);
+
+	while (offset < len) {
+		FD_ZERO(&writefds);
+		FD_SET(fd, &writefds);
+
+		/* we don't bother reinitializing tv. at worst, it will wait a
+		 * bit more time than expected. */
+
+		ret = select(fd + 1, NULL, &writefds, NULL, t);
+		if (ret == -1)
+			break;
+		else if (FD_ISSET(fd, &writefds)) {
+			ret = write(fd, message + offset, len - offset);
+			if (ret <= 0)
+				break;
+			offset += ret;
+		} else
+			break;
+	}
+
+	if (offset != len) {
+		EPRINTF("failure writing message\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int
+tapdisk_control_validate_request(tapdisk_message_t *request)
+{
+	if (strnlen(request->u.params.path,
+		    TAPDISK_MESSAGE_MAX_PATH_LENGTH) >=
+	    TAPDISK_MESSAGE_MAX_PATH_LENGTH)
+		return EINVAL;
+
+	return 0;
+}
+
+static void
+tapdisk_control_list_minors(struct tapdisk_control_connection *connection,
+			    tapdisk_message_t *request)
+{
+	int i;
+	td_vbd_t *vbd;
+	struct list_head *head;
+	tapdisk_message_t response;
+
+	i = 0;
+	memset(&response, 0, sizeof(response));
+
+	response.type = TAPDISK_MESSAGE_LIST_MINORS_RSP;
+	response.cookie = request->cookie;
+
+	head = tapdisk_server_get_all_vbds();
+
+	list_for_each_entry(vbd, head, next) {
+		response.u.minors.list[i++] = vbd->minor;
+		if (i >= TAPDISK_MESSAGE_MAX_MINORS) {
+			response.type = TAPDISK_MESSAGE_ERROR;
+			response.u.response.error = ERANGE;
+			break;
+		}
+	}
+
+	response.u.minors.count = i;
+	tapdisk_control_write_message(connection->socket, &response, 2);
+	tapdisk_control_close_connection(connection);
+}
+
+static void
+tapdisk_control_list(struct tapdisk_control_connection *connection,
+		     tapdisk_message_t *request)
+{
+	td_vbd_t *vbd;
+	struct list_head *head;
+	tapdisk_message_t response;
+	int count, i;
+
+	memset(&response, 0, sizeof(response));
+	response.type = TAPDISK_MESSAGE_LIST_RSP;
+	response.cookie = request->cookie;
+
+	head = tapdisk_server_get_all_vbds();
+
+	count = 0;
+	list_for_each_entry(vbd, head, next)
+		count++;
+
+	list_for_each_entry(vbd, head, next) {
+		response.u.list.count   = count--;
+		response.u.list.minor   = vbd->minor;
+		response.u.list.state   = vbd->state;
+		response.u.list.path[0] = 0;
+
+		if (!list_empty(&vbd->images)) {
+			td_image_t *image = list_entry(vbd->images.next,
+						       td_image_t, next);
+			snprintf(response.u.list.path,
+				 sizeof(response.u.list.path),
+				 "%s:%s",
+				 tapdisk_disk_types[image->type]->name,
+				 image->name);
+		}
+
+		tapdisk_control_write_message(connection->socket, &response, 2);
+	}
+
+	response.u.list.count   = count;
+	response.u.list.minor   = -1;
+	response.u.list.path[0] = 0;
+
+	tapdisk_control_write_message(connection->socket, &response, 2);
+	tapdisk_control_close_connection(connection);
+}
+
+static void
+tapdisk_control_get_pid(struct tapdisk_control_connection *connection,
+			tapdisk_message_t *request)
+{
+	tapdisk_message_t response;
+
+	memset(&response, 0, sizeof(response));
+	response.type = TAPDISK_MESSAGE_PID_RSP;
+	response.cookie = request->cookie;
+	response.u.tapdisk_pid = getpid();
+
+	tapdisk_control_write_message(connection->socket, &response, 2);
+	tapdisk_control_close_connection(connection);
+}
+
+static void
+tapdisk_control_attach_vbd(struct tapdisk_control_connection *connection,
+			   tapdisk_message_t *request)
+{
+	tapdisk_message_t response;
+	char *devname;
+	td_vbd_t *vbd;
+	struct blktap2_params params;
+	image_t image;
+	int minor, err;
+
+	/*
+	 * TODO: check for max vbds per process
+	 */
+
+	vbd = tapdisk_server_get_vbd(request->cookie);
+	if (vbd) {
+		err = -EEXIST;
+		goto out;
+	}
+
+	minor = request->cookie;
+	if (minor < 0) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	vbd = tapdisk_vbd_create(minor);
+	if (!vbd) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	err = asprintf(&devname, BLKTAP2_RING_DEVICE"%d", minor);
+	if (err == -1) {
+		err = -ENOMEM;
+		goto fail_vbd;
+	}
+
+	err = tapdisk_vbd_attach(vbd, devname, minor);
+	free(devname);
+	if (err)
+		goto fail_vbd;
+
+	tapdisk_server_add_vbd(vbd);
+
+out:
+	memset(&response, 0, sizeof(response));
+	response.type = TAPDISK_MESSAGE_ATTACH_RSP;
+	response.cookie = request->cookie;
+	response.u.response.error = -err;
+
+	tapdisk_control_write_message(connection->socket, &response, 2);
+	tapdisk_control_close_connection(connection);
+
+	return;
+
+fail_vbd:
+	tapdisk_vbd_detach(vbd);
+	free(vbd);
+	goto out;
+}
+
+
+static void
+tapdisk_control_detach_vbd(struct tapdisk_control_connection *connection,
+			   tapdisk_message_t *request)
+{
+	tapdisk_message_t response;
+	td_vbd_t *vbd;
+	int err;
+
+	vbd = tapdisk_server_get_vbd(request->cookie);
+	if (!vbd) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	tapdisk_vbd_detach(vbd);
+
+	if (list_empty(&vbd->images)) {
+		tapdisk_server_remove_vbd(vbd);
+		free(vbd);
+	}
+
+	err = 0;
+out:
+	memset(&response, 0, sizeof(response));
+	response.type = TAPDISK_MESSAGE_DETACH_RSP;
+	response.cookie = request->cookie;
+	response.u.response.error = -err;
+
+	tapdisk_control_write_message(connection->socket, &response, 2);
+	tapdisk_control_close_connection(connection);
+}
+
+static void
+tapdisk_control_open_image(struct tapdisk_control_connection *connection,
+			   tapdisk_message_t *request)
+{
+	int err;
+	image_t image;
+	td_vbd_t *vbd;
+	td_flag_t flags;
+	tapdisk_message_t response;
+	struct blktap2_params params;
+
+	vbd = tapdisk_server_get_vbd(request->cookie);
+	if (!vbd) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (vbd->minor == -1) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (vbd->name) {
+		err = -EALREADY;
+		goto out;
+	}
+
+	flags = 0;
+	if (request->u.params.flags & TAPDISK_MESSAGE_FLAG_RDONLY)
+		flags |= TD_OPEN_RDONLY;
+	if (request->u.params.flags & TAPDISK_MESSAGE_FLAG_SHARED)
+		flags |= TD_OPEN_SHAREABLE;
+	if (request->u.params.flags & TAPDISK_MESSAGE_FLAG_ADD_CACHE)
+		flags |= TD_OPEN_ADD_CACHE;
+	if (request->u.params.flags & TAPDISK_MESSAGE_FLAG_VHD_INDEX)
+		flags |= TD_OPEN_VHD_INDEX;
+	if (request->u.params.flags & TAPDISK_MESSAGE_FLAG_LOG_DIRTY)
+		flags |= TD_OPEN_LOG_DIRTY;
+
+	vbd->name = strndup(request->u.params.path,
+			    sizeof(request->u.params.path));
+	if (!vbd->name) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	err = tapdisk_vbd_parse_stack(vbd, request->u.params.path);
+	if (err)
+		goto out;
+
+	err = tapdisk_vbd_open_stack(vbd, request->u.params.storage, flags);
+	if (err)
+		goto out;
+
+	err = tapdisk_vbd_get_image_info(vbd, &image);
+	if (err)
+		goto fail_close;
+
+	params.capacity = image.size;
+	params.sector_size = image.secsize;
+
+	err = ioctl(vbd->ring.fd, BLKTAP2_IOCTL_CREATE_DEVICE, &params);
+	if (err && errno != EEXIST) {
+		err = -errno;
+		EPRINTF("create device failed: %d\n", err);
+		goto fail_close;
+	}
+
+	err = 0;
+
+out:
+	memset(&response, 0, sizeof(response));
+	response.cookie = request->cookie;
+
+	if (err) {
+		response.type                = TAPDISK_MESSAGE_ERROR;
+		response.u.response.error    = -err;
+	} else {
+		response.u.image.sectors     = image.size;
+		response.u.image.sector_size = image.secsize;
+		response.u.image.info        = image.info;
+		response.type                = TAPDISK_MESSAGE_OPEN_RSP;
+	}
+
+	tapdisk_control_write_message(connection->socket, &response, 2);
+	tapdisk_control_close_connection(connection);
+
+	return;
+
+fail_close:
+	tapdisk_vbd_close_vdi(vbd);
+	free(vbd->name);
+	vbd->name = NULL;
+	goto out;
+}
+
+static void
+tapdisk_control_close_image(struct tapdisk_control_connection *connection,
+			    tapdisk_message_t *request)
+{
+	tapdisk_message_t response;
+	td_vbd_t *vbd;
+	int err;
+
+	vbd = tapdisk_server_get_vbd(request->cookie);
+	if (!vbd) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (!list_empty(&vbd->pending_requests)) {
+		err = -EAGAIN;
+		goto out;
+	}
+
+	tapdisk_vbd_close_vdi(vbd);
+
+	/* NB. vbd->name free should probably belong into close_vdi,
+	   but the current blktap1 reopen-stuff likely depends on a
+	   lifetime extended until shutdown. */
+	free(vbd->name);
+	vbd->name = NULL;
+
+	if (vbd->minor == -1) {
+		tapdisk_server_remove_vbd(vbd);
+		tapdisk_vbd_free(vbd);
+	}
+
+	err = 0;
+out:
+	memset(&response, 0, sizeof(response));
+	response.type = TAPDISK_MESSAGE_CLOSE_RSP;
+	response.cookie = request->cookie;
+	response.u.response.error = -err;
+
+	tapdisk_control_write_message(connection->socket, &response, 2);
+	tapdisk_control_close_connection(connection);
+}
+
+static void
+tapdisk_control_pause_vbd(struct tapdisk_control_connection *connection,
+			  tapdisk_message_t *request)
+{
+	int err;
+	td_vbd_t *vbd;
+	tapdisk_message_t response;
+
+	memset(&response, 0, sizeof(response));
+
+	response.type = TAPDISK_MESSAGE_PAUSE_RSP;
+
+	vbd = tapdisk_server_get_vbd(request->cookie);
+	if (!vbd) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	do {
+		err = tapdisk_vbd_pause(vbd);
+
+		if (!err || err != -EAGAIN)
+			break;
+
+		tapdisk_server_iterate();
+	} while (1);
+
+out:
+	response.cookie = request->cookie;
+	response.u.response.error = -err;
+	tapdisk_control_write_message(connection->socket, &response, 2);
+	tapdisk_control_close_connection(connection);
+}
+
+static void
+tapdisk_control_resume_vbd(struct tapdisk_control_connection *connection,
+			   tapdisk_message_t *request)
+{
+	int err;
+	td_vbd_t *vbd;
+	tapdisk_message_t response;
+
+	memset(&response, 0, sizeof(response));
+
+	response.type = TAPDISK_MESSAGE_RESUME_RSP;
+
+	vbd = tapdisk_server_get_vbd(request->cookie);
+	if (!vbd) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (!td_flag_test(vbd->state, TD_VBD_PAUSED)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (request->u.params.path[0]) {
+		free(vbd->name);
+		vbd->name = strndup(request->u.params.path,
+				    sizeof(request->u.params.path));
+		if (!vbd->name) {
+			err = -ENOMEM;
+			goto out;
+		}
+	} else if (!vbd->name) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = tapdisk_vbd_parse_stack(vbd, vbd->name);
+	if (err)
+		goto out;
+
+	err = tapdisk_vbd_resume(vbd, NULL, -1);
+	if (err)
+		goto out;
+
+out:
+	response.cookie = request->cookie;
+	response.u.response.error = -err;
+	tapdisk_control_write_message(connection->socket, &response, 2);
+	tapdisk_control_close_connection(connection);
+}
+
+static void
+tapdisk_control_handle_request(event_id_t id, char mode, void *private)
+{
+	int err;
+	tapdisk_message_t message;
+	struct tapdisk_control_connection *connection =
+		(struct tapdisk_control_connection *)private;
+
+	if (tapdisk_control_read_message(connection->socket, &message, 2)) {
+		EPRINTF("failed to read message from %d\n", connection->socket);
+		tapdisk_control_close_connection(connection);
+		return;
+	}
+
+	err = tapdisk_control_validate_request(&message);
+	if (err)
+		goto fail;
+
+	switch (message.type) {
+	case TAPDISK_MESSAGE_PID:
+		return tapdisk_control_get_pid(connection, &message);
+	case TAPDISK_MESSAGE_LIST_MINORS:
+		return tapdisk_control_list_minors(connection, &message);
+	case TAPDISK_MESSAGE_LIST:
+		return tapdisk_control_list(connection, &message);
+	case TAPDISK_MESSAGE_ATTACH:
+		return tapdisk_control_attach_vbd(connection, &message);
+	case TAPDISK_MESSAGE_DETACH:
+		return tapdisk_control_detach_vbd(connection, &message);
+	case TAPDISK_MESSAGE_OPEN:
+		return tapdisk_control_open_image(connection, &message);
+	case TAPDISK_MESSAGE_PAUSE:
+		return tapdisk_control_pause_vbd(connection, &message);
+	case TAPDISK_MESSAGE_RESUME:
+		return tapdisk_control_resume_vbd(connection, &message);
+	case TAPDISK_MESSAGE_CLOSE:
+		return tapdisk_control_close_image(connection, &message);
+	default: {
+		tapdisk_message_t response;
+	fail:
+
+		EPRINTF("received unsupported message '%s'\n",
+			tapdisk_message_name(message.type));
+
+		memset(&response, 0, sizeof(response));
+
+		response.type = TAPDISK_MESSAGE_ERROR;
+		response.u.response.error = (err ? -err : EINVAL);
+		tapdisk_control_write_message(connection->socket, &response, 2);
+
+		tapdisk_control_close_connection(connection);
+		break;
+	}
+	}
+}
+
+static void
+tapdisk_control_accept(event_id_t id, char mode, void *private)
+{
+	int err, fd;
+	struct tapdisk_control_connection *connection;
+
+	fd = accept(td_control.socket, NULL, NULL);
+	if (fd == -1) {
+		EPRINTF("failed to accept new control connection: %d\n", errno);
+		return;
+	}
+
+	connection = tapdisk_control_allocate_connection(fd);
+	if (!connection) {
+		close(fd);
+		EPRINTF("failed to allocate new control connection\n");
+	}
+
+	err = tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
+					    connection->socket, 0,
+					    tapdisk_control_handle_request,
+					    connection);
+	if (err == -1) {
+		close(fd);
+		free(connection);
+		EPRINTF("failed to register new control event: %d\n", err);
+	}
+
+	connection->event_id = err;
+}
+
+static int
+tapdisk_control_mkdir(const char *dir)
+{
+	int err;
+	char *ptr, *name, *start;
+
+	err = access(dir, W_OK | R_OK);
+	if (!err)
+		return 0;
+
+	name = strdup(dir);
+	if (!name)
+		return -ENOMEM;
+
+	start = name;
+
+	for (;;) {
+		ptr = strchr(start + 1, '/');
+		if (ptr)
+			*ptr = '\0';
+
+		err = mkdir(name, 0755);
+		if (err && errno != EEXIST) {
+			err = -errno;
+			EPRINTF("failed to create directory %s: %d\n",
+				  name, err);
+			break;
+		}
+
+		if (!ptr)
+			break;
+		else {
+			*ptr = '/';
+			start = ptr + 1;
+		}
+	}
+
+	free(name);
+	return err;
+}
+
+static int
+tapdisk_control_create_socket(char **socket_path)
+{
+	int err, flags;
+	struct sockaddr_un saddr;
+
+	err = tapdisk_control_mkdir(BLKTAP2_CONTROL_DIR);
+	if (err) {
+		EPRINTF("failed to create directory %s: %d\n",
+			BLKTAP2_CONTROL_DIR, err);
+		return err;
+	}
+
+	err = asprintf(&td_control.path, "%s/%s%d",
+		       BLKTAP2_CONTROL_DIR, BLKTAP2_CONTROL_SOCKET, getpid());
+	if (err == -1) {
+		td_control.path = NULL;
+		err = (errno ? : ENOMEM);
+		goto fail;
+	}
+
+	if (unlink(td_control.path) && errno != ENOENT) {
+		err = errno;
+		EPRINTF("failed to unlink %s: %d\n", td_control.path, errno);
+		goto fail;
+	}
+
+	td_control.socket = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (td_control.socket == -1) {
+		err = errno;
+		EPRINTF("failed to create control socket: %d\n", err);
+		goto fail;
+	}
+
+	memset(&saddr, 0, sizeof(saddr));
+	strncpy(saddr.sun_path, td_control.path, sizeof(saddr.sun_path));
+	saddr.sun_family = AF_UNIX;
+
+	err = bind(td_control.socket,
+		   (const struct sockaddr *)&saddr, sizeof(saddr));
+	if (err == -1) {
+		err = errno;
+		EPRINTF("failed to bind to %s: %d\n", saddr.sun_path, err);
+		goto fail;
+	}
+
+	err = listen(td_control.socket, 10);
+	if (err == -1) {
+		err = errno;
+		EPRINTF("failed to listen: %d\n", err);
+		goto fail;
+	}
+
+	err = tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
+					    td_control.socket, 0,
+					    tapdisk_control_accept, NULL);
+	if (err < 0) {
+		EPRINTF("failed to add watch: %d\n", err);
+		goto fail;
+	}
+
+	td_control.event_id = err;
+	*socket_path = td_control.path;
+
+	return 0;
+
+fail:
+	tapdisk_control_close();
+	return err;
+}
+
+int
+tapdisk_control_open(char **path)
+{
+	int err;
+
+	tapdisk_control_initialize();
+
+	return tapdisk_control_create_socket(path);
+}
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/drivers/tapdisk-control.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/drivers/tapdisk-control.h	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TAPDISK_CONTROL_H__
+#define __TAPDISK_CONTROL_H__
+
+int tapdisk_control_open(char **path);
+void tapdisk_control_close(void);
+
+#endif
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/drivers/tapdisk-server.c
--- a/tools/blktap2/drivers/tapdisk-server.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-server.c	Mon Jun 07 14:53:16 2010 -0700
@@ -63,6 +63,12 @@
 	return NULL;
 }
 
+struct list_head *
+tapdisk_server_get_all_vbds(void)
+{
+	return &server.vbds;
+}
+
 td_vbd_t *
 tapdisk_server_get_vbd(uint16_t uuid)
 {
@@ -218,24 +224,29 @@
 	tapdisk_server_close_aio();
 }
 
+void
+tapdisk_server_iterate(void)
+{
+	int ret;
+
+	tapdisk_server_assert_locks();
+	tapdisk_server_set_retry_timeout();
+	tapdisk_server_check_progress();
+
+	ret = scheduler_wait_for_events(&server.scheduler);
+	if (ret < 0)
+		DBG(TLOG_WARN, "server wait returned %d\n", ret);
+
+	tapdisk_server_check_vbds();
+	tapdisk_server_submit_tiocbs();
+	tapdisk_server_kick_responses();
+}
+
 static void
 __tapdisk_server_run(void)
 {
-	int ret;
-
-	while (server.run) {
-		tapdisk_server_assert_locks();
-		tapdisk_server_set_retry_timeout();
-		tapdisk_server_check_progress();
-
-		ret = scheduler_wait_for_events(&server.scheduler);
-		if (ret < 0)
-			DBG(TLOG_WARN, "server wait returned %d\n", ret);
-
-		tapdisk_server_check_vbds();
-		tapdisk_server_submit_tiocbs();
-		tapdisk_server_kick_responses();
-	}
+	while (server.run)
+		tapdisk_server_iterate();
 }
 
 static void
@@ -267,22 +278,50 @@
 }
 
 int
+tapdisk_server_init(void)
+{
+	memset(&server, 0, sizeof(server));
+	INIT_LIST_HEAD(&server.vbds);
+
+	scheduler_initialize(&server.scheduler);
+
+	return 0;
+}
+
+int
+tapdisk_server_complete(void)
+{
+	int err;
+
+	err = tapdisk_server_init_aio();
+	if (err)
+		goto fail;
+
+	server.run = 1;
+
+	return 0;
+
+fail:
+	tapdisk_server_close_aio();
+	return err;
+}
+
+int
 tapdisk_server_initialize(void)
 {
 	int err;
 
-	memset(&server, 0, sizeof(tapdisk_server_t));
-	INIT_LIST_HEAD(&server.vbds);
+	tapdisk_server_init();
 
-	scheduler_initialize(&server.scheduler);
-
-	err = tapdisk_server_init_aio();
+	err = tapdisk_server_complete();
 	if (err)
-		return err;
-
-	server.run = 1;
+		goto fail;
 
 	return 0;
+
+fail:
+	tapdisk_server_close();
+	return err;
 }
 
 int
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/drivers/tapdisk-server.h
--- a/tools/blktap2/drivers/tapdisk-server.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-server.h	Mon Jun 07 14:53:16 2010 -0700
@@ -28,6 +28,7 @@
 #ifndef _TAPDISK_SERVER_H_
 #define _TAPDISK_SERVER_H_
 
+#include "list.h"
 #include "tapdisk-vbd.h"
 #include "tapdisk-queue.h"
 
@@ -35,6 +36,7 @@
 
 td_image_t *tapdisk_server_get_shared_image(td_image_t *);
 
+struct list_head *tapdisk_server_get_all_vbds(void);
 td_vbd_t *tapdisk_server_get_vbd(td_uuid_t);
 void tapdisk_server_add_vbd(td_vbd_t *);
 void tapdisk_server_remove_vbd(td_vbd_t *);
@@ -47,8 +49,11 @@
 void tapdisk_server_unregister_event(event_id_t);
 void tapdisk_server_set_max_timeout(int);
 
+int tapdisk_server_init(void);
 int tapdisk_server_initialize(void);
+int tapdisk_server_complete(void);
 int tapdisk_server_run(void);
+void tapdisk_server_iterate(void);
 
 #define TAPDISK_TIOCBS              (TAPDISK_DATA_REQUESTS + 50)
 
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/drivers/tapdisk-vbd.c
--- a/tools/blktap2/drivers/tapdisk-vbd.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-vbd.c	Mon Jun 07 14:53:16 2010 -0700
@@ -38,7 +38,6 @@
 #include <memshr.h>
 #endif
 
-#include "libvhd.h"
 #include "tapdisk-image.h"
 #include "tapdisk-driver.h"
 #include "tapdisk-server.h"
@@ -93,25 +92,20 @@
 	}
 }
 
-int
-tapdisk_vbd_initialize(uint16_t uuid)
+td_vbd_t*
+tapdisk_vbd_create(uint16_t uuid)
 {
+	td_vbd_t *vbd;
 	int i;
-	td_vbd_t *vbd;
-
-	vbd = tapdisk_server_get_vbd(uuid);
-	if (vbd) {
-		EPRINTF("duplicate vbds! %u\n", uuid);
-		return -EEXIST;
-	}
 
 	vbd = calloc(1, sizeof(td_vbd_t));
 	if (!vbd) {
 		EPRINTF("failed to allocate tapdisk state\n");
-		return -ENOMEM;
+		return NULL;
 	}
 
 	vbd->uuid     = uuid;
+	vbd->minor    = -1;
 	vbd->ring.fd  = -1;
 
 	/* default blktap ring completion */
@@ -134,6 +128,22 @@
 	for (i = 0; i < MAX_REQUESTS; i++)
 		tapdisk_vbd_initialize_vreq(vbd->request_list + i);
 
+	return vbd;
+}
+
+int
+tapdisk_vbd_initialize(uint16_t uuid)
+{
+	td_vbd_t *vbd;
+
+	vbd = tapdisk_server_get_vbd(uuid);
+	if (vbd) {
+		EPRINTF("duplicate vbds! %u\n", uuid);
+		return -EEXIST;
+	}
+
+	vbd = tapdisk_vbd_create(uuid);
+
 	tapdisk_server_add_vbd(vbd);
 
 	return 0;
@@ -181,6 +191,8 @@
 
 	INIT_LIST_HEAD(&vbd->images);
 	td_flag_set(vbd->state, TD_VBD_CLOSED);
+
+	tapdisk_vbd_free_stack(vbd);
 }
 
 static int
@@ -646,9 +658,42 @@
 	return 0;
 }
 
+void
+tapdisk_vbd_detach(td_vbd_t *vbd)
+{
+	tapdisk_vbd_unregister_events(vbd);
+
+	tapdisk_vbd_unmap_device(vbd);
+	vbd->minor = -1;
+}
+
+
+int
+tapdisk_vbd_attach(td_vbd_t *vbd, const char *devname, int minor)
+{
+	int err;
+
+	err = tapdisk_vbd_map_device(vbd, devname);
+	if (err)
+		goto fail;
+
+	err = tapdisk_vbd_register_event_watches(vbd);
+	if (err)
+		goto fail;
+
+	vbd->minor = minor;
+
+	return 0;
+
+fail:
+	tapdisk_vbd_detach(vbd);
+
+	return err;
+}
+
 int
 tapdisk_vbd_open(td_vbd_t *vbd, const char *name, uint16_t type,
-		 uint16_t storage, const char *ring, td_flag_t flags)
+		 uint16_t storage, int minor, const char *ring, td_flag_t flags)
 {
 	int err;
 
@@ -656,20 +701,15 @@
 	if (err)
 		goto out;
 
-	err = tapdisk_vbd_map_device(vbd, ring);
-	if (err)
-		goto out;
-
-	err = tapdisk_vbd_register_event_watches(vbd);
+	err = tapdisk_vbd_attach(vbd, ring, minor);
 	if (err)
 		goto out;
 
 	return 0;
 
 out:
+	tapdisk_vbd_detach(vbd);
 	tapdisk_vbd_close_vdi(vbd);
-	tapdisk_vbd_unmap_device(vbd);
-	tapdisk_vbd_unregister_events(vbd);
 	free(vbd->name);
 	vbd->name = NULL;
 	return err;
@@ -727,11 +767,9 @@
 		vbd->kicked);
 
 	tapdisk_vbd_close_vdi(vbd);
-	tapdisk_vbd_unregister_events(vbd);
-	tapdisk_vbd_unmap_device(vbd);
+	tapdisk_vbd_detach(vbd);
 	tapdisk_server_remove_vbd(vbd);
-	free(vbd->name);
-	free(vbd);
+	tapdisk_vbd_free(vbd);
 
 	tlog_print_errors();
 
@@ -941,17 +979,18 @@
 		return -EINVAL;
 	}
 
-	free(vbd->name);
-	vbd->name = strdup(path);
-	if (!vbd->name) {
-		EPRINTF("copying new vbd %s name failed\n", path);
-		return -EINVAL;
+	if (path) {
+		free(vbd->name);
+		vbd->name = strdup(path);
+		if (!vbd->name) {
+			EPRINTF("copying new vbd %s name failed\n", path);
+			return -EINVAL;
+		}
 	}
-	vbd->type = drivertype;
 
 	for (i = 0; i < TD_VBD_EIO_RETRIES; i++) {
 		err = __tapdisk_vbd_open_vdi(vbd, TD_OPEN_STRICT);
-		if (!err)
+		if (err != -EIO)
 			break;
 
 		sleep(TD_VBD_EIO_SLEEP);
@@ -963,6 +1002,7 @@
 	tapdisk_vbd_start_queue(vbd);
 	td_flag_clear(vbd->state, TD_VBD_PAUSED);
 	td_flag_clear(vbd->state, TD_VBD_PAUSE_REQUESTED);
+	tapdisk_vbd_check_state(vbd);
 
 	return 0;
 }
@@ -1607,7 +1647,6 @@
 		err = -ENOMEM;
 		goto out;
 	}
-	vbd->type = type;
 
 	tapdisk_vbd_start_queue(vbd);
 
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/drivers/tapdisk-vbd.h
--- a/tools/blktap2/drivers/tapdisk-vbd.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk-vbd.h	Mon Jun 07 14:53:16 2010 -0700
@@ -89,7 +89,7 @@
 	char                       *name;
 
 	td_uuid_t                   uuid;
-	int                         type;
+	int                         minor;
 
 	struct list_head            driver_stack;
 
@@ -168,18 +168,24 @@
 	return list_entry(image->next.next, td_image_t, next);
 }
 
+td_vbd_t *tapdisk_vbd_create(td_uuid_t);
 int tapdisk_vbd_initialize(td_uuid_t);
 void tapdisk_vbd_set_callback(td_vbd_t *, td_vbd_cb_t, void *);
 int tapdisk_vbd_parse_stack(td_vbd_t *vbd, const char *path);
 int tapdisk_vbd_open(td_vbd_t *, const char *, uint16_t,
-		     uint16_t, const char *, td_flag_t);
+		     uint16_t, int, const char *, td_flag_t);
 int tapdisk_vbd_close(td_vbd_t *);
+void tapdisk_vbd_free(td_vbd_t *);
 void tapdisk_vbd_free_stack(td_vbd_t *);
 
+int tapdisk_vbd_open_stack(td_vbd_t *, uint16_t, td_flag_t);
 int tapdisk_vbd_open_vdi(td_vbd_t *, const char *,
 			 uint16_t, uint16_t, td_flag_t);
 void tapdisk_vbd_close_vdi(td_vbd_t *);
 
+int tapdisk_vbd_attach(td_vbd_t *, const char *, int);
+void tapdisk_vbd_detach(td_vbd_t *);
+
 void tapdisk_vbd_forward_request(td_request_t);
 
 int tapdisk_vbd_get_image_info(td_vbd_t *, image_t *);
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/drivers/tapdisk2.c
--- a/tools/blktap2/drivers/tapdisk2.c	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/drivers/tapdisk2.c	Mon Jun 07 14:53:16 2010 -0700
@@ -28,397 +28,37 @@
 #include <stdio.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <stdlib.h>
 #include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
 #ifdef MEMSHR
 #include <memshr.h>
 #endif
 
 #include "tapdisk.h"
-#include "blktap2.h"
-#include "tapdisk-vbd.h"
 #include "tapdisk-utils.h"
 #include "tapdisk-server.h"
-#include "tapdisk-disktype.h"
-
-#define TAPDISK2_VBD 0
-
-#define cprintf(_err, _f, _a...)					\
-	do {								\
-		if (child_out) {					\
-			fprintf(child_out, "%d: " _f, _err, ##_a);	\
-			fflush(child_out);				\
-		}							\
-	} while (0)
-
-#define CHILD_ERR(_err, _f, _a...)					\
-	do {								\
-		EPRINTF(_f, ##_a);					\
-		cprintf(_err, _f, ##_a);				\
-	} while (0)
-
-static int channel[2];
-static FILE *child_out;
-static struct blktap2_handle handle;
-
-static int
-tapdisk2_prepare_directory(void)
-{
-	int err;
-	char *ptr, *name, *start;
-
-	err = access(BLKTAP2_DIRECTORY, W_OK | R_OK);
-	if (!err)
-		return 0;
-
-	name = strdup(BLKTAP2_DIRECTORY);
-	if (!name)
-		return -ENOMEM;
-
-	start = name;
-
-	for (;;) {
-		ptr = strchr(start + 1, '/');
-		if (ptr)
-			*ptr = '\0';
-
-		err = mkdir(name, 0755);
-		if (err && errno != EEXIST) {
-			err = -errno;
-			CHILD_ERR(err, "failed to create directory %s: %d\n",
-				  name, err);
-			break;
-		}
-
-		if (!ptr)
-			break;
-		else {
-			*ptr = '/';
-			start = ptr + 1;
-		}
-	}
-
-	free(name);
-	return err;
-}
-
-static int
-tapdisk2_make_device(char *devname, int major, int minor, int perm)
-{
-	int err;
-	struct stat st;
-
-	err = tapdisk2_prepare_directory();
-	if (err)
-		return err;
-
-	if (!access(devname, F_OK))
-		if (unlink(devname)) {
-			CHILD_ERR(errno, "error unlinking %s: %d\n",
-				  devname, errno);
-			return -errno;
-		}
-
-	err = mknod(devname, perm, makedev(major, minor));
-	if (err) {
-		CHILD_ERR(errno, "mknod %s failed: %d\n", devname, -errno);
-		return -errno;
-	}
-
-	DPRINTF("Created %s device\n", devname);
-	return 0;
-}
-
-static int
-tapdisk2_check_environment(void)
-{
-	FILE *f;
-	int err, minor;
-	char name[256];
-
-	if (!access(BLKTAP2_CONTROL_DEVICE, R_OK | W_OK))
-		return 0;
-
-	memset(name, 0, sizeof(name));
-
-	f = fopen("/proc/misc", "r");
-	if (!f) {
-		CHILD_ERR(errno, "failed to open /proc/misc: %d\n", errno);
-		return -errno;
-	}
-
-	while (fscanf(f, "%d %256s", &minor, name) == 2)
-		if (!strcmp(name, BLKTAP2_CONTROL_NAME)) {
-			err = tapdisk2_make_device(BLKTAP2_CONTROL_DEVICE,
-						   MISC_MAJOR_NUMBER,
-						   minor, S_IFCHR | 0600);
-			goto out;
-		}
-
-	err = -ENOSYS;
-	CHILD_ERR(err, "didn't find %s in /proc/misc\n", BLKTAP2_CONTROL_NAME);
-
-out:
-	fclose(f);
-	return err;
-}
-
-static void
-tapdisk2_free_device(void)
-{
-	int fd, err;
-
-	fd = open(BLKTAP2_CONTROL_DEVICE, O_RDONLY);
-	if (fd == -1) {
-		CHILD_ERR(errno, "failed to open control device: %d\n", errno);
-		return;
-	}
-
-	err = ioctl(fd, BLKTAP2_IOCTL_FREE_TAP, handle.minor);
-	close(fd);
-}
-
-static int
-tapdisk2_prepare_device(void)
-{
-	char *name;
-	int fd, err;
-
-	fd = open(BLKTAP2_CONTROL_DEVICE, O_RDONLY);
-	if (fd == -1) {
-		CHILD_ERR(errno, "failed to open control device: %d\n", errno);
-		return -errno;
-	}
-
-	err = ioctl(fd, BLKTAP2_IOCTL_ALLOC_TAP, &handle);
-	close(fd);
-	if (err == -1) {
-		CHILD_ERR(errno, "failed to allocate new device: %d\n", errno);
-		return -errno;
-	}
-
-	err = asprintf(&name, "%s%d", BLKTAP2_RING_DEVICE, handle.minor);
-	if (err == -1) {
-		err = -ENOMEM;
-		goto fail;
-	}
-
-	err = tapdisk2_make_device(name, handle.ring,
-				   handle.minor, S_IFCHR | 0600);
-	free(name);
-	if (err) {
-		CHILD_ERR(err, "creating ring device for %d failed: %d\n",
-			  handle.minor, err);
-		goto fail;
-	}
-
-	err = asprintf(&name, "%s%d", BLKTAP2_IO_DEVICE, handle.minor);
-	if (err == -1) {
-		err = -ENOMEM;
-		goto fail;
-	}
-
-	err = tapdisk2_make_device(name, handle.device,
-				   handle.minor, S_IFBLK | 0600);
-	free(name);
-	if (err) {
-		CHILD_ERR(err, "creating IO device for %d failed: %d\n",
-			  handle.minor, err);
-		goto fail;
-	}
-
-	DPRINTF("new interface: ring: %u, device: %u, minor: %u\n",
-		handle.ring, handle.device, handle.minor);
-
-	return 0;
-
-fail:
-	tapdisk2_free_device();
-	return err;
-}
-
-static int
-tapdisk2_open_device(int type, const char *path, const char *name)
-{
-	int err;
-	td_vbd_t *vbd;
-	image_t image;
-	char *devname;
-	struct blktap2_params params;
-
-	err = tapdisk_vbd_initialize(TAPDISK2_VBD);
-	if (err)
-		return err;
-
-	vbd = tapdisk_server_get_vbd(TAPDISK2_VBD);
-	if (!vbd) {
-		err = -ENODEV;
-		CHILD_ERR(err, "couldn't find vbd\n");
-		return err;
-	}
-
-	err = asprintf(&devname, "%s%d", BLKTAP2_RING_DEVICE, handle.minor);
-	if (err == -1) {
-		err = -ENOMEM;
-		CHILD_ERR(err, "couldn't allocate ring\n");
-		return err;
-	}
-
-	err = tapdisk_vbd_parse_stack(vbd, name);
-	if (err) {
-		CHILD_ERR(err, "vbd_parse_stack failed: %d\n", err);
-		return err;
-	}
-
-	/* TODO: clean this up */
-	err = tapdisk_vbd_open(vbd, path, type,
-			       TAPDISK_STORAGE_TYPE_DEFAULT,
-			       devname, 0);
-	free(devname);
-	if (err) {
-		CHILD_ERR(err, "vbd open failed: %d\n", err);
-		return err;
-	}
-
-	memset(&params, 0, sizeof(params));
-	tapdisk_vbd_get_image_info(vbd, &image);
-
-	params.capacity    = image.size;
-	params.sector_size = image.secsize;
-	snprintf(params.name, sizeof(params.name) - 1, "%s", name);
-
-	err = ioctl(vbd->ring.fd, BLKTAP2_IOCTL_CREATE_DEVICE, &params);
-	if (err) {
-		err = -errno;
-		CHILD_ERR(err, "create device failed: %d\n", err);
-		return err;
-	}
-
-	return 0;
-}
-
-static int
-tapdisk2_set_child_fds(void)
-{
-	int i, err;
-
-	err = dup2(channel[1], STDOUT_FILENO);
-	if (err == -1) {
-		CHILD_ERR(errno, "failed duping pipe: %d\n", errno);
-		return errno;
-	}
-
-	child_out = fdopen(STDOUT_FILENO, "w");
-	if (!child_out) {
-		CHILD_ERR(errno, "failed setting child_out: %d\n", errno);
-		return errno;
-	}
-
-	for (i = 0; i < sysconf(_SC_OPEN_MAX); i++)
-		if (i != STDOUT_FILENO)
-			close(i);
-
-	return 0;
-}
-
-static int
-tapdisk2_create_device(const char *params)
-{
-	const char *path;
-	int err, type;
-
-	chdir("/");
-	tapdisk_start_logging("tapdisk2");
-
-	err = tapdisk2_set_child_fds();
-	if (err)
-		goto out;
-
-	err = tapdisk2_check_environment();
-	if (err)
-		goto out;
-
-	err = tapdisk_parse_disk_type(params, &path, &type);
-	if (err)
-		goto out;
-
-	err = tapdisk2_prepare_device();
-	if (err)
-		goto out;
-
-	err = tapdisk_server_initialize();
-	if (err)
-		goto fail;
-
-	err = tapdisk2_open_device(type, path, params);
-	if (err)
-		goto fail;
-
-	cprintf(0, "%s%d\n", BLKTAP2_IO_DEVICE, handle.minor);
-	close(STDOUT_FILENO);
-
-	err = tapdisk_server_run();
-	if (err)
-		goto fail;
-
-	err = 0;
-
-out:
-	tapdisk_stop_logging();
-	return err;
-
-fail:
-	tapdisk2_free_device();
-	goto out;
-}
-
-static int
-tapdisk2_wait_for_device(void)
-{
-	int err;
-	char msg[1024];
-	FILE *parent_in;
-
-	close(channel[1]);
-	parent_in = fdopen(channel[0], "r");
-	if (!parent_in) {
-		printf("failed to connect to child: %d\n", errno);
-		return errno;
-	}
-
-	memset(msg, 0, sizeof(msg));
-	if (fscanf(parent_in, "%d: %1023[^\n]", &err, msg) != 2) {
-		printf("unrecognized child response\n");
-		return EINVAL;
-	}
-
-	printf("%s\n", msg);
-	return (err >= 0 ? err : -err);
-}
+#include "tapdisk-control.h"
 
 static void
 usage(const char *app, int err)
 {
-	fprintf(stderr, "usage: %s <-n file>\n", app);
+	fprintf(stderr, "usage: %s <-u uuid> <-c control socket>\n", app);
 	exit(err);
 }
 
 int
 main(int argc, char *argv[])
 {
-	int c;
-	char *params;
+	char *control;
+	int c, err, nodaemon;
 
-	params = NULL;
+	control  = NULL;
+	nodaemon = 0;
 
-	while ((c = getopt(argc, argv, "n:s:h")) != -1) {
+	while ((c = getopt(argc, argv, "s:Dh")) != -1) {
 		switch (c) {
-		case 'n':
-			params = optarg;
+		case 'D':
+			nodaemon = 1;
 			break;
 		case 'h':
 			usage(argv[0], 0);
@@ -436,21 +76,58 @@
 		}
 	}
 
-	if (!params || optind != argc)
+	if (optind != argc)
 		usage(argv[0], EINVAL);
 
-	if (pipe(channel) == -1) {
-		printf("pipe failed: %d\n", errno);
-		return errno;
+	chdir("/");
+	tapdisk_start_logging("tapdisk2");
+
+	err = tapdisk_server_init();
+	if (err) {
+		DPRINTF("failed to initialize server: %d\n", err);
+		goto out;
 	}
 
-	switch (fork()) {
-	case -1:
-		printf("fork failed: %d\n", errno);
-		return errno;
-	case 0:
-		return tapdisk2_create_device(params);
-	default:
-		return tapdisk2_wait_for_device();
+	if (!nodaemon) {
+		err = daemon(0, 1);
+		if (err) {
+			DPRINTF("failed to daemonize: %d\n", errno);
+			goto out;
+		}
 	}
+
+	err = tapdisk_control_open(&control);
+	if (err) {
+		DPRINTF("failed to open control socket: %d\n", err);
+		goto out;
+	}
+
+	fprintf(stdout, "%s\n", control);
+	fflush(stdout);
+
+	if (!nodaemon) {
+		int fd;
+
+		fd = open("/dev/null", O_RDWR);
+		if (fd != -1) {
+			dup2(fd, STDIN_FILENO);
+			dup2(fd, STDOUT_FILENO);
+			dup2(fd, STDERR_FILENO);
+			if (fd > 2)
+				close(fd);
+		}
+	}
+
+	err = tapdisk_server_complete();
+	if (err) {
+		DPRINTF("failed to complete server: %d\n", err);
+		goto out;
+	}
+
+	err = tapdisk_server_run();
+
+out:
+	tapdisk_control_close();
+	tapdisk_stop_logging();
+	return err;
 }
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/include/blktap2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap2/include/blktap2.h	Mon Jun 07 14:53:16 2010 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _BLKTAP_2_H_
+#define _BLKTAP_2_H_
+
+#define BLKTAP2_MAX_MESSAGE_LEN        256
+
+#define BLKTAP2_RING_MESSAGE_PAUSE     1
+#define BLKTAP2_RING_MESSAGE_RESUME    2
+#define BLKTAP2_RING_MESSAGE_CLOSE     3
+
+#define BLKTAP2_IOCTL_KICK_FE          1
+#define BLKTAP2_IOCTL_ALLOC_TAP        200
+#define BLKTAP2_IOCTL_FREE_TAP         201
+#define BLKTAP2_IOCTL_CREATE_DEVICE    202
+#define BLKTAP2_IOCTL_SET_PARAMS       203
+#define BLKTAP2_IOCTL_PAUSE            204
+#define BLKTAP2_IOCTL_REOPEN           205
+#define BLKTAP2_IOCTL_RESUME           206
+
+#define BLKTAP2_SYSFS_DIR              "/sys/class/blktap2"
+#define BLKTAP2_CONTROL_NAME           "blktap-control"
+#define BLKTAP2_CONTROL_DIR            "/var/run/"BLKTAP2_CONTROL_NAME
+#define BLKTAP2_CONTROL_SOCKET         "ctl"
+#define BLKTAP2_DIRECTORY              "/dev/xen/blktap-2"
+#define BLKTAP2_CONTROL_DEVICE         BLKTAP2_DIRECTORY"/control"
+#define BLKTAP2_RING_DEVICE            BLKTAP2_DIRECTORY"/blktap"
+#define BLKTAP2_IO_DEVICE              BLKTAP2_DIRECTORY"/tapdev"
+
+struct blktap2_handle {
+	unsigned int                   ring;
+	unsigned int                   device;
+	unsigned int                   minor;
+};
+
+struct blktap2_params {
+	char                           name[BLKTAP2_MAX_MESSAGE_LEN];
+	unsigned long long             capacity;
+	unsigned long                  sector_size;
+};
+
+#endif
diff -r 3ea1751e3fe7 -r ccef87cf5f41 tools/blktap2/include/tapdisk-message.h
--- a/tools/blktap2/include/tapdisk-message.h	Mon Jun 07 14:53:15 2010 -0700
+++ b/tools/blktap2/include/tapdisk-message.h	Mon Jun 07 14:53:16 2010 -0700
@@ -33,6 +33,9 @@
 #define TAPDISK_MESSAGE_MAX_PATH_LENGTH  256
 #define TAPDISK_MESSAGE_STRING_LENGTH    256
 
+#define TAPDISK_MESSAGE_MAX_MINORS \
+	((TAPDISK_MESSAGE_MAX_PATH_LENGTH / sizeof(int)) - 1)
+
 #define TAPDISK_MESSAGE_FLAG_SHARED      0x01
 #define TAPDISK_MESSAGE_FLAG_RDONLY      0x02
 #define TAPDISK_MESSAGE_FLAG_ADD_CACHE   0x04
@@ -44,10 +47,13 @@
 typedef struct tapdisk_message_image     tapdisk_message_image_t;
 typedef struct tapdisk_message_params    tapdisk_message_params_t;
 typedef struct tapdisk_message_string    tapdisk_message_string_t;
+typedef struct tapdisk_message_response  tapdisk_message_response_t;
+typedef struct tapdisk_message_minors    tapdisk_message_minors_t;
+typedef struct tapdisk_message_list      tapdisk_message_list_t;
 
 struct tapdisk_message_params {
 	tapdisk_message_flag_t           flags;
-	
+
 	uint8_t                          storage;
 	uint32_t                         devnum;
 	uint32_t                         domid;
@@ -65,6 +71,23 @@
 	char                             text[TAPDISK_MESSAGE_STRING_LENGTH];
 };
 
+struct tapdisk_message_response {
+	int                              error;
+	char                             message[TAPDISK_MESSAGE_STRING_LENGTH];
+};
+
+struct tapdisk_message_minors {
+	int                              count;
+	int                              list[TAPDISK_MESSAGE_MAX_MINORS];
+};
+
+struct tapdisk_message_list {
+	int                              count;
+	int                              minor;
+	int                              state;
+	char                             path[TAPDISK_MESSAGE_MAX_PATH_LENGTH];
+};
+
 struct tapdisk_message {
 	uint16_t                         type;
 	uint16_t                         cookie;
@@ -74,6 +97,9 @@
 		tapdisk_message_image_t  image;
 		tapdisk_message_params_t params;
 		tapdisk_message_string_t string;
+		tapdisk_message_minors_t minors;
+		tapdisk_message_response_t response;
+		tapdisk_message_list_t   list;
 	} u;
 };
 
@@ -82,6 +108,8 @@
 	TAPDISK_MESSAGE_RUNTIME_ERROR,
 	TAPDISK_MESSAGE_PID,
 	TAPDISK_MESSAGE_PID_RSP,
+	TAPDISK_MESSAGE_ATTACH,
+	TAPDISK_MESSAGE_ATTACH_RSP,
 	TAPDISK_MESSAGE_OPEN,
 	TAPDISK_MESSAGE_OPEN_RSP,
 	TAPDISK_MESSAGE_PAUSE,
@@ -90,6 +118,13 @@
 	TAPDISK_MESSAGE_RESUME_RSP,
 	TAPDISK_MESSAGE_CLOSE,
 	TAPDISK_MESSAGE_CLOSE_RSP,
+	TAPDISK_MESSAGE_DETACH,
+	TAPDISK_MESSAGE_DETACH_RSP,
+	TAPDISK_MESSAGE_LIST_MINORS,
+	TAPDISK_MESSAGE_LIST_MINORS_RSP,
+	TAPDISK_MESSAGE_LIST,
+	TAPDISK_MESSAGE_LIST_RSP,
+	TAPDISK_MESSAGE_FORCE_SHUTDOWN,
 	TAPDISK_MESSAGE_EXIT,
 };
 
@@ -127,9 +162,36 @@
 	case TAPDISK_MESSAGE_CLOSE:
 		return "close";
 
+	case TAPDISK_MESSAGE_FORCE_SHUTDOWN:
+		return "force shutdown";
+
 	case TAPDISK_MESSAGE_CLOSE_RSP:
 		return "close response";
 
+	case TAPDISK_MESSAGE_ATTACH:
+		return "attach";
+
+	case TAPDISK_MESSAGE_ATTACH_RSP:
+		return "attach response";
+
+	case TAPDISK_MESSAGE_DETACH:
+		return "detach";
+
+	case TAPDISK_MESSAGE_DETACH_RSP:
+		return "detach response";
+
+	case TAPDISK_MESSAGE_LIST_MINORS:
+		return "list minors";
+
+	case TAPDISK_MESSAGE_LIST_MINORS_RSP:
+		return "list minors response";
+
+	case TAPDISK_MESSAGE_LIST:
+		return "list";
+
+	case TAPDISK_MESSAGE_LIST_RSP:
+		return "list response";
+
 	case TAPDISK_MESSAGE_EXIT:
 		return "exit";
 

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface
  2010-06-07 21:54 [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
                   ` (5 preceding siblings ...)
  2010-06-07 21:54 ` [PATCH 6 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
@ 2010-06-07 21:54 ` Daniel Stodden
  2010-06-09 20:25   ` Jeremy Fitzhardinge
  2010-08-03 19:14 ` [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Łukasz Oleś
  7 siblings, 1 reply; 25+ messages in thread
From: Daniel Stodden @ 2010-06-07 21:54 UTC (permalink / raw)
  To: Xen

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

Signed-off-by: Jake Wires <jake.wires@citrix.com>



[-- Attachment #2: xend.diff --]
[-- Type: text/x-patch, Size: 10659 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1275947596 25200
# Node ID 7e76e35715c885549313acb55b06e607b8276ade
# Parent  ccef87cf5f4125061e46c7eb0d1483e6f369fb77
blktap2: Port Xend to the tap-ctl interface.

Signed-off-by: Jake Wires <jake.wires@citrix.com>

diff -r ccef87cf5f41 -r 7e76e35715c8 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py	Mon Jun 07 14:53:16 2010 -0700
+++ b/tools/python/xen/xend/XendDomainInfo.py	Mon Jun 07 14:53:16 2010 -0700
@@ -63,7 +63,7 @@
 from xen.xend.XendAPIConstants import *
 from xen.xend.XendCPUPool import XendCPUPool
 from xen.xend.server.DevConstants import xenbusState
-from xen.xend.server.BlktapController import TAPDISK_DEVICE, parseDeviceString
+from xen.xend.server.BlktapController import TapdiskController
 
 from xen.xend.XendVMMetrics import XendVMMetrics
 
@@ -549,15 +549,8 @@
                 dev =  xstransact.List(self.vmpath + '/device/tap2')
                 for x in dev:
                     path = self.getDeviceController('tap2').readBackend(x, 'params')
-                    if path and path.startswith(TAPDISK_DEVICE):
-                        try:
-                            _minor, _dev, ctrl = parseDeviceString(path)
-                            #pause the disk
-                            f = open(ctrl + '/pause', 'w')
-                            f.write('pause');
-                            f.close()
-                        except:
-                            pass
+                    if path and path.startswith(TapdiskController.TAP_DEV):
+                        TapdiskController.pause(path)
         except Exception, ex:
             log.warn('Could not pause blktap disk.');
 
@@ -578,17 +571,8 @@
                 dev =  xstransact.List(self.vmpath + '/device/tap2')
                 for x in dev:
                     path = self.getDeviceController('tap2').readBackend(x, 'params')
-                    if path and path.startswith(TAPDISK_DEVICE):
-                        try:
-                            #Figure out the sysfs path.
-                            _minor, _dev, ctrl = parseDeviceString(path)
-                            #unpause the disk
-                            if(os.path.exists(ctrl + '/resume')):                  
-                                f = open(ctrl + '/resume', 'w');
-                                f.write('resume');
-                                f.close();
-                        except:
-                            pass
+                    if path and path.startswith(TapdiskController.TAP_DEV):
+                        TapdiskController.unpause(path)
 
         except Exception, ex:
             log.warn('Could not unpause blktap disk: %s' % str(ex));
diff -r ccef87cf5f41 -r 7e76e35715c8 tools/python/xen/xend/server/BlktapController.py
--- a/tools/python/xen/xend/server/BlktapController.py	Mon Jun 07 14:53:16 2010 -0700
+++ b/tools/python/xen/xend/server/BlktapController.py	Mon Jun 07 14:53:16 2010 -0700
@@ -1,5 +1,5 @@
 # Copyright (c) 2005, XenSource Ltd.
-import string, re
+import string, re, os
 
 from xen.xend.server.blkif import BlkifController
 from xen.xend.XendLogging import log
@@ -8,11 +8,6 @@
 phantomDev = 0;
 phantomId = 0;
 
-TAPDISK_SYSFS   = '/sys/class/blktap2'
-TAPDISK_BINARY  = '/usr/sbin/tapdisk2'
-TAPDISK_DEVICE  = '/dev/xen/blktap-2/tapdev'
-TAPDISK_CONTROL = TAPDISK_SYSFS + '/blktap'
-
 blktap1_disk_types = [
     'aio',
     'sync',
@@ -43,20 +38,6 @@
     rc = proc.wait()
     return (rc,stdout,stderr)
 
-def parseDeviceString(device):
-    if device.find('/dev') == -1:
-        raise Exception, 'invalid tap device: ' + device
-
-    pattern = re.compile(TAPDISK_DEVICE + '(\d+)$')
-    groups  = pattern.search(device)
-    if not groups:
-        raise Exception, 'malformed tap device: ' + device
-
-    minor   = groups.group(1)
-    control = TAPDISK_CONTROL + minor
-
-    return minor, device, control
-
 # blktap1 device controller
 class BlktapController(BlkifController):
     def __init__(self, vm):
@@ -179,18 +160,10 @@
             (typ, params, file) = string.split(uname, ':', 2)
             subtyp = 'tapdisk'
 
-        #check for blktap2 installation.
-        blktap2_installed=0;
-        (rc,stdout, stderr) = doexec("cat /proc/devices");
-        out = stdout.read();
-        stdout.close();
-        stderr.close();
-        if( out.find("blktap2") >= 0 ):
-            blktap2_installed=1;
-
         if typ in ('tap'):
             if subtyp in ('tapdisk', 'ioemu'):
-                if params not in blktap2_disk_types or not blktap2_installed:
+                if params not in blktap2_disk_types or \
+                        TapdiskController.check():
                     # pass this device off to BlktapController
                     log.warn('WARNING: using deprecated blktap module')
                     self.deviceClass = 'tap'
@@ -198,22 +171,7 @@
                     self.deviceClass = 'tap2'
                     return devid
 
-        if self.vm.image and self.vm.image.memory_sharing:
-            cmd = [ TAPDISK_BINARY, '-n', '%s:%s' % (params, file), '-s', '%d' % self.vm.getDomid() ]
-        else:
-            cmd = [ TAPDISK_BINARY, '-n', '%s:%s' % (params, file) ]
-        (rc,stdout,stderr) = doexec(cmd)
-
-        if rc != 0:
-            err = stderr.read();
-            out = stdout.read();
-            stdout.close();
-            stderr.close();
-            raise Exception, 'Failed to create device.\n    stdout: %s\n    stderr: %s\nCheck that target \"%s\" exists and that blktap2 driver installed in dom0.' % (out.rstrip(), err.rstrip(), file);
-
-        minor, device, control = parseDeviceString(stdout.readline())
-        stdout.close();
-        stderr.close();
+        device = TapdiskController.create(params, file)
 
         # modify the configutration to create a blkback for the underlying
         # blktap2 device. Note: we need to preserve the original tapdisk uname
@@ -226,8 +184,7 @@
         config.pop('tapdisk_uname')
         return devid
 
-    # The new blocktap implementation requires a sysfs signal to close
-    # out disks.  This function is called from a thread when the
+    # This function is called from a thread when the
     # domain is detached from the disk.
     def finishDeviceCleanup(self, backpath, path):
         """Perform any device specific cleanup
@@ -239,14 +196,117 @@
 
         #Figure out what we're going to wait on.
         self.waitForBackend_destroy(backpath)
+        TapdiskController.destroy(path)
 
-        #Figure out the sysfs path.
-        minor, dev, ctrl = parseDeviceString(path)
+class TapdiskException(Exception):
+    pass
 
-        #Close out the disk
-        f = open(ctrl + '/remove', 'w')
-        f.write('remove');
-        f.close()
+class TapdiskController(object):
+    '''class which encapsulates all tapdisk control operations'''
 
-        return
+    TAP_CTL = 'tap-ctl'
+    TAP_DEV = '/dev/xen/blktap-2/tapdev'
 
+    class Tapdisk(object):
+        def __init__(self, pid=None, minor=-1, state=None,
+                     dtype='', image=None, device=None):
+            self.pid = pid
+            self.minor = minor
+            self.state = state
+            self.dtype = dtype
+            self.image = image
+            self.device = device
+
+        def __str__(self):
+            return 'image=%s pid=%s minor=%s state=%s type=%s device=%s' \
+                % (self.image, self.pid, self.minor, self.state, self.dtype,
+                   self.device)
+
+    @staticmethod
+    def exc(*args):
+        rc, stdout, stderr = doexec([TapdiskController.TAP_CTL] + list(args))
+        out, err = stdout.read().strip(), stderr.read().strip()
+        stdout.close()
+        stderr.close()
+        if rc:
+            raise TapdiskException('%s failed (%s %s %s)' % \
+                                       (args, rc, out, err))
+        return out
+
+    @staticmethod
+    def check():
+        try:
+            TapdiskController.exc('check')
+            return 0
+        except Exception, e:
+            log.warn("tapdisk2 check failed: %s" % e)
+            return -1
+
+    @staticmethod
+    def list():
+        tapdisks = []
+
+        _list = TapdiskController.exc('list')
+        if not _list: return []
+
+        for line in _list.split('\n'):
+            tapdisk = TapdiskController.Tapdisk()
+
+            for pair in line.split():
+                key, value = pair.split('=')
+                if key == 'pid':
+                    tapdisk.pid = value
+                elif key == 'minor':
+                    tapdisk.minor = int(value)
+                    if tapdisk.minor >= 0:
+                        tapdisk.device = '%s%s' % \
+                            (TapdiskController.TAP_DEV, tapdisk.minor)
+                elif key == 'state':
+                    tapdisk.state = value
+                elif key == 'args' and value.find(':') != -1:
+                    tapdisk.dtype, tapdisk.image = value.split(':')
+
+            tapdisks.append(tapdisk)
+
+        return tapdisks
+
+    @staticmethod
+    def fromDevice(device):
+        if device.startswith(TapdiskController.TAP_DEV):
+            minor = os.minor(os.stat(device).st_rdev)
+            tapdisks = filter(lambda x: x.minor == minor,
+                              TapdiskController.list())
+            if len(tapdisks) == 1:
+                return tapdisks[0]
+        return None
+
+    @staticmethod
+    def create(dtype, image):
+        return TapdiskController.exc('create', '-a%s:%s' % (dtype, image))
+
+    @staticmethod
+    def destroy(device):
+        tapdisk = TapdiskController.fromDevice(device)
+        if tapdisk:
+            if tapdisk.pid:
+                TapdiskController.exc('destroy',
+                                      '-p%s' % tapdisk.pid,
+                                      '-m%s' % tapdisk.minor)
+            else:
+                TapdiskController.exc('free', '-m%s' % tapdisk.minor)
+
+    @staticmethod
+    def pause(device):
+        tapdisk = TapdiskController.fromDevice(device)
+        if tapdisk and tapdisk.pid:
+            TapdiskController.exc('pause',
+                                  '-p%s' % tapdisk.pid,
+                                  '-m%s' % tapdisk.minor)
+
+    @staticmethod
+    def unpause(device):
+        tapdisk = TapdiskController.fromDevice(device)
+        if tapdisk and tapdisk.pid:
+            TapdiskController.exc('unpause',
+                                  '-p%s' % tapdisk.pid,
+                                  '-m%s' % tapdisk.minor)

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* Re: [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface
  2010-06-07 21:54 ` [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface Daniel Stodden
@ 2010-06-09 20:25   ` Jeremy Fitzhardinge
  2010-06-09 20:57     ` Daniel Stodden
  2010-06-10  3:26     ` [PATCH 0 of 4] libxl/blktap2 Daniel Stodden
  0 siblings, 2 replies; 25+ messages in thread
From: Jeremy Fitzhardinge @ 2010-06-09 20:25 UTC (permalink / raw)
  To: Daniel Stodden; +Cc: Xen, Stefano Stabellini

On 06/07/2010 02:54 PM, Daniel Stodden wrote:
> Signed-off-by: Jake Wires <jake.wires@citrix.com>
>
>   

Presumably libxl needs corresponding changes?  At the moment all my
tapdisk processes are dying complaining about being passed a "-n" option.

    J

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

* Re: [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface
  2010-06-09 20:25   ` Jeremy Fitzhardinge
@ 2010-06-09 20:57     ` Daniel Stodden
  2010-06-09 22:11       ` Daniel Stodden
  2010-06-10  3:26     ` [PATCH 0 of 4] libxl/blktap2 Daniel Stodden
  1 sibling, 1 reply; 25+ messages in thread
From: Daniel Stodden @ 2010-06-09 20:57 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: Xen, Stefano Stabellini

On Wed, 2010-06-09 at 16:25 -0400, Jeremy Fitzhardinge wrote:
> On 06/07/2010 02:54 PM, Daniel Stodden wrote:
> > Signed-off-by: Jake Wires <jake.wires@citrix.com>
> >
> >   
> 
> Presumably libxl needs corresponding changes?  At the moment all my
> tapdisk processes are dying complaining about being passed a "-n" option.

Uh, oh. I never looked into that stuff.

Will see what it takes. 

Anyone else maybe interested in doing that? No?

Daniel

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

* Re: [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface
  2010-06-09 20:57     ` Daniel Stodden
@ 2010-06-09 22:11       ` Daniel Stodden
  2010-06-09 22:32         ` Jeremy Fitzhardinge
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Stodden @ 2010-06-09 22:11 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: Xen, Stefano Stabellini

On Wed, 2010-06-09 at 16:57 -0400, Daniel Stodden wrote:
> On Wed, 2010-06-09 at 16:25 -0400, Jeremy Fitzhardinge wrote:
> > On 06/07/2010 02:54 PM, Daniel Stodden wrote:
> > > Signed-off-by: Jake Wires <jake.wires@citrix.com>
> > >
> > >   
> > 
> > Presumably libxl needs corresponding changes?  At the moment all my
> > tapdisk processes are dying complaining about being passed a "-n" option.
> 
> Uh, oh. I never looked into that stuff.
> 
> Will see what it takes. 
> 
> Anyone else maybe interested in doing that? No?

Does anyone have a sample config file flying around?

Thanks.

Daniel

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

* Re: [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface
  2010-06-09 22:11       ` Daniel Stodden
@ 2010-06-09 22:32         ` Jeremy Fitzhardinge
  0 siblings, 0 replies; 25+ messages in thread
From: Jeremy Fitzhardinge @ 2010-06-09 22:32 UTC (permalink / raw)
  To: Daniel Stodden; +Cc: Xen, Stefano Stabellini

On 06/09/2010 03:11 PM, Daniel Stodden wrote:
> On Wed, 2010-06-09 at 16:57 -0400, Daniel Stodden wrote:
>   
>> On Wed, 2010-06-09 at 16:25 -0400, Jeremy Fitzhardinge wrote:
>>     
>>> On 06/07/2010 02:54 PM, Daniel Stodden wrote:
>>>       
>>>> Signed-off-by: Jake Wires <jake.wires@citrix.com>
>>>>
>>>>   
>>>>         
>>> Presumably libxl needs corresponding changes?  At the moment all my
>>> tapdisk processes are dying complaining about being passed a "-n" option.
>>>       
>> Uh, oh. I never looked into that stuff.
>>
>> Will see what it takes. 
>>
>> Anyone else maybe interested in doing that? No?
>>     
> Does anyone have a sample config file flying around?
>   

Stock xm ones should work almost as-is with xl, except you:

    * need to specify a path to the config, as it doesn't default to
      /etc/xen
    * remove all explicit python code and just leave the assignments
    * use full paths for things like hvmloader

    J

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

* [PATCH 0 of 4] libxl/blktap2
  2010-06-09 20:25   ` Jeremy Fitzhardinge
  2010-06-09 20:57     ` Daniel Stodden
@ 2010-06-10  3:26     ` Daniel Stodden
  2010-06-10  3:26       ` [PATCH 1 of 4] blktap2: Fix broken tap-ctl-list type/path filter logic Daniel Stodden
                         ` (3 more replies)
  1 sibling, 4 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-10  3:26 UTC (permalink / raw)
  To: Xen


Cheers,
Daniel

 tools/blktap2/control/tap-ctl.c      |   4 +-
 tools/blktap2/control/tap-ctl-list.c |  30 +++++++++++
 tools/blktap2/control/tap-ctl.h      |   1 +
 tools/Rules.mk                       |   4 +
 tools/blktap2/control/Makefile       |  23 ++++++--
 tools/blktap2/control/tap-ctl.h      |   3 +-
 tools/libxl/Makefile                 |   4 +-
 tools/libxl/libxl.c                  |  93 ++++++++++-------------------------
 8 files changed, 83 insertions(+), 79 deletions(-)

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

* [PATCH 1 of 4] blktap2: Fix broken tap-ctl-list type/path filter logic
  2010-06-10  3:26     ` [PATCH 0 of 4] libxl/blktap2 Daniel Stodden
@ 2010-06-10  3:26       ` Daniel Stodden
  2010-06-10  3:26       ` [PATCH 2 of 4] blktap2: Add tap_ctl_find_minor Daniel Stodden
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-10  3:26 UTC (permalink / raw)
  To: Xen

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

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>


 tools/blktap2/control/tap-ctl.c |  4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)



[-- Attachment #2: tap-ctl-list-filter-fix.diff --]
[-- Type: text/x-patch, Size: 875 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1276140311 25200
# Node ID bbdfc4c5a31e26d23411a83edbef4a55ff904f2d
# Parent  28af9eb507f2c315e53bb72c03399c7e69062787
blktap2: Fix broken tap-ctl-list type/path filter logic.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>

diff -r 28af9eb507f2 -r bbdfc4c5a31e tools/blktap2/control/tap-ctl.c
--- a/tools/blktap2/control/tap-ctl.c	Wed Jun 09 07:55:19 2010 +0100
+++ b/tools/blktap2/control/tap-ctl.c	Wed Jun 09 20:25:11 2010 -0700
@@ -147,10 +147,10 @@
 		if (pid >= 0 && entry->pid != pid)
 			continue;
 
-		if (type && entry->type && strcmp(entry->type, type))
+		if (type && (!entry->type || strcmp(entry->type, type)))
 			continue;
 
-		if (file && entry->path && strcmp(entry->path, file))
+		if (file && (!entry->path || strcmp(entry->path, file)))
 			continue;
 
 		if (tty)

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* [PATCH 2 of 4] blktap2: Add tap_ctl_find_minor
  2010-06-10  3:26     ` [PATCH 0 of 4] libxl/blktap2 Daniel Stodden
  2010-06-10  3:26       ` [PATCH 1 of 4] blktap2: Fix broken tap-ctl-list type/path filter logic Daniel Stodden
@ 2010-06-10  3:26       ` Daniel Stodden
  2010-06-10  3:26       ` [PATCH 3 of 4] blktap2: Build libblktapctl.so Daniel Stodden
  2010-06-10  3:26       ` [PATCH 4 of 4] libxl: Use libblktapctl.so Daniel Stodden
  3 siblings, 0 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-10  3:26 UTC (permalink / raw)
  To: Xen

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

Slack 'tap-ctl find -t <type> -f <path>'.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>


 tools/blktap2/control/tap-ctl-list.c |  30 ++++++++++++++++++++++++++++++
 tools/blktap2/control/tap-ctl.h      |   1 +
 2 files changed, 31 insertions(+), 0 deletions(-)



[-- Attachment #2: tap-ctl-find-minor.diff --]
[-- Type: text/x-patch, Size: 1595 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1276140316 25200
# Node ID 51ed44eb2e9f899d338d9ee9a88903ff3c4216f5
# Parent  bbdfc4c5a31e26d23411a83edbef4a55ff904f2d
blktap2: Add tap_ctl_find_minor.

Slack 'tap-ctl find -t <type> -f <path>'.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>

diff -r bbdfc4c5a31e -r 51ed44eb2e9f tools/blktap2/control/tap-ctl-list.c
--- a/tools/blktap2/control/tap-ctl-list.c	Wed Jun 09 20:25:11 2010 -0700
+++ b/tools/blktap2/control/tap-ctl-list.c	Wed Jun 09 20:25:16 2010 -0700
@@ -504,3 +504,33 @@
 
 	return err;
 }
+
+int
+tap_ctl_find_minor(const char *type, const char *path)
+{
+	tap_list_t **list, **_entry;
+	int minor, err;
+
+	err = tap_ctl_list(&list);
+	if (err)
+		return err;
+
+	minor = -1;
+
+	for (_entry = list; *_entry != NULL; ++_entry) {
+		tap_list_t *entry  = *_entry;
+
+		if (type && (!entry->type || strcmp(entry->type, type)))
+			continue;
+
+		if (path && (!entry->path || strcmp(entry->path, path)))
+			continue;
+
+		minor = entry->minor;
+		break;
+	}
+
+	tap_ctl_free_list(list);
+
+	return minor >= 0 ? minor : -ENOENT;
+}
diff -r bbdfc4c5a31e -r 51ed44eb2e9f tools/blktap2/control/tap-ctl.h
--- a/tools/blktap2/control/tap-ctl.h	Wed Jun 09 20:25:11 2010 -0700
+++ b/tools/blktap2/control/tap-ctl.h	Wed Jun 09 20:25:16 2010 -0700
@@ -77,6 +77,7 @@
 
 int tap_ctl_list(tap_list_t ***list);
 void tap_ctl_free_list(tap_list_t **list);
+int tap_ctl_find_minor(const char *type, const char *path);
 
 int tap_ctl_allocate(int *minor, char **devname);
 int tap_ctl_free(const int minor);

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* [PATCH 3 of 4] blktap2: Build libblktapctl.so
  2010-06-10  3:26     ` [PATCH 0 of 4] libxl/blktap2 Daniel Stodden
  2010-06-10  3:26       ` [PATCH 1 of 4] blktap2: Fix broken tap-ctl-list type/path filter logic Daniel Stodden
  2010-06-10  3:26       ` [PATCH 2 of 4] blktap2: Add tap_ctl_find_minor Daniel Stodden
@ 2010-06-10  3:26       ` Daniel Stodden
  2010-06-10  3:26       ` [PATCH 4 of 4] libxl: Use libblktapctl.so Daniel Stodden
  3 siblings, 0 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-10  3:26 UTC (permalink / raw)
  To: Xen

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

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>


 tools/Rules.mk                  |   4 ++++
 tools/blktap2/control/Makefile  |  23 ++++++++++++++++-------
 tools/blktap2/control/tap-ctl.h |   3 +--
 3 files changed, 21 insertions(+), 9 deletions(-)



[-- Attachment #2: tap-ctl-so.diff --]
[-- Type: text/x-patch, Size: 2527 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1276140319 25200
# Node ID 6237d4168baad956d987c26f3408749c1c557e18
# Parent  51ed44eb2e9f899d338d9ee9a88903ff3c4216f5
blktap2: Build libblktapctl.so

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>

diff -r 51ed44eb2e9f -r 6237d4168baa tools/Rules.mk
--- a/tools/Rules.mk	Wed Jun 09 20:25:16 2010 -0700
+++ b/tools/Rules.mk	Wed Jun 09 20:25:19 2010 -0700
@@ -13,6 +13,7 @@
 XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
 XEN_XENSTORE       = $(XEN_ROOT)/tools/xenstore
 XEN_LIBXENSTAT     = $(XEN_ROOT)/tools/xenstat/libxenstat/src
+XEN_BLKTAP2        = $(XEN_ROOT)/tools/blktap2
 
 CFLAGS_include = -I$(XEN_INCLUDE)
 
@@ -25,6 +26,9 @@
 CFLAGS_libxenstore = -I$(XEN_XENSTORE) $(CFLAGS_include)
 LDFLAGS_libxenstore = -L$(XEN_XENSTORE) -lxenstore
 
+CFLAGS_libblktapctl = -I$(XEN_BLKTAP2)/control -I$(XEN_BLKTAP2)/include $(CFLAGS_include)
+LDFLAGS_libblktapctl = -L$(XEN_BLKTAP2)/control -lblktapctl
+
 X11_LDPATH = -L/usr/X11R6/$(LIBLEAFDIR)
 
 CFLAGS += -D__XEN_TOOLS__
diff -r 51ed44eb2e9f -r 6237d4168baa tools/blktap2/control/Makefile
--- a/tools/blktap2/control/Makefile	Wed Jun 09 20:25:16 2010 -0700
+++ b/tools/blktap2/control/Makefile	Wed Jun 09 20:25:19 2010 -0700
@@ -30,25 +30,34 @@
 CTL_OBJS  += tap-ctl-major.o
 CTL_OBJS  += tap-ctl-check.o
 
-OBJS = $(CTL_OBJS)
-LIBS = libblktapctl.a
+CTL_PICS  = $(patsubst %.o,%.opic,$(CTL_OBJS))
+
+OBJS = $(CTL_OBJS) tap-ctl.o
+PICS = $(CTL_PICS)
+
+LIBS = libblktapctl.a libblktapctl.so
+IBIN = tap-ctl
 
 all: build
 
-build: $(IBIN)
+build: $(IBIN) $(LIBS)
 
-tap-ctl: tap-ctl.o libblktapctl.a
+tap-ctl: tap-ctl.o libblktapctl.so
 	$(CC) $(CFLAGS) -o $@ $^
 
 libblktapctl.a: $(CTL_OBJS)
-	ar r $@ $^
+	$(AR) r $@ $^
 
-install: all
+libblktapctl.so: $(CTL_PICS)
+	$(CC) $(CFLAGS) -fPIC -shared -rdynamic $^ -o $@
+
+install: $(IBIN) $(LIBS)
 	$(INSTALL_DIR) -p $(DESTDIR)$(SBINDIR)
 	$(INSTALL_PROG) $(IBIN) $(DESTDIR)$(SBINDIR)
+	$(INSTALL_PROG) $(LIBS) $(DESTDIR)$(LIBDIR)
 
 clean:
-	rm -f $(OBJS) $(DEPS) $(IBIN) $(LIBS)
+	rm -f $(OBJS) $(PICS) $(DEPS) $(IBIN) $(LIBS)
 	rm -f *~
 
 .PHONY: all build clean install
diff -r 51ed44eb2e9f -r 6237d4168baa tools/blktap2/control/tap-ctl.h
--- a/tools/blktap2/control/tap-ctl.h	Wed Jun 09 20:25:16 2010 -0700
+++ b/tools/blktap2/control/tap-ctl.h	Wed Jun 09 20:25:19 2010 -0700
@@ -30,8 +30,7 @@
 
 #include <syslog.h>
 #include <errno.h>
-
-#include "tapdisk-message.h"
+#include <tapdisk-message.h>
 
 extern int tap_ctl_debug;
 

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* [PATCH 4 of 4] libxl: Use libblktapctl.so
  2010-06-10  3:26     ` [PATCH 0 of 4] libxl/blktap2 Daniel Stodden
                         ` (2 preceding siblings ...)
  2010-06-10  3:26       ` [PATCH 3 of 4] blktap2: Build libblktapctl.so Daniel Stodden
@ 2010-06-10  3:26       ` Daniel Stodden
  2010-06-10 15:43         ` Stefano Stabellini
  2010-06-10 16:25         ` Stefano Stabellini
  3 siblings, 2 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-10  3:26 UTC (permalink / raw)
  To: Xen

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

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>


 tools/libxl/Makefile |   4 +-
 tools/libxl/libxl.c  |  93 +++++++++++++++------------------------------------
 2 files changed, 29 insertions(+), 68 deletions(-)



[-- Attachment #2: libxl-tapctl.diff --]
[-- Type: text/x-patch, Size: 5924 bytes --]

# HG changeset patch
# User Daniel Stodden <daniel.stodden@citrix.com>
# Date 1276140349 25200
# Node ID 4b0360d2bba5ee673a866ac996176462214d3645
# Parent  6237d4168baad956d987c26f3408749c1c557e18
libxl: Use libblktapctl.so

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>

diff -r 6237d4168baa -r 4b0360d2bba5 tools/libxl/Makefile
--- a/tools/libxl/Makefile	Wed Jun 09 20:25:19 2010 -0700
+++ b/tools/libxl/Makefile	Wed Jun 09 20:25:49 2010 -0700
@@ -13,9 +13,9 @@
 
 CFLAGS += -Werror
 CFLAGS += -I. -fPIC
-CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) $(CFLAGS_libxenstore)
+CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) $(CFLAGS_libxenstore) $(CFLAGS_libblktapctl)
 
-LIBS = $(LDFLAGS_libxenctrl) $(LDFLAGS_libxenguest) $(LDFLAGS_libxenstore)
+LIBS = $(LDFLAGS_libxenctrl) $(LDFLAGS_libxenguest) $(LDFLAGS_libxenstore) $(LDFLAGS_libblktapctl)
 
 LIBXL_OBJS-y = osdeps.o libxl_paths.o
 LIBXL_OBJS = flexarray.o libxl.o libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o libxl_internal.o xenguest.o libxl_utils.o $(LIBXL_OBJS-y)
diff -r 6237d4168baa -r 4b0360d2bba5 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c	Wed Jun 09 20:25:19 2010 -0700
+++ b/tools/libxl/libxl.c	Wed Jun 09 20:25:49 2010 -0700
@@ -33,6 +33,7 @@
 #include "libxl_utils.h"
 #include "libxl_internal.h"
 #include "flexarray.h"
+#include "tap-ctl.h"
 
 #define PAGE_TO_MEMKB(pages) ((pages) * 4)
 
@@ -1240,44 +1241,25 @@
 
 /******************************************************************************/
 
-static int is_blktap2_supported(void)
+static char *get_blktap2_device(struct libxl_ctx *ctx,
+				const char *name, const char *type)
 {
-    char buf[1024];
-    FILE *f = fopen("/proc/devices", "r");
-
-    
-    while (fgets(buf, sizeof(buf), f) != NULL) {
-        if (strstr(buf, "blktap2")) {
-            fclose(f);
-            return 1;
-        }
-    }
-    fclose(f);
-    return 0;
+    int minor = tap_ctl_find_minor(type, name);
+    if (minor < 0)
+        return NULL;
+    return libxl_sprintf(ctx, "/dev/xen/blktap-2/tapdev%d", minor);
 }
 
-static char *get_blktap2_device(struct libxl_ctx *ctx, char *name, char *type)
+static char *make_blktap2_device(struct libxl_ctx *ctx,
+				 const char *name, const char *type)
 {
-    char buf[1024];
-    char *p;
-    int devnum;
-    FILE *f = fopen("/sys/class/blktap2/devices", "r");
-
-    
-    while (!feof(f)) {
-        if (fscanf(f, "%d %s", &devnum, buf) != 2)
-            continue;
-        p = strchr(buf, ':');
-        if (p == NULL)
-            continue;
-        p++;
-        if (!strcmp(p, name) && !strncmp(buf, type, 3)) {
-            fclose(f);
-            return libxl_sprintf(ctx, "/dev/xen/blktap-2/tapdev%d", devnum);
-        }
-    }
-    fclose(f);
-    return NULL;
+    char *params, *devname;
+    int err;
+    params = libxl_sprintf(ctx, "%s:%s", type, name);
+    devname = NULL;
+    err = tap_ctl_create(params, &devname);
+    free(params);
+    return err ? NULL : devname;
 }
 
 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
@@ -1328,38 +1310,16 @@
         case PHYSTYPE_FILE:
             /* let's pretend is tap:aio for the moment */
             disk->phystype = PHYSTYPE_AIO;
-        case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD:
-            if (is_blktap2_supported()) {
-                int rc, c, p[2], tot;
-                char buf[1024], *dev;
-                dev = get_blktap2_device(ctx, disk->physpath, device_disk_string_of_phystype(disk->phystype));
-                if (dev == NULL) {
-                    rc= libxl_pipe(ctx, p);  if (rc==-1) return -1;
-                    rc= libxl_fork(ctx);  if (rc==-1) return -1;
-                    if (!rc) { /* child */
-                        int null_r, null_w;
-                        char *args[4];
-                        args[0] = "tapdisk2";
-                        args[1] = "-n";
-                        args[2] = libxl_sprintf(ctx, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath);
-                        args[3] = NULL;
-
-                        null_r = open("/dev/null", O_RDONLY);
-                        null_w = open("/dev/null", O_WRONLY);
-                        libxl_exec(null_r, p[1], null_w,
-                                   libxl_abs_path(ctx, "tapdisk2",
-                                                  libxl_sbindir_path()),
-                                   args);
-                        XL_LOG(ctx, XL_LOG_ERROR, "Error execing tapdisk2");
-                    }
-                    close(p[1]);
-                    tot = 0;
-                    while ((c = read(p[0], buf + tot, sizeof(buf) - tot)) > 0)
-                        tot = tot + c;
-                    close(p[0]);
-                    buf[tot - 1] = '\0';
-                    dev = buf;
-                }
+        case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD: {
+            const char *msg;
+            if (!tap_ctl_check(&msg)) {
+                const char *type = device_disk_string_of_phystype(disk->phystype);
+                char *dev;
+                dev = get_blktap2_device(ctx, disk->physpath, type);
+                if (!dev)
+                    dev = make_blktap2_device(ctx, disk->physpath, type);
+                if (!dev)
+                    return -1;
                 flexarray_set(back, boffset++, "tapdisk-params");
                 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath));
                 flexarray_set(back, boffset++, "params");
@@ -1378,6 +1338,7 @@
 
             device.backend_kind = DEVICE_TAP;
             break;
+        }
         default:
             XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", disk->phystype);
             return ERROR_INVAL;

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* Re: [PATCH 4 of 4] libxl: Use libblktapctl.so
  2010-06-10  3:26       ` [PATCH 4 of 4] libxl: Use libblktapctl.so Daniel Stodden
@ 2010-06-10 15:43         ` Stefano Stabellini
  2010-06-10 20:11           ` Daniel Stodden
  2010-06-10 16:25         ` Stefano Stabellini
  1 sibling, 1 reply; 25+ messages in thread
From: Stefano Stabellini @ 2010-06-10 15:43 UTC (permalink / raw)
  To: Daniel Stodden; +Cc: Xen

On Thu, 10 Jun 2010, Daniel Stodden wrote:
> Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>

This patch broke file: and tap:aio support in xl/libxl.
Did you actually test it?

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

* Re: [PATCH 4 of 4] libxl: Use libblktapctl.so
  2010-06-10  3:26       ` [PATCH 4 of 4] libxl: Use libblktapctl.so Daniel Stodden
  2010-06-10 15:43         ` Stefano Stabellini
@ 2010-06-10 16:25         ` Stefano Stabellini
  2010-06-10 22:27           ` Daniel Stodden
  1 sibling, 1 reply; 25+ messages in thread
From: Stefano Stabellini @ 2010-06-10 16:25 UTC (permalink / raw)
  To: Daniel Stodden; +Cc: Xen

> -static char *get_blktap2_device(struct libxl_ctx *ctx, char *name, char *type)
> +static char *make_blktap2_device(struct libxl_ctx *ctx,
> +				 const char *name, const char *type)
>  {
> -    char buf[1024];
> -    char *p;
> -    int devnum;
> -    FILE *f = fopen("/sys/class/blktap2/devices", "r");
> -
> -    
> -    while (!feof(f)) {
> -        if (fscanf(f, "%d %s", &devnum, buf) != 2)
> -            continue;
> -        p = strchr(buf, ':');
> -        if (p == NULL)
> -            continue;
> -        p++;
> -        if (!strcmp(p, name) && !strncmp(buf, type, 3)) {
> -            fclose(f);
> -            return libxl_sprintf(ctx, "/dev/xen/blktap-2/tapdev%d", devnum);
> -        }
> -    }
> -    fclose(f);
> -    return NULL;
> +    char *params, *devname;
> +    int err;
> +    params = libxl_sprintf(ctx, "%s:%s", type, name);
> +    devname = NULL;
> +    err = tap_ctl_create(params, &devname);
> +    free(params);
> +    return err ? NULL : devname;
>  }
> 

you shouldn't free pointers returned by libxl internal functions,
because libxl will take care of free'ing them.

 
>  int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
> @@ -1328,38 +1310,16 @@
>          case PHYSTYPE_FILE:
>              /* let's pretend is tap:aio for the moment */
>              disk->phystype = PHYSTYPE_AIO;
> -        case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD:
> -            if (is_blktap2_supported()) {
> -                int rc, c, p[2], tot;
> -                char buf[1024], *dev;
> -                dev = get_blktap2_device(ctx, disk->physpath, device_disk_string_of_phystype(disk->phystype));
> -                if (dev == NULL) {
> -                    rc= libxl_pipe(ctx, p);  if (rc==-1) return -1;
> -                    rc= libxl_fork(ctx);  if (rc==-1) return -1;
> -                    if (!rc) { /* child */
> -                        int null_r, null_w;
> -                        char *args[4];
> -                        args[0] = "tapdisk2";
> -                        args[1] = "-n";
> -                        args[2] = libxl_sprintf(ctx, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath);
> -                        args[3] = NULL;
> -
> -                        null_r = open("/dev/null", O_RDONLY);
> -                        null_w = open("/dev/null", O_WRONLY);
> -                        libxl_exec(null_r, p[1], null_w,
> -                                   libxl_abs_path(ctx, "tapdisk2",
> -                                                  libxl_sbindir_path()),
> -                                   args);
> -                        XL_LOG(ctx, XL_LOG_ERROR, "Error execing tapdisk2");
> -                    }
> -                    close(p[1]);
> -                    tot = 0;
> -                    while ((c = read(p[0], buf + tot, sizeof(buf) - tot)) > 0)
> -                        tot = tot + c;
> -                    close(p[0]);
> -                    buf[tot - 1] = '\0';
> -                    dev = buf;
> -                }
> +        case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD: {
> +            const char *msg;
> +            if (!tap_ctl_check(&msg)) {
> +                const char *type = device_disk_string_of_phystype(disk->phystype);
> +                char *dev;
> +                dev = get_blktap2_device(ctx, disk->physpath, type);
> +                if (!dev)
> +                    dev = make_blktap2_device(ctx, disk->physpath, type);
> +                if (!dev)
> +                    return -1;
>                  flexarray_set(back, boffset++, "tapdisk-params");
>                  flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath));
>                  flexarray_set(back, boffset++, "params");
> 

you are calling make_blktap2_device only if(!dev), are you sure it is
correct? get_blktap2_device returns a pointer on success...

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

* Re: [PATCH 4 of 4] libxl: Use libblktapctl.so
  2010-06-10 15:43         ` Stefano Stabellini
@ 2010-06-10 20:11           ` Daniel Stodden
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel Stodden @ 2010-06-10 20:11 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Xen

On Thu, 2010-06-10 at 11:43 -0400, Stefano Stabellini wrote:
> On Thu, 10 Jun 2010, Daniel Stodden wrote:
> > Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
> 
> This patch broke file: and tap:aio support in xl/libxl.
> Did you actually test it?

Yes. Worked for for a couple runs.

Daniel

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

* Re: [PATCH 4 of 4] libxl: Use libblktapctl.so
  2010-06-10 16:25         ` Stefano Stabellini
@ 2010-06-10 22:27           ` Daniel Stodden
  2010-06-11 10:42             ` Stefano Stabellini
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Stodden @ 2010-06-10 22:27 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: xen-devel@lists.xensource.com

On Thu, 2010-06-10 at 12:25 -0400, Stefano Stabellini wrote:
> > -static char *get_blktap2_device(struct libxl_ctx *ctx, char *name, char *type)
> > +static char *make_blktap2_device(struct libxl_ctx *ctx,
> > +				 const char *name, const char *type)
> >  {
> > -    char buf[1024];
> > -    char *p;
> > -    int devnum;
> > -    FILE *f = fopen("/sys/class/blktap2/devices", "r");
> > -
> > -    
> > -    while (!feof(f)) {
> > -        if (fscanf(f, "%d %s", &devnum, buf) != 2)
> > -            continue;
> > -        p = strchr(buf, ':');
> > -        if (p == NULL)
> > -            continue;
> > -        p++;
> > -        if (!strcmp(p, name) && !strncmp(buf, type, 3)) {
> > -            fclose(f);
> > -            return libxl_sprintf(ctx, "/dev/xen/blktap-2/tapdev%d", devnum);
> > -        }
> > -    }
> > -    fclose(f);
> > -    return NULL;
> > +    char *params, *devname;
> > +    int err;
> > +    params = libxl_sprintf(ctx, "%s:%s", type, name);
> > +    devname = NULL;
> > +    err = tap_ctl_create(params, &devname);
> > +    free(params);
> > +    return err ? NULL : devname;
> >  }
> > 
> 
> you shouldn't free pointers returned by libxl internal functions,
> because libxl will take care of free'ing them.

I'll send an update. Sorry for that. Please don't hesitate to submit
corrections right away if you spot more issues.
 
>                  dev = buf;
> > -                }
> > +        case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD: {
> > +            const char *msg;
> > +            if (!tap_ctl_check(&msg)) {
> > +                const char *type = device_disk_string_of_phystype(disk->phystype);
> > +                char *dev;
> > +                dev = get_blktap2_device(ctx, disk->physpath, type);
> > +                if (!dev)
> > +                    dev = make_blktap2_device(ctx, disk->physpath, type);
> > +                if (!dev)
> > +                    return -1;
> >                  flexarray_set(back, boffset++, "tapdisk-params");
> >                  flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath));
> >                  flexarray_set(back, boffset++, "params");
> > 
> 
> you are calling make_blktap2_device only if(!dev), are you sure it is
> correct? get_blktap2_device returns a pointer on success...

I don't quite manage to follow this comment. The behavior was meant to
match the original version of that code. It still looks like it does. Is
that what you question?

Unless you're worried about null pointer handling with massively broken
compilers? Did you ever manage to find one? I didn't %-)

But again, if you're not happy with it, please just go ahead and make it
suit your coding preferences. I got zero stakes in that code. 

Btw, someone probably should also fix the device teardown path as well,
it seems to be consistently leaking device nodes. I guess enumerating
backend physical-device nodes to count vbds would probably do for a
'light' control layer.

Thanks for the input.

Daniel

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

* Re: [PATCH 4 of 4] libxl: Use libblktapctl.so
  2010-06-10 22:27           ` Daniel Stodden
@ 2010-06-11 10:42             ` Stefano Stabellini
  2010-06-11 13:00               ` Stefano Stabellini
  0 siblings, 1 reply; 25+ messages in thread
From: Stefano Stabellini @ 2010-06-11 10:42 UTC (permalink / raw)
  To: Daniel Stodden; +Cc: xen-devel@lists.xensource.com, Stefano Stabellini

On Thu, 10 Jun 2010, Daniel Stodden wrote:
> I don't quite manage to follow this comment. The behavior was meant to
> match the original version of that code. It still looks like it does. Is
> that what you question?
> 
> Unless you're worried about null pointer handling with massively broken
> compilers? Did you ever manage to find one? I didn't %-)
> 
> But again, if you're not happy with it, please just go ahead and make it
> suit your coding preferences. I got zero stakes in that code. 
> 

Nope, you are right, after a second look the code seems correct.
However it still doesn't work for me.
The device returned by make_blktap2_device is /dev/xen/blktap-2/tapdev0,
but "cat /sys/class/blktap2/devices" returns nothing and my VM doesn't
start.
Am I missing something?

> Btw, someone probably should also fix the device teardown path as well,
> it seems to be consistently leaking device nodes. I guess enumerating
> backend physical-device nodes to count vbds would probably do for a
> 'light' control layer.
> 

you are right, are you volunteering ? ;-)

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

* Re: [PATCH 4 of 4] libxl: Use libblktapctl.so
  2010-06-11 10:42             ` Stefano Stabellini
@ 2010-06-11 13:00               ` Stefano Stabellini
  0 siblings, 0 replies; 25+ messages in thread
From: Stefano Stabellini @ 2010-06-11 13:00 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: xen-devel@lists.xensource.com, Daniel Stodden

On Fri, 11 Jun 2010, Stefano Stabellini wrote:
> On Thu, 10 Jun 2010, Daniel Stodden wrote:
> > I don't quite manage to follow this comment. The behavior was meant to
> > match the original version of that code. It still looks like it does. Is
> > that what you question?
> > 
> > Unless you're worried about null pointer handling with massively broken
> > compilers? Did you ever manage to find one? I didn't %-)
> > 
> > But again, if you're not happy with it, please just go ahead and make it
> > suit your coding preferences. I got zero stakes in that code. 
> > 
> 
> Nope, you are right, after a second look the code seems correct.
> However it still doesn't work for me.
> The device returned by make_blktap2_device is /dev/xen/blktap-2/tapdev0,
> but "cat /sys/class/blktap2/devices" returns nothing and my VM doesn't
> start.
> Am I missing something?

Yes, I was missing something: my tapdisk2 was outdated, everything works
now.

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

* Re: [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface
@ 2010-07-07 16:33 Chao-Rui Chang
  0 siblings, 0 replies; 25+ messages in thread
From: Chao-Rui Chang @ 2010-07-07 16:33 UTC (permalink / raw)
  To: xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 195 bytes --]

Hello,

Does this patch work for xm tool ?

I can create vm by xl, but I can't create vm by xm.

It seems that xm does not call /usr/sbin/tap-ctl to set tap device
correctly.

any help?

Thanks.

[-- Attachment #1.2: Type: text/html, Size: 235 bytes --]

[-- Attachment #2: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* Re: [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library
  2010-06-07 21:54 [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
                   ` (6 preceding siblings ...)
  2010-06-07 21:54 ` [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface Daniel Stodden
@ 2010-08-03 19:14 ` Łukasz Oleś
  7 siblings, 0 replies; 25+ messages in thread
From: Łukasz Oleś @ 2010-08-03 19:14 UTC (permalink / raw)
  To: xen-devel

On Monday 07 June 2010 23:54:47 Daniel Stodden wrote:
> Hi.
> 
> Apart from removing some dead code and tidying up tapdisk-vbd a
> little, the bigger introduces our new tap-ctl utility code.
> 
> The code aims to be a complete replacement for the original blktap2
> control path, run through sysfs. Fully implemented in userspace, all
> tapdisks now gained a small IPC layer on top of Unix domain sockets.
> 
> Sample usage:
> 
> # tap-ctl allocate
> /dev/xen/blktap-2/tapdev0
> 
> # tap-ctl spawn
> tapdisk spawned with pid 4168
> 
> # tap-ctl list
>     4168  -    -          - -
>        -  0    -          - -
> 
> # tap-ctl attach -p 4168 -m 0
> # tap-ctl list
>     4168  0    0          - -
> 
> # tap-ctl open -p 4168 -m 0 -a aio:/var/tmp/lenny.ext
> 
> # tap-ctl list
>     4168  0    0        aio /var/tmp/lenny.ext
> 
> # tap-ctl close -p 4168 -m 0
> # tap-ctl detach -p 4168 -m 0
> # tap-ctl free -m 0
> 
> The above example is a bit noisy, because it's mediating between minor
> number (block devices), tapdisks and tapdisk VBDs (the tapdisk I/O
> queue running a bdev) in detail.
> 
> There are shortcuts. At the same time, the low-level interface should
> be general enough to stay extensible, and help accomodate some of the
> more esoteric features, like shared images and/or multiple VBDs
> sharing the same tapdisk.

I think README file should be also updated.

And maybe its good idea to merge it to xen 4.0?

--
Łukasz Oleś

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

end of thread, other threads:[~2010-08-03 19:14 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-07 21:54 [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
2010-06-07 21:54 ` [PATCH 1 of 7] blktap2: Remove tapdisk-ipc module Daniel Stodden
2010-06-07 21:54 ` [PATCH 2 of 7] blktap2: Remove LVM hacks Daniel Stodden
2010-06-07 21:54 ` [PATCH 3 of 7] blktap2: Fix tapdisk disktype issues Daniel Stodden
2010-06-07 21:54 ` [PATCH 4 of 7] blktap2: Fix E/DPRINTF defs all around the driver/ subdir Daniel Stodden
2010-06-07 21:54 ` [PATCH 5 of 7] blktap2: Cleanup vdi stacking code Daniel Stodden
2010-06-07 21:54 ` [PATCH 6 of 7] blktap2: The tap-ctl userspace control utility and library Daniel Stodden
2010-06-07 21:54 ` [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface Daniel Stodden
2010-06-09 20:25   ` Jeremy Fitzhardinge
2010-06-09 20:57     ` Daniel Stodden
2010-06-09 22:11       ` Daniel Stodden
2010-06-09 22:32         ` Jeremy Fitzhardinge
2010-06-10  3:26     ` [PATCH 0 of 4] libxl/blktap2 Daniel Stodden
2010-06-10  3:26       ` [PATCH 1 of 4] blktap2: Fix broken tap-ctl-list type/path filter logic Daniel Stodden
2010-06-10  3:26       ` [PATCH 2 of 4] blktap2: Add tap_ctl_find_minor Daniel Stodden
2010-06-10  3:26       ` [PATCH 3 of 4] blktap2: Build libblktapctl.so Daniel Stodden
2010-06-10  3:26       ` [PATCH 4 of 4] libxl: Use libblktapctl.so Daniel Stodden
2010-06-10 15:43         ` Stefano Stabellini
2010-06-10 20:11           ` Daniel Stodden
2010-06-10 16:25         ` Stefano Stabellini
2010-06-10 22:27           ` Daniel Stodden
2010-06-11 10:42             ` Stefano Stabellini
2010-06-11 13:00               ` Stefano Stabellini
2010-08-03 19:14 ` [PATCH 0 of 7] blktap2: The tap-ctl userspace control utility and library Łukasz Oleś
  -- strict thread matches above, loose matches on Subject: below --
2010-07-07 16:33 [PATCH 7 of 7] blktap2: Port Xend to the tap-ctl interface Chao-Rui Chang

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