This patch adds block driver functions to use qcow2 image annotations. Signed-off-by: Laurent Vivier Signed-off-by: Jorge Lucángeli Obes --- diff --git a/qemu/block.c b/qemu/block.c index 39ec37a..4d794f6 100644 --- a/qemu/block.c +++ b/qemu/block.c @@ -56,6 +56,8 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, static BlockDriverState *bdrv_first; static BlockDriver *first_drv; +static char *filter_name(char *name); + int path_is_absolute(const char *path) { const char *p; @@ -1037,6 +1039,8 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) snprintf(buf, buf_size, "%-10s%-20s%7s%20s%15s", "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); + } else if (bdrv_snapshot_annotated(sn)) { + snprintf(buf, buf_size, "%s: '%s'", filter_name(sn->name), sn->annot); } else { ti = sn->date_sec; #ifdef _WIN32 @@ -1361,3 +1365,128 @@ void bdrv_set_locked(BlockDriverState *bs, int locked) drv->bdrv_set_locked(bs, locked); } } + +/**************************************************************/ +/* image annotation support */ + +static char *prepare_name(const char *name) +{ + char *res = malloc(1024 * sizeof(char)); + + res[0] = '\n'; + return strncat(res, name, 1022); +} + +static char *filter_name(char *name) +{ + return strtok(name, "\n"); +} + +int bdrv_snapshot_annotated(QEMUSnapshotInfo *sn) +{ + return (sn->name[0] == '\n' && + sn->vm_state_size == 0 && + *sn->annot != '\0'); +} + +int bdrv_set_annot(BlockDriverState *bs, + const char *name, + const char *annotation) +{ + int nbsnaps, i; + int ret = 0; + + char *fltname; + char *prepname; + char *id_annot = NULL; + + QEMUSnapshotInfo *sn_info; + BlockDriver *drv = bs->drv; + + nbsnaps = drv->bdrv_snapshot_list(bs, &sn_info); + + if (nbsnaps < 0) { + ret = -1; + goto end; + } + + for (i = 0; i < nbsnaps; i++) { + fltname = filter_name(sn_info[i].name); + + if (sn_info[i].name[0] == '\n' && + !strcmp(fltname, name) && + sn_info[i].vm_state_size == 0) { + + id_annot = sn_info[i].id_str; + break; + } + } + + if (id_annot != NULL) + drv->bdrv_snapshot_delete(bs, id_annot); + + if (strlen(annotation) == 0) + goto end; + + QEMUSnapshotInfo *new_sn_info = qemu_malloc(sizeof(QEMUSnapshotInfo)); + + if (!new_sn_info) { + ret = -ENOMEM; + goto end; + } + + prepname = prepare_name(name); + + // No id, set by create + new_sn_info->id_str[0] = '\0'; + pstrcpy(new_sn_info->name, 1024, prepname); + pstrcpy(new_sn_info->annot, 1024, annotation); + + new_sn_info->vm_state_size = new_sn_info->date_sec = + new_sn_info->date_nsec = new_sn_info->vm_clock_nsec = 0; + + if (drv->bdrv_snapshot_create(bs, new_sn_info) < 0) + ret = -1; + + free(prepname); + free(new_sn_info); + +end: + free(sn_info); + return ret; +} + +char *bdrv_get_annot(BlockDriverState *bs, const char *name) +{ + int nbsnaps, i; + char *filteredn; + char *res; + + QEMUSnapshotInfo *sn_info = NULL; + + res = malloc(1024 * sizeof(char)); + if (!res) + return NULL; + + nbsnaps = bs->drv->bdrv_snapshot_list(bs, &sn_info); + + if (nbsnaps < 0) { + free(sn_info); + free(res); + return NULL; + } + + for (i = 0; i < nbsnaps; i++) { + filteredn = filter_name(sn_info[i].name); + + if (sn_info[i].name[0] == '\n' && + !strcmp(filteredn, name) && + sn_info[i].vm_state_size == 0) { + + pstrcpy(res, 1024, sn_info[i].annot); + break; + } + } + + return res; +}