From: Bruce Rogers <brogers@suse.com>
Date: Fri, 8 Jun 2018 11:04:36 -0600
Subject: xen: add block resize support for xen disks

Provide monitor naming of xen disks, and plumb guest driver
notification through xenstore of resizing instigated via the
monitor.

[BR: minor edits to pass qemu's checkpatch script]
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
 block/block-backend.c          | 12 +++++++++++-
 blockdev.c                     |  8 ++++++++
 hw/block/xen_disk.c            | 24 ++++++++++++++++++++++++
 include/hw/xen/xen.h           |  4 ++++
 include/sysemu/block-backend.h |  1 +
 stubs/xen-common.c             |  9 +++++++++
 6 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 3a3d888633..35e3edb861 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -23,6 +23,7 @@
 #include "qemu/option.h"
 #include "trace.h"
 #include "migration/misc.h"
+#include "hw/xen/xen.h"
 
 /* Number of coroutines to reserve per attached device model */
 #define COROUTINE_POOL_RESERVATION 64
@@ -910,7 +911,9 @@ char *blk_get_attached_dev_id(BlockBackend *blk)
 {
     DeviceState *dev;
 
-    assert(!blk->legacy_dev);
+    if (blk->legacy_dev) {
+        return xen_blk_get_attached_dev_id(blk->dev);
+    }
     dev = blk->dev;
 
     if (!dev) {
@@ -2016,6 +2019,13 @@ int blk_truncate(BlockBackend *blk, int64_t offset, PreallocMode prealloc,
     return bdrv_truncate(blk->root, offset, prealloc, errp);
 }
 
+void blk_legacy_resize_cb(BlockBackend *blk)
+{
+        if (blk->legacy_dev) {
+            xen_blk_resize_cb(blk->dev);
+        }
+}
+
 static void blk_pdiscard_entry(void *opaque)
 {
     BlkRwCo *rwco = opaque;
diff --git a/blockdev.c b/blockdev.c
index 81f95d920b..e67116974e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3091,6 +3091,7 @@ void qmp_block_resize(bool has_device, const char *device,
 {
     Error *local_err = NULL;
     BlockBackend *blk = NULL;
+    BlockBackend *cb_blk = NULL;
     BlockDriverState *bs;
     AioContext *aio_context;
     int ret;
@@ -3103,6 +3104,10 @@ void qmp_block_resize(bool has_device, const char *device,
         return;
     }
 
+    if (has_device) {
+        cb_blk = blk_by_name(device);
+    }
+
     aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
@@ -3129,6 +3134,9 @@ void qmp_block_resize(bool has_device, const char *device,
 
     bdrv_drained_begin(bs);
     ret = blk_truncate(blk, size, PREALLOC_MODE_OFF, errp);
+    if (!ret && cb_blk) {
+        blk_legacy_resize_cb(cb_blk);
+    }
     bdrv_drained_end(bs);
 
 out:
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index ddd5c7cbfd..d9a55faf27 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -761,6 +761,7 @@ static int blk_connect(struct XenDevice *xendev)
     int order, ring_ref;
     unsigned int ring_size, max_grants;
     unsigned int i;
+    Error *errp = NULL;
 
     trace_xen_disk_connect(xendev->name);
 
@@ -821,6 +822,13 @@ static int blk_connect(struct XenDevice *xendev)
         blk_ref(blkdev->blk);
     }
     blk_attach_dev_legacy(blkdev->blk, blkdev);
+    if (!monitor_add_blk(blkdev->blk, g_strdup(blkdev->dev), &errp)) {
+        xen_pv_printf(&blkdev->xendev, 0, "error: %s\n",
+                      error_get_pretty(errp));
+        error_free(errp);
+        return -1;
+    }
+
     blkdev->file_size = blk_getlength(blkdev->blk);
     if (blkdev->file_size < 0) {
         BlockDriverState *bs = blk_bs(blkdev->blk);
@@ -971,6 +979,7 @@ static void blk_disconnect(struct XenDevice *xendev)
     if (blkdev->blk) {
         blk_set_aio_context(blkdev->blk, qemu_get_aio_context());
         blk_detach_dev(blkdev->blk, blkdev);
+        monitor_remove_blk(blkdev->blk);
         blk_unref(blkdev->blk);
         blkdev->blk = NULL;
     }
@@ -1018,6 +1027,21 @@ static void blk_event(struct XenDevice *xendev)
     qemu_bh_schedule(blkdev->bh);
 }
 
+void xen_blk_resize_cb(void *dev)
+{
+    struct XenBlkDev *blkdev = dev;
+    blkdev->file_size = blk_getlength(blkdev->blk);
+    xenstore_write_be_int64(&blkdev->xendev, "sectors",
+                            blkdev->file_size / blkdev->file_blk);
+    xen_be_set_state(&blkdev->xendev, blkdev->xendev.be_state);
+}
+
+char *xen_blk_get_attached_dev_id(void *dev)
+{
+    struct XenBlkDev *blkdev = dev;
+    return g_strdup_printf("xen-qdisk-%i", blkdev->xendev.dev);
+}
+
 struct XenDevOps xen_blkdev_ops = {
     .flags      = DEVOPS_FLAG_NEED_GNTDEV,
     .size       = sizeof(struct XenBlkDev),
diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
index 7efcdaa8fe..45c8c0b6f7 100644
--- a/include/hw/xen/xen.h
+++ b/include/hw/xen/xen.h
@@ -48,4 +48,8 @@ void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length);
 
 void xen_register_framebuffer(struct MemoryRegion *mr);
 
+void xen_blk_resize_cb(void *dev);
+
+char *xen_blk_get_attached_dev_id(void *dev);
+
 #endif /* QEMU_HW_XEN_H */
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index c96bcdee14..0488cf45ff 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -236,5 +236,6 @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
                                    BlockBackend *blk_out, int64_t off_out,
                                    int bytes, BdrvRequestFlags read_flags,
                                    BdrvRequestFlags write_flags);
+void blk_legacy_resize_cb(BlockBackend *blk);
 
 #endif
diff --git a/stubs/xen-common.c b/stubs/xen-common.c
index 09fce2dd36..91542fc019 100644
--- a/stubs/xen-common.c
+++ b/stubs/xen-common.c
@@ -12,3 +12,12 @@
 void xenstore_store_pv_console_info(int i, Chardev *chr)
 {
 }
+
+void xen_blk_resize_cb(void *dev)
+{
+}
+
+char *xen_blk_get_attached_dev_id(void *dev)
+{
+    return g_strdup("");
+}
