ia64/xen-unstable

changeset 13587:c9ac0bace498

bimodal blkback: Support multiple ring protocols.

This is needed for 32-on-64 support. Right now there are three
protocols: native, x86_32 and x86_64. If needed it can be extended.

Interface changes (io/blkif.h)
* Define the x86_32 and x86_64 structs additionally to the native
version.
* Add helper functions to convert them requests to native.

Backend changes:
* Look at the "protocol" name 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.

Signed-off-by: Gerd Hoffmann <kraxel@suse.de>
author kfraser@localhost.localdomain
date Wed Jan 24 10:38:17 2007 +0000 (2007-01-24)
parents 349e95826a8f
children b064775fba7d
files linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c linux-2.6-xen-sparse/drivers/xen/blkback/common.h linux-2.6-xen-sparse/drivers/xen/blkback/interface.c linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c linux-2.6-xen-sparse/drivers/xen/blktap/common.h linux-2.6-xen-sparse/drivers/xen/blktap/interface.c linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c linux-2.6-xen-sparse/include/xen/blkif.h xen/include/public/io/blkif.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c	Wed Jan 24 10:22:06 2007 +0000
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c	Wed Jan 24 10:38:17 2007 +0000
     1.3 @@ -298,17 +298,20 @@ irqreturn_t blkif_be_int(int irq, void *
     1.4  
     1.5  static int do_block_io_op(blkif_t *blkif)
     1.6  {
     1.7 -	blkif_back_ring_t *blk_ring = &blkif->blk_ring;
     1.8 +	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
     1.9  	blkif_request_t req;
    1.10  	pending_req_t *pending_req;
    1.11  	RING_IDX rc, rp;
    1.12  	int more_to_do = 0;
    1.13  
    1.14 -	rc = blk_ring->req_cons;
    1.15 -	rp = blk_ring->sring->req_prod;
    1.16 +	rc = blk_rings->common.req_cons;
    1.17 +	rp = blk_rings->common.sring->req_prod;
    1.18  	rmb(); /* Ensure we see queued requests up to 'rp'. */
    1.19  
    1.20 -	while ((rc != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) {
    1.21 +	while ((rc != rp)) {
    1.22 +
    1.23 +		if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
    1.24 +			break;
    1.25  
    1.26  		pending_req = alloc_req();
    1.27  		if (NULL == pending_req) {
    1.28 @@ -317,8 +320,20 @@ static int do_block_io_op(blkif_t *blkif
    1.29  			break;
    1.30  		}
    1.31  
    1.32 -		memcpy(&req, RING_GET_REQUEST(blk_ring, rc), sizeof(req));
    1.33 -		blk_ring->req_cons = ++rc; /* before make_response() */
    1.34 +		switch (blkif->blk_protocol) {
    1.35 +		case BLKIF_PROTOCOL_NATIVE:
    1.36 +			memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req));
    1.37 +			break;
    1.38 +		case BLKIF_PROTOCOL_X86_32:
    1.39 +			blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc));
    1.40 +			break;
    1.41 +		case BLKIF_PROTOCOL_X86_64:
    1.42 +			blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc));
    1.43 +			break;
    1.44 +		default:
    1.45 +			BUG();
    1.46 +		}
    1.47 +		blk_rings->common.req_cons = ++rc; /* before make_response() */
    1.48  
    1.49  		switch (req.operation) {
    1.50  		case BLKIF_OP_READ:
    1.51 @@ -498,34 +513,48 @@ static void dispatch_rw_block_io(blkif_t
    1.52  static void make_response(blkif_t *blkif, unsigned long id, 
    1.53  			  unsigned short op, int st)
    1.54  {
    1.55 -	blkif_response_t *resp;
    1.56 +	blkif_response_t  resp;
    1.57  	unsigned long     flags;
    1.58 -	blkif_back_ring_t *blk_ring = &blkif->blk_ring;
    1.59 +	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
    1.60  	int more_to_do = 0;
    1.61  	int notify;
    1.62  
    1.63 -	spin_lock_irqsave(&blkif->blk_ring_lock, flags);
    1.64 +	resp.id        = id;
    1.65 +	resp.operation = op;
    1.66 +	resp.status    = st;
    1.67  
    1.68 -	/* Place on the response ring for the relevant domain. */ 
    1.69 -	resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
    1.70 -	resp->id        = id;
    1.71 -	resp->operation = op;
    1.72 -	resp->status    = st;
    1.73 -	blk_ring->rsp_prod_pvt++;
    1.74 -	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify);
    1.75 -
    1.76 -	if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) {
    1.77 +	spin_lock_irqsave(&blkif->blk_ring_lock, flags);
    1.78 +	/* Place on the response ring for the relevant domain. */
    1.79 +	switch (blkif->blk_protocol) {
    1.80 +	case BLKIF_PROTOCOL_NATIVE:
    1.81 +		memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt),
    1.82 +		       &resp, sizeof(resp));
    1.83 +		break;
    1.84 +	case BLKIF_PROTOCOL_X86_32:
    1.85 +		memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt),
    1.86 +		       &resp, sizeof(resp));
    1.87 +		break;
    1.88 +	case BLKIF_PROTOCOL_X86_64:
    1.89 +		memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt),
    1.90 +		       &resp, sizeof(resp));
    1.91 +		break;
    1.92 +	default:
    1.93 +		BUG();
    1.94 +	}
    1.95 +	blk_rings->common.rsp_prod_pvt++;
    1.96 +	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
    1.97 +	if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) {
    1.98  		/*
    1.99  		 * Tail check for pending requests. Allows frontend to avoid
   1.100  		 * notifications if requests are already in flight (lower
   1.101  		 * overheads and promotes batching).
   1.102  		 */
   1.103 -		RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do);
   1.104 +		RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
   1.105  
   1.106 -	} else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) {
   1.107 +	} else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) {
   1.108  		more_to_do = 1;
   1.109 +	}
   1.110  
   1.111 -	}
   1.112  	spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
   1.113  
   1.114  	if (more_to_do)
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h	Wed Jan 24 10:22:06 2007 +0000
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h	Wed Jan 24 10:38:17 2007 +0000
     2.3 @@ -40,8 +40,7 @@
     2.4  #include <asm/pgalloc.h>
     2.5  #include <xen/evtchn.h>
     2.6  #include <asm/hypervisor.h>
     2.7 -#include <xen/interface/io/blkif.h>
     2.8 -#include <xen/interface/io/ring.h>
     2.9 +#include <xen/blkif.h>
    2.10  #include <xen/gnttab.h>
    2.11  #include <xen/driver_util.h>
    2.12  #include <xen/xenbus.h>
    2.13 @@ -67,7 +66,8 @@ typedef struct blkif_st {
    2.14  	/* Physical parameters of the comms window. */
    2.15  	unsigned int      irq;
    2.16  	/* Comms information. */
    2.17 -	blkif_back_ring_t blk_ring;
    2.18 +	enum blkif_protocol blk_protocol;
    2.19 +	blkif_back_rings_t blk_rings;
    2.20  	struct vm_struct *blk_ring_area;
    2.21  	/* The VBD attached to this interface. */
    2.22  	struct vbd        vbd;
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c	Wed Jan 24 10:22:06 2007 +0000
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c	Wed Jan 24 10:38:17 2007 +0000
     3.3 @@ -95,7 +95,6 @@ static void unmap_frontend_page(blkif_t 
     3.4  
     3.5  int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
     3.6  {
     3.7 -	blkif_sring_t *sring;
     3.8  	int err;
     3.9  
    3.10  	/* Already connected through? */
    3.11 @@ -111,8 +110,31 @@ int blkif_map(blkif_t *blkif, unsigned l
    3.12  		return err;
    3.13  	}
    3.14  
    3.15 -	sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
    3.16 -	BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
    3.17 +	switch (blkif->blk_protocol) {
    3.18 +	case BLKIF_PROTOCOL_NATIVE:
    3.19 +	{
    3.20 +		blkif_sring_t *sring;
    3.21 +		sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
    3.22 +		BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE);
    3.23 +		break;
    3.24 +	}
    3.25 +	case BLKIF_PROTOCOL_X86_32:
    3.26 +	{
    3.27 +		blkif_x86_32_sring_t *sring_x86_32;
    3.28 +		sring_x86_32 = (blkif_x86_32_sring_t *)blkif->blk_ring_area->addr;
    3.29 +		BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE);
    3.30 +		break;
    3.31 +	}
    3.32 +	case BLKIF_PROTOCOL_X86_64:
    3.33 +	{
    3.34 +		blkif_x86_64_sring_t *sring_x86_64;
    3.35 +		sring_x86_64 = (blkif_x86_64_sring_t *)blkif->blk_ring_area->addr;
    3.36 +		BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE);
    3.37 +		break;
    3.38 +	}
    3.39 +	default:
    3.40 +		BUG();
    3.41 +	}
    3.42  
    3.43  	err = bind_interdomain_evtchn_to_irqhandler(
    3.44  		blkif->domid, evtchn, blkif_be_int, 0, "blkif-backend", blkif);
    3.45 @@ -143,10 +165,10 @@ void blkif_disconnect(blkif_t *blkif)
    3.46  		blkif->irq = 0;
    3.47  	}
    3.48  
    3.49 -	if (blkif->blk_ring.sring) {
    3.50 +	if (blkif->blk_rings.common.sring) {
    3.51  		unmap_frontend_page(blkif);
    3.52  		free_vm_area(blkif->blk_ring_area);
    3.53 -		blkif->blk_ring.sring = NULL;
    3.54 +		blkif->blk_rings.common.sring = NULL;
    3.55  	}
    3.56  }
    3.57  
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Wed Jan 24 10:22:06 2007 +0000
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Wed Jan 24 10:38:17 2007 +0000
     4.3 @@ -459,6 +459,7 @@ static int connect_ring(struct backend_i
     4.4  	struct xenbus_device *dev = be->dev;
     4.5  	unsigned long ring_ref;
     4.6  	unsigned int evtchn;
     4.7 +	char protocol[64] = "";
     4.8  	int err;
     4.9  
    4.10  	DPRINTK("%s", dev->otherend);
    4.11 @@ -472,6 +473,24 @@ static int connect_ring(struct backend_i
    4.12  		return err;
    4.13  	}
    4.14  
    4.15 +	be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
    4.16 +	err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
    4.17 +			    "%63s", protocol, NULL);
    4.18 +	if (err)
    4.19 +		strcpy(protocol, "unspecified, assuming native");
    4.20 +	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
    4.21 +		be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
    4.22 +	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
    4.23 +		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
    4.24 +	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
    4.25 +		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
    4.26 +	else {
    4.27 +		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
    4.28 +		return -1;
    4.29 +	}
    4.30 +	printk("blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
    4.31 +	       ring_ref, evtchn, be->blkif->blk_protocol, protocol);
    4.32 +
    4.33  	/* Map the shared frame, irq etc. */
    4.34  	err = blkif_map(be->blkif, ring_ref, evtchn);
    4.35  	if (err) {
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c	Wed Jan 24 10:22:06 2007 +0000
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c	Wed Jan 24 10:38:17 2007 +0000
     5.3 @@ -1091,15 +1091,15 @@ irqreturn_t tap_blkif_be_int(int irq, vo
     5.4  static int print_dbug = 1;
     5.5  static int do_block_io_op(blkif_t *blkif)
     5.6  {
     5.7 -	blkif_back_ring_t *blk_ring = &blkif->blk_ring;
     5.8 +	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
     5.9  	blkif_request_t req;
    5.10  	pending_req_t *pending_req;
    5.11  	RING_IDX rc, rp;
    5.12  	int more_to_do = 0;
    5.13  	tap_blkif_t *info;
    5.14  
    5.15 -	rc = blk_ring->req_cons;
    5.16 -	rp = blk_ring->sring->req_prod;
    5.17 +	rc = blk_rings->common.req_cons;
    5.18 +	rp = blk_rings->common.sring->req_prod;
    5.19  	rmb(); /* Ensure we see queued requests up to 'rp'. */
    5.20  
    5.21  	/*Check blkif has corresponding UE ring*/
    5.22 @@ -1130,8 +1130,8 @@ static int do_block_io_op(blkif_t *blkif
    5.23  			more_to_do = 1;
    5.24  			break;
    5.25  		}
    5.26 -		
    5.27 -		if (RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) {
    5.28 +
    5.29 +		if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) {
    5.30  			WPRINTK("RING_REQUEST_CONS_OVERFLOW!"
    5.31  			       " More to do\n");
    5.32  			more_to_do = 1;
    5.33 @@ -1145,8 +1145,21 @@ static int do_block_io_op(blkif_t *blkif
    5.34  			break;
    5.35  		}
    5.36  
    5.37 -		memcpy(&req, RING_GET_REQUEST(blk_ring, rc), sizeof(req));
    5.38 -		blk_ring->req_cons = ++rc; /* before make_response() */	
    5.39 +		switch (blkif->blk_protocol) {
    5.40 +		case BLKIF_PROTOCOL_NATIVE:
    5.41 +			memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc),
    5.42 +			       sizeof(req));
    5.43 +			break;
    5.44 +		case BLKIF_PROTOCOL_X86_32:
    5.45 +			blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc));
    5.46 +			break;
    5.47 +		case BLKIF_PROTOCOL_X86_64:
    5.48 +			blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc));
    5.49 +			break;
    5.50 +		default:
    5.51 +			BUG();
    5.52 +		}
    5.53 +		blk_rings->common.req_cons = ++rc; /* before make_response() */
    5.54  
    5.55  		switch (req.operation) {
    5.56  		case BLKIF_OP_READ:
    5.57 @@ -1222,7 +1235,7 @@ static void dispatch_rw_block_io(blkif_t
    5.58  		WPRINTK("blktap: fe_ring is full, can't add "
    5.59  			"IO Request will be dropped. %d %d\n",
    5.60  			RING_SIZE(&info->ufe_ring),
    5.61 -			RING_SIZE(&blkif->blk_ring));
    5.62 +			RING_SIZE(&blkif->blk_rings.common));
    5.63  		goto fail_response;
    5.64  	}
    5.65  
    5.66 @@ -1410,32 +1423,51 @@ static void dispatch_rw_block_io(blkif_t
    5.67  static void make_response(blkif_t *blkif, unsigned long id, 
    5.68                            unsigned short op, int st)
    5.69  {
    5.70 -	blkif_response_t *resp;
    5.71 +	blkif_response_t  resp;
    5.72  	unsigned long     flags;
    5.73 -	blkif_back_ring_t *blk_ring = &blkif->blk_ring;
    5.74 +	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
    5.75  	int more_to_do = 0;
    5.76  	int notify;
    5.77  
    5.78 +	resp.id        = id;
    5.79 +	resp.operation = op;
    5.80 +	resp.status    = st;
    5.81 +
    5.82  	spin_lock_irqsave(&blkif->blk_ring_lock, flags);
    5.83 -	/* Place on the response ring for the relevant domain. */ 
    5.84 -	resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
    5.85 -	resp->id        = id;
    5.86 -	resp->operation = op;
    5.87 -	resp->status    = st;
    5.88 -	blk_ring->rsp_prod_pvt++;
    5.89 -	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify);
    5.90 +	/* Place on the response ring for the relevant domain. */
    5.91 +	switch (blkif->blk_protocol) {
    5.92 +	case BLKIF_PROTOCOL_NATIVE:
    5.93 +		memcpy(RING_GET_RESPONSE(&blk_rings->native,
    5.94 +					 blk_rings->native.rsp_prod_pvt),
    5.95 +		       &resp, sizeof(resp));
    5.96 +		break;
    5.97 +	case BLKIF_PROTOCOL_X86_32:
    5.98 +		memcpy(RING_GET_RESPONSE(&blk_rings->x86_32,
    5.99 +					 blk_rings->x86_32.rsp_prod_pvt),
   5.100 +		       &resp, sizeof(resp));
   5.101 +		break;
   5.102 +	case BLKIF_PROTOCOL_X86_64:
   5.103 +		memcpy(RING_GET_RESPONSE(&blk_rings->x86_64,
   5.104 +					 blk_rings->x86_64.rsp_prod_pvt),
   5.105 +		       &resp, sizeof(resp));
   5.106 +		break;
   5.107 +	default:
   5.108 +		BUG();
   5.109 +	}
   5.110 +	blk_rings->common.rsp_prod_pvt++;
   5.111 +	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
   5.112  
   5.113 -	if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) {
   5.114 +	if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) {
   5.115  		/*
   5.116  		 * Tail check for pending requests. Allows frontend to avoid
   5.117  		 * notifications if requests are already in flight (lower
   5.118  		 * overheads and promotes batching).
   5.119  		 */
   5.120 -		RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do);
   5.121 -	} else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) {
   5.122 +		RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
   5.123 +	} else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) {
   5.124  		more_to_do = 1;
   5.125 +	}
   5.126  
   5.127 -	}	
   5.128  	spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
   5.129  	if (more_to_do)
   5.130  		blkif_notify_work(blkif);
     6.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h	Wed Jan 24 10:22:06 2007 +0000
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h	Wed Jan 24 10:38:17 2007 +0000
     6.3 @@ -39,8 +39,7 @@
     6.4  #include <asm/pgalloc.h>
     6.5  #include <xen/evtchn.h>
     6.6  #include <asm/hypervisor.h>
     6.7 -#include <xen/interface/io/blkif.h>
     6.8 -#include <xen/interface/io/ring.h>
     6.9 +#include <xen/blkif.h>
    6.10  #include <xen/gnttab.h>
    6.11  #include <xen/driver_util.h>
    6.12  
    6.13 @@ -58,7 +57,8 @@ typedef struct blkif_st {
    6.14  	/* Physical parameters of the comms window. */
    6.15  	unsigned int      irq;
    6.16  	/* Comms information. */
    6.17 -	blkif_back_ring_t blk_ring;
    6.18 +	enum blkif_protocol blk_protocol;
    6.19 +	blkif_back_rings_t blk_rings;
    6.20  	struct vm_struct *blk_ring_area;
    6.21  	/* Back pointer to the backend_info. */
    6.22  	struct backend_info *be;
     7.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c	Wed Jan 24 10:22:06 2007 +0000
     7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c	Wed Jan 24 10:38:17 2007 +0000
     7.3 @@ -96,7 +96,6 @@ static void unmap_frontend_page(blkif_t 
     7.4  int tap_blkif_map(blkif_t *blkif, unsigned long shared_page, 
     7.5  		  unsigned int evtchn)
     7.6  {
     7.7 -	blkif_sring_t *sring;
     7.8  	int err;
     7.9  
    7.10  	/* Already connected through? */
    7.11 @@ -112,8 +111,31 @@ int tap_blkif_map(blkif_t *blkif, unsign
    7.12  		return err;
    7.13  	}
    7.14  
    7.15 -	sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
    7.16 -	BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
    7.17 +	switch (blkif->blk_protocol) {
    7.18 +	case BLKIF_PROTOCOL_NATIVE:
    7.19 +	{
    7.20 +		blkif_sring_t *sring;
    7.21 +		sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
    7.22 +		BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE);
    7.23 +		break;
    7.24 +	}
    7.25 +	case BLKIF_PROTOCOL_X86_32:
    7.26 +	{
    7.27 +		blkif_x86_32_sring_t *sring_x86_32;
    7.28 +		sring_x86_32 = (blkif_x86_32_sring_t *)blkif->blk_ring_area->addr;
    7.29 +		BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE);
    7.30 +		break;
    7.31 +	}
    7.32 +	case BLKIF_PROTOCOL_X86_64:
    7.33 +	{
    7.34 +		blkif_x86_64_sring_t *sring_x86_64;
    7.35 +		sring_x86_64 = (blkif_x86_64_sring_t *)blkif->blk_ring_area->addr;
    7.36 +		BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE);
    7.37 +		break;
    7.38 +	}
    7.39 +	default:
    7.40 +		BUG();
    7.41 +	}
    7.42  
    7.43  	err = bind_interdomain_evtchn_to_irqhandler(
    7.44  		blkif->domid, evtchn, tap_blkif_be_int,
    7.45 @@ -134,10 +156,10 @@ void tap_blkif_unmap(blkif_t *blkif)
    7.46  		unbind_from_irqhandler(blkif->irq, blkif);
    7.47  		blkif->irq = 0;
    7.48  	}
    7.49 -	if (blkif->blk_ring.sring) {
    7.50 +	if (blkif->blk_rings.common.sring) {
    7.51  		unmap_frontend_page(blkif);
    7.52  		free_vm_area(blkif->blk_ring_area);
    7.53 -		blkif->blk_ring.sring = NULL;
    7.54 +		blkif->blk_rings.common.sring = NULL;
    7.55  	}
    7.56  }
    7.57  
     8.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c	Wed Jan 24 10:22:06 2007 +0000
     8.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c	Wed Jan 24 10:38:17 2007 +0000
     8.3 @@ -340,6 +340,7 @@ static int connect_ring(struct backend_i
     8.4  	struct xenbus_device *dev = be->dev;
     8.5  	unsigned long ring_ref;
     8.6  	unsigned int evtchn;
     8.7 +	char protocol[64];
     8.8  	int err;
     8.9  
    8.10  	DPRINTK("%s\n", dev->otherend);
    8.11 @@ -353,6 +354,24 @@ static int connect_ring(struct backend_i
    8.12  		return err;
    8.13  	}
    8.14  
    8.15 +	be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
    8.16 +	err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
    8.17 +			    "%63s", protocol, NULL);
    8.18 +	if (err)
    8.19 +		strcpy(protocol, "unspecified, assuming native");
    8.20 +	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
    8.21 +		be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
    8.22 +	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
    8.23 +		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
    8.24 +	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
    8.25 +		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
    8.26 +	else {
    8.27 +		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
    8.28 +		return -1;
    8.29 +	}
    8.30 +	printk("blktap: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
    8.31 +	       ring_ref, evtchn, be->blkif->blk_protocol, protocol);
    8.32 +
    8.33  	/* Map the shared frame, irq etc. */
    8.34  	err = tap_blkif_map(be->blkif, ring_ref, evtchn);
    8.35  	if (err) {
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/linux-2.6-xen-sparse/include/xen/blkif.h	Wed Jan 24 10:38:17 2007 +0000
     9.3 @@ -0,0 +1,97 @@
     9.4 +#ifndef __XEN_BLKIF_H__
     9.5 +#define __XEN_BLKIF_H__
     9.6 +
     9.7 +#include <xen/interface/io/ring.h>
     9.8 +#include <xen/interface/io/blkif.h>
     9.9 +#include <xen/interface/io/protocols.h>
    9.10 +
    9.11 +/* Not a real protocol.  Used to generate ring structs which contain
    9.12 + * the elements common to all protocols only.  This way we get a
    9.13 + * compiler-checkable way to use common struct elements, so we can
    9.14 + * avoid using switch(protocol) in a number of places.  */
    9.15 +struct blkif_common_request {
    9.16 +	char dummy;
    9.17 +};
    9.18 +struct blkif_common_response {
    9.19 +	char dummy;
    9.20 +};
    9.21 +
    9.22 +/* i386 protocol version */
    9.23 +#pragma pack(push, 4)
    9.24 +struct blkif_x86_32_request {
    9.25 +	uint8_t        operation;    /* BLKIF_OP_???                         */
    9.26 +	uint8_t        nr_segments;  /* number of segments                   */
    9.27 +	blkif_vdev_t   handle;       /* only for read/write requests         */
    9.28 +	uint64_t       id;           /* private guest value, echoed in resp  */
    9.29 +	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
    9.30 +	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
    9.31 +};
    9.32 +struct blkif_x86_32_response {
    9.33 +	uint64_t        id;              /* copied from request */
    9.34 +	uint8_t         operation;       /* copied from request */
    9.35 +	int16_t         status;          /* BLKIF_RSP_???       */
    9.36 +};
    9.37 +typedef struct blkif_x86_32_request blkif_x86_32_request_t;
    9.38 +typedef struct blkif_x86_32_response blkif_x86_32_response_t;
    9.39 +#pragma pack(pop)
    9.40 +
    9.41 +/* x86_64 protocol version */
    9.42 +struct blkif_x86_64_request {
    9.43 +	uint8_t        operation;    /* BLKIF_OP_???                         */
    9.44 +	uint8_t        nr_segments;  /* number of segments                   */
    9.45 +	blkif_vdev_t   handle;       /* only for read/write requests         */
    9.46 +	uint64_t       __attribute__((__aligned__(8))) id;
    9.47 +	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
    9.48 +	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
    9.49 +};
    9.50 +struct blkif_x86_64_response {
    9.51 +	uint64_t       __attribute__((__aligned__(8))) id;
    9.52 +	uint8_t         operation;       /* copied from request */
    9.53 +	int16_t         status;          /* BLKIF_RSP_???       */
    9.54 +};
    9.55 +typedef struct blkif_x86_64_request blkif_x86_64_request_t;
    9.56 +typedef struct blkif_x86_64_response blkif_x86_64_response_t;
    9.57 +
    9.58 +DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, struct blkif_common_response);
    9.59 +DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, struct blkif_x86_32_response);
    9.60 +DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, struct blkif_x86_64_response);
    9.61 +
    9.62 +union blkif_back_rings {
    9.63 +	blkif_back_ring_t        native;
    9.64 +	blkif_common_back_ring_t common;
    9.65 +	blkif_x86_32_back_ring_t x86_32;
    9.66 +	blkif_x86_64_back_ring_t x86_64;
    9.67 +};
    9.68 +typedef union blkif_back_rings blkif_back_rings_t;
    9.69 +
    9.70 +enum blkif_protocol {
    9.71 +	BLKIF_PROTOCOL_NATIVE = 1,
    9.72 +	BLKIF_PROTOCOL_X86_32 = 2,
    9.73 +	BLKIF_PROTOCOL_X86_64 = 3,
    9.74 +};
    9.75 +
    9.76 +static void inline blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src)
    9.77 +{
    9.78 +	int i;
    9.79 +	dst->operation = src->operation;
    9.80 +	dst->nr_segments = src->nr_segments;
    9.81 +	dst->handle = src->handle;
    9.82 +	dst->id = src->id;
    9.83 +	dst->sector_number = src->sector_number;
    9.84 +	for (i = 0; i < src->nr_segments; i++)
    9.85 +		dst->seg[i] = src->seg[i];
    9.86 +}
    9.87 +
    9.88 +static void inline blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src)
    9.89 +{
    9.90 +	int i;
    9.91 +	dst->operation = src->operation;
    9.92 +	dst->nr_segments = src->nr_segments;
    9.93 +	dst->handle = src->handle;
    9.94 +	dst->id = src->id;
    9.95 +	dst->sector_number = src->sector_number;
    9.96 +	for (i = 0; i < src->nr_segments; i++)
    9.97 +		dst->seg[i] = src->seg[i];
    9.98 +}
    9.99 +
   9.100 +#endif /* __XEN_BLKIF_H__ */
    10.1 --- a/xen/include/public/io/blkif.h	Wed Jan 24 10:22:06 2007 +0000
    10.2 +++ b/xen/include/public/io/blkif.h	Wed Jan 24 10:38:17 2007 +0000
    10.3 @@ -71,18 +71,20 @@
    10.4   */
    10.5  #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
    10.6  
    10.7 +struct blkif_request_segment {
    10.8 +    grant_ref_t gref;        /* reference to I/O buffer frame        */
    10.9 +    /* @first_sect: first sector in frame to transfer (inclusive).   */
   10.10 +    /* @last_sect: last sector in frame to transfer (inclusive).     */
   10.11 +    uint8_t     first_sect, last_sect;
   10.12 +};
   10.13 +
   10.14  struct blkif_request {
   10.15      uint8_t        operation;    /* BLKIF_OP_???                         */
   10.16      uint8_t        nr_segments;  /* number of segments                   */
   10.17      blkif_vdev_t   handle;       /* only for read/write requests         */
   10.18      uint64_t       id;           /* private guest value, echoed in resp  */
   10.19      blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
   10.20 -    struct blkif_request_segment {
   10.21 -        grant_ref_t gref;        /* reference to I/O buffer frame        */
   10.22 -        /* @first_sect: first sector in frame to transfer (inclusive).   */
   10.23 -        /* @last_sect: last sector in frame to transfer (inclusive).     */
   10.24 -        uint8_t     first_sect, last_sect;
   10.25 -    } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   10.26 +    struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   10.27  };
   10.28  typedef struct blkif_request blkif_request_t;
   10.29