From: Daniel Stodden <daniel.stodden@citrix.com>
To: Brendan Cully <brendan@cs.ubc.ca>, Ryan O'Connor <rjo@cs.ubc.ca>
Cc: "andy@cs.ubc.ca" <andy@cs.ubc.ca>,
"xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>
Subject: Re: [PATCH 08 of 11] blktap2: configurable driver chains
Date: Fri, 6 Nov 2009 13:12:44 -0800 [thread overview]
Message-ID: <1257541964.5041.22.camel@agari.van.xensource.com> (raw)
In-Reply-To: <4ca00ee41ce9731b8725.1257461913@localhost.localdomain>
Hey Ryan.
The command line idea is ok, but how about "!"?
Also, please check the line width.
Also, please don't alter the kernel list macros [..or submit yours to
lkml].
Daniel
On Thu, 2009-11-05 at 17:58 -0500, Brendan Cully wrote:
> # HG changeset patch
> # User Ryan O'Connor <rjo@cs.ubc.ca>
> # Date 1252530408 25200
> # Node ID 4ca00ee41ce9731b8725c736b27c841b484dce5d
> # Parent 6ca67fe3514ada809a62282c30fe46d5df5ce265
> 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@cs.ubc.ca>
>
> diff --git a/tools/blktap2/drivers/tapdisk-vbd.c b/tools/blktap2/drivers/tapdisk-vbd.c
> --- a/tools/blktap2/drivers/tapdisk-vbd.c
> +++ b/tools/blktap2/drivers/tapdisk-vbd.c
> @@ -106,6 +106,7 @@
> 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 @@
> 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,36 @@
> 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;
> - }
> + /* 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;
>
> - if (!image)
> - goto fail;
> + /* after each loop, append the created stack to the result stack */
> + list_splice(images, &vbd->images);
> + free(images);
>
> - 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);
> + /* 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,14 +701,91 @@
> 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 createion? */
> 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(¶ms, 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;
> +}
> +
> int
> tapdisk_vbd_open_vdi(td_vbd_t *vbd, const char *path,
> uint16_t drivertype, uint16_t storage, td_flag_t flags)
> @@ -759,7 +914,7 @@
> {
> 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 --git a/tools/blktap2/drivers/tapdisk-vbd.h b/tools/blktap2/drivers/tapdisk-vbd.h
> --- a/tools/blktap2/drivers/tapdisk-vbd.h
> +++ b/tools/blktap2/drivers/tapdisk-vbd.h
> @@ -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,12 +80,20 @@
> 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;
>
> uint8_t reopened;
> @@ -164,6 +173,7 @@
>
> 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 --git a/tools/blktap2/drivers/tapdisk2.c b/tools/blktap2/drivers/tapdisk2.c
> --- a/tools/blktap2/drivers/tapdisk2.c
> +++ b/tools/blktap2/drivers/tapdisk2.c
> @@ -264,6 +264,13 @@
> 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 --git a/tools/blktap2/include/list.h b/tools/blktap2/include/list.h
> --- a/tools/blktap2/include/list.h
> +++ b/tools/blktap2/include/list.h
> @@ -87,6 +87,26 @@
> 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-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel
next prev parent reply other threads:[~2009-11-06 21:12 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-11-05 22:58 [PATCH 00 of 11] Remus 0.9 released! Brendan Cully
2009-11-05 22:58 ` [PATCH 01 of 11] Add callbacks for suspend, postcopy and preresume in xc_domain_save Brendan Cully
2009-11-05 22:58 ` [PATCH 02 of 11] Make xc_domain_restore loop until the fd is closed Brendan Cully
2009-11-05 22:58 ` [PATCH 03 of 11] Initiate failover if a packet is not received every 500ms Brendan Cully
2009-11-05 22:58 ` [PATCH 04 of 11] Buffer checkpoint data locally until domain has resumed execution Brendan Cully
2009-11-05 22:58 ` [PATCH 05 of 11] Do not bother with to_skip/to_fix bitmaps after the first final round Brendan Cully
2009-11-05 22:58 ` [PATCH 06 of 11] Do bitmap scan word-by-word before bit-by-bit Brendan Cully
2009-11-05 22:58 ` [PATCH 07 of 11] Make checkpoint buffering HVM-aware Brendan Cully
2009-11-05 22:58 ` [PATCH 08 of 11] blktap2: configurable driver chains Brendan Cully
2009-11-06 21:12 ` Daniel Stodden [this message]
2009-11-05 22:58 ` [PATCH 09 of 11] blktap2: only open driver stack once Brendan Cully
2009-11-05 22:58 ` [PATCH 10 of 11] Fixup for tap:tapdisk syntax in remus uname Brendan Cully
2009-11-05 22:58 ` [PATCH 11 of 11] blktap2: add remus driver Brendan Cully
2009-11-09 8:52 ` [PATCH 00 of 11] Remus 0.9 released! Keir Fraser
2009-12-22 2:32 ` Keith Coleman
2009-12-28 20:07 ` gilberto nunes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1257541964.5041.22.camel@agari.van.xensource.com \
--to=daniel.stodden@citrix.com \
--cc=andy@cs.ubc.ca \
--cc=brendan@cs.ubc.ca \
--cc=rjo@cs.ubc.ca \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.