[v6,02/16] block: check bdrv_in_use() before blockdev operations

Submitted by Stefan Hajnoczi on Jan. 18, 2012, 2:40 p.m.

Details

Message ID 1326897655-2799-3-git-send-email-stefanha@linux.vnet.ibm.com
State New
Headers show

Commit Message

Stefan Hajnoczi Jan. 18, 2012, 2:40 p.m.
Long-running block operations like block migration and image streaming
must have continual access to their block device.  It is not safe to
perform operations like hotplug, eject, change, resize, commit, or
external snapshot while a long-running operation is in progress.

This patch adds the missing bdrv_in_use() checks so that block migration
and image streaming never have the rug pulled out from underneath them.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
---
 block.c    |    4 ++++
 blockdev.c |   16 +++++++++++++++-
 2 files changed, 19 insertions(+), 1 deletions(-)

Patch hide | download patch | download mbox

diff --git a/block.c b/block.c
index 3f072f6..43f6484 100644
--- a/block.c
+++ b/block.c
@@ -1020,6 +1020,10 @@  int bdrv_commit(BlockDriverState *bs)
         return -EACCES;
     }
 
+    if (bdrv_in_use(bs) || bdrv_in_use(bs->backing_hd)) {
+        return -EBUSY;
+    }
+
     backing_drv = bs->backing_hd->drv;
     ro = bs->backing_hd->read_only;
     strncpy(filename, bs->backing_hd->filename, sizeof(filename));
diff --git a/blockdev.c b/blockdev.c
index c832782..6d78b36 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -592,12 +592,18 @@  void do_commit(Monitor *mon, const QDict *qdict)
     if (!strcmp(device, "all")) {
         bdrv_commit_all();
     } else {
+        int ret;
+
         bs = bdrv_find(device);
         if (!bs) {
             qerror_report(QERR_DEVICE_NOT_FOUND, device);
             return;
         }
-        bdrv_commit(bs);
+        ret = bdrv_commit(bs);
+        if (ret == -EBUSY) {
+            qerror_report(QERR_DEVICE_IN_USE, device);
+            return;
+        }
     }
 }
 
@@ -616,6 +622,10 @@  void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
+    if (bdrv_in_use(bs)) {
+        error_set(errp, QERR_DEVICE_IN_USE, device);
+        return;
+    }
 
     pstrcpy(old_filename, sizeof(old_filename), bs->filename);
 
@@ -667,6 +677,10 @@  void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
 
 static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
 {
+    if (bdrv_in_use(bs)) {
+        qerror_report(QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
+        return -1;
+    }
     if (!bdrv_dev_has_removable_media(bs)) {
         qerror_report(QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs));
         return -1;