This patch implements XenbusStateAttached handler for blkback, which is called
when Kemari restores the guest. First, the handler attaches the back-end ring
to the device channel using BACK_RING_ATTACH macro. Then, it adjusts producer
and consumer indexes of the back-end, so that the front-end driver in the guest
can continue transparently.
Signed-off-by: Yoshi Tamura <tamura.yoshiaki@xxxxxxxxxxxxx>
Signed-off-by: Yoshisato Yanagisawa <yanagisawa.yoshisato@xxxxxxxxxxxxx>
---
drivers/xen/blkback/common.h | 2 +
drivers/xen/blkback/interface.c | 41 +++++++++++++++++++++++++++
drivers/xen/blkback/xenbus.c | 59 +++
diff -r e410857fd83c drivers/xen/blkback/common.h
--- a/drivers/xen/blkback/common.h Wed Oct 22 14:55:29 2008 +0100
+++ b/drivers/xen/blkback/common.h Thu Mar 05 09:56:14 2009 +0900
@@ -100,6 +100,8 @@
void blkif_disconnect(blkif_t *blkif);
void blkif_free(blkif_t *blkif);
int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn);
+int blkif_attach(blkif_t *blkif, unsigned long shared_page,
+ unsigned int evtchn);
#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
#define blkif_put(_b) \
diff -r e410857fd83c drivers/xen/blkback/interface.c
--- a/drivers/xen/blkback/interface.c Wed Oct 22 14:55:29 2008 +0100
+++ b/drivers/xen/blkback/interface.c Thu Mar 05 09:56:14 2009 +0900
@@ -144,6 +144,47 @@
return 0;
}
+int blkif_attach(blkif_t *blkif, unsigned long shared_page,
+ unsigned int evtchn)
+{
+ /* Sorry! Only 32bit curretly. */
+ blkif_x86_32_sring_t *sring_x86_32;
+ int err;
+
+ /* Already connected through? */
+ if (blkif->irq)
+ return 0;
+
+ if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
+ return -ENOMEM;
+
+ err = map_frontend_page(blkif, shared_page);
+ if (err) {
+ free_vm_area(blkif->blk_ring_area);
+ return err;
+ }
+
+ sring_x86_32 =
+ (blkif_x86_32_sring_t *)blkif->blk_ring_area->addr;
+ BACK_RING_ATTACH(&blkif->blk_rings.x86_32,
+ sring_x86_32, PAGE_SIZE);
+
+ err = bind_interdomain_evtchn_to_irqhandler(
+ blkif->domid, evtchn, blkif_be_int, 0, "blkif-backend", blkif);
+ if (err < 0)
+ {
+ unmap_frontend_page(blkif);
+ free_vm_area(blkif->blk_ring_area);
+ blkif->blk_rings.common.sring = NULL;
+ return err;
+ }
+ blkif->irq = err;
+
+ blkif->blk_rings.x86_32.req_cons = blkif->blk_rings.x86_32.rsp_prod_pvt;
+
+ return 0;
+}
+
void blkif_disconnect(blkif_t *blkif)
{
if (blkif->xenblkd) {
diff -r e410857fd83c drivers/xen/blkback/xenbus.c
--- a/drivers/xen/blkback/xenbus.c Wed Oct 22 14:55:29 2008 +0100
+++ b/drivers/xen/blkback/xenbus.c Thu Mar 05 09:56:14 2009 +0900
@@ -39,6 +39,7 @@
static void connect(struct backend_info *);
static int connect_ring(struct backend_info *);
+static int attach_ring(struct backend_info *);
static void backend_changed(struct xenbus_watch *, const char **,
unsigned int);
@@ -376,6 +377,16 @@
update_blkif_status(be->blkif);
break;
+ case XenbusStateAttached:
+ if (dev->state == XenbusStateAttached)
+ break;
+
+ err = attach_ring(be);
+ if (err)
+ break;
+ update_blkif_status(be->blkif);
+ break;
+
case XenbusStateClosing:
blkif_disconnect(be->blkif);
xenbus_switch_state(dev, XenbusStateClosing);
@@ -515,6 +526,54 @@
return 0;
}
+static int attach_ring(struct backend_info *be)
+{
+ struct xenbus_device *dev = be->dev;
+ unsigned long ring_ref;
+ unsigned int evtchn;
+ char protocol[64] = "";
+ int err;
+
+ DPRINTK("%s", dev->otherend);
+
+ err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu",
&ring_ref,
+ "event-channel", "%u", &evtchn,
NULL);
+ if (err) {
+ xenbus_dev_fatal(dev, err,
+ "reading %s/ring-ref and
event-channel",
+ dev->otherend);
+ return err;
+ }
+
+ be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+ err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
+ "%63s", protocol, NULL);
+ if (err)
+ strcpy(protocol, "unspecified, assuming native");
+ else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
+ be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+ else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
+ be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
+ else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
+ be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
+ else {
+ xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
+ return -1;
+ }
+ printk(KERN_INFO
+ "blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
+ ring_ref, evtchn, be->blkif->blk_protocol, protocol);
+
+ /* Map the shared frame, irq etc. */
+ err = blkif_attach(be->blkif, ring_ref, evtchn);
+ if (err) {
+ xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
+ ring_ref, evtchn);
+ return err;
+ }
+
+ return 0;
+}
/* ** Driver Registration ** */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|