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
