diff --git a/blockdev.h b/blockdev.h
index d73d552..4a1b508 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -66,4 +66,133 @@ 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 BlkTransactionStates, 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 BlkTransactionOperationSync {
+    BLK_SN_SYNC_CREATE = 0,
+    BLK_SN_SYNC_DELETE,
+} BlkTransactionOperationSync;
+
+/* internal snapshot */
+
+typedef struct SNTime {
+    uint32_t date_sec; /* UTC date of the snapshot */
+    uint32_t date_nsec;
+    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 were 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 were 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 were all put here ignoring the difference of
+   different operation type as create/delete. */
+typedef struct BlkTransactionStatesSync {
+    /* caller input */
+    BlkSnapshotType type;
+    union {
+        BlkSnapshotInternal internal;
+        BlkSnapshotExternal external;
+    };
+    bool use_existing;
+    BlkTransactionOperationSync op;
+} BlkTransactionStatesSync;
+
+/* async snapshot, not supported now */
+typedef struct BlkTransactionStatesAsync {
+    int reserved;
+} BlkTransactionStatesAsync;
+
+/* Core structure for group snapshots, fill in it and then call the API. */
+typedef struct BlkTransactionStates BlkTransactionStates;
+
+struct BlkTransactionStates {
+    /* caller input */
+    bool async;
+    union {
+        BlkTransactionStatesSync st_sync;
+        BlkTransactionStatesSync st_async;
+    };
+    /* following were used internal */
+    Error *err;
+    int (*blk_trans_do)(BlkTransactionStates *states, Error **errp);
+    int (*blk_trans_invalid)(BlkTransactionStates *states, Error **errp);
+    int (*blk_trans_cancel)(BlkTransactionStates *states, Error **errp);
+    QSIMPLEQ_ENTRY(BlkTransactionStates) entry;
+};
+
+typedef QSIMPLEQ_HEAD(snap_bdrv_states, BlkTransactionStates) \
+                      BlkTransactionStatesList;
+
+/* API */
+BlkTransactionStates *blk_trans_st_new(void);
+void blk_trans_st_delete(BlkTransactionStates **p_st);
+BlkTransactionStatesList *blk_trans_st_list_new(void);
+void blk_trans_st_list_delete(BlkTransactionStatesList **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(BlkTransactionStatesList *list,
+                    BlkTransactionStates *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(BlkTransactionStatesList *list, Error **errp);
+
+/* helper */
+SNTime get_sn_time(void);
+void generate_sn_name_from_time(SNTime *time, char *time_str, int size);
 #endif
