{
        int err;
        struct xen_blkif *blkif = ring->blkif;
+       const struct blkif_common_sring *sring_common;
+       RING_IDX rsp_prod, req_prod;
+       unsigned int size;
 
        /* Already connected through? */
        if (ring->irq)
        if (err < 0)
                return err;
 
+       sring_common = (struct blkif_common_sring *)ring->blk_ring;
+       rsp_prod = READ_ONCE(sring_common->rsp_prod);
+       req_prod = READ_ONCE(sring_common->req_prod);
+
        switch (blkif->blk_protocol) {
        case BLKIF_PROTOCOL_NATIVE:
        {
-               struct blkif_sring *sring;
-               sring = (struct blkif_sring *)ring->blk_ring;
-               BACK_RING_INIT(&ring->blk_rings.native, sring,
-                              XEN_PAGE_SIZE * nr_grefs);
+               struct blkif_sring *sring_native =
+                       (struct blkif_sring *)ring->blk_ring;
+
+               BACK_RING_ATTACH(&ring->blk_rings.native, sring_native,
+                                rsp_prod, XEN_PAGE_SIZE * nr_grefs);
+               size = __RING_SIZE(sring_native, XEN_PAGE_SIZE * nr_grefs);
                break;
        }
        case BLKIF_PROTOCOL_X86_32:
        {
-               struct blkif_x86_32_sring *sring_x86_32;
-               sring_x86_32 = (struct blkif_x86_32_sring *)ring->blk_ring;
-               BACK_RING_INIT(&ring->blk_rings.x86_32, sring_x86_32,
-                              XEN_PAGE_SIZE * nr_grefs);
+               struct blkif_x86_32_sring *sring_x86_32 =
+                       (struct blkif_x86_32_sring *)ring->blk_ring;
+
+               BACK_RING_ATTACH(&ring->blk_rings.x86_32, sring_x86_32,
+                                rsp_prod, XEN_PAGE_SIZE * nr_grefs);
+               size = __RING_SIZE(sring_x86_32, XEN_PAGE_SIZE * nr_grefs);
                break;
        }
        case BLKIF_PROTOCOL_X86_64:
        {
-               struct blkif_x86_64_sring *sring_x86_64;
-               sring_x86_64 = (struct blkif_x86_64_sring *)ring->blk_ring;
-               BACK_RING_INIT(&ring->blk_rings.x86_64, sring_x86_64,
-                              XEN_PAGE_SIZE * nr_grefs);
+               struct blkif_x86_64_sring *sring_x86_64 =
+                       (struct blkif_x86_64_sring *)ring->blk_ring;
+
+               BACK_RING_ATTACH(&ring->blk_rings.x86_64, sring_x86_64,
+                                rsp_prod, XEN_PAGE_SIZE * nr_grefs);
+               size = __RING_SIZE(sring_x86_64, XEN_PAGE_SIZE * nr_grefs);
                break;
        }
        default:
                BUG();
        }
 
+       err = -EIO;
+       if (req_prod - rsp_prod > size)
+               goto fail;
+
        err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn,
                                                    xen_blkif_be_int, 0,
                                                    "blkif-backend", ring);
-       if (err < 0) {
-               xenbus_unmap_ring_vfree(blkif->be->dev, ring->blk_ring);
-               ring->blk_rings.common.sring = NULL;
-               return err;
-       }
+       if (err < 0)
+               goto fail;
        ring->irq = err;
 
        return 0;
+
+fail:
+       xenbus_unmap_ring_vfree(blkif->be->dev, ring->blk_ring);
+       ring->blk_rings.common.sring = NULL;
+       return err;
 }
 
 static int xen_blkif_disconnect(struct xen_blkif *blkif)
        .ids  = xen_blkbk_ids,
        .probe = xen_blkbk_probe,
        .remove = xen_blkbk_remove,
-       .otherend_changed = frontend_changed
+       .otherend_changed = frontend_changed,
+       .allow_rebind = true,
 };
 
 int xen_blkif_xenbus_init(void)