From f62e542eee2427d8bea9ef58d70758e63169508d Mon Sep 17 00:00:00 2001 From: root Date: Fri, 7 Jan 2011 07:52:20 -0500 Subject: [PATCH 1/2] backport snapshot --- block.c | 16 ++++++++++++++++ block.h | 2 ++ block/qcow2-snapshot.c | 31 +++++++++++++++++++++++++++++++ block/qcow2.c | 1 + block/qcow2.h | 1 + block_int.h | 2 ++ qemu-img-cmds.hx | 4 ++-- qemu-img.c | 15 ++++++++++++++- qemu-img.texi | 4 ++-- 9 files changed, 71 insertions(+), 5 deletions(-) diff --git a/block.c b/block.c index 01f4050..ee6db7c 100644 --- a/block.c +++ b/block.c @@ -1747,6 +1747,22 @@ int bdrv_snapshot_list(BlockDriverState *bs, return drv->bdrv_snapshot_list(bs, psn_info); } +int bdrv_snapshot_load_tmp(BlockDriverState *bs, + const char *snapshot_name) +{ + BlockDriver *drv = bs->drv; + if (!drv) { + return -ENOMEDIUM; + } + if (!bs->read_only) { + return -EINVAL; + } + if (drv->bdrv_snapshot_load_tmp) { + return drv->bdrv_snapshot_load_tmp(bs, snapshot_name); + } + return -ENOTSUP; +} + #define NB_SUFFIXES 4 char *get_human_readable_size(char *buf, int buf_size, int64_t size) diff --git a/block.h b/block.h index 90cbef9..6e97caa 100644 --- a/block.h +++ b/block.h @@ -194,6 +194,8 @@ int bdrv_snapshot_goto(BlockDriverState *bs, int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); int bdrv_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_info); +int bdrv_snapshot_load_tmp(BlockDriverState *bs, + const char *snapshot_name); char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); char *get_human_readable_size(char *buf, int buf_size, int64_t size); diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 6228612..71101c7 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -416,3 +416,34 @@ int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) return s->nb_snapshots; } +int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name) +{ + int i, snapshot_index, l1_size2; + BDRVQcowState *s = bs->opaque; + QCowSnapshot *sn; + + snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_name); + if (snapshot_index < 0) { + return -ENOENT; + } + + sn = &s->snapshots[snapshot_index]; + s->l1_size = sn->l1_size; + l1_size2 = s->l1_size * sizeof(uint64_t); + if (s->l1_table != NULL) { + qemu_free(s->l1_table); + } + + s->l1_table_offset = sn->l1_table_offset; + s->l1_table = qemu_mallocz(align_offset(l1_size2, 512)); + + if (bdrv_pread(bs->file, sn->l1_table_offset, + s->l1_table, l1_size2) != l1_size2) { + return -1; + } + + for(i = 0;i < s->l1_size; i++) { + be64_to_cpus(&s->l1_table[i]); + } + return 0; +} diff --git a/block/qcow2.c b/block/qcow2.c index 258de50..c3ed379 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1312,6 +1312,7 @@ static BlockDriver bdrv_qcow2 = { .bdrv_snapshot_goto = qcow2_snapshot_goto, .bdrv_snapshot_delete = qcow2_snapshot_delete, .bdrv_snapshot_list = qcow2_snapshot_list, + .bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp, .bdrv_get_info = qcow_get_info, .bdrv_save_vmstate = qcow_save_vmstate, diff --git a/block/qcow2.h b/block/qcow2.h index 9368d7e..6743c26 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -205,6 +205,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info); int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id); int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab); +int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name); void qcow2_free_snapshots(BlockDriverState *bs); int qcow2_read_snapshots(BlockDriverState *bs); diff --git a/block_int.h b/block_int.h index df53b8a..0618216 100644 --- a/block_int.h +++ b/block_int.h @@ -93,6 +93,8 @@ struct BlockDriver { int (*bdrv_snapshot_delete)(BlockDriverState *bs, const char *snapshot_id); int (*bdrv_snapshot_list)(BlockDriverState *bs, QEMUSnapshotInfo **psn_info); + int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs, + const char *snapshot_name); int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); int (*bdrv_save_vmstate)(BlockDriverState *bs, const uint8_t *buf, diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index f96876a..2abb163 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -28,9 +28,9 @@ STEXI ETEXI DEF("convert", img_convert, - "convert [-c] [-f fmt] [-O output_fmt] [-o options] filename [filename2 [...]] output_filename") + "convert [-c] [-f fmt] [-O output_fmt] [-o options] [-s snapshot_name] filename [filename2 [...]] output_filename") STEXI -@item convert [-c] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] @var{filename} [@var{filename2} [...]] @var{output_filename} +@item convert [-c] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename} ETEXI DEF("info", img_info, diff --git a/qemu-img.c b/qemu-img.c index b9e7e73..eec8a8a 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -616,13 +616,14 @@ static int img_convert(int argc, char **argv) BlockDriverInfo bdi; QEMUOptionParameter *param = NULL; char *options = NULL; + const char *snapshot_name = NULL; fmt = NULL; out_fmt = "raw"; out_baseimg = NULL; flags = 0; for(;;) { - c = getopt(argc, argv, "f:O:B:hce6o:"); + c = getopt(argc, argv, "f:O:B:s:hce6o:"); if (c == -1) break; switch(c) { @@ -650,6 +651,9 @@ static int img_convert(int argc, char **argv) case 'o': options = optarg; break; + case 's': + snapshot_name = optarg; + break; } } @@ -674,6 +678,15 @@ static int img_convert(int argc, char **argv) total_sectors += bs_sectors; } + if (snapshot_name != NULL) { + if (bs_n > 1) { + error("No support for concatenating multiple snapshot\n"); + } + if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) { + error("Failed to load snapshot\n"); + } + } + /* Find driver and parse its options */ drv = bdrv_find_format(out_fmt); if (!drv) diff --git a/qemu-img.texi b/qemu-img.texi index ac97854..9cb8fac 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -77,9 +77,9 @@ it doesn't need to be specified separately in this case. Commit the changes recorded in @var{filename} in its base image. -@item convert [-c] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] @var{filename} [@var{filename2} [...]] @var{output_filename} +@item convert [-c] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename} -Convert the disk image @var{filename} to disk image @var{output_filename} +Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename} using format @var{output_fmt}. It can be optionally compressed (@code{-c} option) or use any format specific options like encryption (@code{-o} option). -- 1.7.1