WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] blktap2: configurable driver chains

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] blktap2: configurable driver chains
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 09 Nov 2009 12:00:49 -0800
Delivery-date: Mon, 09 Nov 2009 12:01:57 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1257795614 0
# Node ID 94c3f3d4b864bf74801bffb384d7354142850709
# Parent  f6091947ffed5707b60120fe44d3d038a3307591
blktap2: configurable driver chains

Blktap2 allows block device drivers to be layered to create more
advanced virtual block devices. However, composing a layered driver is
not exposed to the user. This patch fixes this, and allows the user to
explicitly specify a driver chain when starting a tapdisk process,
using the pipe character ('|') to explicitly seperate layers in a
blktap2 configuration string.

for example, the command:
  ~$ tapdisk2 -n "log:|aio:/path/to/file.img"
will create a blktap2 device where read and write requests are passed
to the 'log' driver, then forwarded to the 'aio' driver.

Signed-off-by: Ryan O'Connor <rjo@xxxxxxxxx>
---
 tools/blktap2/drivers/tapdisk-vbd.c |  248 +++++++++++++++++++++++++++++-------
 tools/blktap2/drivers/tapdisk-vbd.h |   10 +
 tools/blktap2/drivers/tapdisk2.c    |    7 +
 tools/blktap2/include/list.h        |   20 ++
 4 files changed, 238 insertions(+), 47 deletions(-)

diff -r f6091947ffed -r 94c3f3d4b864 tools/blktap2/drivers/tapdisk-vbd.c
--- a/tools/blktap2/drivers/tapdisk-vbd.c       Mon Nov 09 19:19:27 2009 +0000
+++ b/tools/blktap2/drivers/tapdisk-vbd.c       Mon Nov 09 19:40:14 2009 +0000
@@ -106,6 +106,7 @@ tapdisk_vbd_initialize(int rfd, int wfd,
        vbd->callback = tapdisk_vbd_callback;
        vbd->argument = vbd;
 
+       INIT_LIST_HEAD(&vbd->driver_stack);
        INIT_LIST_HEAD(&vbd->images);
        INIT_LIST_HEAD(&vbd->new_requests);
        INIT_LIST_HEAD(&vbd->pending_requests);
@@ -541,6 +542,105 @@ regerr:
        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)
+{
+       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;
+       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;
+               }
+
+               if (!image)
+                       return NULL;
+
+
+               /* 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;
+               }
+
+               /* TODO: non-sink drivers that don't care about their child
+                * currently return EINVAL. Could return TD_PARENT_OK or
+                * TD_ANY_PARENT */
+
+               err = td_get_parent_id(image, &id);
+               if (err && (err != TD_NO_PARENT && err != -EINVAL)) {
+                       td_close(image);
+                       return NULL;
+               }
+
+               if (!image->storage)
+                       image->storage = vbd->storage;
+
+               /* add this image to the end of the list */
+               list_add_tail(&image->next, images);
+
+               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;
+
+               name   = id.name;
+               type   = id.drivertype;
+#if 0
+               /* catch this by validate, not here */
+               flags |= (TD_OPEN_RDONLY | TD_OPEN_SHAREABLE);
+#endif
+       }
+       return images;
+}
+
 static int
 __tapdisk_vbd_open_vdi(td_vbd_t *vbd, td_flag_t extra_flags)
 {
@@ -548,58 +648,35 @@ __tapdisk_vbd_open_vdi(td_vbd_t *vbd, td
        int err, type;
        td_flag_t flags;
        td_disk_id_t id;
-       td_image_t *image, *tmp;
+       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;
 
        err = tapdisk_vbd_reactivate_volumes(vbd, 0);
        if (err)
                return err;
 
        flags = (vbd->flags & ~TD_OPEN_SHAREABLE) | extra_flags;
-       file  = vbd->name;
-       type  = vbd->type;
-
-       for (;;) {
-               err   = -ENOMEM;
-               image = tapdisk_image_allocate(file, type,
-                                              vbd->storage, flags, vbd);
-
-               if (file != vbd->name) {
-                       free(file);
-                       file = NULL;
-               }
-
-               if (!image)
-                       goto fail;
-
-               err = td_load(image);
-               if (err) {
-                       if (err != -ENODEV)
-                               goto fail;
-
-                       err = td_open(image);
-                       if (err)
-                               goto fail;
-               }
-
-               err = td_get_parent_id(image, &id);
-               if (err && err != TD_NO_PARENT) {
-                       td_close(image);
-                       goto fail;
-               }
-
-               if (!image->storage)
-                       image->storage = vbd->storage;
-
-               tapdisk_vbd_add_image(vbd, image);
-               image = NULL;
-
-               if (err == TD_NO_PARENT)
-                       break;
-
-               file   = id.name;
-               type   = id.drivertype;
-               flags |= (TD_OPEN_RDONLY | TD_OPEN_SHAREABLE);
+
+       /* 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;
+
+               /* after each loop, append the created stack to the result 
stack */
+               list_splice(images, &vbd->images);
+               free(images);
+
+               /* set the parent_info to the first diskinfo on the stack */
+               tmp = tapdisk_vbd_first_image(vbd);
+               parent_info = &tmp->info;
        }
 
        if (td_flag_test(vbd->flags, TD_OPEN_LOG_DIRTY)) {
@@ -623,11 +700,88 @@ __tapdisk_vbd_open_vdi(td_vbd_t *vbd, td
        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;
+}
+
+/* this populates a vbd type based on path */
+int
+tapdisk_vbd_parse_stack(td_vbd_t *vbd, const char *path)
+{
+       int err;
+       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;
+
+
+       /* tokenize params based on pipe '|' */
+       driver_str = strtok(params, "|");
+       while(driver_str != NULL)
+       {
+               /* parse driver info and add to vbd */
+               driver = calloc(1, sizeof(td_vbd_driver_info_t));
+               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 */
+               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);
+       }
+
+       return err;
+}
+
+/* NOTE: driver type, etc. must be set */
+static int
+tapdisk_vbd_open_stack(td_vbd_t *vbd, uint16_t storage, td_flag_t flags)
+{
+       int i, err;
+
+       vbd->flags   = flags;
+       vbd->storage = storage;
+
+       for (i = 0; i < TD_VBD_EIO_RETRIES; i++) {
+               err = __tapdisk_vbd_open_vdi(vbd, 0);
+               if (err != -EIO)
+                       break;
+
+               sleep(TD_VBD_EIO_SLEEP);
+       }
+       if (err)
+               goto fail;
+
+       return 0;
+
+ fail:
        return err;
 }
 
@@ -759,7 +913,7 @@ tapdisk_vbd_open(td_vbd_t *vbd, const ch
 {
        int err;
 
-       err = tapdisk_vbd_open_vdi(vbd, name, type, storage, flags);
+       err = tapdisk_vbd_open_stack(vbd, storage, flags);
        if (err)
                goto out;
 
diff -r f6091947ffed -r 94c3f3d4b864 tools/blktap2/drivers/tapdisk-vbd.h
--- a/tools/blktap2/drivers/tapdisk-vbd.h       Mon Nov 09 19:19:27 2009 +0000
+++ b/tools/blktap2/drivers/tapdisk-vbd.h       Mon Nov 09 19:40:14 2009 +0000
@@ -53,6 +53,7 @@
 
 typedef struct td_ring              td_ring_t;
 typedef struct td_vbd_request       td_vbd_request_t;
+typedef struct td_vbd_driver_info   td_vbd_driver_info_t;
 typedef struct td_vbd_handle        td_vbd_t;
 typedef void (*td_vbd_cb_t)        (void *, blkif_response_t *);
 
@@ -79,11 +80,19 @@ struct td_vbd_request {
        struct list_head            next;
 };
 
+struct td_vbd_driver_info {
+       char                       *params;
+       int                         type;
+       struct list_head            next;
+};
+
 struct td_vbd_handle {
        char                       *name;
 
        td_uuid_t                   uuid;
        int                         type;
+
+       struct list_head            driver_stack;
 
        int                         storage;
 
@@ -164,6 +173,7 @@ tapdisk_vbd_next_image(td_image_t *image
 
 int tapdisk_vbd_initialize(int, int, 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);
 int tapdisk_vbd_close(td_vbd_t *);
diff -r f6091947ffed -r 94c3f3d4b864 tools/blktap2/drivers/tapdisk2.c
--- a/tools/blktap2/drivers/tapdisk2.c  Mon Nov 09 19:19:27 2009 +0000
+++ b/tools/blktap2/drivers/tapdisk2.c  Mon Nov 09 19:40:14 2009 +0000
@@ -264,6 +264,13 @@ tapdisk2_open_device(int type, const cha
                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);
diff -r f6091947ffed -r 94c3f3d4b864 tools/blktap2/include/list.h
--- a/tools/blktap2/include/list.h      Mon Nov 09 19:19:27 2009 +0000
+++ b/tools/blktap2/include/list.h      Mon Nov 09 19:40:14 2009 +0000
@@ -87,6 +87,26 @@ static inline int list_is_last(const str
        return list->next == head;
 }
 
+static inline void __list_splice(struct list_head *list,
+                                struct list_head *head)
+{
+       struct list_head *first = list->next;
+       struct list_head *last = list->prev;
+       struct list_head *at = head->next;
+
+       first->prev = head;
+       head->next = first;
+
+       last->next = at;
+       at->prev = last;
+}
+
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+       if (!list_empty(list))
+               __list_splice(list, head);
+}
+
 #define list_entry(ptr, type, member)                                   \
         ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
 

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] blktap2: configurable driver chains, Xen patchbot-unstable <=