aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorK. Y. Srinivasan2010-03-11 13:39:50 -0800
committerKonrad Rzeszutek Wilk2011-04-14 18:26:10 -0400
commit2ccbfe26c106a1a93a402567b7853c1484c4a0b0 (patch)
treec564bf3003924ddbc946407dc150d42427e9ad35
parent5cf6e4f6f6d5549904db6ecb3ffd5b8f71f41250 (diff)
xen/blkback: Propagate changed size of VBDs
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>
-rw-r--r--drivers/xen/blkback/blkback.c3
-rw-r--r--drivers/xen/blkback/common.h2
-rw-r--r--drivers/xen/blkback/vbd.c43
3 files changed, 48 insertions, 0 deletions
diff --git a/drivers/xen/blkback/blkback.c b/drivers/xen/blkback/blkback.c
index a2ac7189cc0a..6d897664802d 100644
--- a/drivers/xen/blkback/blkback.c
+++ b/drivers/xen/blkback/blkback.c
@@ -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,
diff --git a/drivers/xen/blkback/common.h b/drivers/xen/blkback/common.h
index aaf36485bc01..cebcc2b7e9f6 100644
--- a/drivers/xen/blkback/common.h
+++ b/drivers/xen/blkback/common.h
@@ -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) \
diff --git a/drivers/xen/blkback/vbd.c b/drivers/xen/blkback/vbd.c
index 410c2eac5ad7..0635c54079f8 100644
--- a/drivers/xen/blkback/vbd.c
+++ b/drivers/xen/blkback/vbd.c
@@ -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);
+}