]> xenbits.xensource.com Git - people/royger/linux-2.6.18-xen.git/commitdiff
xenblk: dynamic vbd resizing
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 15 Mar 2010 13:31:19 +0000 (13:31 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 15 Mar 2010 13:31:19 +0000 (13:31 +0000)
Signed-off-by: K. Y. Srinivasan <ksrinivasan@novell.com>
drivers/xen/blkback/blkback.c
drivers/xen/blkback/common.h
drivers/xen/blkback/vbd.c
drivers/xen/blkfront/blkfront.c

index bbe9bad25ed1113233944439eb3a81453e2894e1..018bf1df2c1177aa016a49f650b9a8719dadabd2 100644 (file)
@@ -205,6 +205,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);
 
@@ -214,6 +215,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 afe21b8b95829b8dc9eeaa8d603001c25f7c91e9..0921567c9f5ed1b3acd5920d4e1f166d7132284b 100644 (file)
@@ -56,6 +56,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;
@@ -104,6 +105,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 3876c027b43d6285ff2306548eb8f974d7ff646b..802b786832bdb1483b96d75bafb8011611714f73 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);
+}
index 54b14408f9b6e0bbc6ce8a70c8608aae9f1c563f..d36f11876085440b91e344093f6889ca8f9c87ac 100644 (file)
@@ -326,9 +326,24 @@ static void connect(struct blkfront_info *info)
        unsigned int binfo;
        int err;
 
-       if ((info->connected == BLKIF_STATE_CONNECTED) ||
-           (info->connected == BLKIF_STATE_SUSPENDED) )
+       switch (info->connected) {
+       case BLKIF_STATE_CONNECTED:
+               /*
+                * Potentially, the back-end may be signalling
+                * a capacity change; update the capacity.
+                */
+               err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+                                  "sectors", "%Lu", &sectors);
+               if (XENBUS_EXIST_ERR(err))
+                       return;
+               printk(KERN_INFO "Setting capacity to %Lu\n",
+                      sectors);
+               set_capacity(info->gd, sectors);
+
+               /* fall through */
+       case BLKIF_STATE_SUSPENDED:
                return;
+       }
 
        DPRINTK("blkfront.c:connect:%s.\n", info->xbdev->otherend);