xen/blkback: Propagate changed size of VBDs
authorK. Y. Srinivasan <ksrinivasan@novell.com>
Thu, 11 Mar 2010 21:39:50 +0000 (13:39 -0800)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Thu, 14 Apr 2011 22:26:10 +0000 (18:26 -0400)
Support dynamic resizing of virtual block devices. This patch supports
both file backed block devices as well as physical devices that can be
dynamically resized on the host side.

Signed-off-by: K. Y. Srinivasan <ksrinivasan@novell.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
drivers/xen/blkback/blkback.c
drivers/xen/blkback/common.h
drivers/xen/blkback/vbd.c

index a2ac718..6d89766 100644 (file)
@@ -207,6 +207,7 @@ static void print_stats(blkif_t *blkif)
 int blkif_schedule(void *arg)
 {
        blkif_t *blkif = arg;
+       struct vbd *vbd = &blkif->vbd;
 
        blkif_get(blkif);
 
@@ -216,6 +217,8 @@ int blkif_schedule(void *arg)
        while (!kthread_should_stop()) {
                if (try_to_freeze())
                        continue;
+               if (unlikely(vbd->size != vbd_size(vbd)))
+                       vbd_resize(blkif);
 
                wait_event_interruptible(
                        blkif->wq,
index aaf3648..cebcc2b 100644 (file)
@@ -52,6 +52,7 @@ struct vbd {
        unsigned char  type;        /* VDISK_xxx */
        u32            pdevice;     /* phys device that this vbd maps to */
        struct block_device *bdev;
+       sector_t       size;        /* Cached size parameter */
 };
 
 struct backend_info;
@@ -98,6 +99,7 @@ blkif_t *blkif_alloc(domid_t domid);
 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);
+void vbd_resize(blkif_t *blkif);
 
 #define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
 #define blkif_put(_b)                                  \
index 410c2ea..0635c54 100644 (file)
@@ -73,6 +73,7 @@ int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major,
        }
 
        vbd->bdev = bdev;
+       vbd->size = vbd_size(vbd);
 
        if (vbd->bdev->bd_disk == NULL) {
                DPRINTK("vbd_creat: device %08x doesn't exist.\n",
@@ -116,3 +117,45 @@ int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation)
  out:
        return rc;
 }
+
+void vbd_resize(blkif_t *blkif)
+{
+       struct vbd *vbd = &blkif->vbd;
+       struct xenbus_transaction xbt;
+       int err;
+       struct xenbus_device *dev = blkif->be->dev;
+       unsigned long long new_size = vbd_size(vbd);
+
+       printk(KERN_INFO "VBD Resize: new size %Lu\n", new_size);
+       vbd->size = new_size;
+again:
+       err = xenbus_transaction_start(&xbt);
+       if (err) {
+               printk(KERN_WARNING "Error starting transaction");
+               return;
+       }
+       err = xenbus_printf(xbt, dev->nodename, "sectors", "%Lu",
+                           vbd_size(vbd));
+       if (err) {
+               printk(KERN_WARNING "Error writing new size");
+               goto abort;
+       }
+       /*
+        * Write the current state; we will use this to synchronize
+        * the front-end. If the current state is "connected" the
+        * front-end will get the new size information online.
+        */
+       err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state);
+       if (err) {
+               printk(KERN_WARNING "Error writing the state");
+               goto abort;
+       }
+
+       err = xenbus_transaction_end(xbt, 0);
+       if (err == -EAGAIN)
+               goto again;
+       if (err)
+               printk(KERN_WARNING "Error ending transaction");
+abort:
+       xenbus_transaction_end(xbt, 1);
+}