Patchwork hw/9pfs: use migration blockers to prevent live migration when virtfs export path is mounted

login
register
mail settings
Submitter Aneesh Kumar K.V
Date Nov. 28, 2011, 5:37 p.m.
Message ID <1322501842-9828-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/128034/
State New
Headers show

Comments

Aneesh Kumar K.V - Nov. 28, 2011, 5:37 p.m.
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>

Now when you try to migrate with VirtFS export path mounted, you get a proper QMP error:

(qemu) migrate tcp:localhost:4444
Migration is disabled when VirtFS export path '/tmp/' is mounted in the guest using mount_tag 'v_tmp'
(qemu)

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9pfs/virtio-9p-device.c |   22 +++++++++++-----------
 hw/9pfs/virtio-9p.c        |   10 ++++++++++
 hw/9pfs/virtio-9p.h        |    4 ++--
 qerror.c                   |    5 +++++
 qerror.h                   |    3 +++
 5 files changed, 31 insertions(+), 13 deletions(-)

Patch

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 57dc77c..cd343e1 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -33,13 +33,15 @@  static V9fsState *to_virtio_9p(VirtIODevice *vdev)
 
 static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
 {
+    int len;
     struct virtio_9p_config *cfg;
     V9fsState *s = to_virtio_9p(vdev);
 
-    cfg = g_malloc0(sizeof(struct virtio_9p_config) +
-                        s->tag_len);
-    stw_raw(&cfg->tag_len, s->tag_len);
-    memcpy(cfg->tag, s->tag, s->tag_len);
+    len = strlen(s->tag);
+    cfg = g_malloc0(sizeof(struct virtio_9p_config) + len);
+    stw_raw(&cfg->tag_len, len);
+    /* We don't copy the terminating null to config space */
+    memcpy(cfg->tag, s->tag, len);
     memcpy(config, cfg, s->config_size);
     g_free(cfg);
 }
@@ -96,20 +98,18 @@  VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     }
 
     len = strlen(conf->tag);
-    if (len > MAX_TAG_LEN) {
+    if (len > MAX_TAG_LEN - 1) {
         fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
-                "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN);
+                "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN - 1);
         exit(1);
     }
-    /* s->tag is non-NULL terminated string */
-    s->tag = g_malloc(len);
-    memcpy(s->tag, conf->tag, len);
-    s->tag_len = len;
+
+    s->tag = strdup(conf->tag);
     s->ctx.uid = -1;
 
     s->ops = fse->ops;
     s->vdev.get_features = virtio_9p_get_features;
-    s->config_size = sizeof(struct virtio_9p_config) + s->tag_len;
+    s->config_size = sizeof(struct virtio_9p_config) + len;
     s->vdev.get_config = virtio_9p_get_config;
     s->fid_list = NULL;
     qemu_co_rwlock_init(&s->rename_lock);
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 840227a..223a191 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -24,6 +24,7 @@ 
 #include "virtio-9p-coth.h"
 #include "trace.h"
 #include "qemu-error.h"
+#include "migration.h"
 
 int open_fd_hw;
 int total_open_fd;
@@ -1264,6 +1265,10 @@  static void v9fs_attach(void *opaque)
     err = offset;
     trace_v9fs_attach_return(pdu->tag, pdu->id,
                              qid.type, qid.version, qid.path);
+    /* disable migration */
+    error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
+              s->ctx.fs_root, s->tag);
+    migrate_add_blocker(s->migration_blocker);
 out:
     put_fid(pdu, fidp);
 out_nofid:
@@ -1283,6 +1288,11 @@  static void v9fs_detach(void *opaque)
     trace_v9fs_detach_return(pdu->tag, pdu->id);
     complete_pdu(pdu->s, pdu, 7);
 
+    if (pdu->s->migration_blocker) {
+        migrate_del_blocker(pdu->s->migration_blocker);
+        error_free(pdu->s->migration_blocker);
+        pdu->s->migration_blocker = NULL;
+    }
     return;
 }
 
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 5a30d6e..a98d624 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -248,8 +248,7 @@  typedef struct V9fsState
     V9fsFidState *fid_list;
     FileOperations *ops;
     FsContext ctx;
-    uint16_t tag_len;
-    uint8_t *tag;
+    char *tag;
     size_t config_size;
     enum p9_proto_version proto_version;
     int32_t msize;
@@ -258,6 +257,7 @@  typedef struct V9fsState
      * on rename.
      */
     CoRwlock rename_lock;
+    Error *migration_blocker;
 } V9fsState;
 
 typedef struct V9fsStatState {
diff --git a/qerror.c b/qerror.c
index fdf62b9..25bc91e 100644
--- a/qerror.c
+++ b/qerror.c
@@ -235,6 +235,11 @@  static const QErrorStringTable qerror_table[] = {
                      "supported by this qemu version: %(feature)",
     },
     {
+        .error_fmt = QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
+        .desc      = "Migration is disabled when VirtFS export path '%(path)' "
+                     "is mounted in the guest using mount_tag '%(tag)'",
+    },
+    {
         .error_fmt = QERR_VNC_SERVER_FAILED,
         .desc      = "Could not start VNC server on %(target)",
     },
diff --git a/qerror.h b/qerror.h
index 2d3d43b..6414cd9 100644
--- a/qerror.h
+++ b/qerror.h
@@ -192,6 +192,9 @@  QError *qobject_to_qerror(const QObject *obj);
 #define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \
     "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }"
 
+#define QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION \
+    "{ 'class': 'VirtFSFeatureBlocksMigration', 'data': { 'path': %s, 'tag': %s } }"
+
 #define QERR_VNC_SERVER_FAILED \
     "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"