Patchwork [V2,1/3] virtio-9p: Add support for 9p migration.

login
register
mail settings
Submitter Benoît Canet
Date April 11, 2013, 2:41 p.m.
Message ID <1365691268-18036-2-git-send-email-benoit@irqsave.net>
Download mbox | patch
Permalink /patch/235760/
State New
Headers show

Comments

Benoît Canet - April 11, 2013, 2:41 p.m.
This patch use the old migration framework because of lack
of support for migrating linked list in the new generic framework.

This patch is a rebase of Aneesh Kumar's patch.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
---
 hw/9pfs/virtio-9p-device.c |  152 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 152 insertions(+)

Patch

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index d321c80..2af4858 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -20,6 +20,149 @@ 
 #include "virtio-9p-xattr.h"
 #include "virtio-9p-coth.h"
 
+static void virtio_9p_save_path(QEMUFile *f, V9fsPath *path)
+{
+    qemu_put_be16(f, path->size);
+    qemu_put_buffer(f, (const uint8_t *) path->data, path->size);
+}
+
+static void virtio_9p_save_string(QEMUFile *f, V9fsString *s)
+{
+    qemu_put_be16(f, s->size);
+    qemu_put_buffer(f, (const uint8_t *) s->data, s->size);
+}
+
+static void virtio_9p_save_xattr(QEMUFile *f, V9fsXattr *xattr)
+{
+    qemu_put_be64(f, xattr->copied_len);
+    qemu_put_be64(f, xattr->len);
+    qemu_put_buffer(f, (const uint8_t *) xattr->value, xattr->len);
+    virtio_9p_save_string(f, &xattr->name);
+    qemu_put_be32(f, xattr->flags);
+}
+
+static void virtio_9p_save_fid(QEMUFile *f, V9fsFidState *fid)
+{
+    /* First close the fid and mark it for reopen if migration fail */
+    if (fid->fid_type == P9_FID_FILE) {
+        close(fid->fs.fd);
+        fid->fs.fd = -1;
+    } else if (fid->fid_type == P9_FID_DIR) {
+        closedir(fid->fs.dir);
+        fid->fs.dir = NULL;
+    }
+
+    qemu_put_be32(f, fid->fid_type);
+    if (fid->fid_type == P9_FID_XATTR) {
+        /* we don't save fs_reclaim */
+        virtio_9p_save_xattr(f, &fid->fs.xattr);
+    }
+    qemu_put_be32(f, fid->fid);
+    virtio_9p_save_path(f, &fid->path);
+    qemu_put_be32(f, fid->flags);
+    qemu_put_be32(f, fid->open_flags);
+    qemu_put_be32(f, fid->uid);
+    qemu_put_be32(f, fid->ref);
+    qemu_put_be32(f, fid->clunked);
+}
+
+static void virtio_9p_save(QEMUFile *f, void *opaque)
+{
+    int fidcount = 0;
+    V9fsState *s = opaque;
+    V9fsFidState *fid;
+
+    virtio_save(&s->vdev, f);
+
+    for (fid = s->fid_list; fid; fid = fid->next) {
+        fidcount++;
+    }
+    /* Write the total number of fid structure */
+    qemu_put_be32(f, fidcount);
+
+    for (fid = s->fid_list; fid; fid = fid->next) {
+        virtio_9p_save_fid(f, fid);
+    }
+
+    qemu_put_be32(f, s->proto_version);
+    qemu_put_be32(f, s->msize);
+}
+
+static void virtio_9p_load_path(QEMUFile *f, V9fsPath *path)
+{
+    path->size = qemu_get_be16(f);
+    path->data = g_malloc0(path->size);
+    qemu_get_buffer(f, (uint8_t *) path->data, path->size);
+}
+
+static void virtio_9p_load_string(QEMUFile *f, V9fsString *s)
+{
+    s->size = qemu_get_be16(f);
+    s->data = g_malloc0(s->size);
+    qemu_get_buffer(f, (uint8_t *) s->data, s->size);
+}
+
+static void virtio_9p_load_xattr(QEMUFile *f, V9fsXattr *xattr)
+{
+    xattr->copied_len = qemu_get_be64(f);
+    xattr->len = qemu_get_be64(f);
+    qemu_get_buffer(f, (uint8_t *) xattr->value, xattr->len);
+    virtio_9p_load_string(f, &xattr->name);
+    xattr->flags = qemu_get_be32(f);
+}
+
+static V9fsFidState *virtio_9p_load_fid(QEMUFile *f)
+{
+    V9fsFidState *fid;
+    fid = g_new0(V9fsFidState, 1);
+
+    fid->fid_type    = qemu_get_be32(f);
+    if (fid->fid_type == P9_FID_XATTR) {
+        virtio_9p_load_xattr(f, &fid->fs.xattr);
+    }
+    fid->fid         = qemu_get_be32(f);
+    virtio_9p_load_path(f, &fid->path);
+    fid->flags       = qemu_get_be32(f);
+    fid->open_flags  = qemu_get_be32(f);
+    fid->uid         = qemu_get_be32(f);
+    fid->ref         = qemu_get_be32(f);
+    fid->clunked     = qemu_get_be32(f);
+
+    /* If it's a file fid mark the file descriptors as closed.
+     * DIR is null thanks to g_new0.
+     * When doing get_fid v9fs_reopen_fid will reopen the file or the directory.
+     */
+    if (fid->fid_type == P9_FID_FILE) {
+        fid->fs.fd = -1;
+    }
+    return fid;
+}
+
+static int virtio_9p_load(QEMUFile *f, void *opaque, int version_id)
+{
+    int fidcount;
+    V9fsState *s = opaque;
+    V9fsFidState **fid;
+
+    if (version_id != 1) {
+        return -EINVAL;
+    }
+    virtio_load(&s->vdev, f);
+    fidcount = qemu_get_be32(f);
+
+    fid = &s->fid_list;
+    while (fidcount) {
+        *fid = virtio_9p_load_fid(f);
+        fid = &((*fid)->next);
+        fidcount--;
+    }
+
+    s->proto_version  = qemu_get_be32(f);
+    s->msize          = qemu_get_be32(f);
+
+    return 0;
+}
+
 static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
 {
     features |= 1 << VIRTIO_9P_MOUNT_TAG;
@@ -53,6 +196,7 @@  VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     struct stat stat;
     FsDriverEntry *fse;
     V9fsPath path;
+    static int virtio_9p_id;
 
     s = (V9fsState *)virtio_common_init("virtio-9p",
                                     VIRTIO_ID_9P,
@@ -102,6 +246,14 @@  VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     s->config_size = sizeof(struct virtio_9p_config) + len;
     s->vdev.get_config = virtio_9p_get_config;
     s->fid_list = NULL;
+
+    /* Original patch says that instance id must be derived of tag
+     * name. Hash functions do have collisions so why would it be better
+     * than an increment ?
+     */
+    register_savevm(dev, "virtio-9p", virtio_9p_id++, 1,
+                    virtio_9p_save, virtio_9p_load, s);
+
     qemu_co_rwlock_init(&s->rename_lock);
 
     if (s->ops->init(&s->ctx) < 0) {