Patchwork [V2,05/10] snapshot: design of internal common API to take snapshots

login
register
mail settings
Submitter Wayne Xia
Date Jan. 7, 2013, 7:28 a.m.
Message ID <1357543689-11415-7-git-send-email-xiawenc@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/209875/
State New
Headers show

Comments

Wayne Xia - Jan. 7, 2013, 7:28 a.m.
This patch added API to take snapshots in unified style for
both internal or external type. The core structure is based
on transaction, for that there is a qmp interface need to support
, qmp_transaction, so all operations are packed as requests.
  In this way a sperate internal layer for snapshot is splitted
out from qmp layer, and now qmp can just translate the user request
and fill in internal API. Internal API use params defined inside
qemu, so other component inside qemu can use it without considering
the qmp's parameter format.

v2:
  Renamed BlkTransaction* to BlkTrans* to make name shorter.
  Use present tense in comments.
  Deleted async snapshot related member.
  Use qemu_timeval in SNTime.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
 include/sysemu/blockdev.h |  119 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 119 insertions(+), 0 deletions(-)

Patch

diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 1fe5332..4d61485 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -66,4 +66,123 @@  void qmp_change_blockdev(const char *device, const char *filename,
                          bool has_format, const char *format, Error **errp);
 void do_commit(Monitor *mon, const QDict *qdict);
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
+
+
+/* snapshot transaction API.
+ * Split out a layer around core struct BlkTransStates, so other
+ * component in qemu can fill the request and simply use the API to submit,
+ * QMP may just use part of the API's function, no need to expose all internal
+ * function to user.
+ */
+
+/* sync snapshot */
+
+typedef enum BlkTransOperationSync {
+    BLK_SN_SYNC_CREATE = 0,
+    BLK_SN_SYNC_DELETE,
+} BlkTransOperationSync;
+
+/* internal snapshot */
+
+typedef struct SNTime {
+    qemu_timeval tv;
+    uint64_t vm_clock_nsec; /* VM clock relative to boot */
+} SNTime;
+
+typedef enum BlkSnapshotIntStep {
+    BLK_SNAPSHOT_INT_START = 0,
+    BLK_SNAPSHOT_INT_CREATED,
+    BLK_SNAPSHOT_INT_CANCELED,
+} BlkSnapshotIntStep;
+
+typedef struct BlkSnapshotInternal {
+    /* caller input */
+    const char *sn_name; /* must be set in create/delete. */
+    BlockDriverState *bs; /* must be set in create/delete */
+    SNTime time; /* must be set in create. */
+    uint64_t vm_state_size; /* optional, default is 0, only valid in create. */
+    /* following are used internal */
+    QEMUSnapshotInfo sn;
+    QEMUSnapshotInfo old_sn;
+    bool old_sn_exist;
+    BlkSnapshotIntStep step;
+} BlkSnapshotInternal;
+
+/* external snapshot */
+
+typedef enum BlkSnapshotExtStep {
+    BLK_SNAPSHOT_EXT_START = 0,
+    BLK_SNAPSHOT_EXT_CREATED,
+    BLK_SNAPSHOT_EXT_INVALIDATED,
+    BLK_SNAPSHOT_EXT_CANCELED,
+} BlkSnapshotExtStep;
+
+typedef struct BlkSnapshotExternal {
+    /* caller input */
+    const char *new_image_file; /* must be set in create/delete. */
+    BlockDriverState *old_bs; /* must be set in create/delete. */
+    const char *format; /* must be set in create. */
+    /* following are used internal */
+    BlockDriverState *new_bs;
+    BlockDriver *format_drv;
+    BlkSnapshotExtStep step;
+} BlkSnapshotExternal;
+
+typedef enum BlkSnapshotType {
+    BLK_SNAPSHOT_INTERNAL = 0,
+    BLK_SNAPSHOT_EXTERNAL,
+    BLK_SNAPSHOT_NOSUPPORT,
+} BlkSnapshotType;
+
+/* for simple sync type params are all put here ignoring the difference of
+   different operation type as create/delete. */
+typedef struct BlkTransStatesSync {
+    /* caller input */
+    BlkSnapshotType type;
+    union {
+        BlkSnapshotInternal internal;
+        BlkSnapshotExternal external;
+    };
+    bool use_existing;
+    BlkTransOperationSync op;
+} BlkTransStatesSync;
+
+/* Core structure for group snapshots, fill in it and then call the API. */
+typedef struct BlkTransStates BlkTransStates;
+
+struct BlkTransStates {
+    /* caller input */
+    BlkTransStatesSync st_sync;
+    /* following are used internal */
+    Error *err;
+    int (*blk_trans_do)(BlkTransStates *states, Error **errp);
+    int (*blk_trans_invalid)(BlkTransStates *states, Error **errp);
+    int (*blk_trans_cancel)(BlkTransStates *states, Error **errp);
+    QSIMPLEQ_ENTRY(BlkTransStates) entry;
+};
+
+typedef QSIMPLEQ_HEAD(snap_bdrv_states, BlkTransStates) \
+                      BlkTransStatesList;
+
+/* API */
+BlkTransStates *blk_trans_st_new(void);
+void blk_trans_st_delete(BlkTransStates **p_st);
+BlkTransStatesList *blk_trans_st_list_new(void);
+void blk_trans_st_list_delete(BlkTransStatesList **p_list);
+
+/* add a request to list, request would be checked to see if it is valid,
+   return -1 when met error and states would not be queued. */
+int add_transaction(BlkTransStatesList *list,
+                    BlkTransStates *states,
+                    Error **errp);
+
+/* 'Atomic' submit the request. In snapshot creation case, if any
+ * fail then we do not pivot any of the devices in the group, and abandon the
+ * snapshots
+ */
+int submit_transaction(BlkTransStatesList *list, Error **errp);
+
+/* helper */
+SNTime get_sn_time(void);
+void generate_sn_name_from_time(SNTime *time, char *time_str, int size);
 #endif