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/rfc] multiprotocol blkback drivers (32-on-64)

To: Xen devel list <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [patch/rfc] multiprotocol blkback drivers (32-on-64)
From: Gerd Hoffmann <kraxel@xxxxxxx>
Date: Mon, 18 Dec 2006 17:39:02 +0100
Cc: jan Beulich <jbeulich@xxxxxxxxxx>
Delivery-date: Mon, 18 Dec 2006 08:39:04 -0800
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 1.5.0.8 (X11/20060911)
  Hi,

This is a patch for the block interface, frontend drivers, backend
drivers and tools to support multiple ring protocols.  Right there are
now just two: the 32bit and the 64bit one.  If needed it can be extended.

Interface changes (io/blkif.h)
 * Have both request structs there, with "v1" and "v2" added to the
   name.  The old name is aliased to the native protocol of the
   architecture.
 * Add helper functions to convert v1/v2 requests to native.

Frontend changes:
 * Create a new node "protocol", add the protocol number it speaks
   there.

Backend changes:
 * Look at the "protocol" number of the frontend and switch ring
   handling accordingly.  If the protocol node isn't present it assumes
   native protocol.
 * As the request struct is copied anyway before being processed (for
   security reasons) it is converted to native at that point so most
   backend code doesn't need to know what the frontend speaks.
 * In case of blktap this is completely transparent to userspace, the
   kernel/userspace ring is always native no matter what the frontend
   speaks.

Tools changes:
 * Add one more option to the disk configuration, so one can specify the
   protocol the frontend speaks in the config file.  This is needed for
   old frontends which don't advertise the protocol they are speaking
   themself.
   I'm not that happy with this approach, but it works for now and I'm
   kida lost in the stack of python classes doing domain and device
   handling ...

Consider the code experimental, not all frontend/backend combinations
are tested.

Comments?  Questions?  Suggesions?

cheers,
  Gerd

PS: Anyone working on blkback/blktap code sharing?  While walking
    through the code I've noticed quite alot of it is cut&paste ...

-- 
Gerd Hoffmann <kraxel@xxxxxxx>
---
 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c   |   79 ++++++++++++-----
 linux-2.6-xen-sparse/drivers/xen/blkback/common.h    |    4 
 linux-2.6-xen-sparse/drivers/xen/blkback/interface.c |   17 ++-
 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c    |   14 +++
 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c |    6 +
 linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c     |   86 +++++++++++++------
 linux-2.6-xen-sparse/drivers/xen/blktap/common.h     |    4 
 linux-2.6-xen-sparse/drivers/xen/blktap/interface.c  |   17 ++-
 linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c     |   14 +++
 tools/python/xen/xend/server/blkif.py                |    3 
 tools/python/xen/xm/create.py                        |    7 +
 xen/include/public/io/blkif.h                        |   81 +++++++++++++++--
 12 files changed, 264 insertions(+), 68 deletions(-)

Index: 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
===================================================================
--- 
build-64-release304-12901.orig/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
+++ build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
@@ -298,17 +298,33 @@ irqreturn_t blkif_be_int(int irq, void *
 
 static int do_block_io_op(blkif_t *blkif)
 {
-       blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+       blkif_v1_back_ring_t *blk_v1_ring = NULL;
+       blkif_v2_back_ring_t *blk_v2_ring = NULL;
        blkif_request_t req;
        pending_req_t *pending_req;
        RING_IDX rc, rp;
        int more_to_do = 0;
 
-       rc = blk_ring->req_cons;
-       rp = blk_ring->sring->req_prod;
+       if (1 == blkif->blk_protocol) {
+               blk_v1_ring = &blkif->blk_v1_ring;
+               rc = blk_v1_ring->req_cons;
+               rp = blk_v1_ring->sring->req_prod;
+       } else {
+               blk_v2_ring = &blkif->blk_v2_ring;
+               rc = blk_v2_ring->req_cons;
+               rp = blk_v2_ring->sring->req_prod;
+       }
        rmb(); /* Ensure we see queued requests up to 'rp'. */
 
-       while ((rc != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) {
+       while ((rc != rp)) {
+
+               if (1 == blkif->blk_protocol) {
+                       if (RING_REQUEST_CONS_OVERFLOW(blk_v1_ring, rc))
+                               break;
+               } else {
+                       if (RING_REQUEST_CONS_OVERFLOW(blk_v2_ring, rc))
+                               break;
+               }
 
                pending_req = alloc_req();
                if (NULL == pending_req) {
@@ -317,8 +333,13 @@ static int do_block_io_op(blkif_t *blkif
                        break;
                }
 
-               memcpy(&req, RING_GET_REQUEST(blk_ring, rc), sizeof(req));
-               blk_ring->req_cons = ++rc; /* before make_response() */
+               if (1 == blkif->blk_protocol) {
+                       blkif_get_v1_req(&req, RING_GET_REQUEST(blk_v1_ring, 
rc));
+                       blk_v1_ring->req_cons = ++rc; /* before make_response() 
*/
+               } else {
+                       blkif_get_v2_req(&req, RING_GET_REQUEST(blk_v2_ring, 
rc));
+                       blk_v2_ring->req_cons = ++rc; /* before make_response() 
*/
+               }
 
                switch (req.operation) {
                case BLKIF_OP_READ:
@@ -500,32 +521,48 @@ static void make_response(blkif_t *blkif
 {
        blkif_response_t *resp;
        unsigned long     flags;
-       blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+       blkif_v1_back_ring_t *blk_v1_ring = NULL;
+       blkif_v2_back_ring_t *blk_v2_ring = NULL;
        int more_to_do = 0;
        int notify;
 
        spin_lock_irqsave(&blkif->blk_ring_lock, flags);
 
        /* Place on the response ring for the relevant domain. */ 
-       resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
+       if (1 == blkif->blk_protocol) {
+               blk_v1_ring = &blkif->blk_v1_ring;
+               resp = RING_GET_RESPONSE(blk_v1_ring, 
blk_v1_ring->rsp_prod_pvt);
+       } else {
+               blk_v2_ring = &blkif->blk_v2_ring;
+               resp = RING_GET_RESPONSE(blk_v2_ring, 
blk_v2_ring->rsp_prod_pvt);
+       }
        resp->id        = id;
        resp->operation = op;
        resp->status    = st;
-       blk_ring->rsp_prod_pvt++;
-       RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify);
-
-       if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) {
-               /*
-                * Tail check for pending requests. Allows frontend to avoid
-                * notifications if requests are already in flight (lower
-                * overheads and promotes batching).
-                */
-               RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do);
-
-       } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) {
-               more_to_do = 1;
+       if (1 == blkif->blk_protocol) {
+               blk_v1_ring->rsp_prod_pvt++;
+               RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_v1_ring, notify);
+               if (blk_v1_ring->rsp_prod_pvt == blk_v1_ring->req_cons) {
+                       /*
+                        * Tail check for pending requests. Allows frontend to 
avoid
+                        * notifications if requests are already in flight 
(lower
+                        * overheads and promotes batching).
+                        */
+                       RING_FINAL_CHECK_FOR_REQUESTS(blk_v1_ring, more_to_do);
 
+               } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_v1_ring)) {
+                       more_to_do = 1;
+               }
+       } else {
+               blk_v2_ring->rsp_prod_pvt++;
+               RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_v2_ring, notify);
+               if (blk_v2_ring->rsp_prod_pvt == blk_v2_ring->req_cons) {
+                       RING_FINAL_CHECK_FOR_REQUESTS(blk_v2_ring, more_to_do);
+               } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_v2_ring)) {
+                       more_to_do = 1;
+               }
        }
+
        spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
 
        if (more_to_do)
Index: 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blkback/common.h
===================================================================
--- 
build-64-release304-12901.orig/linux-2.6-xen-sparse/drivers/xen/blkback/common.h
+++ build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blkback/common.h
@@ -68,7 +68,9 @@ typedef struct blkif_st {
        unsigned int      evtchn;
        unsigned int      irq;
        /* Comms information. */
-       blkif_back_ring_t blk_ring;
+       int               blk_protocol;
+       blkif_v1_back_ring_t blk_v1_ring;
+       blkif_v2_back_ring_t blk_v2_ring;
        struct vm_struct *blk_ring_area;
        /* The VBD attached to this interface. */
        struct vbd        vbd;
Index: 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
===================================================================
--- 
build-64-release304-12901.orig/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
+++ 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
@@ -95,7 +95,8 @@ static void unmap_frontend_page(blkif_t 
 
 int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
 {
-       blkif_sring_t *sring;
+       blkif_v1_sring_t *sring_v1;
+       blkif_v2_sring_t *sring_v2;
        int err;
        struct evtchn_bind_interdomain bind_interdomain;
 
@@ -125,8 +126,13 @@ int blkif_map(blkif_t *blkif, unsigned l
 
        blkif->evtchn = bind_interdomain.local_port;
 
-       sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
-       BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
+       if (1 == blkif->blk_protocol) {
+               sring_v1 = (blkif_v1_sring_t *)blkif->blk_ring_area->addr;
+               BACK_RING_INIT(&blkif->blk_v1_ring, sring_v1, PAGE_SIZE);
+       } else {
+               sring_v2 = (blkif_v2_sring_t *)blkif->blk_ring_area->addr;
+               BACK_RING_INIT(&blkif->blk_v2_ring, sring_v2, PAGE_SIZE);
+       }
 
        blkif->irq = bind_evtchn_to_irqhandler(
                blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);
@@ -150,10 +156,11 @@ void blkif_disconnect(blkif_t *blkif)
                blkif->irq = 0;
        }
 
-       if (blkif->blk_ring.sring) {
+       if (blkif->blk_v1_ring.sring || blkif->blk_v2_ring.sring) {
                unmap_frontend_page(blkif);
                free_vm_area(blkif->blk_ring_area);
-               blkif->blk_ring.sring = NULL;
+               blkif->blk_v1_ring.sring = NULL;
+               blkif->blk_v2_ring.sring = NULL;
        }
 }
 
Index: 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
===================================================================
--- 
build-64-release304-12901.orig/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
+++ build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
@@ -435,6 +435,7 @@ static int connect_ring(struct backend_i
        struct xenbus_device *dev = be->dev;
        unsigned long ring_ref;
        unsigned int evtchn;
+       unsigned int protocol;
        int err;
 
        DPRINTK("%s", dev->otherend);
@@ -448,6 +449,19 @@ static int connect_ring(struct backend_i
                return err;
        }
 
+       err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
+                           "%u", &protocol, NULL);
+       if (err)
+               protocol = BLKIF_NATIVE_PROTOCOL;
+       if (protocol < 1 || protocol > 2) {
+               xenbus_dev_fatal(dev, err, "unknown fe protocol %d", protocol);
+               return -1;
+       }
+       be->blkif->blk_protocol = protocol;
+
+       printk("blkback: ring-ref %ld, event-channel %d, protocol %d\n",
+              ring_ref, evtchn, protocol);
+
        /* Map the shared frame, irq etc. */
        err = blkif_map(be->blkif, ring_ref, evtchn);
        if (err) {
Index: 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
===================================================================
--- 
build-64-release304-12901.orig/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
+++ 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
@@ -180,6 +180,12 @@ again:
                message = "writing event-channel";
                goto abort_transaction;
        }
+       err = xenbus_printf(xbt, dev->nodename,
+                           "protocol", "%u", BLKIF_NATIVE_PROTOCOL);
+       if (err) {
+               message = "writing protocol";
+               goto abort_transaction;
+       }
 
        err = xenbus_transaction_end(xbt, 0);
        if (err) {
Index: build-64-release304-12901/xen/include/public/io/blkif.h
===================================================================
--- build-64-release304-12901.orig/xen/include/public/io/blkif.h
+++ build-64-release304-12901/xen/include/public/io/blkif.h
@@ -71,20 +71,36 @@
  */
 #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
 
-struct blkif_request {
+struct blkif_request_segment {
+    grant_ref_t gref;        /* reference to I/O buffer frame        */
+    /* @first_sect: first sector in frame to transfer (inclusive).   */
+    /* @last_sect: last sector in frame to transfer (inclusive).     */
+    uint8_t     first_sect, last_sect;
+};
+
+/* i386 protocol version */
+#pragma pack(push, 4)
+struct blkif_v1_request {
     uint8_t        operation;    /* BLKIF_OP_???                         */
     uint8_t        nr_segments;  /* number of segments                   */
     blkif_vdev_t   handle;       /* only for read/write requests         */
     uint64_t       id;           /* private guest value, echoed in resp  */
     blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-    struct blkif_request_segment {
-        grant_ref_t gref;        /* reference to I/O buffer frame        */
-        /* @first_sect: first sector in frame to transfer (inclusive).   */
-        /* @last_sect: last sector in frame to transfer (inclusive).     */
-        uint8_t     first_sect, last_sect;
-    } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+    struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
-typedef struct blkif_request blkif_request_t;
+typedef struct blkif_v1_request blkif_v1_request_t;
+#pragma pack(pop)
+
+/* x86_64 protocol version */
+struct blkif_v2_request {
+    uint8_t        operation;    /* BLKIF_OP_???                         */
+    uint8_t        nr_segments;  /* number of segments                   */
+    blkif_vdev_t   handle;       /* only for read/write requests         */
+    uint64_t       __attribute__((__aligned__(8))) id;
+    blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+    struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+typedef struct blkif_v2_request blkif_v2_request_t;
 
 struct blkif_response {
     uint64_t        id;              /* copied from request */
@@ -107,7 +123,54 @@ typedef struct blkif_response blkif_resp
  * Generate blkif ring structures and types.
  */
 
-DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response);
+DEFINE_RING_TYPES(blkif_v1, struct blkif_v1_request, struct blkif_response);
+DEFINE_RING_TYPES(blkif_v2, struct blkif_v2_request, struct blkif_response);
+
+#if defined(__i386__)
+
+#define BLKIF_NATIVE_PROTOCOL 1
+typedef struct blkif_v1_request blkif_request_t;
+DEFINE_RING_TYPES(blkif, struct blkif_v1_request, struct blkif_response);
+
+#elif defined(__x86_64__)
+
+#define BLKIF_NATIVE_PROTOCOL 2
+typedef struct blkif_v2_request blkif_request_t;
+DEFINE_RING_TYPES(blkif, struct blkif_v2_request, struct blkif_response);
+
+#else
+# error arch fixup needed here
+#endif
+
+#ifdef __KERNEL__
+
+/* translate requests: v1/v2 to native */
+#if 1 == BLKIF_NATIVE_PROTOCOL
+static void inline blkif_get_v1_req(blkif_request_t *dst, blkif_v1_request_t 
*src)
+#else
+static void inline blkif_get_v2_req(blkif_request_t *dst, blkif_v2_request_t 
*src)
+#endif
+{
+       memcpy(dst, src, sizeof(*dst));
+}
+
+#if 1 == BLKIF_NATIVE_PROTOCOL
+static void inline blkif_get_v2_req(blkif_request_t *dst, blkif_v2_request_t 
*src)
+#else
+static void inline blkif_get_v1_req(blkif_request_t *dst, blkif_v1_request_t 
*src)
+#endif
+{
+       int i;
+       dst->operation = src->operation;
+       dst->nr_segments = src->nr_segments;
+       dst->handle = src->handle;
+       dst->id = src->id;
+       dst->sector_number = src->sector_number;
+       for (i = 0; i < src->nr_segments; i++)
+               dst->seg[i] = src->seg[i];
+}
+
+#endif
 
 #define VDISK_CDROM        0x1
 #define VDISK_REMOVABLE    0x2
Index: build-64-release304-12901/tools/python/xen/xend/server/blkif.py
===================================================================
--- build-64-release304-12901.orig/tools/python/xen/xend/server/blkif.py
+++ build-64-release304-12901/tools/python/xen/xend/server/blkif.py
@@ -38,6 +38,7 @@ class BlkifController(DevController):
         """@see DevController.getDeviceDetails"""
         uname = config.get('uname', '')
         dev = config.get('dev', '')
+        protocol = config.get('protocol')
         
         if 'ioemu:' in dev:
             (_, dev) = string.split(dev, ':', 1)
@@ -85,6 +86,8 @@ class BlkifController(DevController):
         front = { 'virtual-device' : "%i" % devid,
                   'device-type' : dev_type
                 }
+       if protocol:
+           front.update({ 'protocol' : protocol });
 
         return (devid, back, front)
 
Index: build-64-release304-12901/tools/python/xen/xm/create.py
===================================================================
--- build-64-release304-12901.orig/tools/python/xen/xm/create.py
+++ build-64-release304-12901/tools/python/xen/xm/create.py
@@ -531,7 +531,7 @@ def configure_image(vals):
 def configure_disks(config_devs, vals):
     """Create the config for disks (virtual block devices).
     """
-    for (uname, dev, mode, backend) in vals.disk:
+    for (uname, dev, mode, backend, protocol) in vals.disk:
         if uname.startswith('tap:'):
             cls = 'tap'
         else:
@@ -543,6 +543,8 @@ def configure_disks(config_devs, vals):
                       ['mode', mode ] ]
         if backend:
             config_vbd.append(['backend', backend])
+        if protocol:
+            config_vbd.append(['protocol', protocol])
         config_devs.append(['device', config_vbd])
 
 def configure_pci(config_devs, vals):
@@ -787,7 +789,10 @@ def preprocess_disk(vals):
         n = len(d)
         if n == 3:
             d.append(None)
+            d.append(None)
         elif n == 4:
+            d.append(None)
+        elif n == 5:
             pass
         else:
             err('Invalid disk specifier: ' + v)
Index: 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
===================================================================
--- 
build-64-release304-12901.orig/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
+++ build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
@@ -1094,15 +1094,24 @@ irqreturn_t tap_blkif_be_int(int irq, vo
 static int print_dbug = 1;
 static int do_block_io_op(blkif_t *blkif)
 {
-       blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+       blkif_v1_back_ring_t *blk_v1_ring = NULL;
+       blkif_v2_back_ring_t *blk_v2_ring = NULL;
        blkif_request_t req;
        pending_req_t *pending_req;
        RING_IDX rc, rp;
-       int more_to_do = 0;
+       int retval, more_to_do = 0;
        tap_blkif_t *info;
 
-       rc = blk_ring->req_cons;
-       rp = blk_ring->sring->req_prod;
+       if (1 == blkif->blk_protocol) {
+               blk_v1_ring = &blkif->blk_v1_ring;
+               rc = blk_v1_ring->req_cons;
+               rp = blk_v1_ring->sring->req_prod;
+       } else {
+               blk_v2_ring = &blkif->blk_v2_ring;
+               rc = blk_v2_ring->req_cons;
+               rp = blk_v2_ring->sring->req_prod;
+       }
+
        rmb(); /* Ensure we see queued requests up to 'rp'. */
 
        /*Check blkif has corresponding UE ring*/
@@ -1133,8 +1142,11 @@ static int do_block_io_op(blkif_t *blkif
                        more_to_do = 1;
                        break;
                }
-               
-               if (RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) {
+
+               retval = (1 == blkif->blk_protocol)
+                       ? RING_REQUEST_CONS_OVERFLOW(blk_v1_ring, rc)
+                       : RING_REQUEST_CONS_OVERFLOW(blk_v2_ring, rc);
+               if (retval) {
                        WPRINTK("RING_REQUEST_CONS_OVERFLOW!"
                               " More to do\n");
                        more_to_do = 1;
@@ -1148,8 +1160,13 @@ static int do_block_io_op(blkif_t *blkif
                        break;
                }
 
-               memcpy(&req, RING_GET_REQUEST(blk_ring, rc), sizeof(req));
-               blk_ring->req_cons = ++rc; /* before make_response() */ 
+               if (1 == blkif->blk_protocol) {
+                       blkif_get_v1_req(&req, RING_GET_REQUEST(blk_v1_ring, 
rc));
+                       blk_v1_ring->req_cons = ++rc; /* before make_response() 
*/
+               } else {
+                       blkif_get_v2_req(&req, RING_GET_REQUEST(blk_v2_ring, 
rc));
+                       blk_v2_ring->req_cons = ++rc; /* before make_response() 
*/
+               }
 
                switch (req.operation) {
                case BLKIF_OP_READ:
@@ -1225,7 +1242,9 @@ static void dispatch_rw_block_io(blkif_t
                WPRINTK("blktap: fe_ring is full, can't add "
                        "IO Request will be dropped. %d %d\n",
                        RING_SIZE(&info->ufe_ring),
-                       RING_SIZE(&blkif->blk_ring));
+                       (1 == blkif->blk_protocol)
+                           ? RING_SIZE(&blkif->blk_v1_ring)
+                           : RING_SIZE(&blkif->blk_v2_ring));
                goto fail_response;
        }
 
@@ -1415,30 +1434,47 @@ static void make_response(blkif_t *blkif
 {
        blkif_response_t *resp;
        unsigned long     flags;
-       blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+       blkif_v1_back_ring_t *blk_v1_ring = NULL;
+       blkif_v2_back_ring_t *blk_v2_ring = NULL;
        int more_to_do = 0;
        int notify;
 
+
        spin_lock_irqsave(&blkif->blk_ring_lock, flags);
-       /* Place on the response ring for the relevant domain. */ 
-       resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
+       /* Place on the response ring for the relevant domain. */
+       if (1 == blkif->blk_protocol) {
+               blk_v1_ring = &blkif->blk_v1_ring;
+               resp = RING_GET_RESPONSE(blk_v1_ring, 
blk_v1_ring->rsp_prod_pvt);
+       } else {
+               blk_v2_ring = &blkif->blk_v2_ring;
+               resp = RING_GET_RESPONSE(blk_v2_ring, 
blk_v2_ring->rsp_prod_pvt);
+       }
        resp->id        = id;
        resp->operation = op;
        resp->status    = st;
-       blk_ring->rsp_prod_pvt++;
-       RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify);
-
-       if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) {
-               /*
-                * Tail check for pending requests. Allows frontend to avoid
-                * notifications if requests are already in flight (lower
-                * overheads and promotes batching).
-                */
-               RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do);
-       } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) {
-               more_to_do = 1;
+       if (1 == blkif->blk_protocol) {
+               blk_v1_ring->rsp_prod_pvt++;
+               RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_v1_ring, notify);
+               if (blk_v1_ring->rsp_prod_pvt == blk_v1_ring->req_cons) {
+                       /*
+                        * Tail check for pending requests. Allows frontend to 
avoid
+                        * notifications if requests are already in flight 
(lower
+                        * overheads and promotes batching).
+                        */
+                       RING_FINAL_CHECK_FOR_REQUESTS(blk_v1_ring, more_to_do);
+               } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_v1_ring)) {
+                       more_to_do = 1;
+               }
+       } else {
+               blk_v2_ring->rsp_prod_pvt++;
+               RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_v2_ring, notify);
+               if (blk_v2_ring->rsp_prod_pvt == blk_v2_ring->req_cons) {
+                       RING_FINAL_CHECK_FOR_REQUESTS(blk_v2_ring, more_to_do);
+               } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_v2_ring)) {
+                       more_to_do = 1;
+               }
+       }
 
-       }       
        spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
        if (more_to_do)
                blkif_notify_work(blkif);
Index: 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blktap/common.h
===================================================================
--- 
build-64-release304-12901.orig/linux-2.6-xen-sparse/drivers/xen/blktap/common.h
+++ build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blktap/common.h
@@ -59,7 +59,9 @@ typedef struct blkif_st {
        unsigned int      evtchn;
        unsigned int      irq;
        /* Comms information. */
-       blkif_back_ring_t blk_ring;
+       int               blk_protocol;
+       blkif_v1_back_ring_t blk_v1_ring;
+       blkif_v2_back_ring_t blk_v2_ring;
        struct vm_struct *blk_ring_area;
        /* Back pointer to the backend_info. */
        struct backend_info *be;
Index: 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c
===================================================================
--- 
build-64-release304-12901.orig/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c
+++ 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c
@@ -96,7 +96,8 @@ static void unmap_frontend_page(blkif_t 
 int tap_blkif_map(blkif_t *blkif, unsigned long shared_page, 
                  unsigned int evtchn)
 {
-       blkif_sring_t *sring;
+       blkif_v1_sring_t *sring_v1;
+       blkif_v2_sring_t *sring_v2;
        int err;
        struct evtchn_bind_interdomain bind_interdomain;
 
@@ -126,8 +127,13 @@ int tap_blkif_map(blkif_t *blkif, unsign
 
        blkif->evtchn = bind_interdomain.local_port;
 
-       sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
-       BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
+       if (1 == blkif->blk_protocol) {
+               sring_v1 = (blkif_v1_sring_t *)blkif->blk_ring_area->addr;
+               BACK_RING_INIT(&blkif->blk_v1_ring, sring_v1, PAGE_SIZE);
+       } else {
+               sring_v2 = (blkif_v2_sring_t *)blkif->blk_ring_area->addr;
+               BACK_RING_INIT(&blkif->blk_v2_ring, sring_v2, PAGE_SIZE);
+       }
 
        blkif->irq = bind_evtchn_to_irqhandler(
                blkif->evtchn, tap_blkif_be_int, 0, "blkif-backend", blkif);
@@ -141,10 +147,11 @@ void tap_blkif_unmap(blkif_t *blkif)
                unbind_from_irqhandler(blkif->irq, blkif);
                blkif->irq = 0;
        }
-       if (blkif->blk_ring.sring) {
+       if (blkif->blk_v1_ring.sring || blkif->blk_v2_ring.sring) {
                unmap_frontend_page(blkif);
                free_vm_area(blkif->blk_ring_area);
-               blkif->blk_ring.sring = NULL;
+               blkif->blk_v1_ring.sring = NULL;
+               blkif->blk_v2_ring.sring = NULL;
        }
 }
 
Index: 
build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
===================================================================
--- 
build-64-release304-12901.orig/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
+++ build-64-release304-12901/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
@@ -316,6 +316,7 @@ static int connect_ring(struct backend_i
        struct xenbus_device *dev = be->dev;
        unsigned long ring_ref;
        unsigned int evtchn;
+       unsigned int protocol;
        int err;
 
        DPRINTK("%s\n", dev->otherend);
@@ -329,6 +330,19 @@ static int connect_ring(struct backend_i
                return err;
        }
 
+       err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
+                           "%u", &protocol, NULL);
+       if (err)
+               protocol = BLKIF_NATIVE_PROTOCOL;
+       if (protocol < 1 || protocol > 2) {
+               xenbus_dev_fatal(dev, err, "unknown fe protocol %d", protocol);
+               return -1;
+       }
+       be->blkif->blk_protocol = protocol;
+
+       printk("blktap: ring-ref %ld, event-channel %d, protocol %d\n",
+              ring_ref, evtchn, protocol);
+
        /* Map the shared frame, irq etc. */
        err = tap_blkif_map(be->blkif, ring_ref, evtchn);
        if (err) {
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel