Message ID | 1384121021-24815-3-git-send-email-xiawenc@linux.vnet.ibm.com |
---|---|
State | New |
Headers | show |
Am 10.11.2013 um 23:03 hat Wenchao Xia geschrieben: > Now it is possible to directly export an internal snapshot, which > can be used to probe the snapshot's contents without qemu-img > convert. > > Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> > --- > block/snapshot.c | 18 +++++++++++++++++ > include/block/snapshot.h | 8 +++++++ > qemu-nbd.c | 47 ++++++++++++++++++++++++++++++++++++++++++++- > qemu-nbd.texi | 8 ++++++- > 4 files changed, 78 insertions(+), 3 deletions(-) > > diff --git a/block/snapshot.c b/block/snapshot.c > index e51a7db..7cc45fa 100644 > --- a/block/snapshot.c > +++ b/block/snapshot.c > @@ -25,6 +25,24 @@ > #include "block/snapshot.h" > #include "block/block_int.h" > > +QemuOptsList internal_snapshot_opts = { > + .name = "snapshot", > + .head = QTAILQ_HEAD_INITIALIZER(internal_snapshot_opts.head), > + .desc = { > + { > + .name = SNAPSHOT_OPT_ID, > + .type = QEMU_OPT_STRING, > + .help = "snapshot id" > + },{ > + .name = SNAPSHOT_OPT_NAME, > + .type = QEMU_OPT_STRING, > + .help = "snapshot name" > + },{ > + /* end of list */ > + } > + }, > +}; > + > int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, > const char *name) > { > diff --git a/include/block/snapshot.h b/include/block/snapshot.h > index d05bea7..770d9bb 100644 > --- a/include/block/snapshot.h > +++ b/include/block/snapshot.h > @@ -27,6 +27,14 @@ > > #include "qemu-common.h" > #include "qapi/error.h" > +#include "qemu/option.h" > + > + > +#define SNAPSHOT_OPT_BASE "snapshot." > +#define SNAPSHOT_OPT_ID "snapshot.id" > +#define SNAPSHOT_OPT_NAME "snapshot.name" > + > +extern QemuOptsList internal_snapshot_opts; > > typedef struct QEMUSnapshotInfo { > char id_str[128]; /* unique snapshot id */ > diff --git a/qemu-nbd.c b/qemu-nbd.c > index c26c98e..f934eaa 100644 > --- a/qemu-nbd.c > +++ b/qemu-nbd.c > @@ -20,6 +20,7 @@ > #include "block/block.h" > #include "block/nbd.h" > #include "qemu/main-loop.h" > +#include "block/snapshot.h" > > #include <stdarg.h> > #include <stdio.h> > @@ -79,7 +80,14 @@ static void usage(const char *name) > "\n" > "Block device options:\n" > " -r, --read-only export read-only\n" > -" -s, --snapshot use snapshot file\n" > +" -s, --snapshot use FILE as an external snapshot, create a temporary\n" > +" file with backing_file=FILE, redirect the write to\n" > +" the temporary one\n" > +" -l, --load-snapshot=SNAPSHOT_PARAM\n" > +" load an internal snapshot inside FILE and export it\n" > +" as an read-only device, SNAPSHOT_PARAM format is\n" > +" 'snapshot.id=[ID],snapshot.name=[NAME]', or\n" > +" '[ID_OR_NAME]'\n" > " -n, --nocache disable host cache\n" > " --cache=MODE set cache mode (none, writeback, ...)\n" > #ifdef CONFIG_LINUX_AIO > @@ -315,7 +323,9 @@ int main(int argc, char **argv) > char *device = NULL; > int port = NBD_DEFAULT_PORT; > off_t fd_size; > - const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:t"; > + QemuOpts *sn_opts = NULL; > + const char *sn_id_or_name = NULL; > + const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:"; > struct option lopt[] = { > { "help", 0, NULL, 'h' }, > { "version", 0, NULL, 'V' }, > @@ -328,6 +338,7 @@ int main(int argc, char **argv) > { "connect", 1, NULL, 'c' }, > { "disconnect", 0, NULL, 'd' }, > { "snapshot", 0, NULL, 's' }, > + { "load-snapshot", 1, NULL, 'l' }, > { "nocache", 0, NULL, 'n' }, > { "cache", 1, NULL, QEMU_NBD_OPT_CACHE }, > #ifdef CONFIG_LINUX_AIO > @@ -428,6 +439,18 @@ int main(int argc, char **argv) > errx(EXIT_FAILURE, "Offset must be positive `%s'", optarg); > } > break; > + case 'l': > + if (strncmp(optarg, SNAPSHOT_OPT_BASE, strlen(SNAPSHOT_OPT_BASE)) > + == 0) { You can avoid this ugly line break by using strstart(): if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) { ... Kevin
δΊ 2013/11/19 19:26, Kevin Wolf ει: > Am 10.11.2013 um 23:03 hat Wenchao Xia geschrieben: >> Now it is possible to directly export an internal snapshot, which >> can be used to probe the snapshot's contents without qemu-img >> convert. >> >> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> >> --- >> block/snapshot.c | 18 +++++++++++++++++ >> include/block/snapshot.h | 8 +++++++ >> qemu-nbd.c | 47 ++++++++++++++++++++++++++++++++++++++++++++- >> qemu-nbd.texi | 8 ++++++- >> 4 files changed, 78 insertions(+), 3 deletions(-) >> >> diff --git a/block/snapshot.c b/block/snapshot.c >> index e51a7db..7cc45fa 100644 >> --- a/block/snapshot.c >> +++ b/block/snapshot.c >> @@ -25,6 +25,24 @@ >> #include "block/snapshot.h" >> #include "block/block_int.h" >> >> +QemuOptsList internal_snapshot_opts = { >> + .name = "snapshot", >> + .head = QTAILQ_HEAD_INITIALIZER(internal_snapshot_opts.head), >> + .desc = { >> + { >> + .name = SNAPSHOT_OPT_ID, >> + .type = QEMU_OPT_STRING, >> + .help = "snapshot id" >> + },{ >> + .name = SNAPSHOT_OPT_NAME, >> + .type = QEMU_OPT_STRING, >> + .help = "snapshot name" >> + },{ >> + /* end of list */ >> + } >> + }, >> +}; >> + >> int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, >> const char *name) >> { >> diff --git a/include/block/snapshot.h b/include/block/snapshot.h >> index d05bea7..770d9bb 100644 >> --- a/include/block/snapshot.h >> +++ b/include/block/snapshot.h >> @@ -27,6 +27,14 @@ >> >> #include "qemu-common.h" >> #include "qapi/error.h" >> +#include "qemu/option.h" >> + >> + >> +#define SNAPSHOT_OPT_BASE "snapshot." >> +#define SNAPSHOT_OPT_ID "snapshot.id" >> +#define SNAPSHOT_OPT_NAME "snapshot.name" >> + >> +extern QemuOptsList internal_snapshot_opts; >> >> typedef struct QEMUSnapshotInfo { >> char id_str[128]; /* unique snapshot id */ >> diff --git a/qemu-nbd.c b/qemu-nbd.c >> index c26c98e..f934eaa 100644 >> --- a/qemu-nbd.c >> +++ b/qemu-nbd.c >> @@ -20,6 +20,7 @@ >> #include "block/block.h" >> #include "block/nbd.h" >> #include "qemu/main-loop.h" >> +#include "block/snapshot.h" >> >> #include <stdarg.h> >> #include <stdio.h> >> @@ -79,7 +80,14 @@ static void usage(const char *name) >> "\n" >> "Block device options:\n" >> " -r, --read-only export read-only\n" >> -" -s, --snapshot use snapshot file\n" >> +" -s, --snapshot use FILE as an external snapshot, create a temporary\n" >> +" file with backing_file=FILE, redirect the write to\n" >> +" the temporary one\n" >> +" -l, --load-snapshot=SNAPSHOT_PARAM\n" >> +" load an internal snapshot inside FILE and export it\n" >> +" as an read-only device, SNAPSHOT_PARAM format is\n" >> +" 'snapshot.id=[ID],snapshot.name=[NAME]', or\n" >> +" '[ID_OR_NAME]'\n" >> " -n, --nocache disable host cache\n" >> " --cache=MODE set cache mode (none, writeback, ...)\n" >> #ifdef CONFIG_LINUX_AIO >> @@ -315,7 +323,9 @@ int main(int argc, char **argv) >> char *device = NULL; >> int port = NBD_DEFAULT_PORT; >> off_t fd_size; >> - const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:t"; >> + QemuOpts *sn_opts = NULL; >> + const char *sn_id_or_name = NULL; >> + const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:"; >> struct option lopt[] = { >> { "help", 0, NULL, 'h' }, >> { "version", 0, NULL, 'V' }, >> @@ -328,6 +338,7 @@ int main(int argc, char **argv) >> { "connect", 1, NULL, 'c' }, >> { "disconnect", 0, NULL, 'd' }, >> { "snapshot", 0, NULL, 's' }, >> + { "load-snapshot", 1, NULL, 'l' }, >> { "nocache", 0, NULL, 'n' }, >> { "cache", 1, NULL, QEMU_NBD_OPT_CACHE }, >> #ifdef CONFIG_LINUX_AIO >> @@ -428,6 +439,18 @@ int main(int argc, char **argv) >> errx(EXIT_FAILURE, "Offset must be positive `%s'", optarg); >> } >> break; >> + case 'l': >> + if (strncmp(optarg, SNAPSHOT_OPT_BASE, strlen(SNAPSHOT_OPT_BASE)) >> + == 0) { > > You can avoid this ugly line break by using strstart(): > > if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) { > ... > > Kevin > Will use strstart(), thanks for tipping.
diff --git a/block/snapshot.c b/block/snapshot.c index e51a7db..7cc45fa 100644 --- a/block/snapshot.c +++ b/block/snapshot.c @@ -25,6 +25,24 @@ #include "block/snapshot.h" #include "block/block_int.h" +QemuOptsList internal_snapshot_opts = { + .name = "snapshot", + .head = QTAILQ_HEAD_INITIALIZER(internal_snapshot_opts.head), + .desc = { + { + .name = SNAPSHOT_OPT_ID, + .type = QEMU_OPT_STRING, + .help = "snapshot id" + },{ + .name = SNAPSHOT_OPT_NAME, + .type = QEMU_OPT_STRING, + .help = "snapshot name" + },{ + /* end of list */ + } + }, +}; + int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, const char *name) { diff --git a/include/block/snapshot.h b/include/block/snapshot.h index d05bea7..770d9bb 100644 --- a/include/block/snapshot.h +++ b/include/block/snapshot.h @@ -27,6 +27,14 @@ #include "qemu-common.h" #include "qapi/error.h" +#include "qemu/option.h" + + +#define SNAPSHOT_OPT_BASE "snapshot." +#define SNAPSHOT_OPT_ID "snapshot.id" +#define SNAPSHOT_OPT_NAME "snapshot.name" + +extern QemuOptsList internal_snapshot_opts; typedef struct QEMUSnapshotInfo { char id_str[128]; /* unique snapshot id */ diff --git a/qemu-nbd.c b/qemu-nbd.c index c26c98e..f934eaa 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -20,6 +20,7 @@ #include "block/block.h" #include "block/nbd.h" #include "qemu/main-loop.h" +#include "block/snapshot.h" #include <stdarg.h> #include <stdio.h> @@ -79,7 +80,14 @@ static void usage(const char *name) "\n" "Block device options:\n" " -r, --read-only export read-only\n" -" -s, --snapshot use snapshot file\n" +" -s, --snapshot use FILE as an external snapshot, create a temporary\n" +" file with backing_file=FILE, redirect the write to\n" +" the temporary one\n" +" -l, --load-snapshot=SNAPSHOT_PARAM\n" +" load an internal snapshot inside FILE and export it\n" +" as an read-only device, SNAPSHOT_PARAM format is\n" +" 'snapshot.id=[ID],snapshot.name=[NAME]', or\n" +" '[ID_OR_NAME]'\n" " -n, --nocache disable host cache\n" " --cache=MODE set cache mode (none, writeback, ...)\n" #ifdef CONFIG_LINUX_AIO @@ -315,7 +323,9 @@ int main(int argc, char **argv) char *device = NULL; int port = NBD_DEFAULT_PORT; off_t fd_size; - const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:t"; + QemuOpts *sn_opts = NULL; + const char *sn_id_or_name = NULL; + const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:"; struct option lopt[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, @@ -328,6 +338,7 @@ int main(int argc, char **argv) { "connect", 1, NULL, 'c' }, { "disconnect", 0, NULL, 'd' }, { "snapshot", 0, NULL, 's' }, + { "load-snapshot", 1, NULL, 'l' }, { "nocache", 0, NULL, 'n' }, { "cache", 1, NULL, QEMU_NBD_OPT_CACHE }, #ifdef CONFIG_LINUX_AIO @@ -428,6 +439,18 @@ int main(int argc, char **argv) errx(EXIT_FAILURE, "Offset must be positive `%s'", optarg); } break; + case 'l': + if (strncmp(optarg, SNAPSHOT_OPT_BASE, strlen(SNAPSHOT_OPT_BASE)) + == 0) { + sn_opts = qemu_opts_parse(&internal_snapshot_opts, optarg, 0); + if (!sn_opts) { + errx(EXIT_FAILURE, "Failed in parsing snapshot param `%s'", + optarg); + } + } else { + sn_id_or_name = optarg; + } + /* fall through */ case 'r': nbdflags |= NBD_FLAG_READ_ONLY; flags &= ~BDRV_O_RDWR; @@ -581,6 +604,22 @@ int main(int argc, char **argv) error_get_pretty(local_err)); } + if (sn_opts) { + ret = bdrv_snapshot_load_tmp(bs, + qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID), + qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME), + &local_err); + } else if (sn_id_or_name) { + ret = bdrv_snapshot_load_tmp_by_id_or_name(bs, sn_id_or_name, + &local_err); + } + if (ret < 0) { + errno = -ret; + err(EXIT_FAILURE, + "Failed to load snapshot: %s", + error_get_pretty(local_err)); + } + fd_size = bdrv_getlength(bs); if (partition != -1) { @@ -641,6 +680,10 @@ int main(int argc, char **argv) unlink(sockpath); } + if (sn_opts) { + qemu_opts_del(sn_opts); + } + if (device) { void *ret; pthread_join(client_thread, &ret); diff --git a/qemu-nbd.texi b/qemu-nbd.texi index 6055ec6..5b55f76 100644 --- a/qemu-nbd.texi +++ b/qemu-nbd.texi @@ -27,7 +27,13 @@ Export QEMU disk image using NBD protocol. @item -P, --partition=@var{num} only expose partition @var{num} @item -s, --snapshot - use snapshot file + use @var{filename} as an external snapshot, create a temporary + file with backing_file=@var{filename}, redirect the write to + the temporary one +@item -l, --load-snapshot=@var{snapshot_param} + load an internal snapshot inside @var{filename} and export it + as an read-only device, @var{snapshot_param} format is + 'snapshot.id=[ID],snapshot.name=[NAME]' or '[ID_OR_NAME]' @item -n, --nocache @itemx --cache=@var{cache} set cache mode to be used with the file. See the documentation of
Now it is possible to directly export an internal snapshot, which can be used to probe the snapshot's contents without qemu-img convert. Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> --- block/snapshot.c | 18 +++++++++++++++++ include/block/snapshot.h | 8 +++++++ qemu-nbd.c | 47 ++++++++++++++++++++++++++++++++++++++++++++- qemu-nbd.texi | 8 ++++++- 4 files changed, 78 insertions(+), 3 deletions(-)