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-devel

[Xen-devel] [PATCH 2/4] provide vhd support to blktap

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 2/4] provide vhd support to blktap
From: Ben Guthro <bguthro@xxxxxxxxxxxxxxx>
Date: Tue, 19 Jun 2007 09:16:26 -0400
Delivery-date: Tue, 19 Jun 2007 06:13:11 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 2.0.0.0 (X11/20070418)
[PATCH 2/4] provide vhd support to blktap
tapdisk-vhd-support.patch
Provides integration of vdisk library, and implementation of block-vhd
into blktap
Signed-off-by: Boris Ostrovsky <bostrovsky@xxxxxxxxxxxxxxx>
Signed-off-by: Ben Guthro <bguthro@xxxxxxxxxxxxxxx>
diff -r 92f2f05d6839 tools/blktap/drivers/Makefile
--- a/tools/blktap/drivers/Makefile     Tue Jun 19 08:00:26 2007 -0400
+++ b/tools/blktap/drivers/Makefile     Tue Jun 19 08:00:26 2007 -0400
@@ -7,12 +7,14 @@ QCOW_UTIL    = img2qcow qcow2raw qcow-cr
 QCOW_UTIL    = img2qcow qcow2raw qcow-create
 INST_DIR     = /usr/sbin
 LIBAIO_DIR   = ../../libaio/src
+LIBVDISK_DIR = ../../vdisk
+LIBSDIR      = lib64
 
 CFLAGS   += -Werror
 CFLAGS   += -Wno-unused
 CFLAGS   += -fno-strict-aliasing
 CFLAGS   += -I $(XEN_LIBXC) -I $(LIBAIO_DIR)
-CFLAGS   += $(INCLUDES) -I. -I../../xenstore 
+CFLAGS   += $(INCLUDES) -I. -I../../xenstore -I$(LIBVDISK_DIR)
 CFLAGS   += -D_GNU_SOURCE
 
 # Get gcc to generate the dependencies for us.
@@ -21,10 +23,10 @@ DEPS      = .*.d
 
 THREADLIB := -lpthread -lz
 LIBS      := -L. -L.. -L../lib
-LIBS      += -L$(XEN_LIBXC)
+LIBS      += -L$(XEN_LIBXC) -L$(LIBVDISK_DIR) -L$(LIBAIO_DIR)
 LIBS      += -lblktap -lxenctrl
 LIBS      += -lcrypto
-LIBS      += -lz
+LIBS      += -lz -lvdisk -laio
 LIBS      += -L$(XEN_XENSTORE) -lxenstore
 
 AIOLIBS   := $(LIBAIO_DIR)/libaio.a
@@ -34,14 +36,15 @@ BLK-OBJS  += block-vmdk.o
 BLK-OBJS  += block-vmdk.o
 BLK-OBJS  += block-ram.o
 BLK-OBJS  += block-qcow.o
+BLK-OBJS  += block-vhd.o
 BLK-OBJS  += aes.o
 
 all: $(IBIN) qcow-util
 
-blktapctrl: blktapctrl.c
+blktapctrl: blktapctrl.c tapdisk.h
        $(CC) $(CFLAGS) -o blktapctrl $(LIBS) blktapctrl.c
 
-tapdisk: $(BLK-OBJS) tapdisk.c
+tapdisk: $(BLK-OBJS) tapdisk.c tapdisk.h
        $(CC) $(CFLAGS) -o tapdisk $(BLK-OBJS) tapdisk.c \
                $(AIOLIBS) $(LIBS)
 
diff -r 92f2f05d6839 tools/blktap/drivers/block-vhd.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/blktap/drivers/block-vhd.c  Tue Jun 19 08:12:30 2007 -0400
@@ -0,0 +1,312 @@
+// Copyright (c) 2003-2007, Virtual Iron Software, Inc.
+//
+// Portions have been modified by Virtual Iron Software, Inc.
+// (c) 2007. This file and the modifications can be redistributed and/or
+// modified under the terms and conditions of the GNU General Public
+// License, version 2.1 and not any later version of the GPL, as published
+// by the Free Software Foundation.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <dlfcn.h>
+#include "tapdisk.h"
+#include <vdisk.h>
+
+
+struct tdvhd_state {
+       vdisk_dev_t *vdisk;
+       int poll_pipe[2]; /* dummy fd for polling on */
+       int fd;
+};
+
+typedef struct td_cbinfo {
+       struct td_state *s;
+       td_callback_t cb;
+       struct vdisk_dev *vdisk;
+       void *private;
+       int id; 
+       int cnt;
+} td_cbinfo_t;
+
+static int
+tdvhd_queue_rw(struct disk_driver *dd, uint64_t sector,
+              int nb_sectors, char *buf, td_callback_t cb,
+              int id, void *private, int op)
+{
+       struct tdvhd_state *prv = (struct tdvhd_state *)dd->private;
+       int res = 0;
+       int aio_cnt = prv->vdisk->aio_cnt;
+       td_cbinfo_t *cbi;
+
+       cbi = malloc(sizeof(td_cbinfo_t));
+       if (cbi == NULL) {
+               VIDDBG(0, "Can't allocate callback info\n");
+               return (-ENOMEM);
+       }
+       
+       cbi->s = dd->td_state;
+       cbi->cb = cb;
+       cbi->id = id;
+       cbi->vdisk = prv->vdisk;
+       cbi->private = private;
+
+       res = vdisk_rw(prv->vdisk, sector, (uint8_t *)buf, 
+                      nb_sectors, op, (void *)cbi);
+       if (res == -EBUSY) {
+               blkif_t *blkif = cbi->s->blkif;
+
+               /*
+                * This really should be done in tapdisk.c.
+                * However, we since we don't want to touch it,
+                * we do it here.
+                */
+               blkif->pending_list[id].secs_pending -= nb_sectors;
+
+               free(cbi);
+       }
+
+       // Didn't use async IO
+       if (res > 0) {
+               cbi->cb(dd, 0/*XXX: pass error*/, 
+                       sector, res>>9,
+                       cbi->id, cbi->private);
+       }
+
+       // How many AIOs have been created for this request
+       cbi->cnt = prv->vdisk->aio_cnt - aio_cnt;
+
+       return (res);
+
+}
+
+int tdvhd_queue_read(struct disk_driver *dd, uint64_t sector,
+                    int nb_sectors, char *buf, td_callback_t cb,
+                    int id, void *private)
+{
+       return (tdvhd_queue_rw(dd, sector, nb_sectors, buf,
+                              cb, id, private, VDISK_READ));
+}
+
+int tdvhd_queue_write(struct disk_driver *dd, uint64_t sector,
+                     int nb_sectors, char *buf, td_callback_t cb,
+                     int id, void *private)
+{
+       return (tdvhd_queue_rw(dd, sector, nb_sectors, buf,
+                              cb, id, private, VDISK_WRITE));
+}
+
+int tdvhd_close(struct disk_driver *dd)
+{
+       struct tdvhd_state *prv;
+
+       // We can be called more than once
+       if (dd == NULL)
+               return (0);
+       
+       prv = (struct tdvhd_state *)dd->private;        
+       if ((prv == NULL) || (prv->vdisk == NULL))
+               return (0); // XXX: Or error?
+
+       vdisk_fini(prv->vdisk);
+
+       free(prv->vdisk);
+       prv->vdisk = NULL;
+
+       close(prv->poll_pipe[0]);
+       close(prv->poll_pipe[1]);
+
+       return 0;
+}
+
+static void tdvhd_get_fd(struct disk_driver *dd)
+{
+       struct tdvhd_state *prv = (struct tdvhd_state *)dd->private;
+       vdisk_dev_t *vdisk = (vdisk_dev_t *)prv->vdisk;
+       int i;
+
+       /*initialise the FD array*/
+       for(i=0;i<MAX_IOFD;i++)
+               dd->io_fd[i] = 0;
+
+       dd->io_fd[0] = vdisk->aio_fd;
+}
+
+/* Open the disk file and initialize aio state. */
+int tdvhd_open (struct disk_driver *dd, const char *filename, td_flag_t flags)
+{
+       int i, fd, ret = 0;
+       struct tdvhd_state *prv = (struct tdvhd_state *)dd->private;
+       int heads, secs, cyls;
+       struct program_props props;
+       
+       prv->vdisk = malloc(sizeof(struct vdisk_dev));
+       if (prv->vdisk == NULL) {
+               VIDDBG(0, "Can't allocate memory for vdisk\n");
+               return (-ENOMEM);
+       }
+
+       prv->vdisk->use_aio = 1;
+
+       props.alloc_func = NULL;
+       props.free_func = NULL;
+       props.out_target = VDISK_OUT_SYSLOG;
+       ret = vdisk_init(prv->vdisk, (char *)filename, &props, 0);
+       if (ret) {
+               VIDDBG(0, "Can't initialize vdisk for %s\n", filename);
+               free(prv->vdisk);
+               return (ret>0?(-1*ret):ret);
+       }
+       
+       /* set up a pipe so that we can hand back a poll fd that won't fire.*/
+       ret = pipe(prv->poll_pipe);
+       if (ret != 0)
+               return (0 - errno);
+       
+       // VHD format limits geometry to roughly 136GB (0xffff cylinders,
+        // 0x10 heads and 0xff sectors per cylinder). We'll report "original
+        // size" (as specified by the header), not CHS product
+       dd->td_state->size = prv->vdisk->sz >> 9;
+       dd->td_state->sector_size = DEFAULT_SECTOR_SIZE;
+
+       tdvhd_get_fd(dd);
+
+done:
+       return ret;     
+}
+
+int tdvhd_submit(struct disk_driver *dd)
+{
+       int res;
+       struct tdvhd_state *prv = (struct tdvhd_state *)dd->private;
+       vdisk_dev_t *vdisk = (vdisk_dev_t *)prv->vdisk;
+
+       if (!vdisk->use_aio)
+               return (0);
+
+       if (!vdisk->aio_cnt)
+               return (0);
+
+       VIDDBG(50, "Submitting %d requests\n", vdisk->aio_cnt);
+
+       res = io_submit(vdisk->ioctx, vdisk->aio_cnt, vdisk->aio_submit);
+       if (res != vdisk->aio_cnt)
+               VIDDBG(0, "Can't submit %d AIO requests (submitted %d)\n",
+                      vdisk->aio_cnt, res);
+
+       vdisk->aio_cnt = 0;
+
+       return 0;       
+}
+
+int tdvhd_do_callbacks(struct disk_driver *dd, int sid)
+{
+       struct tdvhd_state *prv = (struct tdvhd_state *)dd->private;
+       vdisk_dev_t *vdisk = (vdisk_dev_t *)prv->vdisk;
+        int ret, i, rsp = 1, *ptr;
+        struct io_event *ep;
+       td_cbinfo_t *cbi;
+       uint32_t blk;
+
+       /* Non-blocking test for completed io. */
+        ret = io_getevents(vdisk->ioctx, 0, VDISK_HASH_SZ,
+                          vdisk->aio_events, NULL);
+
+        for (ep=vdisk->aio_events, i=ret; i>0; i--, ep++) {
+                struct iocb        *io  = ep->obj;
+                struct pending_aio *pio;
+               int err;
+               
+               err = 0;
+
+                pio = (struct pending_aio *)io->data;
+               if (pio == NULL) {
+                       VIDDBG(0, "Can't find pending AIO data\n");
+                       return (-EIO);
+               }
+
+               if ((signed long)ep->res < 0) {
+                       VIDDBG(0, "AIO to block %u for %u blocks reported "
+                              "error %ld (%ld)\n", pio->block, pio->num_blocks,
+                              ep->res, ep->res2);
+                       err = ep->res;
+               } else if (ep->res != io->u.c.nbytes) {
+                        /* TODO: handle this case better. */
+                       ptr = (int *)&ep->res;
+                        VIDDBG(0, "AIO did less than I asked it to "
+                               "[%lu,%lu,%d]\n", 
+                               ep->res, io->u.c.nbytes, *ptr);
+                       err = -EIO;
+                }
+
+               cbi = (td_cbinfo_t *)pio->aiocb;                
+               if (cbi == NULL) {
+                       VIDDBG(0, "callback info is missing\n");
+                       //XXX: This is pretty bad. Maybe we should die?
+                       continue;
+               }
+               if (cbi->vdisk == NULL) {
+                       VIDDBG(0, "Can't find vdisk for pending AIO\n");
+                       err = -EIO;
+               } else {
+                       int vdisk_err;
+
+                       // Let vdisk know that a pending IO has completed
+                       pio->res = err;
+                       vdisk_err = vdisk_xfer_cb(cbi->vdisk, pio);
+                       if (vdisk_err != 0) {
+                               VIDDBG(0, "vdisk callback failed\n");
+                               //XXX: return (error) ???
+                               
+                               if (err == 0) // Report the earliest error
+                                       err = vdisk_err;
+                       }
+               }
+
+               cbi->cnt--;
+
+               // blktap's callback (usually to kick the driver)
+               rsp += cbi->cb(dd, err, 
+                              pio->block,            /* sector */
+                              pio->num_blocks,       /* nb_sectors */
+                              cbi->id, cbi->private);
+
+               if (cbi->cnt == 0)
+                       free(cbi);
+        }
+
+       // XXX: What do we return on errors?
+        return rsp;
+}
+int tdvhd_get_parent_id (struct disk_driver *dd, struct disk_id *id)
+{
+    return TD_NO_PARENT;
+}
+
+int tdvhd_validate_parent (struct disk_driver *dd, 
+                                 struct disk_driver *p, td_flag_t flags)
+{
+       return -EINVAL;
+}
+
+
+
+struct tap_disk tapdisk_vhd = {
+       "tapdisk_vhd",
+       sizeof(struct tdvhd_state),
+       tdvhd_open,
+       tdvhd_queue_read,
+       tdvhd_queue_write,
+       tdvhd_submit,
+       tdvhd_close,
+       tdvhd_do_callbacks,
+        tdvhd_get_parent_id,
+        tdvhd_validate_parent
+};
diff -r 92f2f05d6839 tools/blktap/drivers/tapdisk.c
--- a/tools/blktap/drivers/tapdisk.c    Tue Jun 19 08:00:26 2007 -0400
+++ b/tools/blktap/drivers/tapdisk.c    Tue Jun 19 08:00:26 2007 -0400
@@ -556,15 +556,22 @@ int send_responses(struct disk_driver *d
        preq = &blkif->pending_list[idx];
        req  = &preq->req;
 
-       if (res == BLK_NOT_ALLOCATED) {
-               res = do_cow_read(dd, req, sidx, sector, nr_secs);
+        if (res == BLK_NOT_ALLOCATED) {
+#if 1 
+        /* VHD - do not support */
+            DPRINTF("invalid for VHD's\n");
+            return 0;
+#else
+        /* Original xen code */
+                res = do_cow_read(dd, req, sidx, sector, nr_secs);
                if (res >= 0) {
                        secs_done = res;
                        res = 0;
                } else
                        secs_done = 0;
-       }
-
+#endif
+       }
+        
        preq->secs_pending -= secs_done;
 
        if (res == -EBUSY && preq->submitting) 
diff -r 92f2f05d6839 tools/blktap/drivers/tapdisk.h
--- a/tools/blktap/drivers/tapdisk.h    Tue Jun 19 08:00:26 2007 -0400
+++ b/tools/blktap/drivers/tapdisk.h    Tue Jun 19 08:00:26 2007 -0400
@@ -156,6 +156,7 @@ extern struct tap_disk tapdisk_vmdk;
 extern struct tap_disk tapdisk_vmdk;
 extern struct tap_disk tapdisk_ram;
 extern struct tap_disk tapdisk_qcow;
+extern struct tap_disk tapdisk_vhd;
 
 #define MAX_DISK_TYPES     20
 
@@ -164,6 +165,7 @@ extern struct tap_disk tapdisk_qcow;
 #define DISK_TYPE_VMDK     2
 #define DISK_TYPE_RAM      3
 #define DISK_TYPE_QCOW     4
+#define DISK_TYPE_VHD      5
 
 
 /*Define Individual Disk Parameters here */
@@ -214,6 +216,16 @@ static disk_info_t qcow_disk = {
        0,
 #ifdef TAPDISK
        &tapdisk_qcow,
+#endif
+};
+
+static disk_info_t vhd_disk = {
+       DISK_TYPE_VHD,
+       "VHD disk (vhd)",
+       "vhd",
+       1,
+#ifdef TAPDISK
+       &tapdisk_vhd,
 #endif
 };
 
@@ -224,6 +236,7 @@ static disk_info_t *dtypes[] = {
        &vmdk_disk,
        &ram_disk,
        &qcow_disk,
+       &vhd_disk,
 };
 
 typedef struct driver_list_entry {

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 2/4] provide vhd support to blktap, Ben Guthro <=