Re: [Qemu-devel] [PATCH v6 2/2] qemu-ga: sample fsfreeze hooks
On 2012/12/05 1:51, Luiz Capitulino wrote: > On Fri, 30 Nov 2012 22:33:57 +0900 > Tomoki Sekiyama wrote: > >> Adds sample hook scripts for --fsfreeze-hook option of qemu-ga. >> - fsfreeze-hook : execute scripts in fsfreeze-hook.d/ >> - fsfreeze-hook.d.sample/mysql-flush.sh : quiesce MySQL before snapshot >> >> Signed-off-by: Tomoki Sekiyama >> --- >> docs/qemu-guest-agent/fsfreeze-hook| 33 >> .../fsfreeze-hook.d.sample/mysql-flush.sh | 55 >> >> 2 files changed, 88 insertions(+) >> create mode 100755 docs/qemu-guest-agent/fsfreeze-hook >> create mode 100755 >> docs/qemu-guest-agent/fsfreeze-hook.d.sample/mysql-flush.sh >> >> diff --git a/docs/qemu-guest-agent/fsfreeze-hook >> b/docs/qemu-guest-agent/fsfreeze-hook >> new file mode 100755 >> index 000..ed7d86d >> --- /dev/null >> +++ b/docs/qemu-guest-agent/fsfreeze-hook >> @@ -0,0 +1,33 @@ >> +#!/bin/sh >> + >> +# This script is executed when a guest agent receives fsfreeze-freeze and >> +# fsfreeze-thaw command, if it is specified in --fsfreeze-hook (-F) >> +# option of qemu-ga or placed in default path (/etc/qemu/fsfreeze-hook). >> +# When the agent receives fsfreeze-freeze request, this script is issued >> with >> +# "freeze" argument before the filesystem is freezed. And for fsfreeze-thaw >> +# request, it is issued with "thaw" argument after filesystem is thawed. >> + >> +LOGFILE=/var/log/qga-fsfreeze-hook.log >> +FSFREEZE_D=$(dirname -- "$0")/fsfreeze-hook.d > > The script you introduce is called fsfreeze-hook.d.sample. If it's expected > that people really use these two scripts (vs. doc purposes only) I suggest > the following: > > 1. Move these files to scripts/ > 2. Drop the .sample suffix It is good for "fsfreeze-hook". But as for "mysql-flush.sh", users may need to configure authentication etc. if their environments are with non-default setup (by edditing either the script or ~/.my.cnf file). So, I'd like to (1)move these files to scripts/, but (2)reamin .sample suffix to indicate that users may need to modify the script. How do you think? Thanks, -- Tomoki Sekiyama Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory
Re: [Qemu-devel] [PATCH v6 2/2] qemu-ga: sample fsfreeze hooks
On 2012/12/05 20:49, Luiz Capitulino wrote: > On Wed, 05 Dec 2012 17:41:08 +0900 > Tomoki Sekiyama wrote: > >> On 2012/12/05 1:51, Luiz Capitulino wrote: >>> On Fri, 30 Nov 2012 22:33:57 +0900 >>> Tomoki Sekiyama wrote: >>> >>>> Adds sample hook scripts for --fsfreeze-hook option of qemu-ga. >>>> - fsfreeze-hook : execute scripts in fsfreeze-hook.d/ >>>> - fsfreeze-hook.d.sample/mysql-flush.sh : quiesce MySQL before snapshot >>>> >>>> Signed-off-by: Tomoki Sekiyama >>>> --- >>>> docs/qemu-guest-agent/fsfreeze-hook| 33 >>>> .../fsfreeze-hook.d.sample/mysql-flush.sh | 55 >>>> >>>> 2 files changed, 88 insertions(+) >>>> create mode 100755 docs/qemu-guest-agent/fsfreeze-hook >>>> create mode 100755 >>>> docs/qemu-guest-agent/fsfreeze-hook.d.sample/mysql-flush.sh >>>> >>>> diff --git a/docs/qemu-guest-agent/fsfreeze-hook >>>> b/docs/qemu-guest-agent/fsfreeze-hook >>>> new file mode 100755 >>>> index 000..ed7d86d >>>> --- /dev/null >>>> +++ b/docs/qemu-guest-agent/fsfreeze-hook >>>> @@ -0,0 +1,33 @@ >>>> +#!/bin/sh >>>> + >>>> +# This script is executed when a guest agent receives fsfreeze-freeze and >>>> +# fsfreeze-thaw command, if it is specified in --fsfreeze-hook (-F) >>>> +# option of qemu-ga or placed in default path (/etc/qemu/fsfreeze-hook). >>>> +# When the agent receives fsfreeze-freeze request, this script is issued >>>> with >>>> +# "freeze" argument before the filesystem is freezed. And for >>>> fsfreeze-thaw >>>> +# request, it is issued with "thaw" argument after filesystem is thawed. >>>> + >>>> +LOGFILE=/var/log/qga-fsfreeze-hook.log >>>> +FSFREEZE_D=$(dirname -- "$0")/fsfreeze-hook.d >>> >>> The script you introduce is called fsfreeze-hook.d.sample. If it's expected >>> that people really use these two scripts (vs. doc purposes only) I suggest >>> the following: >>> >>> 1. Move these files to scripts/ >>> 2. Drop the .sample suffix >> >> It is good for "fsfreeze-hook". But as for "mysql-flush.sh", users may >> need to configure authentication etc. if their environments are with >> non-default setup (by edditing either the script or ~/.my.cnf file). >> >> So, I'd like to (1)move these files to scripts/, but (2)reamin .sample >> suffix to indicate that users may need to modify the script. >> How do you think? > > You could add the '.sample' suffix to the mysql script and add that > suffix to is_ignored_file(). > Okey, I will try this in the next version. (It seems Makefile also needs a patch to treat directry named "*.d".) Thanks, -- Tomoki Sekiyama Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory
Re: [Qemu-devel] [PATCH v7 2/2] qemu-ga: sample fsfreeze hooks
Adds sample hook scripts for --fsfreeze-hook option of qemu-ga. - fsfreeze-hook : execute scripts in fsfreeze-hook.d/ - fsfreeze-hook.d/mysql-flush.sh.sample : quiesce MySQL before snapshot Signed-off-by: Tomoki Sekiyama --- .gitignore |1 Makefile |2 - scripts/qemu-guest-agent/fsfreeze-hook | 33 .../fsfreeze-hook.d/mysql-flush.sh.sample | 55 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100755 scripts/qemu-guest-agent/fsfreeze-hook create mode 100755 scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample diff --git a/.gitignore b/.gitignore index bd6ba1c..286822d 100644 --- a/.gitignore +++ b/.gitignore @@ -93,3 +93,4 @@ cscope.* tags TAGS *~ +!scripts/qemu-guest-agent/fsfreeze-hook.d diff --git a/Makefile b/Makefile index 9ecbcbb..466dcd7 100644 --- a/Makefile +++ b/Makefile @@ -248,7 +248,7 @@ clean: # avoid old build problems by removing potentially incorrect old files rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h rm -f qemu-options.def - find . -name '*.[od]' -exec rm -f {} + + find . -name '*.[od]' -type f -exec rm -f {} + rm -f *.a *.lo $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f qemu-img-cmds.h diff --git a/scripts/qemu-guest-agent/fsfreeze-hook b/scripts/qemu-guest-agent/fsfreeze-hook new file mode 100755 index 000..4f7ff15 --- /dev/null +++ b/scripts/qemu-guest-agent/fsfreeze-hook @@ -0,0 +1,33 @@ +#!/bin/sh + +# This script is executed when a guest agent receives fsfreeze-freeze and +# fsfreeze-thaw command, if it is specified in --fsfreeze-hook (-F) +# option of qemu-ga or placed in default path (/etc/qemu/fsfreeze-hook). +# When the agent receives fsfreeze-freeze request, this script is issued with +# "freeze" argument before the filesystem is freezed. And for fsfreeze-thaw +# request, it is issued with "thaw" argument after filesystem is thawed. + +LOGFILE=/var/log/qga-fsfreeze-hook.log +FSFREEZE_D=$(dirname -- "$0")/fsfreeze-hook.d + +# Check whether file $1 is a backup or rpm-generated file and should be ignored +is_ignored_file() { +case "$1" in +*~ | *.bak | *.orig | *.rpmnew | *.rpmorig | *.rpmsave | *.sample) +return 0 ;; +esac +return 1 +} + +# Iterate executables in directory "fsfreeze-hook.d" with the specified args +[ ! -d "$FSFREEZE_D" ] && exit 1 +for file in "$FSFREEZE_D"/* ; do +is_ignored_file "$file" && continue +[ -x "$file" ] || continue +echo "$(date): execute $file $@" >>$LOGFILE +"$file" "$@" >>$LOGFILE 2>&1 +STATUS=$? +echo "$(date): $file finished with status=$STATUS" >>$LOGFILE +done + +exit 0 diff --git a/scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample b/scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample new file mode 100755 index 000..c69b8ad --- /dev/null +++ b/scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample @@ -0,0 +1,55 @@ +#!/bin/sh + +# Flush MySQL tables to the disk before the filesystem is freezed. +# At the same time, this keeps a read lock in order to avoid write accesses +# from the other clients until the filesystem is thawed. + +MYSQL="/usr/bin/mysql" +MYSQL_OPTS="-uroot" #"-prootpassword" +FIFO=/tmp/mysql-flush.fifo +MYSQL_CMD="$MYSQL $MYSQL_OPTS" + +# Check mysql is installed and the server running +[ -x $MYSQL ] && $MYSQL_CMD < /dev/null || exit 0 + +flush_and_wait() { +printf "FLUSH TABLES WITH READ LOCK \\G\n" +read < $FIFO +printf "UNLOCK TABLES \\G\n" +} + +case "$1" in +freeze) +mkfifo $FIFO || exit 1 +flush_and_wait | $MYSQL_CMD & +# wait until every block is flushed +while [ "$(echo 'SHOW STATUS LIKE "Key_blocks_not_flushed"' |\ + $MYSQL_CMD | tail -1 | cut -f 2)" -gt 0 ]; do +sleep 1 +done +# for InnoDB, wait until every log is flushed +INNODB_STATUS=$(mktemp /tmp/mysql-flush.XX) +[ $? -ne 0 ] && exit 2 +trap "rm -f $INNODB_STATUS" SIGINT +while :; do +printf "SHOW ENGINE INNODB STATUS \\G" | $MYSQL_CMD > $INNODB_STATUS +LOG_CURRENT=$(grep 'Log sequence number' $INNODB_STATUS |\ + tr -s ' ' | cut -d' ' -f4) +LOG_FLUSHED=$(grep 'Log flushed up to' $INNODB_STATUS |\ + tr -s ' ' | cut -d' ' -f5) +[ "$LOG_CURRENT" = "$LOG_FLUSHED" ] && break +sleep 1 +done +rm -f $INNODB_STATUS +;; + +thaw) +[ ! -p $FIFO ] && exit 1 +echo > $FIFO +rm -f $FIFO +;; + +*) +exit 1 +;; +esac
Re: [Qemu-devel] [PATCH v7 1/2] qemu-ga: execute hook to quiesce the guest on fsfreeze-freeze/thaw
To use the online disk snapshot for online-backup, application-level consistency of the snapshot image is required. However, currently the guest agent can provide only filesystem-level consistency, and the snapshot may contain dirty data, for example, incomplete transactions. This patch provides the opportunity to quiesce applications before snapshot is taken. If --fsfreeze-hook option is specified, the hook is executed with "freeze" argument before the filesystem is frozen by fsfreeze-freeze command. As for fsfreeze-thaw command, the hook is executed with "thaw" argument after the filesystem is thawed. This patch depends on patchset to improve error reporting by Luiz Capitulino: http://lists.gnu.org/archive/html/qemu-devel/2012-11/msg03016.html Signed-off-by: Tomoki Sekiyama --- qemu-ga.c | 42 + qga/commands-posix.c | 69 qga/guest-agent-core.h |1 + 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/qemu-ga.c b/qemu-ga.c index 9b59a52..53ce462 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -34,6 +34,12 @@ #include "qga/service-win32.h" #include #endif +#ifdef __linux__ +#include +#ifdef FIFREEZE +#define CONFIG_FSFREEZE +#endif +#endif #ifndef _WIN32 #define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0" @@ -42,6 +48,9 @@ #endif #define QGA_STATEDIR_DEFAULT CONFIG_QEMU_LOCALSTATEDIR "/run" #define QGA_PIDFILE_DEFAULT QGA_STATEDIR_DEFAULT "/qemu-ga.pid" +#ifdef CONFIG_FSFREEZE +#define QGA_FSFREEZE_HOOK_DEFAULT CONFIG_QEMU_CONFDIR "/fsfreeze-hook" +#endif #define QGA_SENTINEL_BYTE 0xFF struct GAState { @@ -64,6 +73,9 @@ struct GAState { const char *log_filepath; const char *pid_filepath; } deferred_options; +#ifdef CONFIG_FSFREEZE +const char *fsfreeze_hook; +#endif }; struct GAState *ga_state; @@ -153,6 +165,10 @@ static void usage(const char *cmd) "%s)\n" " -l, --logfile set logfile path, logs to stderr by default\n" " -f, --pidfile specify pidfile (default is %s)\n" +#ifdef CONFIG_FSFREEZE +" -F, --fsfreeze-hook\n" +"enable fsfreeze hook (default is %s)\n" +#endif " -t, --statedirspecify dir to store state information (absolute paths\n" "only, default is %s)\n" " -v, --verbose log extra debugging information\n" @@ -167,6 +183,9 @@ static void usage(const char *cmd) "\n" "Report bugs to \n" , cmd, QEMU_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT, +#ifdef CONFIG_FSFREEZE +QGA_FSFREEZE_HOOK_DEFAULT, +#endif QGA_STATEDIR_DEFAULT); } @@ -401,6 +420,13 @@ void ga_unset_frozen(GAState *s) } } +#ifdef CONFIG_FSFREEZE +const char *ga_fsfreeze_hook(GAState *s) +{ +return s->fsfreeze_hook; +} +#endif + static void become_daemon(const char *pidfile) { #ifndef _WIN32 @@ -678,10 +704,13 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[]) int main(int argc, char **argv) { -const char *sopt = "hVvdm:p:l:f:b:s:t:"; +const char *sopt = "hVvdm:p:l:f:F::b:s:t:"; const char *method = NULL, *path = NULL; const char *log_filepath = NULL; const char *pid_filepath = QGA_PIDFILE_DEFAULT; +#ifdef CONFIG_FSFREEZE +const char *fsfreeze_hook = NULL; +#endif const char *state_dir = QGA_STATEDIR_DEFAULT; #ifdef _WIN32 const char *service = NULL; @@ -691,6 +720,9 @@ int main(int argc, char **argv) { "version", 0, NULL, 'V' }, { "logfile", 1, NULL, 'l' }, { "pidfile", 1, NULL, 'f' }, +#ifdef CONFIG_FSFREEZE +{ "fsfreeze-hook", 2, NULL, 'F' }, +#endif { "verbose", 0, NULL, 'v' }, { "method", 1, NULL, 'm' }, { "path", 1, NULL, 'p' }, @@ -723,6 +755,11 @@ int main(int argc, char **argv) case 'f': pid_filepath = optarg; break; +#ifdef CONFIG_FSFREEZE +case 'F': +fsfreeze_hook = optarg ? optarg : QGA_FSFREEZE_HOOK_DEFAULT; +break; +#endif case 't': state_dir = optarg; break; @@ -786,6 +823,9 @@ int main(int argc, char **argv) s = g_malloc0(sizeof(GAState)); s->log_level = log_level; s->log_file = stderr; +#ifdef CONFIG_FSFREEZE +s->fsfreeze_hook = fsfreeze_hook; +#endif g_log_set_default_handler(ga_log, s); g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR); ga_enable_logging(s); diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 2591a3c..f7c0d9a 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -410,6
[Qemu-devel] [PATCH v7 0/2] qemu-ga: add hook to quiesce the guest on fsfreeze-freeze/thaw
Hi, This is version 7 of the qemu-ga fsfreeze hook patchset. *Changes from v6: ( http://patchwork.ozlabs.org/patch/202959/ ) 1/2: Improved an error message on failure of access(2) to fsfreeze-hook. 2/2: Moved hook scripts from docs/ to scripts/. Move fsfreeze.d.sample/flush-mysql.sh to fsfreeze.d/flush-mysql.sh.sample. fsfreeze-hook now ignores fsfreeze.d/*.sample. This patchset depends on Luiz Capitulino's patchset to improve error handling, which is available at: https://lists.gnu.org/archive/html/qemu-devel/2012-11/msg03016.html --- Tomoki Sekiyama (2): qemu-ga: execute hook to quiesce the guest on fsfreeze-freeze/thaw qemu-ga: sample fsfreeze hooks .gitignore |1 Makefile |2 - qemu-ga.c | 42 qga/commands-posix.c | 69 qga/guest-agent-core.h |1 scripts/qemu-guest-agent/fsfreeze-hook | 33 ++ .../fsfreeze-hook.d/mysql-flush.sh.sample | 55 7 files changed, 201 insertions(+), 2 deletions(-) create mode 100755 scripts/qemu-guest-agent/fsfreeze-hook create mode 100755 scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample Thanks, -- Tomoki Sekiyama Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory
Re: [Qemu-devel] [PATCH v7 2/2] qemu-ga: sample fsfreeze hooks
Hi, sorry for my late reply. On 2012/12/08 3:57, Luiz Capitulino wrote: > On Fri, 07 Dec 2012 11:37:44 -0700 > Eric Blake wrote: > >> On 12/07/2012 11:31 AM, Luiz Capitulino wrote: >>>>>> +++ b/.gitignore >>>>>> @@ -93,3 +93,4 @@ cscope.* >>>>>> tags >>>>>> TAGS >>>>>> *~ >>>>>> +!scripts/qemu-guest-agent/fsfreeze-hook.d >>>>> >>>>> Why? Do we expect to have *~ files in there? >>>> >>>> What does your question have to do with the patch, which isn't even >>>> touching the pre-existing *~ line? >>> >>> As far I could understand the ! prefix in gitignore documention, it's >>> changing the *~ meaning for the fsfreeze-hoo.d directory, and I wanted >>> to understand why. >>> >> >> No, it is changing a much earlier line: >> >> *.d >> >> to say that this _particular_ .d is allowed to be committed. It has >> nothing to do with *~. Yes, it's for adding fsfreeze-hook.d into the repo. > Ah, now it makes a lot of sense, thanks Eric. > > It would be nice to move it right below *.d, to avoid stupid comments :) And OK, I will move this there. >> Still, I have to wonder if we really want to store these files in a .d >> in the repository itself, or if we should store them under some other >> file name and only at 'make install' time insert them into a .d at the >> install destination. It would clean up this confusion about the >> .gitignore as well as the change to the 'find' command during 'make clean'. > > Well, now that I understand it both ways are fine with me (ie. what you > suggest and what's been implemented in this patch). Then I'd like to keep current implementation. Thanks, -- Tomoki Sekiyama Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory
Re: [Qemu-devel] [PATCH v7 2/2] qemu-ga: sample fsfreeze hooks
Hi Eric, Thanks for your review. On 2012/12/08 3:34, Eric Blake wrote: > On 12/07/2012 01:39 AM, Tomoki Sekiyama wrote: >> Adds sample hook scripts for --fsfreeze-hook option of qemu-ga. >> - fsfreeze-hook : execute scripts in fsfreeze-hook.d/ >> - fsfreeze-hook.d/mysql-flush.sh.sample : quiesce MySQL before snapshot >> >> Signed-off-by: Tomoki Sekiyama >> --- > >> @@ -0,0 +1,33 @@ >> +#!/bin/sh >> + >> +# This script is executed when a guest agent receives fsfreeze-freeze and >> +# fsfreeze-thaw command, if it is specified in --fsfreeze-hook (-F) >> +# option of qemu-ga or placed in default path (/etc/qemu/fsfreeze-hook). >> +# When the agent receives fsfreeze-freeze request, this script is issued >> with >> +# "freeze" argument before the filesystem is freezed. And for fsfreeze-thaw > > s/freezed/frozen/ Oops... >> + >> +# Iterate executables in directory "fsfreeze-hook.d" with the specified args >> +[ ! -d "$FSFREEZE_D" ] && exit 1 > > Do you really want to fail the entire operation if the directory doesn't > exist? Shouldn't you instead exit 0 because there is nothing to do? I thought that was installation failure, but this might be too cautious. Exiting 0 is also reasonable, so I will change this. >> +for file in "$FSFREEZE_D"/* ; do >> +is_ignored_file "$file" && continue >> +[ -x "$file" ] || continue >> +echo "$(date): execute $file $@" >>$LOGFILE > > This is unsafe (although the worst that will happen is a poor message to > the log file). $file might contain backslash, and echo cannot portably > be mixed with backslash. Use printf(1) instead. OK, I will use printf here, and >> +"$file" "$@" >>$LOGFILE 2>&1 >> +STATUS=$? >> +echo "$(date): $file finished with status=$STATUS" >>$LOGFILE > > Again. here too. >> @@ -0,0 +1,55 @@ >> +#!/bin/sh >> + >> +# Flush MySQL tables to the disk before the filesystem is freezed. > > s/freezed/frozen/ > >> +# At the same time, this keeps a read lock in order to avoid write accesses >> +# from the other clients until the filesystem is thawed. >> + >> +MYSQL="/usr/bin/mysql" >> +MYSQL_OPTS="-uroot" #"-prootpassword" >> +FIFO=/tmp/mysql-flush.fifo >> +MYSQL_CMD="$MYSQL $MYSQL_OPTS" >> + >> +# Check mysql is installed and the server running >> +[ -x $MYSQL ] && $MYSQL_CMD < /dev/null || exit 0 > > Safe as written, since you just initialized $MYSQL above; but risky, > since the mere use of MYSQL in the initialization might encourage > someone to point to an alternate path that includes spaces. Then again, > if they do that, then MYSQL_CMD is broken. It might be better to be > explicit and write > [ -x "$MYSQL" ] && "$MYSQL" $MYSQL_OPTS < /dev/null > but I won't insist. OK, I will replace $MYSQL_CMD with "$MYSQL" $MYSQL_OPTS. >> +# for InnoDB, wait until every log is flushed >> +INNODB_STATUS=$(mktemp /tmp/mysql-flush.XX) >> +[ $? -ne 0 ] && exit 2 >> +trap "rm -f $INNODB_STATUS" SIGINT > > POSIX says that 'trap foo INT' is required to work, but 'trap foo > SIGINT' is optional. Also, shouldn't you also worry about HUP, ALRM, > and TERM? I will fix this to trap "..." HUP INT QUIT ALRM TERM Thanks, -- Tomoki Sekiyama Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory
[Qemu-devel] [PATCH v8 0/2] qemu-ga: add hook to quiesce the guest on fsfreeze-freeze/thaw
Hi, This is version 8 of the qemu-ga fsfreeze hook patchset. *Changes from v7: ( http://patchwork.ozlabs.org/patch/204426/ ) 1/2: Not changed. 2/2: Moved .gitignore exception for fsfreeze-hook.d right below "*.d". Make fsfreeze success even if fsfreeze-hook.d doesn't exist. Use printf(1) instead of echo to output logs. Use "$MYSQL" $MYSQL_OPTS instead of $MYSQL_CMD for safety. Improve signal handling in flush-mysql.sh. Fix misspelling. This patchset depends on Luiz Capitulino's patchset to improve error handling, which is available at: https://lists.gnu.org/archive/html/qemu-devel/2012-11/msg03016.html --- Tomoki Sekiyama (2): qemu-ga: execute hook to quiesce the guest on fsfreeze-freeze/thaw qemu-ga: sample fsfreeze hooks .gitignore |1 Makefile |2 - qemu-ga.c | 42 qga/commands-posix.c | 69 qga/guest-agent-core.h |1 scripts/qemu-guest-agent/fsfreeze-hook | 33 ++ .../fsfreeze-hook.d/mysql-flush.sh.sample | 56 7 files changed, 202 insertions(+), 2 deletions(-) create mode 100755 scripts/qemu-guest-agent/fsfreeze-hook create mode 100755 scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample Thanks, -- Tomoki Sekiyama Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory
Re: [Qemu-devel] [PATCH v8 2/2] qemu-ga: sample fsfreeze hooks
Adds sample hook scripts for --fsfreeze-hook option of qemu-ga. - fsfreeze-hook : execute scripts in fsfreeze-hook.d/ - fsfreeze-hook.d/mysql-flush.sh.sample : quiesce MySQL before snapshot Signed-off-by: Tomoki Sekiyama --- .gitignore |1 Makefile |2 - scripts/qemu-guest-agent/fsfreeze-hook | 33 .../fsfreeze-hook.d/mysql-flush.sh.sample | 56 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100755 scripts/qemu-guest-agent/fsfreeze-hook create mode 100755 scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample diff --git a/.gitignore b/.gitignore index bd6ba1c..6456e9d 100644 --- a/.gitignore +++ b/.gitignore @@ -68,6 +68,7 @@ fsdev/virtfs-proxy-helper.pod *.tp *.vr *.d +!scripts/qemu-guest-agent/fsfreeze-hook.d *.o *.lo *.la diff --git a/Makefile b/Makefile index 9ecbcbb..466dcd7 100644 --- a/Makefile +++ b/Makefile @@ -248,7 +248,7 @@ clean: # avoid old build problems by removing potentially incorrect old files rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h rm -f qemu-options.def - find . -name '*.[od]' -exec rm -f {} + + find . -name '*.[od]' -type f -exec rm -f {} + rm -f *.a *.lo $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f qemu-img-cmds.h diff --git a/scripts/qemu-guest-agent/fsfreeze-hook b/scripts/qemu-guest-agent/fsfreeze-hook new file mode 100755 index 000..c27b29f --- /dev/null +++ b/scripts/qemu-guest-agent/fsfreeze-hook @@ -0,0 +1,33 @@ +#!/bin/sh + +# This script is executed when a guest agent receives fsfreeze-freeze and +# fsfreeze-thaw command, if it is specified in --fsfreeze-hook (-F) +# option of qemu-ga or placed in default path (/etc/qemu/fsfreeze-hook). +# When the agent receives fsfreeze-freeze request, this script is issued with +# "freeze" argument before the filesystem is frozen. And for fsfreeze-thaw +# request, it is issued with "thaw" argument after filesystem is thawed. + +LOGFILE=/var/log/qga-fsfreeze-hook.log +FSFREEZE_D=$(dirname -- "$0")/fsfreeze-hook.d + +# Check whether file $1 is a backup or rpm-generated file and should be ignored +is_ignored_file() { +case "$1" in +*~ | *.bak | *.orig | *.rpmnew | *.rpmorig | *.rpmsave | *.sample) +return 0 ;; +esac +return 1 +} + +# Iterate executables in directory "fsfreeze-hook.d" with the specified args +[ ! -d "$FSFREEZE_D" ] && exit 0 +for file in "$FSFREEZE_D"/* ; do +is_ignored_file "$file" && continue +[ -x "$file" ] || continue +printf "$(date): execute $file $@\n" >>$LOGFILE +"$file" "$@" >>$LOGFILE 2>&1 +STATUS=$? +printf "$(date): $file finished with status=$STATUS\n" >>$LOGFILE +done + +exit 0 diff --git a/scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample b/scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample new file mode 100755 index 000..2b4fa3a --- /dev/null +++ b/scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample @@ -0,0 +1,56 @@ +#!/bin/sh + +# Flush MySQL tables to the disk before the filesystem is frozen. +# At the same time, this keeps a read lock in order to avoid write accesses +# from the other clients until the filesystem is thawed. + +MYSQL="/usr/bin/mysql" +MYSQL_OPTS="-uroot" #"-prootpassword" +FIFO=/var/run/mysql-flush.fifo + +# Check mysql is installed and the server running +[ -x "$MYSQL" ] && "$MYSQL" $MYSQL_OPTS < /dev/null || exit 0 + +flush_and_wait() { +printf "FLUSH TABLES WITH READ LOCK \\G\n" +trap 'printf "$(date): $0 is killed\n">&2' HUP INT QUIT ALRM TERM +read < $FIFO +printf "UNLOCK TABLES \\G\n" +rm -f $FIFO +} + +case "$1" in +freeze) +mkfifo $FIFO || exit 1 +flush_and_wait | "$MYSQL" $MYSQL_OPTS & +# wait until every block is flushed +while [ "$(echo 'SHOW STATUS LIKE "Key_blocks_not_flushed"' |\ + "$MYSQL" $MYSQL_OPTS | tail -1 | cut -f 2)" -gt 0 ]; do +sleep 1 +done +# for InnoDB, wait until every log is flushed +INNODB_STATUS=$(mktemp /tmp/mysql-flush.XX) +[ $? -ne 0 ] && exit 2 +trap "rm -f $INNODB_STATUS; exit 1" HUP INT QUIT ALRM TERM +while :; do +printf "SHOW ENGINE INNODB STATUS \\G" |\ +"$MYSQL" $MYSQL_OPTS > $INNODB_STATUS +LOG_CURRENT=$(grep 'Log sequence number' $INNODB_STATUS |\ +
Re: [Qemu-devel] [PATCH v8 1/2] qemu-ga: execute hook to quiesce the guest on fsfreeze-freeze/thaw
To use the online disk snapshot for online-backup, application-level consistency of the snapshot image is required. However, currently the guest agent can provide only filesystem-level consistency, and the snapshot may contain dirty data, for example, incomplete transactions. This patch provides the opportunity to quiesce applications before snapshot is taken. If --fsfreeze-hook option is specified, the hook is executed with "freeze" argument before the filesystem is frozen by fsfreeze-freeze command. As for fsfreeze-thaw command, the hook is executed with "thaw" argument after the filesystem is thawed. This patch depends on patchset to improve error reporting by Luiz Capitulino: http://lists.gnu.org/archive/html/qemu-devel/2012-11/msg03016.html Signed-off-by: Tomoki Sekiyama Reviewed-by: Luiz Capitulino --- qemu-ga.c | 42 + qga/commands-posix.c | 69 qga/guest-agent-core.h |1 + 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/qemu-ga.c b/qemu-ga.c index 9b59a52..53ce462 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -34,6 +34,12 @@ #include "qga/service-win32.h" #include #endif +#ifdef __linux__ +#include +#ifdef FIFREEZE +#define CONFIG_FSFREEZE +#endif +#endif #ifndef _WIN32 #define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0" @@ -42,6 +48,9 @@ #endif #define QGA_STATEDIR_DEFAULT CONFIG_QEMU_LOCALSTATEDIR "/run" #define QGA_PIDFILE_DEFAULT QGA_STATEDIR_DEFAULT "/qemu-ga.pid" +#ifdef CONFIG_FSFREEZE +#define QGA_FSFREEZE_HOOK_DEFAULT CONFIG_QEMU_CONFDIR "/fsfreeze-hook" +#endif #define QGA_SENTINEL_BYTE 0xFF struct GAState { @@ -64,6 +73,9 @@ struct GAState { const char *log_filepath; const char *pid_filepath; } deferred_options; +#ifdef CONFIG_FSFREEZE +const char *fsfreeze_hook; +#endif }; struct GAState *ga_state; @@ -153,6 +165,10 @@ static void usage(const char *cmd) "%s)\n" " -l, --logfile set logfile path, logs to stderr by default\n" " -f, --pidfile specify pidfile (default is %s)\n" +#ifdef CONFIG_FSFREEZE +" -F, --fsfreeze-hook\n" +"enable fsfreeze hook (default is %s)\n" +#endif " -t, --statedirspecify dir to store state information (absolute paths\n" "only, default is %s)\n" " -v, --verbose log extra debugging information\n" @@ -167,6 +183,9 @@ static void usage(const char *cmd) "\n" "Report bugs to \n" , cmd, QEMU_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT, +#ifdef CONFIG_FSFREEZE +QGA_FSFREEZE_HOOK_DEFAULT, +#endif QGA_STATEDIR_DEFAULT); } @@ -401,6 +420,13 @@ void ga_unset_frozen(GAState *s) } } +#ifdef CONFIG_FSFREEZE +const char *ga_fsfreeze_hook(GAState *s) +{ +return s->fsfreeze_hook; +} +#endif + static void become_daemon(const char *pidfile) { #ifndef _WIN32 @@ -678,10 +704,13 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[]) int main(int argc, char **argv) { -const char *sopt = "hVvdm:p:l:f:b:s:t:"; +const char *sopt = "hVvdm:p:l:f:F::b:s:t:"; const char *method = NULL, *path = NULL; const char *log_filepath = NULL; const char *pid_filepath = QGA_PIDFILE_DEFAULT; +#ifdef CONFIG_FSFREEZE +const char *fsfreeze_hook = NULL; +#endif const char *state_dir = QGA_STATEDIR_DEFAULT; #ifdef _WIN32 const char *service = NULL; @@ -691,6 +720,9 @@ int main(int argc, char **argv) { "version", 0, NULL, 'V' }, { "logfile", 1, NULL, 'l' }, { "pidfile", 1, NULL, 'f' }, +#ifdef CONFIG_FSFREEZE +{ "fsfreeze-hook", 2, NULL, 'F' }, +#endif { "verbose", 0, NULL, 'v' }, { "method", 1, NULL, 'm' }, { "path", 1, NULL, 'p' }, @@ -723,6 +755,11 @@ int main(int argc, char **argv) case 'f': pid_filepath = optarg; break; +#ifdef CONFIG_FSFREEZE +case 'F': +fsfreeze_hook = optarg ? optarg : QGA_FSFREEZE_HOOK_DEFAULT; +break; +#endif case 't': state_dir = optarg; break; @@ -786,6 +823,9 @@ int main(int argc, char **argv) s = g_malloc0(sizeof(GAState)); s->log_level = log_level; s->log_file = stderr; +#ifdef CONFIG_FSFREEZE +s->fsfreeze_hook = fsfreeze_hook; +#endif g_log_set_default_handler(ga_log, s); g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR); ga_enable_logging(s); diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 2591a3c..f7c0d9a 100644 --- a/qga/commands-posix.c +++ b/qga/
[Qemu-devel] [RFC PATCH 00/10] qemu-ga: support fsfreeze on Windows using VSS
Hi, This patch series attempts to add fsfreeze support for Windows qemu-guest-agent. In Windows, VSS (Volume Shadow Copy Service) can provide a facility to quiesce filesystems and applications before snapshots are taken. VSS consists from some components. - VSS Writers:applications to be quiesced. - VSS Providers: modules to provide a snapshot feature - VSS Requesters: modules to control snapshotting processes This patch series adds VSS provider and requester feature to qemu-ga. When guest-fsfreeze-freeze command is sent, qemu-ga request VSS to freeze applications and filesystems. After frozen, VSS requests providers to take snapshots using COM+. Qemu-ga hooks this event by registering its own VSS provider and relay it to qemu-ga. guest-fsfreeze-freeze command is finished by this event. When guest-fsfreeze-thaw command is sent, qemu-ga provider tells VSS that snapshot is finished. Then, VSS thaws the filesystems and applications and notify the requester of snapshot completion. The VSS provider in this patch series only provides snapshotting to implement fsfreeze commands, but doesn't provide functions to query for snapshots, recovery, and so on. Auto-recovery(*) feature of VSS is not either supported becuase it requires writable snapshots. *http://msdn.microsoft.com/en-us//library/windows/desktop/aa819771(v=vs.85).aspx Still, this could be useful as a base for future extentions. * How to build & run qemu-ga with VSS support - Download Microsoft VSS SDK from: http://www.microsoft.com/en-us/download/details.aspx?id=23490 - Setup the SDK (wine can be used to run the setup) - Specify installed SDK directory to configure option as: ./configure -with-vss-sdk="path/to/VSS SDK" --cross-prefix=i686-w64-mingw32- - Make qemu-ga.exe - Install qemu-ga.exe and qga/vss-win32-provider/qga-provider.{dll,tlb} into the same directory in guests - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests --- Tomoki Sekiyama (10): configure: Support configuring c++ compiler Fix errors and warnings while compiling with c++ compilier qemu-ga: Add an configure option to specify path to Windows VSS SDK qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze qemu-ga: Add Windows VSS requester to quisce applications and filesystems qemu-ga: call Windows VSS requester in fsfreeze command handler qemu-ga: install Windows VSS provider on `qemu-ga -s install' qemu-ga: Add VSS provider .tlb file in the repository QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly .gitignore |1 Makefile|4 QMP/qemu-ga-client |4 QMP/qmp.py |4 configure | 52 +++ hmp.c |2 hw/pci/pci.c|2 qapi-schema.json|4 qga/Makefile.objs | 15 + qga/commands-win32.c| 74 - qga/main.c | 41 +++ qga/vss-win32-provider.h| 26 ++ qga/vss-win32-provider/Makefile | 30 ++ qga/vss-win32-provider/install.cpp | 494 +++ qga/vss-win32-provider/provider.cpp | 474 ++ qga/vss-win32-provider/qga-provider.def | 10 + qga/vss-win32-provider/qga-provider.idl | 20 + qga/vss-win32-provider/qga-provider.tlb | Bin qga/vss-win32-requester.cpp | 393 + qga/vss-win32-requester.h | 31 ++ qga/vss-win32.h | 93 ++ rules.mak |7 22 files changed, 1766 insertions(+), 15 deletions(-) create mode 100644 qga/vss-win32-provider.h create mode 100644 qga/vss-win32-provider/Makefile create mode 100644 qga/vss-win32-provider/install.cpp create mode 100644 qga/vss-win32-provider/provider.cpp create mode 100644 qga/vss-win32-provider/qga-provider.def create mode 100644 qga/vss-win32-provider/qga-provider.idl create mode 100644 qga/vss-win32-provider/qga-provider.tlb create mode 100644 qga/vss-win32-requester.cpp create mode 100644 qga/vss-win32-requester.h create mode 100644 qga/vss-win32.h Any feedback are appliciated. Thanks, -- Tomoki Sekiyama Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory
[Qemu-devel] [RFC PATCH 05/10] qemu-ga: Add Windows VSS requester to quisce applications and filesystems
This adds VSS requester functions for to qemu-ga. This provides facility to request VSS service in Windows guest to quisce applications and filesystems. This function is only supported in Windows 2003 or later. In older guests, this function does nothing. Signed-off-by: Tomoki Sekiyama --- qga/Makefile.objs | 15 ++ qga/vss-win32-requester.cpp | 393 +++ qga/vss-win32-requester.h | 31 +++ 3 files changed, 439 insertions(+) create mode 100644 qga/vss-win32-requester.cpp create mode 100644 qga/vss-win32-requester.h diff --git a/qga/Makefile.objs b/qga/Makefile.objs index b8d7cd0..2e4a8d6 100644 --- a/qga/Makefile.objs +++ b/qga/Makefile.objs @@ -3,3 +3,18 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o qga-obj-y += qapi-generated/qga-qmp-marshal.o + +ifeq ($(CONFIG_QGA_VSS),y) + +qga-obj-$(CONFIG_WIN32) += vss-win32-requester.o +QEMU_CFLAGS += -DHAS_VSS_SDK +QGALIB_EXTDIR = $(obj)/vss-win32-provider + +qemu-ga$(EXESUF): $(QGALIB_EXTDIR)/qga-provider.dll +$(obj)/vss-win32-requester.o: QEMU_CXXFLAGS += -Wno-unknown-pragmas + +$(QGALIB_EXTDIR)/qga-provider.tlb: $(QGALIB_EXTDIR)/qga-provider.dll +$(QGALIB_EXTDIR)/qga-provider.dll: $(qga-lib-src) $(obj)/vss-win32.h + $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C qga/$(QGALIB_EXTDIR) V="$(V)" all,) + +endif diff --git a/qga/vss-win32-requester.cpp b/qga/vss-win32-requester.cpp new file mode 100644 index 000..f84f464 --- /dev/null +++ b/qga/vss-win32-requester.cpp @@ -0,0 +1,393 @@ +/* + * QEMU Guest Agent win32 VSS Requester implementations + * + * Copyright Hitachi, Ltd. 2013 + * + * Authors: + * Tomoki Sekiyama + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +extern "C" { +#include "guest-agent-core.h" +} +#include "vss-win32-requester.h" +#include "vss-win32-provider.h" +#include "vss-win32.h" +#include "inc/win2003/vswriter.h" +#include "inc/win2003/vsbackup.h" + +/* Functions in VSSAPI.DLL */ +typedef HRESULT (STDAPICALLTYPE* t_CreateVssBackupComponents)(OUT IVssBackupComponents **); +typedef void (APIENTRY* t_VssFreeSnapshotProperties)(IN VSS_SNAPSHOT_PROP*); + +static t_CreateVssBackupComponents _CreateVssBackupComponents = NULL; +static t_VssFreeSnapshotProperties _VssFreeSnapshotProperties = NULL; +static IVssBackupComponents *pVssbc = NULL; +static IVssAsync *pAsyncSnapshot = NULL; +static HMODULE hLib = NULL; +static HANDLE hEvent = INVALID_HANDLE_VALUE, hEvent2 = INVALID_HANDLE_VALUE; +static int cFrozenVols = 0; + +GCC_FMT_ATTR(1, 2) +static void errmsg(const char *fmt, ...) +{ +va_list ap; +va_start(ap, fmt); +char *msg = g_strdup_vprintf(fmt, ap); +va_end(ap); +MessageBox(NULL, msg, "Error in QEMU guest agent", MB_OK | MB_ICONWARNING); +g_free(msg); +} + +static void error_set_win32(Error **errp, DWORD err, +ErrorClass eclass, const char *text) +{ +char *msg = NULL, *nul = strchr(text, '('); +int len = nul ? nul - text : -1; + +/* print error message in native encoding */ +FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (char *)&msg, 0, NULL); +printf("%.*s. (Error: %lx) %s\n", len, text, err, msg); +LocalFree(msg); + +/* set error message in UTF-8 encoding */ +msg = g_win32_error_message(err); +error_set(errp, eclass, "%.*s. (Error: %lx) %s", len, text, err, msg); +g_free(msg); +} +#define error_setg_win32(errp, err, text) \ +error_set_win32(errp, err, ERROR_CLASS_GENERIC_ERROR, text) + +#define _chk(status, text, errp, err_label)\ +do {\ +HRESULT __hr = (status);\ +if (FAILED(__hr)) { \ +error_setg_win32(errp, __hr, text); \ +goto err_label; \ +} \ +} while(0) + +#define chk(status) _chk(status, "Failed to " #status, err, out) + + +HRESULT WaitForAsync(IVssAsync *pAsync) +{ +HRESULT ret, hr; + +do { +hr = pAsync->Wait(); +if (FAILED(hr)) { +ret = hr; +break; +} +hr = pAsync->QueryStatus(&ret, NULL); +if (FAILED(hr)) { +ret = hr; +break; +} +} while (ret == VSS_S_ASYNC_PENDING); + +return ret; +} + +HRESULT vss_init(void) +{ +HRESULT hr; + +hr = VSSCheckOSVersion(); +
[Qemu-devel] [RFC PATCH 06/10] qemu-ga: call Windows VSS requester in fsfreeze command handler
Support guest-fsfreeze-freeze and guest-fsfreeze-thaw commands for Windows guests. When fsfreeze command is issued, it calls the VSS requester to freeze filesystems and applications. On thaw command, it again tells the VSS requester to thaw them. This also adds calling of initialize functions for the VSS requester. Signed-off-by: Tomoki Sekiyama --- qga/commands-win32.c | 74 ++ qga/main.c | 33 ++ 2 files changed, 100 insertions(+), 7 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 7e8ecb3..1ed9fc1 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -15,6 +15,7 @@ #include #include #include "qga/guest-agent-core.h" +#include "qga/vss-win32-requester.h" #include "qga-qmp-commands.h" #include "qapi/qmp/qerror.h" @@ -145,34 +146,95 @@ void qmp_guest_file_flush(int64_t handle, Error **err) error_set(err, QERR_UNSUPPORTED); } +#ifdef HAS_VSS_SDK + /* * Return status of freeze/thaw */ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) { -error_set(err, QERR_UNSUPPORTED); -return 0; +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +if (ga_is_frozen(ga_state)) { +return GUEST_FSFREEZE_STATUS_FROZEN; +} + +return GUEST_FSFREEZE_STATUS_THAWED; } /* - * Walk list of mounted file systems in the guest, and freeze the ones which - * are real local file systems. + * Freeze local file systems using Volume Shadow-copy Service. + * The frozen state is limited for up to 10 seconds by VSS. */ int64_t qmp_guest_fsfreeze_freeze(Error **err) { -error_set(err, QERR_UNSUPPORTED); +int i; + +slog("guest-fsfreeze called"); + +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +/* cannot risk guest agent blocking itself on a write in this state */ +ga_set_frozen(ga_state); + +qga_vss_fsfreeze_freeze(&i, err); +if (error_is_set(err)) { +goto error; +} + +return i; + +error: +qmp_guest_fsfreeze_thaw(NULL); return 0; } /* - * Walk list of frozen file systems in the guest, and thaw them. + * Thaw local file systems using Volume Shadow-copy Service. */ int64_t qmp_guest_fsfreeze_thaw(Error **err) { +int i; + +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +qga_vss_fsfreeze_thaw(&i, err); + +ga_unset_frozen(ga_state); +return i; +} + +#else + +GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) +{ +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +int64_t qmp_guest_fsfreeze_freeze(Error **err) +{ +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +int64_t qmp_guest_fsfreeze_thaw(Error **err) +{ error_set(err, QERR_UNSUPPORTED); return 0; } +#endif + /* * Walk list of mounted file systems in the guest, and discard unused * areas. diff --git a/qga/main.c b/qga/main.c index db281a5..423d41b 100644 --- a/qga/main.c +++ b/qga/main.c @@ -32,6 +32,10 @@ #include "qga/channel.h" #ifdef _WIN32 #include "qga/service-win32.h" +#ifdef HAS_VSS_SDK +#include "qga/vss-win32-provider.h" +#include "qga/vss-win32-requester.h" +#endif #include #endif #ifdef __linux__ @@ -675,6 +679,25 @@ static gboolean channel_init(GAState *s, const gchar *method, const gchar *path) } #ifdef _WIN32 + +static gboolean vss_win32_init(void) +{ +#ifdef HAS_VSS_SDK +if (FAILED(vss_init())) { +g_critical("failed to initialize VSS"); +return false; +} +#endif +return true; +} + +static void vss_win32_deinit(void) +{ +#ifdef HAS_VSS_SDK +vss_deinit(); +#endif +} + DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data, LPVOID ctx) { @@ -717,8 +740,12 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[]) service->status.dwWaitHint = 0; SetServiceStatus(service->status_handle, &service->status); +if (!vss_win32_init()) { +goto out_bad; +} g_main_loop_run(ga_state->main_loop); - +vss_win32_deinit(); +out_bad: service->status.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(service->status_handle, &service->status); } @@ -943,7 +970,11 @@ int main(int argc, char **argv) { (char *)QGA_SERVICE_NAME, service_main }, { NULL, NULL } }; StartServiceCtrlDispatcher(service_table); } else { +if (!vss_win32_init()) { +goto out_bad; +} g_main_loop_run(ga_state->main_loop); +vss_win32_deinit(); } #endif
[Qemu-devel] [RFC PATCH 04/10] qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze
Implements a basic stub of software VSS provider. Currently, this modules only provides a relay function of events between qemu-guest-agent and Windows VSS when VSS finished filesystem freeze and when qemu snapshot is done. In the future, this module could be extended to support the other VSS functions, such as query for snapshot volumes and recovery. Signed-off-by: Tomoki Sekiyama --- Makefile|1 configure |5 qga/vss-win32-provider.h| 26 ++ qga/vss-win32-provider/Makefile | 30 ++ qga/vss-win32-provider/install.cpp | 494 +++ qga/vss-win32-provider/provider.cpp | 474 ++ qga/vss-win32-provider/qga-provider.def | 10 + qga/vss-win32-provider/qga-provider.idl | 20 + qga/vss-win32.h | 93 ++ 9 files changed, 1152 insertions(+), 1 deletion(-) create mode 100644 qga/vss-win32-provider.h create mode 100644 qga/vss-win32-provider/Makefile create mode 100644 qga/vss-win32-provider/install.cpp create mode 100644 qga/vss-win32-provider/provider.cpp create mode 100644 qga/vss-win32-provider/qga-provider.def create mode 100644 qga/vss-win32-provider/qga-provider.idl create mode 100644 qga/vss-win32.h diff --git a/Makefile b/Makefile index fab664f..f0734b7 100644 --- a/Makefile +++ b/Makefile @@ -225,6 +225,7 @@ clean: rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp) rm -rf qapi-generated rm -rf qga/qapi-generated + $(MAKE) -C qga/vss-win32-provider clean $(MAKE) -C tests/tcg clean for d in $(ALL_SUBDIRS); do \ if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ diff --git a/configure b/configure index da49c52..15abdc4 100755 --- a/configure +++ b/configure @@ -3264,9 +3264,12 @@ if test "$softmmu" = yes ; then virtfs=no fi fi - if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then + if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" -o "$mingw32" = "yes" ] ; then if [ "$guest_agent" = "yes" ]; then tools="qemu-ga\$(EXESUF) $tools" + if [ "$mingw32" = "yes" ]; then +tools="qga/vss-win32-provider/qga-provider.dll qga/vss-win32-provider/qga-provider.tlb $tools" + fi fi fi fi diff --git a/qga/vss-win32-provider.h b/qga/vss-win32-provider.h new file mode 100644 index 000..e312977 --- /dev/null +++ b/qga/vss-win32-provider.h @@ -0,0 +1,26 @@ +/* + * QEMU Guest Agent win32 VSS provider declarations + * + * Copyright Hitachi, Ltd. 2013 + * + * Authors: + * Tomoki Sekiyama + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef VSS_WIN32_PROVIDER_H +#define VSS_WIN32_PROVIDER_H + +#include + +STDAPI VSSCheckOSVersion(void); + +STDAPI COMRegister(void); +STDAPI COMUnregister(void); + +STDAPI DllRegisterServer(void); +STDAPI DllUnregisterServer(void); + +#endif diff --git a/qga/vss-win32-provider/Makefile b/qga/vss-win32-provider/Makefile new file mode 100644 index 000..1f213f2 --- /dev/null +++ b/qga/vss-win32-provider/Makefile @@ -0,0 +1,30 @@ +-include ../../config-host.mak +-include ../../rules.mak + +# To build .tlb from .idl, WindowsSDK and C++ must be installed +MIDL=midl +WINSDK="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include" + +qga-prv-dll = qga-provider.dll +qga-prv-tlb = $(qga-prv-dll:.dll=.tlb) +qga-prv-def = $(qga-prv-dll:.dll=.def) +qga-prv-idl = $(qga-prv-dll:.dll=.idl) +qga-prv-obj-y = provider.o install.o + +.PYONY: all clean + +all: $(qga-prv-dll) + +$(qga-prv-tlb): $(qga-prv-idl) + $(call quiet-command,$(MIDL) -I $(WINSDK) $<," MIDL $(TARGET_DIR)$@") + +$(qga-prv-obj-y): QEMU_CXXFLAGS = $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls -fstack-protector-all, $(QEMU_CFLAGS)) +$(qga-prv-obj-y): QEMU_CXXFLAGS += -Wno-unknown-pragmas -Wno-delete-non-virtual-dtor + +$(qga-prv-dll): LDFLAGS = -shared -Wl,--add-stdcall-alias,--enable-stdcall-fixup -lole32 -loleaut32 -lshlwapi -luuid -static +$(qga-prv-dll): $(qga-prv-obj-y) $(qga-prv-def) $(qga-prv-tlb) + $(call quiet-command,$(CXX) -o $@ $(qga-prv-obj-y) $(qga-prv-def) $(CXXFLAGS) $(LDFLAGS)," LINK $(TARGET_DIR)$@") + +# *.tlb is not removed because it is not generated by MinGW +clean: + rm -f *.o *.d *.dll *.exe *~ diff --git a/qga/vss-win32-provider/install.cpp b/qga/vss-win32-provider/install.cpp new file mode 100644 index 000..43a12d7 --- /dev/null +++ b/qga/vss-win32-provider/install.cpp @@ -0,0 +1,494 @@ +/* + * QEMU
[Qemu-devel] [RFC PATCH 08/10] qemu-ga: Add VSS provider .tlb file in the repository
To build type library (.tlb) from COM IDL (.idl), MIDL program in VisualC++ is required. Because MinGW does not support building .tlb files, this file cannot be cross-compiled in non-Windows systems. This patch adds pre-compiled .tlb file in the repository in order to enable cross-compile qemu-ga for Windows with VSS support. Signed-off-by: Tomoki Sekiyama --- Makefile|2 +- qga/vss-win32-provider/qga-provider.tlb | Bin 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 qga/vss-win32-provider/qga-provider.tlb diff --git a/Makefile b/Makefile index f0734b7..405657f 100644 --- a/Makefile +++ b/Makefile @@ -215,7 +215,7 @@ clean: rm -f qemu-options.def find . -name '*.[oda]' -type f -exec rm -f {} + find . -name '*.l[oa]' -type f -exec rm -f {} + - rm -f $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ + rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f qemu-img-cmds.h @# May not be present in GENERATED_HEADERS diff --git a/qga/vss-win32-provider/qga-provider.tlb b/qga/vss-win32-provider/qga-provider.tlb new file mode 100644 index ..226452a1861371ffe0cad1019cf90fdfdcd5ef49 GIT binary patch literal 1528 zcmeYbb_-!*U}OLRP8Kl5;0UB3A_y8H!@$4OPh6a(1_GM|T)fx!kz-UGh_rLWKC!yoBjb#vz`9Lwu4+R-SJ!kIOX4xLBUUGN9-NyTyP76j}@n z2f!qQ8-xepfXD+7rW+{SKz4&@7#qX~^1#sn3O|tFK>%ciE<&_Q3PuKoMqI)S5zj9Ngog_= gXfrXehlhjmFbIJB4$8MKU>*YlD1Z9^F{m5{03Vre%>V!Z literal 0 HcmV?d1
[Qemu-devel] [RFC PATCH 07/10] qemu-ga: install Windows VSS provider on `qemu-ga -s install'
Register QGA VSS provider library into Windows when qemu-ga is installed as Windows service ('-s install' option). It is deregistered when the service is uninstalled ('-s uninstall' option). Signed-off-by: Tomoki Sekiyama --- qga/main.c |8 1 file changed, 8 insertions(+) diff --git a/qga/main.c b/qga/main.c index 423d41b..3e6d95e 100644 --- a/qga/main.c +++ b/qga/main.c @@ -850,8 +850,16 @@ int main(int argc, char **argv) case 's': service = optarg; if (strcmp(service, "install") == 0) { +#ifdef HAS_VSS_SDK +if (FAILED(COMRegister())) { +return EXIT_FAILURE; +} +#endif return ga_install_service(path, log_filepath); } else if (strcmp(service, "uninstall") == 0) { +#ifdef HAS_VSS_SDK +COMUnregister(); +#endif return ga_uninstall_service(); } else { printf("Unknown service command.\n");
[Qemu-devel] [RFC PATCH 02/10] Fix errors and warnings while compiling with c++ compilier
Rename 'class' member in class_info of PciDeviceInfo to 'dev_class', and add some casts to avoid errors from c++ compiler. Signed-off-by: Tomoki Sekiyama --- hmp.c|2 +- hw/pci/pci.c |2 +- qapi-schema.json |4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hmp.c b/hmp.c index 1689e6f..a889c89 100644 --- a/hmp.c +++ b/hmp.c @@ -482,7 +482,7 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) if (dev->class_info.has_desc) { monitor_printf(mon, "%s", dev->class_info.desc); } else { -monitor_printf(mon, "Class %04" PRId64, dev->class_info.class); +monitor_printf(mon, "Class %04" PRId64, dev->class_info.dev_class); } monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n", diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 905dc4a..2ca0675 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1385,7 +1385,7 @@ static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus, info->function = PCI_FUNC(dev->devfn); class = pci_get_word(dev->config + PCI_CLASS_DEVICE); -info->class_info.class = class; +info->class_info.dev_class = class; desc = get_class_desc(class); if (desc->desc) { info->class_info.has_desc = true; diff --git a/qapi-schema.json b/qapi-schema.json index cdd8384..413df5c 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1150,7 +1150,7 @@ # # @class_info.desc: #optional a string description of the device's class # -# @class_info.class: the class code of the device +# @class_info.dev_class: the class code of the device # # @id.device: the PCI device id # @@ -1171,7 +1171,7 @@ ## { 'type': 'PciDeviceInfo', 'data': {'bus': 'int', 'slot': 'int', 'function': 'int', - 'class_info': {'*desc': 'str', 'class': 'int'}, + 'class_info': {'*desc': 'str', 'dev_class': 'int'}, 'id': {'device': 'int', 'vendor': 'int'}, '*irq': 'int', 'qdev_id': 'str', '*pci_bridge': 'PciBridgeInfo', 'regions': ['PciMemoryRegion']} }
[Qemu-devel] [RFC PATCH 01/10] configure: Support configuring c++ compiler
Add configuration for c++ compiler (${corss_prefix}g++ as default) in configure and Makefiles. Currently, usage of c++ language is only for access to Windows VSS using COM+ services in qemu-guest-agent for Windows. Signed-off-by: Tomoki Sekiyama --- configure |6 ++ rules.mak |7 +++ 2 files changed, 13 insertions(+) diff --git a/configure b/configure index 0657b1a..e279263 100755 --- a/configure +++ b/configure @@ -265,6 +265,7 @@ else cc="${CC-${cross_prefix}gcc}" fi +cxx="${CXX-${cross_prefix}g++}" ar="${AR-${cross_prefix}ar}" as="${AS-${cross_prefix}as}" cpp="${CPP-$cc -E}" @@ -598,6 +599,8 @@ for opt do ;; --host-cc=*) host_cc="$optarg" ;; + --cxx=*) cxx="$optarg" + ;; --objcc=*) objcc="$optarg" ;; --make=*) make="$optarg" @@ -1023,6 +1026,7 @@ echo " --cross-prefix=PREFIXuse PREFIX for compile tools [$cross_prefix]" echo " --cc=CC use C compiler CC [$cc]" echo " --host-cc=CC use C compiler CC [$host_cc] for code run at" echo " build time" +echo " --cxx=CXXuse C++ compiler CXX [$cxx]" echo " --objcc=OBJCCuse Objective-C compiler OBJCC [$objcc]" echo " --extra-cflags=CFLAGSappend extra C compiler flags QEMU_CFLAGS" echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS" @@ -3260,6 +3264,7 @@ fi echo "Source path $source_path" echo "C compiler$cc" echo "Host C compiler $host_cc" +echo "C++ compiler $cxx" echo "Objective-C compiler $objcc" echo "CFLAGS$CFLAGS" echo "QEMU_CFLAGS $QEMU_CFLAGS" @@ -3760,6 +3765,7 @@ echo "PYTHON=$python" >> $config_host_mak echo "CC=$cc" >> $config_host_mak echo "CC_I386=$cc_i386" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak +echo "CXX=$cxx" >> $config_host_mak echo "OBJCC=$objcc" >> $config_host_mak echo "AR=$ar" >> $config_host_mak echo "AS=$as" >> $config_host_mak diff --git a/rules.mak b/rules.mak index edc2552..f468f3f 100644 --- a/rules.mak +++ b/rules.mak @@ -8,9 +8,13 @@ MAKEFLAGS += -rR %.d: %.h: %.c: +%.cpp: %.m: %.mak: +# Flags for C++ compilation +QEMU_CXXFLAGS = -D__STDC_LIMIT_MACROS $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls, $(QEMU_CFLAGS)) + # Flags for dependency generation QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d @@ -45,6 +49,9 @@ endif %.o: %.asm $(call quiet-command,$(AS) $(ASFLAGS) -o $@ $<," AS $(TARGET_DIR)$@") +%.o: %.cpp + $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CXX $(TARGET_DIR)$@") + %.o: %.m $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@")
[Qemu-devel] [RFC PATCH 03/10] qemu-ga: Add an configure option to specify path to Windows VSS SDK
To enable VSS support in qemu-ga for Windows, header files included in VSS SDK is required. The VSS support is enabled when the option like below: ./configure --with-vss-sdk="/pass/to/VSS SDK" VSS SDK is available from: http://www.microsoft.com/en-us/download/details.aspx?id=23490 To cross-compilie using mingw32 for Linux, you need to setup the SDK on Windows environments to extract headers. You can also use wine to run the setup of SDK on Linux etc. Signed-off-by: Tomoki Sekiyama --- .gitignore |1 + Makefile |1 + configure | 41 + 3 files changed, 43 insertions(+) diff --git a/.gitignore b/.gitignore index 53fe9c3..3f450e8 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,7 @@ fsdev/virtfs-proxy-helper.pod *.la *.pc .libs +.sdk *.swp *.orig .pc diff --git a/Makefile b/Makefile index 0d9099a..fab664f 100644 --- a/Makefile +++ b/Makefile @@ -252,6 +252,7 @@ distclean: clean for d in $(TARGET_DIRS); do \ rm -rf $$d || exit 1 ; \ done + rm -Rf .sdk if test -f pixman/config.log; then make -C pixman distclean; fi KEYMAPS=da en-gb et fr fr-ch is lt modifiers no pt-br sv \ diff --git a/configure b/configure index e279263..da49c52 100755 --- a/configure +++ b/configure @@ -220,6 +220,8 @@ usb_redir="" opengl="" zlib="yes" guest_agent="yes" +guest_agent_with_vss="no" +vss_win32_sdk="" want_tools="yes" libiscsi="" coroutine="" @@ -884,6 +886,8 @@ for opt do ;; --disable-guest-agent) guest_agent="no" ;; + --with-vss-sdk=*) vss_win32_sdk="$optarg" + ;; --enable-tools) want_tools="yes" ;; --disable-tools) want_tools="no" @@ -1142,6 +1146,7 @@ echo " --disable-usb-redir disable usb network redirection support" echo " --enable-usb-redir enable usb network redirection support" echo " --disable-guest-agentdisable building of the QEMU Guest Agent" echo " --enable-guest-agent enable building of the QEMU Guest Agent" +echo " --with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent" echo " --disable-seccompdisable seccomp support" echo " --enable-seccomp enables seccomp support" echo " --with-coroutine=BACKEND coroutine backend. Supported options:" @@ -2897,6 +2902,38 @@ if test "$usb_redir" != "no" ; then fi ## +# check if we have VSS SDK headers for win + +if test "$mingw32" = "yes" -a "$guest_agent" = "yes" ; then + case "$vss_win32_sdk" in +"") vss_win32_include="" ;; +*\ *) # The SDK is installed in "Program Files" by default, but we cannot + # handle path with spaces. So we copy the headers into ".sdk/sdk". + vss_win32_include="-I$source_path/.sdk/vss" + symlink "$vss_win32_sdk/inc" "$source_path/.sdk/vss/inc" + ;; +*)vss_win32_include="-I$vss_win32_sdk" + esac + cat > $TMPC << EOF +#define __MIDL_user_allocate_free_DEFINED__ +#include +int main(void) { return VSS_CTX_BACKUP; } +EOF + if compile_prog "$vss_win32_include" "" ; then +guest_agent_with_vss="yes" +QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include" +libs_qga="-lole32 -loleaut32 -lshlwapi -luuid -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga" + else +if test "$vss_win32_sdk" != "" ; then + echo "ERROR: Please download and install Microsoft VSS SDK from" + echo "ERROR: http://www.microsoft.com/en-us/download/details.aspx?id=23490"; + feature_not_found "VSS support" +fi +guest_agent_with_vss="no" + fi +fi + +## ## # check if we have fdatasync @@ -3343,6 +3380,7 @@ echo "usb net redir $usb_redir" echo "OpenGL support$opengl" echo "libiscsi support $libiscsi" echo "build guest agent $guest_agent" +echo "QGA VSS support $guest_agent_with_vss" echo "seccomp support $seccomp" echo "coroutine backend $coroutine_backend" echo "GlusterFS support $glusterfs" @@ -3404,6 +3442,9 @@ if test "$mingw32" = "yes" ; then version_micro=0 echo "CONFIG_FILEVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak echo "CONFIG_PRODUCTVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak + if test "$guest_agent_with_vss" = "yes" ; then +echo "CONFIG_QGA_VSS=y" >> $config_host_mak + fi else echo "CONFIG_POSIX=y" >> $config_host_mak fi
[Qemu-devel] [RFC PATCH 10/10] QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly
qemu-ga in Windows might return error message with multibyte characters when the guest OS language is set to other than English. To display such messages correctly, this decodes the message based on locale settings. Signed-off-by: Tomoki Sekiyama --- QMP/qmp.py |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/QMP/qmp.py b/QMP/qmp.py index c551df1..ee21819 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -11,6 +11,7 @@ import json import errno import socket +import locale class QMPError(Exception): pass @@ -133,7 +134,8 @@ class QEMUMonitorProtocol: def command(self, cmd, **kwds): ret = self.cmd(cmd, kwds) if ret.has_key('error'): -raise Exception(ret['error']['desc']) +enc = locale.getpreferredencoding() +raise Exception(ret['error']['desc'].encode(enc)) return ret['return'] def pull_event(self, wait=False):
[Qemu-devel] [RFC PATCH 09/10] QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command
guest-fsfreeze-freeze command can take longer than 3 seconds when heavy disk I/O is running. To avoid unexpected timeout, this changes the timeout to 30 seconds. Signed-off-by: Tomoki Sekiyama --- QMP/qemu-ga-client |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/QMP/qemu-ga-client b/QMP/qemu-ga-client index 46676c3..1f7011a 100755 --- a/QMP/qemu-ga-client +++ b/QMP/qemu-ga-client @@ -267,7 +267,9 @@ def main(address, cmd, args): print('Hint: qemu is not running?') sys.exit(1) -if cmd != 'ping': +if cmd == 'fsfreeze' and args[0] == 'freeze': +client.sync(30) +elif cmd != 'ping': client.sync() globals()['_cmd_' + cmd](client, args)
Re: [Qemu-devel] [RFC PATCH 04/10] qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze
Hi Paolo, thanks for your review. On 2013/02/14 22:22, Paolo Bonzini wrote:> Il 14/02/2013 07:10, Tomoki Sekiyama ha scritto: >> diff --git a/qga/vss-win32-provider/Makefile b/qga/vss-win32-provider/Makefile >> new file mode 100644 >> index 000..1f213f2 >> --- /dev/null >> +++ b/qga/vss-win32-provider/Makefile >> @@ -0,0 +1,30 @@ >> +-include ../../config-host.mak >> +-include ../../rules.mak > > Please try to use a non-recursive makefile style. See > libcacard/Makefile for an example. OK. >> +# To build .tlb from .idl, WindowsSDK and C++ must be installed >> +MIDL=midl >> +WINSDK="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include" > > When cross-compiling, does it work to use Wine's widl implementation? > widl needs a "-t" flag when creating a .tlb, but otherwise should be > compatible. And unlike some other wine tools, it has no dependency on > the Wine runtime. > > It would be great to choose between midl or widl in configure. It's > okay to require a specific option (like --midl=FOO) when compiling under > Windows, and to require installation of Wine tools to build the VSS > stuff under non-Windows. I see. I am not sure whether this works without importlib line, but if it does, I will add the configuration for use widl. Thanks, -- Tomoki Sekiyama
Re: [Qemu-devel] [RFC PATCH 03/10] qemu-ga: Add an configure option to specify path to Windows VSS SDK
On 2013/02/15 9:47, mdroth wrote: [...] > > Hi Tomoki, Hi, > Did you happen to run into this issue compiling the test program? > > [mdroth@vm qemu-build]$ ls ~/w/vsssdk/inc/win2003/ > vdslun.hvsbackup.hvscoordint.idl vsmgmt.idl vsprov.idl > vss.idlvsswprv.idl > vdslun.idl vscoordint.h vsmgmt.hvsprov.hvss.h > vsswprv.h vswriter.h > [mdroth@vm qemu-build]$ cat test.c > #define __MIDL_user_allocate_free_DEFINED__ > #include > int main(void) { return VSS_CTX_BACKUP; } > [mdroth@vm qemu-build]$ gcc -I ~/w/vsssdk/ -o test test.c > In file included from test.c:2:0: > /home/mdroth/w/vsssdk/inc/win2003/vss.h:25:17: fatal error: rpc.h: No > such file or directory > compilation terminated. > > I can't seem to locate any mingw or microsoft package that provides that. > It's also not present anywhere on the Wine filesystem I installed the > VSS SDK to. > Hmm, I haven't seen this yet. I am testing this on Fedora 18 x86_64 host, and it provides package "mingw32-headers.noarch" or "mingw64-headers.noarch" which contains the rpc.h (filepath is /usr/x86_64-w64-mingw32/sys-root/mingw/include/rpc.h ) -- Tomoki Sekiyama Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory
Re: [Qemu-devel] [RFC PATCH 03/10] qemu-ga: Add an configure option to specify path to Windows VSS SDK
Hi Paolo, On 2013/02/14 23:36, Paolo Bonzini wrote: > Il 14/02/2013 07:10, Tomoki Sekiyama ha scritto: >> To enable VSS support in qemu-ga for Windows, header files included in >> VSS SDK is required. >> The VSS support is enabled when the option like below: >> ./configure --with-vss-sdk="/pass/to/VSS SDK" >> >> VSS SDK is available from: >> http://www.microsoft.com/en-us/download/details.aspx?id=23490 >> >> To cross-compilie using mingw32 for Linux, you need to setup the SDK on >> Windows environments to extract headers. You can also use wine to run the >> setup of SDK on Linux etc. > > You can also use msitools (https://live.gnome.org/msitools; right now > they are not packaged for any distro, but will be in Fedora soon): > > - > #! /bin/bash > > # extract-vsssdk-headers > # Author: Paolo Bonzini > > set -e > if test $# = 0 || ! test -f "$1"; then > echo 'Usage: extract-vsssdk-headers /path/to/setup.exe > exit 1 > fi > > # Extract .MSI file in the .exe, looking for the OLE compound > # document signature. Extra data at the end does not matter. > export LC_ALL=C > MAGIC=$'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1' > offset=`grep -abom1 "$MAGIC" setup.exe | sed -n 's/:/\n/; P' ` > (dd of=/dev/null skip=$offset bs=1 count=0; cat) < "$1" > vsssdk.msi > > # Now extract the files. > tmpdir=tmp$$ > mkdir $tmpdir > msiextract -C $tmpdir vsssdk.msi > mv "$tmpdir/Program Files/Microsoft/VSSSDK72/inc" inc > rm -rf $tmpdir vsssdk.msi > exit 0 > - > > Can you add this in scripts/extract-vsssdk-headers please? Thank you for the code (tricky!), I will add this. >> ## >> +# check if we have VSS SDK headers for win >> + >> +if test "$mingw32" = "yes" -a "$guest_agent" = "yes" ; then >> + case "$vss_win32_sdk" in >> +"") vss_win32_include="" ;; >> +*\ *) # The SDK is installed in "Program Files" by default, but we >> cannot >> + # handle path with spaces. So we copy the headers into ".sdk/sdk". >> + vss_win32_include="-I$source_path/.sdk/vss" >> + symlink "$vss_win32_sdk/inc" "$source_path/.sdk/vss/inc" >> + ;; >> +*)vss_win32_include="-I$vss_win32_sdk" >> + esac > > Please also add support for these: > > --with-vss-sdk=no and --without-vss-sdk to disable VSS > > --with-vss-sdk (with no path) is the same as "--with-vss-sdk=", but > should fail if the program does not compile. > > The default should be what you have now, i.e. test and proceed according > to the result. I see. >> + cat > $TMPC << EOF >> +#define __MIDL_user_allocate_free_DEFINED__ >> +#include >> +int main(void) { return VSS_CTX_BACKUP; } >> +EOF >> + if compile_prog "$vss_win32_include" "" ; then >> +guest_agent_with_vss="yes" >> +QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include" >> +libs_qga="-lole32 -loleaut32 -lshlwapi -luuid -lstdc++ >> -Wl,--enable-stdcall-fixup $libs_qga" >> + else >> +if test "$vss_win32_sdk" != "" ; then >> + echo "ERROR: Please download and install Microsoft VSS SDK from" >> + echo "ERROR: >> http://www.microsoft.com/en-us/download/details.aspx?id=23490"; > > Please add a note here detailing how to extract the headers on POSIX > systems. OK, thanks again. > Paolo > >> + feature_not_found "VSS support" >> +fi >> +guest_agent_with_vss="no" >> + fi >> +fi >> + >> +## >> >> ## >> # check if we have fdatasync >> @@ -3343,6 +3380,7 @@ echo "usb net redir $usb_redir" >> echo "OpenGL support$opengl" >> echo "libiscsi support $libiscsi" >> echo "build guest agent $guest_agent" >> +echo "QGA VSS support $guest_agent_with_vss" >> echo "seccomp support $seccomp" >> echo "coroutine backend $coroutine_backend" >> echo "GlusterFS support $glusterfs" >> @@ -3404,6 +3442,9 @@ if test "$mingw32" = "yes" ; then >>version_micro=0 >>echo >> "CONFIG_FILEVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> >> $config_host_mak >>echo >> "CONFIG_PRODUCTVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> >> $config_host_mak >> + if test "$guest_agent_with_vss" = "yes" ; then >> +echo "CONFIG_QGA_VSS=y" >> $config_host_mak >> + fi >> else >>echo "CONFIG_POSIX=y" >> $config_host_mak >> fi >> >> >> -- Tomoki Sekiyama
Re: [Qemu-devel] [RFC PATCH 02/10] Fix errors and warnings while compiling with c++ compilier
On 2013/02/14 21:27, Luiz Capitulino wrote: > On Thu, 14 Feb 2013 15:10:36 +0900 > Tomoki Sekiyama wrote: > >> Rename 'class' member in class_info of PciDeviceInfo to 'dev_class', and >> add some casts to avoid errors from c++ compiler. > > [...] > >> # >> # @class_info.desc: #optional a string description of the device's class >> # >> -# @class_info.class: the class code of the device >> +# @class_info.dev_class: the class code of the device >> # >> # @id.device: the PCI device id >> # >> @@ -1171,7 +1171,7 @@ >> ## >> { 'type': 'PciDeviceInfo', >>'data': {'bus': 'int', 'slot': 'int', 'function': 'int', >> - 'class_info': {'*desc': 'str', 'class': 'int'}, >> + 'class_info': {'*desc': 'str', 'dev_class': 'int'}, >> 'id': {'device': 'int', 'vendor': 'int'}, >> '*irq': 'int', 'qdev_id': 'str', '*pci_bridge': 'PciBridgeInfo', >> 'regions': ['PciMemoryRegion']} } > > The right way of doing this is to add 'class' to the set of reserved > words in scripts/qapi.py:c_var(). Then you'll have to adapt the code to > use the 'q_' prefix. Thank you for the information, I will try that. > Now, is using C++ required? Why can't you use plain C? It is because Windows COM+ framework (which VSS uses) is designed based on C++ objective programming interface. Implementing this with plain C is theoretically possible, but that will require parsing C++ objects' vtables manually so the code would be much complex. (However, It might be possible to push Windows-specific C++ stuff into a DLL to and avoid involving qemu related headers.) Thanks, -- Tomoki Sekiyama
Re: [Qemu-devel] [RFC PATCH 03/10] qemu-ga: Add an configure option to specify path to Windows VSS SDK
On 2013/02/19 9:15, mdroth wrote: > On Fri, Feb 15, 2013 at 12:55:49PM +0900, Tomoki Sekiyama wrote: >> On 2013/02/15 9:47, mdroth wrote: >> [...] >>> >>> Hi Tomoki, >> >> Hi, >> >>> Did you happen to run into this issue compiling the test program? >>> >>> [mdroth@vm qemu-build]$ ls ~/w/vsssdk/inc/win2003/ >>> vdslun.hvsbackup.hvscoordint.idl vsmgmt.idl vsprov.idl >>> vss.idlvsswprv.idl >>> vdslun.idl vscoordint.h vsmgmt.hvsprov.hvss.h >>> vsswprv.h vswriter.h >>> [mdroth@vm qemu-build]$ cat test.c >>> #define __MIDL_user_allocate_free_DEFINED__ >>> #include >>> int main(void) { return VSS_CTX_BACKUP; } >>> [mdroth@vm qemu-build]$ gcc -I ~/w/vsssdk/ -o test test.c >>> In file included from test.c:2:0: >>> /home/mdroth/w/vsssdk/inc/win2003/vss.h:25:17: fatal error: rpc.h: No >>> such file or directory >>> compilation terminated. >>> >>> I can't seem to locate any mingw or microsoft package that provides that. >>> It's also not present anywhere on the Wine filesystem I installed the >>> VSS SDK to. >>> >> >> Hmm, I haven't seen this yet. >> I am testing this on Fedora 18 x86_64 host, and it provides package >> "mingw32-headers.noarch" or "mingw64-headers.noarch" which contains >> the rpc.h >> (filepath is /usr/x86_64-w64-mingw32/sys-root/mingw/include/rpc.h ) > > Thanks. I actually did have that header, but I was doing something silly > (forgot to use cross-compiler for the test program). The configure issue > I was hitting was also an error on my part (options with "~" weren't > resolving to my home dir). I did end up missing ntverp.h however in > vss-win32.h using Fedora 15. I made some progress trying the build > without it however. Can you confirm all the headers in vss-win32.h are > needed? Some of headers in vss-win32.h (nterp,h, rpc.h, rpcndr.h, etc) seems needed to build qemu-ga.exe in a native build environment(mingw on Windows). In my Fedora 18 environment, these don't cause errors, but it also succeeded to build even without the headers. > I went ahead and put together an FC18 environment, but would be > nice if we can get this building for older environments (if possible). I will try this with some of my old VMs and investigate which headers are really needed. Thanks, -- Tomoki Sekiyama
[Qemu-devel] [RFC PATCH v2 01/11] configure: Support configuring c++ compiler
Add configuration for c++ compiler (${corss_prefix}g++ as default) in configure and Makefiles. Currently, usage of c++ language is only for access to Windows VSS using COM+ services in qemu-guest-agent for Windows. Signed-off-by: Tomoki Sekiyama --- configure |6 ++ rules.mak |9 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 1ed939a..b74572f 100755 --- a/configure +++ b/configure @@ -278,6 +278,7 @@ else cc="${CC-${cross_prefix}gcc}" fi +cxx="${CXX-${cross_prefix}g++}" ar="${AR-${cross_prefix}ar}" as="${AS-${cross_prefix}as}" cpp="${CPP-$cc -E}" @@ -615,6 +616,8 @@ for opt do ;; --host-cc=*) host_cc="$optarg" ;; + --cxx=*) cxx="$optarg" + ;; --objcc=*) objcc="$optarg" ;; --make=*) make="$optarg" @@ -1053,6 +1056,7 @@ echo " --cross-prefix=PREFIXuse PREFIX for compile tools [$cross_prefix]" echo " --cc=CC use C compiler CC [$cc]" echo " --host-cc=CC use C compiler CC [$host_cc] for code run at" echo " build time" +echo " --cxx=CXXuse C++ compiler CXX [$cxx]" echo " --objcc=OBJCCuse Objective-C compiler OBJCC [$objcc]" echo " --extra-cflags=CFLAGSappend extra C compiler flags QEMU_CFLAGS" echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS" @@ -3349,6 +3353,7 @@ fi echo "Source path $source_path" echo "C compiler$cc" echo "Host C compiler $host_cc" +echo "C++ compiler $cxx" echo "Objective-C compiler $objcc" echo "CFLAGS$CFLAGS" echo "QEMU_CFLAGS $QEMU_CFLAGS" @@ -3860,6 +3865,7 @@ echo "PYTHON=$python" >> $config_host_mak echo "CC=$cc" >> $config_host_mak echo "CC_I386=$cc_i386" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak +echo "CXX=$cxx" >> $config_host_mak echo "OBJCC=$objcc" >> $config_host_mak echo "AR=$ar" >> $config_host_mak echo "AS=$as" >> $config_host_mak diff --git a/rules.mak b/rules.mak index edc2552..9dfd23a 100644 --- a/rules.mak +++ b/rules.mak @@ -8,9 +8,13 @@ MAKEFLAGS += -rR %.d: %.h: %.c: +%.cpp: %.m: %.mak: +# Flags for C++ compilation +QEMU_CXXFLAGS = -D__STDC_LIMIT_MACROS $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls, $(QEMU_CFLAGS)) + # Flags for dependency generation QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d @@ -45,6 +49,9 @@ endif %.o: %.asm $(call quiet-command,$(AS) $(ASFLAGS) -o $@ $<," AS $(TARGET_DIR)$@") +%.o: %.cpp + $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CXX $(TARGET_DIR)$@") + %.o: %.m $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@") @@ -65,7 +72,7 @@ quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1)) cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \ >/dev/null 2>&1 && echo OK), $2, $3) -VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.sh +VPATH_SUFFIXES = %.c %.h %.S %.cpp %.m %.mak %.texi %.sh set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) # find-in-path
[Qemu-devel] [RFC PATCH v2 02/11] Fix errors and warnings while compiling with c++ compilier
Add C++ keywords to avoid errors in compiling with c++ compiler. This also renames class member of PciDeviceInfo to q_class. Signed-off-by: Tomoki Sekiyama --- hmp.c |2 +- hw/pci/pci.c|2 +- scripts/qapi.py |9 - 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/hmp.c b/hmp.c index dbe9b90..9fa89a4 100644 --- a/hmp.c +++ b/hmp.c @@ -484,7 +484,7 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) if (dev->class_info.has_desc) { monitor_printf(mon, "%s", dev->class_info.desc); } else { -monitor_printf(mon, "Class %04" PRId64, dev->class_info.class); +monitor_printf(mon, "Class %04" PRId64, dev->class_info.q_class); } monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n", diff --git a/hw/pci/pci.c b/hw/pci/pci.c index d5257ed..a3eaf47 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1460,7 +1460,7 @@ static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus, info->function = PCI_FUNC(dev->devfn); class = pci_get_word(dev->config + PCI_CLASS_DEVICE); -info->class_info.class = class; +info->class_info.q_class = class; desc = get_class_desc(class); if (desc->desc) { info->class_info.has_desc = true; diff --git a/scripts/qapi.py b/scripts/qapi.py index afc5f32..b174acb 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -156,9 +156,16 @@ def c_var(name, protect=True): # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html # excluding _.* gcc_words = set(['asm', 'typeof']) +# C++ ISO/IEC 14882:2003 2.11 +cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete', + 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable', + 'namespace', 'new', 'operator', 'private', 'protected', + 'public', 'reinterpret_cast', 'static_cast', 'template', + 'this', 'throw', 'true', 'try', 'typeid', 'typename', + 'using', 'virtual', 'wchar_t']) # namespace pollution: polluted_words = set(['unix']) -if protect and (name in c89_words | c99_words | c11_words | gcc_words | polluted_words): +if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words): return "q_" + name return name.replace('-', '_').lstrip("*")
[Qemu-devel] [RFC PATCH v2 03/11] Add a script to extract VSS SDK headers on POSIX system
VSS SDK(*) setup.exe is only runnable on Windows. This adds a script to extract VSS SDK headers on POSIX-systems using msitools. * http://www.microsoft.com/en-us/download/details.aspx?id=23490 From: Paolo Bonzini Signed-off-by: Tomoki Sekiyama --- scripts/extract-vsssdk-headers | 25 + 1 file changed, 25 insertions(+) create mode 100755 scripts/extract-vsssdk-headers diff --git a/scripts/extract-vsssdk-headers b/scripts/extract-vsssdk-headers new file mode 100755 index 000..5877137 --- /dev/null +++ b/scripts/extract-vsssdk-headers @@ -0,0 +1,25 @@ +#! /bin/bash + +# extract-vsssdk-headers +# Author: Paolo Bonzini + +set -e +if test $# = 0 || ! test -f "$1"; then + echo 'Usage: extract-vsssdk-headers /path/to/setup.exe' + exit 1 +fi + +# Extract .MSI file in the .exe, looking for the OLE compound +# document signature. Extra data at the end does not matter. +export LC_ALL=C +MAGIC=$'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1' +offset=`grep -abom1 "$MAGIC" "$1" | sed -n 's/:/\n/; P' ` +(dd of=/dev/null skip=$offset bs=1 count=0; cat) < "$1" > vsssdk.msi + +# Now extract the files. +tmpdir=tmp$$ +mkdir $tmpdir +msiextract -C $tmpdir vsssdk.msi +mv "$tmpdir/Program Files/Microsoft/VSSSDK72/inc" inc +rm -rf $tmpdir vsssdk.msi +exit 0
[Qemu-devel] [RFC PATCH v2 09/11] qemu-ga: Add VSS provider .tlb file in the repository
To build type library (.tlb) for qga-provider.dll from COM IDL (.idl), MIDL in VisualC++ and stdole2.tlb in Windows SDK are required. This patch adds pre-compiled .tlb file in the repository in order to enable cross-compile qemu-ga.exe for Windows with VSS support. Signed-off-by: Tomoki Sekiyama --- Makefile|2 +- qga/vss-win32-provider/Makefile.objs|4 qga/vss-win32-provider/qga-provider.tlb | Bin 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 qga/vss-win32-provider/qga-provider.tlb diff --git a/Makefile b/Makefile index 8d4506f..c938aec 100644 --- a/Makefile +++ b/Makefile @@ -224,7 +224,7 @@ clean: rm -f qemu-options.def find . -name '*.[oda]' -type f -exec rm -f {} + find . -name '*.l[oa]' -type f -exec rm -f {} + - rm -f $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ + rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f qemu-img-cmds.h @# May not be present in GENERATED_HEADERS diff --git a/qga/vss-win32-provider/Makefile.objs b/qga/vss-win32-provider/Makefile.objs index 73ef752..698359b 100644 --- a/qga/vss-win32-provider/Makefile.objs +++ b/qga/vss-win32-provider/Makefile.objs @@ -18,4 +18,8 @@ MIDL=midl WINSDK="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include" $(obj)/qga-provider.tlb: $(SRC_PATH)/$(obj)/qga-provider.idl +ifeq ($(wildcard $(SRC_PATH)/$(obj)/qga-provider.tlb),) $(call quiet-command,$(MIDL) -m64 -o $@ -I $(WINSDK) $<," MIDL $(TARGET_DIR)$@") +else + $(call quiet-command,cp $(dir $<)qga-provider.tlb $@, " COPY $(TARGET_DIR)$@") +endif diff --git a/qga/vss-win32-provider/qga-provider.tlb b/qga/vss-win32-provider/qga-provider.tlb new file mode 100644 index ..226452a1861371ffe0cad1019cf90fdfdcd5ef49 GIT binary patch literal 1528 zcmeYbb_-!*U}OLRP8Kl5;0UB3A_y8H!@$4OPh6a(1_GM|T)fx!kz-UGh_rLWKC!yoBjb#vz`9Lwu4+R-SJ!kIOX4xLBUUGN9-NyTyP76j}@n z2f!qQ8-xepfXD+7rW+{SKz4&@7#qX~^1#sn3O|tFK>%ciE<&_Q3PuKoMqI)S5zj9Ngog_= gXfrXehlhjmFbIJB4$8MKU>*YlD1Z9^F{m5{03Vre%>V!Z literal 0 HcmV?d1
[Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS
Hi, This patch series is attempts to add fsfreeze support for Windows qemu-guest-agent. changes from v1: - Fix out-tree build by stop using recursive Makefile - Added script to extract VSS SDK headers on POSIX systems using msitools (thanks Paolo) - Remove some unnecessary header files v1: http://lists.gnu.org/archive/html/qemu-devel/2013-02/msg01963.html * Description In Windows, VSS (Volume Shadow Copy Service) provides a facility to quiesce filesystems and applications before disk snapshots are taken. This patch series implements "fsfreeze" command of qemu-ga using VSS. * How to build & run qemu-ga with VSS support - Download Microsoft VSS SDK from: http://www.microsoft.com/en-us/download/details.aspx?id=23490 - Setup the SDK scripts/extract-vsssdk-headers setup.exe (on POSIX-systems) - Specify installed SDK directory to configure option as: ./configure -with-vss-sdk="path/to/VSS SDK" --cross-prefix=i686-w64-mingw32- - Make qemu-ga.exe - Install qemu-ga.exe and qga/vss-win32-provider/qga-provider.{dll,tlb} into the same directory in guests - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests Any feedback are appliciated. --- Tomoki Sekiyama (11): configure: Support configuring c++ compiler Fix errors and warnings while compiling with c++ compilier Add a script to extract VSS SDK headers on POSIX system qemu-ga: Add an configure option to specify path to Windows VSS SDK qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze qemu-ga: Add Windows VSS requester to quisce applications and filesystems qemu-ga: call Windows VSS requester in fsfreeze command handler qemu-ga: install Windows VSS provider on `qemu-ga -s install' qemu-ga: Add VSS provider .tlb file in the repository QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly .gitignore |1 Makefile|3 Makefile.objs |2 QMP/qemu-ga-client |4 QMP/qmp.py |4 configure | 59 hmp.c |2 hw/pci/pci.c|2 qga/Makefile.objs |7 qga/commands-win32.c| 74 - qga/main.c | 41 +++ qga/vss-win32-provider.h| 26 ++ qga/vss-win32-provider/Makefile.objs| 25 ++ qga/vss-win32-provider/install.cpp | 494 +++ qga/vss-win32-provider/provider.cpp | 474 ++ qga/vss-win32-provider/qga-provider.def | 10 + qga/vss-win32-provider/qga-provider.idl | 20 + qga/vss-win32-provider/qga-provider.tlb | Bin qga/vss-win32-requester.cpp | 393 + qga/vss-win32-requester.h | 31 ++ qga/vss-win32.h | 85 + rules.mak |9 + scripts/extract-vsssdk-headers | 25 ++ scripts/qapi.py |9 + 24 files changed, 1785 insertions(+), 15 deletions(-) create mode 100644 qga/vss-win32-provider.h create mode 100644 qga/vss-win32-provider/Makefile.objs create mode 100644 qga/vss-win32-provider/install.cpp create mode 100644 qga/vss-win32-provider/provider.cpp create mode 100644 qga/vss-win32-provider/qga-provider.def create mode 100644 qga/vss-win32-provider/qga-provider.idl create mode 100644 qga/vss-win32-provider/qga-provider.tlb create mode 100644 qga/vss-win32-requester.cpp create mode 100644 qga/vss-win32-requester.h create mode 100644 qga/vss-win32.h create mode 100755 scripts/extract-vsssdk-headers
[Qemu-devel] [RFC PATCH v2 04/11] qemu-ga: Add an configure option to specify path to Windows VSS SDK
To enable VSS support in qemu-ga for Windows, header files included in VSS SDK is required. The VSS support is enabled when the option like below: ./configure --with-vss-sdk="/pass/to/VSS SDK" VSS SDK is available from: http://www.microsoft.com/en-us/download/details.aspx?id=23490 To cross-compilie using mingw32 for Linux, you need to setup the SDK on Windows environments to extract headers. You can also extract the SDK headers using scripts/extract-vss-headers, written by Paolo Bonzini. Signed-off-by: Tomoki Sekiyama --- .gitignore |1 + Makefile |1 + configure | 48 3 files changed, 50 insertions(+) diff --git a/.gitignore b/.gitignore index 487813a..b98e851 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ fsdev/virtfs-proxy-helper.pod *.la *.pc .libs +.sdk *.swp *.orig .pc diff --git a/Makefile b/Makefile index 0b6e6a1..8d4506f 100644 --- a/Makefile +++ b/Makefile @@ -261,6 +261,7 @@ distclean: clean for d in $(TARGET_DIRS); do \ rm -rf $$d || exit 1 ; \ done + rm -Rf .sdk if test -f pixman/config.log; then make -C pixman distclean; fi KEYMAPS=da en-gb et fr fr-ch is lt modifiers no pt-br sv \ diff --git a/configure b/configure index b74572f..310bf9f 100755 --- a/configure +++ b/configure @@ -230,6 +230,8 @@ usb_redir="" glx="" zlib="yes" guest_agent="yes" +guest_agent_with_vss="no" +vss_win32_sdk="" want_tools="yes" libiscsi="" coroutine="" @@ -901,6 +903,12 @@ for opt do ;; --disable-guest-agent) guest_agent="no" ;; + --with-vss-sdk) vss_win32_sdk="" + ;; + --with-vss-sdk=*) vss_win32_sdk="$optarg" + ;; + --without-vss-sdk) vss_win32_sdk="no" + ;; --enable-tools) want_tools="yes" ;; --disable-tools) want_tools="no" @@ -1177,6 +1185,7 @@ echo " --disable-usb-redir disable usb network redirection support" echo " --enable-usb-redir enable usb network redirection support" echo " --disable-guest-agentdisable building of the QEMU Guest Agent" echo " --enable-guest-agent enable building of the QEMU Guest Agent" +echo " --with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent" echo " --disable-seccompdisable seccomp support" echo " --enable-seccomp enables seccomp support" echo " --with-coroutine=BACKEND coroutine backend. Supported options:" @@ -2948,6 +2957,41 @@ if test "$usb_redir" != "no" ; then fi ## +# check if we have VSS SDK headers for win + +if test "$mingw32" = "yes" -a "$guest_agent" = "yes" -a "$vss_win32_sdk" != "no" ; then + case "$vss_win32_sdk" in +"") vss_win32_include="-I$source_path" ;; +*\ *) # The SDK is installed in "Program Files" by default, but we cannot + # handle path with spaces. So we symlink the headers into ".sdk/vss". + vss_win32_include="-I$source_path/.sdk/vss" + symlink "$vss_win32_sdk/inc" "$source_path/.sdk/vss/inc" + ;; +*)vss_win32_include="-I$vss_win32_sdk" + esac + cat > $TMPC << EOF +#define __MIDL_user_allocate_free_DEFINED__ +#include +int main(void) { return VSS_CTX_BACKUP; } +EOF + if compile_prog "$vss_win32_include" "" ; then +guest_agent_with_vss="yes" +QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include" +libs_qga="-lole32 -loleaut32 -lshlwapi -luuid -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga" + else +if test "$vss_win32_sdk" != "" ; then + echo "ERROR: Please download and install Microsoft VSS SDK:" + echo "ERROR: http://www.microsoft.com/en-us/download/details.aspx?id=23490"; + echo "ERROR: On POSIX-systems, you can extract the SDK headers by:" + echo "ERROR: scripts/extract-vsssdk-headers setup.exe" + echo "ERROR: The headers are extracted in the directory \`inc'." + feature_not_found "VSS support" +fi +guest_agent_with_vss="no" + fi +fi + +## ## # check if we have fdatasync @@ -3433,6 +3477,7 @@ echo "usb net redir $usb_redir" echo "GLX support $glx" echo "libiscsi support $libiscsi" echo "build guest agent $guest_agent" +echo "QGA VSS support $guest_agent_with_vss" echo "seccomp support $seccomp" echo "coroutine backend $coroutine" echo "GlusterFS support $glusterfs" @@ -3496,6 +3541,9 @@ if test "$mingw32" = "yes" ; then version_micro=0 echo "CONFIG_FILEVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak echo "CONFIG_PRODUCTVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak + if test "$guest_agent_with_vss" = "yes" ; then +echo "CONFIG_QGA_VSS=y" >> $config_host_mak + fi else echo "CONFIG_POSIX=y" >> $config_host_mak fi
[Qemu-devel] [RFC PATCH v2 07/11] qemu-ga: call Windows VSS requester in fsfreeze command handler
Support guest-fsfreeze-freeze and guest-fsfreeze-thaw commands for Windows guests. When fsfreeze command is issued, it calls the VSS requester to freeze filesystems and applications. On thaw command, it again tells the VSS requester to thaw them. This also adds calling of initialize functions for the VSS requester. Signed-off-by: Tomoki Sekiyama --- qga/commands-win32.c | 74 ++ qga/main.c | 33 ++ 2 files changed, 100 insertions(+), 7 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 24e4ad0..67dca60 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -15,6 +15,7 @@ #include #include #include "qga/guest-agent-core.h" +#include "qga/vss-win32-requester.h" #include "qga-qmp-commands.h" #include "qapi/qmp/qerror.h" @@ -151,34 +152,95 @@ void qmp_guest_file_flush(int64_t handle, Error **err) error_set(err, QERR_UNSUPPORTED); } +#ifdef HAS_VSS_SDK + /* * Return status of freeze/thaw */ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) { -error_set(err, QERR_UNSUPPORTED); -return 0; +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +if (ga_is_frozen(ga_state)) { +return GUEST_FSFREEZE_STATUS_FROZEN; +} + +return GUEST_FSFREEZE_STATUS_THAWED; } /* - * Walk list of mounted file systems in the guest, and freeze the ones which - * are real local file systems. + * Freeze local file systems using Volume Shadow-copy Service. + * The frozen state is limited for up to 10 seconds by VSS. */ int64_t qmp_guest_fsfreeze_freeze(Error **err) { -error_set(err, QERR_UNSUPPORTED); +int i; + +slog("guest-fsfreeze called"); + +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +/* cannot risk guest agent blocking itself on a write in this state */ +ga_set_frozen(ga_state); + +qga_vss_fsfreeze_freeze(&i, err); +if (error_is_set(err)) { +goto error; +} + +return i; + +error: +qmp_guest_fsfreeze_thaw(NULL); return 0; } /* - * Walk list of frozen file systems in the guest, and thaw them. + * Thaw local file systems using Volume Shadow-copy Service. */ int64_t qmp_guest_fsfreeze_thaw(Error **err) { +int i; + +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +qga_vss_fsfreeze_thaw(&i, err); + +ga_unset_frozen(ga_state); +return i; +} + +#else + +GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) +{ +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +int64_t qmp_guest_fsfreeze_freeze(Error **err) +{ +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +int64_t qmp_guest_fsfreeze_thaw(Error **err) +{ error_set(err, QERR_UNSUPPORTED); return 0; } +#endif + /* * Walk list of mounted file systems in the guest, and discard unused * areas. diff --git a/qga/main.c b/qga/main.c index 1841759..92230e9 100644 --- a/qga/main.c +++ b/qga/main.c @@ -34,6 +34,10 @@ #include "qemu/bswap.h" #ifdef _WIN32 #include "qga/service-win32.h" +#ifdef HAS_VSS_SDK +#include "qga/vss-win32-provider.h" +#include "qga/vss-win32-requester.h" +#endif #include #endif #ifdef __linux__ @@ -685,6 +689,25 @@ static gboolean channel_init(GAState *s, const gchar *method, const gchar *path) } #ifdef _WIN32 + +static gboolean vss_win32_init(void) +{ +#ifdef HAS_VSS_SDK +if (FAILED(vss_init())) { +g_critical("failed to initialize VSS"); +return false; +} +#endif +return true; +} + +static void vss_win32_deinit(void) +{ +#ifdef HAS_VSS_SDK +vss_deinit(); +#endif +} + DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data, LPVOID ctx) { @@ -727,8 +750,12 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[]) service->status.dwWaitHint = 0; SetServiceStatus(service->status_handle, &service->status); +if (!vss_win32_init()) { +goto out_bad; +} g_main_loop_run(ga_state->main_loop); - +vss_win32_deinit(); +out_bad: service->status.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(service->status_handle, &service->status); } @@ -1132,7 +1159,11 @@ int main(int argc, char **argv) { (char *)QGA_SERVICE_NAME, service_main }, { NULL, NULL } }; StartServiceCtrlDispatcher(service_table); } else { +if (!vss_win32_init()) { +goto out_bad; +} g_main_loop_run(ga_state->main_loop); +vss_win32_deinit(); } #endif
[Qemu-devel] [RFC PATCH v2 06/11] qemu-ga: Add Windows VSS requester to quisce applications and filesystems
This adds VSS requester functions for to qemu-ga. This provides facility to request VSS service in Windows guest to quisce applications and filesystems. This function is only supported in Windows 2003 or later. In older guests, this function does nothing. Signed-off-by: Tomoki Sekiyama --- qga/Makefile.objs |3 qga/vss-win32-requester.cpp | 393 +++ qga/vss-win32-requester.h | 31 +++ 3 files changed, 426 insertions(+), 1 deletion(-) create mode 100644 qga/vss-win32-requester.cpp create mode 100644 qga/vss-win32-requester.h diff --git a/qga/Makefile.objs b/qga/Makefile.objs index 8d93866..f17a380 100644 --- a/qga/Makefile.objs +++ b/qga/Makefile.objs @@ -6,6 +6,7 @@ qga-obj-y += qapi-generated/qga-qmp-marshal.o ifeq ($(CONFIG_QGA_VSS),y) QEMU_CFLAGS += -DHAS_VSS_SDK -qga-obj-y += vss-win32-provider/ +qga-obj-y += vss-win32-provider/ vss-win32-requester.o qga-prv-obj-y += vss-win32-provider/ +$(obj)/vss-win32-requester.o: QEMU_CXXFLAGS += -Wno-unknown-pragmas endif diff --git a/qga/vss-win32-requester.cpp b/qga/vss-win32-requester.cpp new file mode 100644 index 000..90ff026 --- /dev/null +++ b/qga/vss-win32-requester.cpp @@ -0,0 +1,393 @@ +/* + * QEMU Guest Agent win32 VSS Requester implementations + * + * Copyright Hitachi Data Systems Corp. 2013 + * + * Authors: + * Tomoki Sekiyama + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +extern "C" { +#include "guest-agent-core.h" +} +#include "vss-win32-requester.h" +#include "vss-win32-provider.h" +#include "vss-win32.h" +#include "inc/win2003/vswriter.h" +#include "inc/win2003/vsbackup.h" + +/* Functions in VSSAPI.DLL */ +typedef HRESULT (STDAPICALLTYPE* t_CreateVssBackupComponents)(OUT IVssBackupComponents **); +typedef void (APIENTRY* t_VssFreeSnapshotProperties)(IN VSS_SNAPSHOT_PROP*); + +static t_CreateVssBackupComponents _CreateVssBackupComponents = NULL; +static t_VssFreeSnapshotProperties _VssFreeSnapshotProperties = NULL; +static IVssBackupComponents *pVssbc = NULL; +static IVssAsync *pAsyncSnapshot = NULL; +static HMODULE hLib = NULL; +static HANDLE hEvent = INVALID_HANDLE_VALUE, hEvent2 = INVALID_HANDLE_VALUE; +static int cFrozenVols = 0; + +GCC_FMT_ATTR(1, 2) +static void errmsg(const char *fmt, ...) +{ +va_list ap; +va_start(ap, fmt); +char *msg = g_strdup_vprintf(fmt, ap); +va_end(ap); +MessageBox(NULL, msg, "Error in QEMU guest agent", MB_OK | MB_ICONWARNING); +g_free(msg); +} + +static void error_set_win32(Error **errp, DWORD err, +ErrorClass eclass, const char *text) +{ +char *msg = NULL, *nul = strchr(text, '('); +int len = nul ? nul - text : -1; + +/* print error message in native encoding */ +FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (char *)&msg, 0, NULL); +printf("%.*s. (Error: %lx) %s\n", len, text, err, msg); +LocalFree(msg); + +/* set error message in UTF-8 encoding */ +msg = g_win32_error_message(err); +error_set(errp, eclass, "%.*s. (Error: %lx) %s", len, text, err, msg); +g_free(msg); +} +#define error_setg_win32(errp, err, text) \ +error_set_win32(errp, err, ERROR_CLASS_GENERIC_ERROR, text) + +#define _chk(status, text, errp, err_label)\ +do {\ +HRESULT __hr = (status);\ +if (FAILED(__hr)) { \ +error_setg_win32(errp, __hr, text); \ +goto err_label; \ +} \ +} while(0) + +#define chk(status) _chk(status, "Failed to " #status, err, out) + + +HRESULT WaitForAsync(IVssAsync *pAsync) +{ +HRESULT ret, hr; + +do { +hr = pAsync->Wait(); +if (FAILED(hr)) { +ret = hr; +break; +} +hr = pAsync->QueryStatus(&ret, NULL); +if (FAILED(hr)) { +ret = hr; +break; +} +} while (ret == VSS_S_ASYNC_PENDING); + +return ret; +} + +HRESULT vss_init(void) +{ +HRESULT hr; + +hr = VSSCheckOSVersion(); +if (hr == S_FALSE) { +return hr; +} + +hr = CoInitialize(NULL); +if (FAILED(hr)) { +errmsg("CoInitialize failed [%lx]", hr); +goto out; +}; +hr = CoInitializeSecurity( +NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, +RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL); +if (FAILED(hr)) { +errmsg("CoInitializeSecurity failed [%lx]", hr); +goto out; +
[Qemu-devel] [RFC PATCH v2 08/11] qemu-ga: install Windows VSS provider on `qemu-ga -s install'
Register QGA VSS provider library into Windows when qemu-ga is installed as Windows service ('-s install' option). It is deregistered when the service is uninstalled ('-s uninstall' option). Signed-off-by: Tomoki Sekiyama --- qga/main.c |8 1 file changed, 8 insertions(+) diff --git a/qga/main.c b/qga/main.c index 92230e9..09fa291 100644 --- a/qga/main.c +++ b/qga/main.c @@ -1029,8 +1029,16 @@ int main(int argc, char **argv) case 's': service = optarg; if (strcmp(service, "install") == 0) { +#ifdef HAS_VSS_SDK +if (FAILED(COMRegister())) { +return EXIT_FAILURE; +} +#endif return ga_install_service(path, log_filepath); } else if (strcmp(service, "uninstall") == 0) { +#ifdef HAS_VSS_SDK +COMUnregister(); +#endif return ga_uninstall_service(); } else { printf("Unknown service command.\n");
[Qemu-devel] [RFC PATCH v2 05/11] qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze
Implements a basic stub of software VSS provider. Currently, this modules only provides a relay function of events between qemu-guest-agent and Windows VSS when VSS finished filesystem freeze and when qemu snapshot is done. In the future, this module could be extended to support the other VSS functions, such as query for snapshot volumes and recovery. Signed-off-by: Tomoki Sekiyama --- Makefile.objs |2 configure |5 qga/Makefile.objs |6 qga/vss-win32-provider.h| 26 ++ qga/vss-win32-provider/Makefile.objs| 21 + qga/vss-win32-provider/install.cpp | 494 +++ qga/vss-win32-provider/provider.cpp | 474 ++ qga/vss-win32-provider/qga-provider.def | 10 + qga/vss-win32-provider/qga-provider.idl | 20 + qga/vss-win32.h | 85 + 10 files changed, 1142 insertions(+), 1 deletion(-) create mode 100644 qga/vss-win32-provider.h create mode 100644 qga/vss-win32-provider/Makefile.objs create mode 100644 qga/vss-win32-provider/install.cpp create mode 100644 qga/vss-win32-provider/provider.cpp create mode 100644 qga/vss-win32-provider/qga-provider.def create mode 100644 qga/vss-win32-provider/qga-provider.idl create mode 100644 qga/vss-win32.h diff --git a/Makefile.objs b/Makefile.objs index e568c01..15264a1 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -96,6 +96,7 @@ common-obj-y += disas/ # FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed # by libqemuutil.a. These should be moved to a separate .json schema. qga-obj-y = qga/ qapi-types.o qapi-visit.o +qga-prv-obj-y = qga/ vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) @@ -107,6 +108,7 @@ nested-vars += \ stub-obj-y \ util-obj-y \ qga-obj-y \ + qga-prv-obj-y \ block-obj-y \ common-obj-y dummy := $(call unnest-vars) diff --git a/configure b/configure index 310bf9f..ebc4114 100755 --- a/configure +++ b/configure @@ -3360,9 +3360,12 @@ if test "$softmmu" = yes ; then virtfs=no fi fi - if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then + if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" -o "$mingw32" = "yes" ] ; then if [ "$guest_agent" = "yes" ]; then tools="qemu-ga\$(EXESUF) $tools" + if [ "$mingw32" = "yes" ]; then +tools="qga/vss-win32-provider/qga-provider.dll qga/vss-win32-provider/qga-provider.tlb $tools" + fi fi fi fi diff --git a/qga/Makefile.objs b/qga/Makefile.objs index b8d7cd0..8d93866 100644 --- a/qga/Makefile.objs +++ b/qga/Makefile.objs @@ -3,3 +3,9 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o qga-obj-y += qapi-generated/qga-qmp-marshal.o + +ifeq ($(CONFIG_QGA_VSS),y) +QEMU_CFLAGS += -DHAS_VSS_SDK +qga-obj-y += vss-win32-provider/ +qga-prv-obj-y += vss-win32-provider/ +endif diff --git a/qga/vss-win32-provider.h b/qga/vss-win32-provider.h new file mode 100644 index 000..a437e71 --- /dev/null +++ b/qga/vss-win32-provider.h @@ -0,0 +1,26 @@ +/* + * QEMU Guest Agent win32 VSS provider declarations + * + * Copyright Hitachi Data Systems Corp. 2013 + * + * Authors: + * Tomoki Sekiyama + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef VSS_WIN32_PROVIDER_H +#define VSS_WIN32_PROVIDER_H + +#include + +STDAPI VSSCheckOSVersion(void); + +STDAPI COMRegister(void); +STDAPI COMUnregister(void); + +STDAPI DllRegisterServer(void); +STDAPI DllUnregisterServer(void); + +#endif diff --git a/qga/vss-win32-provider/Makefile.objs b/qga/vss-win32-provider/Makefile.objs new file mode 100644 index 000..73ef752 --- /dev/null +++ b/qga/vss-win32-provider/Makefile.objs @@ -0,0 +1,21 @@ +# rules to build qga-provider.dll + +qga-obj-y += qga-provider.dll +qga-prv-obj-y += provider.o install.o + +obj-qga-prv-obj-y = $(addprefix $(obj)/, $(qga-prv-obj-y)) +$(obj-qga-prv-obj-y): QEMU_CXXFLAGS = $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls -fstack-protector-all, $(QEMU_CFLAGS)) -Wno-unknown-pragmas -Wno-delete-non-virtual-dtor + +$(obj)/qga-provider.dll: LDFLAGS = -shared -Wl,--add-stdcall-alias,--enable-stdcall-fixup -lole32 -loleaut32 -lshlwapi -luuid -static +$(obj)/qga-provider.dll: $(obj-qga-prv-obj-y) $(SRC_PATH)/$(obj)/qga-provider.def $(obj)/qga-provider.tlb + $(call quiet-command,$(CXX) -o $@ $(qga-prv-obj-y)
[Qemu-devel] [RFC PATCH v2 10/11] QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command
guest-fsfreeze-freeze command can take longer than 3 seconds when heavy disk I/O is running. To avoid unexpected timeout, this changes the timeout to 30 seconds. Signed-off-by: Tomoki Sekiyama --- QMP/qemu-ga-client |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/QMP/qemu-ga-client b/QMP/qemu-ga-client index 46676c3..1f7011a 100755 --- a/QMP/qemu-ga-client +++ b/QMP/qemu-ga-client @@ -267,7 +267,9 @@ def main(address, cmd, args): print('Hint: qemu is not running?') sys.exit(1) -if cmd != 'ping': +if cmd == 'fsfreeze' and args[0] == 'freeze': +client.sync(30) +elif cmd != 'ping': client.sync() globals()['_cmd_' + cmd](client, args)
[Qemu-devel] [RFC PATCH v2 11/11] QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly
qemu-ga in Windows might return error message with multibyte characters when the guest OS language is set to other than English. To display such messages correctly, this decodes the message based on locale settings. Signed-off-by: Tomoki Sekiyama --- QMP/qmp.py |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/QMP/qmp.py b/QMP/qmp.py index c551df1..ee21819 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -11,6 +11,7 @@ import json import errno import socket +import locale class QMPError(Exception): pass @@ -133,7 +134,8 @@ class QEMUMonitorProtocol: def command(self, cmd, **kwds): ret = self.cmd(cmd, kwds) if ret.has_key('error'): -raise Exception(ret['error']['desc']) +enc = locale.getpreferredencoding() +raise Exception(ret['error']['desc'].encode(enc)) return ret['return'] def pull_event(self, wait=False):
Re: [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS
Hi Baiqing, Thank you for your testing. >1 Extcuting the command "net start qemu-ga" failed,but the command >"qemu-qa.exe -m virtio-serial -p \\.\Global\org.qemu.guest_agent.1" is ok. `qemu-ga.exe -s install -p \\.\Global\org.qemu.guest_agent.1' may help to use virtio-serial ".1" in qemu-ga service. Otherwise ".0" is used by default. >2 executing the command "{"execute":"guest-fsfreeze-freeze"}" >failed,the output is: > {"execute":"guest-fsfreeze-freeze"} > {"error": {"class": "GenericError", "desc": "Failed to >pVssbc->SetContext. (Error: 8004231b) "}} > > Could you give me some advise to debug this problem ? I can provide more >information if need. Is there any logs corresponding to the error in Event Viewer? And this might be caused by unsupported VSS_VOLSNAP_ATTR_* flags in SetContext() called from qga_vss_fsfreeze_freeze() at qga/vss-win32-requester.cpp, but I couldn't find out flags not supported on Windows 7 from VSS references. Could you try whether removing some of these flags is effective to avoid the error in your environment? Thanks, Tomoki Sekiyama On 4/23/13 7:08 , "Libaiqing" wrote: >Hi, > I tried the patch v2,with the following config. > > Guest os : win7 32bit professional > Host os : fedora 17 > Command: > qemu-kvm -enable-kvm -name win7 -M pc-0.15 -m 1024 -smp 2 -boot c >-device virtio-serial -drive >file=/home/libaiqing/vss/win7.img,if=virtio,index=0,format=qcow2 - >-monitor stdio -vga qxl -vnc :1 -chardev > >socket,id=charchannel0,path=/var/lib/libvirt/qemu/wahaha1_requester,server >,nowait -device >virtserialport,chardev=charchannel0,id=channel0,name=org.qemu.guest_agent. >1 > > > Issue: >1 Extcuting the command "net start qemu-ga" failed,but the command >"qemu-qa.exe -m virtio-serial -p \\.\Global\org.qemu.guest_agent.1" is ok. >2 executing the command "{"execute":"guest-fsfreeze-freeze"}" >failed,the output is: > > [root@fedora121 ~]# socat stdio,ignoreeof >unix-connect:/var/lib/libvirt/qemu/wahaha1_requester >{'execute':'guest-info'} >{"return": {"version": "1.4.50", "supported_commands": [{"enabled": true, >"name": "guest-set-vcpus"}, {"enabled": true, "name": "guest-get-vcpus"}, >{"enabled": true, "name": "guest-network-get-interfaces"}, {"enabled": >true, "name": "guest-suspend-hybrid"}, {"enabled": true, "name": >"guest-suspend-ram"}, {"enabled": true, "name": "guest-suspend-disk"}, >{"enabled": true, "name": "guest-fstrim"}, {"enabled": true, "name": >"guest-fsfreeze-thaw"}, {"enabled": true, "name": >"guest-fsfreeze-freeze"}, {"enabled": true, "name": >"guest-fsfreeze-status"}, {"enabled": true, "name": "guest-file-flush"}, >{"enabled": true, "name": "guest-file-seek"}, {"enabled": true, "name": >"guest-file-write"}, {"enabled": true, "name": "guest-file-read"}, >{"enabled": true, "name": "guest-file-close"}, {"enabled": true, "name": >"guest-file-open"}, {"enabled": true, "name": "guest-shutdown"}, >{"enabled": true, "name": "guest-info"}, {"enabled": true, "name": >"guest-set-time"}, {"enabled": true, "name": "guest-get-time"}, >{"enabled": true, "name": "guest-ping"}, {"enabled": true, "name": >"guest-sync"}, {"enabled": true, "name": "guest-sync-delimited"}]}} >{"execute":"guest-fsfreeze-status"} >{"return": "thawed"} >{"execute":"guest-fsfreeze-freeze"} >{"error": {"class": "GenericError", "desc": "Failed to >pVssbc->SetContext. (Error: 8004231b) "}} > >Could you give me some advise to debug this problem ? I can provide more >information if need. > >Regards, >baiqing >-Original Message- >From: qemu-devel-bounces+libaiqing=huawei@nongnu.org >[mailto:qemu-devel-bounces+libaiqing=huawei@nongnu.org] On Behalf Of >Tomoki Sekiyama >Sent: Saturda
Re: [Qemu-devel] [PATCH v4 0/2] qga: Add guest-fsfreeze-freeze-list command
Any comments for this patch? -- Tomoki Sekiyama On 6/5/14 10:57 , "Tomoki Sekiyama" wrote: >Hi, > >This is v4 patch for qemu-ga to add functions to freeze specific file >systems >mounted in a guest. > >PATCH 1 adds a guest-fsfreeze-freeze-list command, which takes an >additional >argument to specify which filesystems to be frozen, derived from >guest-fsfreeze-freeze command. > >PATCH 2 adds a guest-get-fsinfo command to get a list of mounted file >systems in the guest with disk devices information to resolve backend disk >images for a management layer such as libvirt. > >Changes since v3: > - PATCH 1: make it a new command which accepts 'mountpoints' argument >in order to discover optional params are accepted or not. > - PATCH 2: code cleanups... > (v3: http://lists.gnu.org/archive/html/qemu-devel/2014-05/msg04571.html) > >--- >Tomoki Sekiyama (2): > qga: Add guest-fsfreeze-freeze-list command > qga: Add guest-get-fsinfo command > > > qga/commands-posix.c | 454 >++ > qga/commands-win32.c | 15 ++ > qga/qapi-schema.json | 96 +++ > 3 files changed, 563 insertions(+), 2 deletions(-) > >-- >Regards, >Tomoki Sekiyama
Re: [Qemu-devel] [PATCH v4 2/2] qga: Add guest-get-fsinfo command
Hi Eric, Thank you for the review. On 6/19/14 17:23 , "Eric Blake" wrote: >On 06/05/2014 08:57 AM, Tomoki Sekiyama wrote: >> Add command to get mounted filesystems information in the guest. >> The returned value contains a list of mountpoint paths and >> corresponding disks info such as disk bus type, drive address, >> and the disk controllers' PCI addresses, so that management layer >> such as libvirt can resolve the disk backends. >> >> For example, when `lsblk' result is: > > >> >> In Linux guest, the disk information is resolved from sysfs. So far, >> it only supports virtio-blk, virtio-scsi, IDE, SATA, SCSI disks on x86 >> hosts, and "disk" parameter may be empty for unsupported disk types. >> >> Signed-off-by: Tomoki Sekiyama >> --- >> qga/commands-posix.c | 422 >>++ >> qga/commands-win32.c |6 + >> qga/qapi-schema.json | 79 + >> 3 files changed, 506 insertions(+), 1 deletion(-) >> > >> +static int dev_major_minor(const char *devpath, >> + unsigned int *devmajor, unsigned int >>*devminor) >> +{ >> +struct stat st; >> + >> +*devmajor = 0; >> +*devminor = 0; >> + >> +if (stat(devpath, &st) < 0) { >> +slog("failed to stat device file '%s': %s", devpath, >>strerror(errno)); >> +return -1; >> +} >> +if (S_ISDIR(st.st_mode)) { >> +/* It is bind mount */ >> +return -2; >> +} >> +if (S_ISBLK(st.st_mode)) { >> +*devmajor = major(st.st_rdev); >> +*devminor = minor(st.st_rdev); > >major() and minor() are not POSIX functions. While they work on Linux, >and appear to have BSD origins, I still wonder if you need to be more >careful on guarding their use. This function is guarded by '#if defined(__linux__)' (and also '#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)' ), so I believe it is ok here. >> + >> +static void decode_mntname(char *name, int len) >> +{ >> +int i, j = 0; >> +for (i = 0; i <= len; i++) { >> +if (name[i] != '\\') { >> +name[j++] = name[i]; >> +} else if (name[i+1] == '\\') { >> +name[j++] = '\\'; >> +i++; >> +} else if (name[i+1] == '0' && name[i+2] == '4' && name[i+3] >>== '0') { > >Spaces around binary '+' OK, I will fix these, and also other binary operators. >> +name[j++] = ' '; >> +i += 3; >> +} else if (name[i+1] == '0' && name[i+2] == '1' && name[i+3] >>== '1') { >> +name[j++] = '\t'; >> +i += 3; >> +} else if (name[i+1] == '0' && name[i+2] == '1' && name[i+3] >>== '2') { >> +name[j++] = '\n'; >> +i += 3; >> +} else if (name[i+1] == '1' && name[i+2] == '3' && name[i+3] >>== '4') { >> +name[j++] = '\\'; >> +i += 3; >> +} else { > >This loop looks a bit hard-coded, in that it only recognizes certain >escapes. Wouldn't it be more generic to handle ALL instances of \ >followed by three octal digits, even if mount names tend not to encode >that many characters as an escape? I will replace this with more generic that covers every three octal digits (\000 - \377). Mount names only escape above characters, but anyway it is harmless to make it more generic. >> +name[j++] = name[i]; >> +} >> +} >> +} >> + >> +static void build_fs_mount_list(FsMountList *mounts, Error **errp) >> +{ >> +FsMount *mount; >> +char const *mountinfo = "/proc/self/mountinfo"; > >The file /proc/self/mountinfo is Linux-specific, but you are in the file >commands-posix.c. Is this function properly guarded to not cause >compilation issues on BSD? Again, this is inside '#if defined(__linux__)', so it won't be compiled on BSD. >> +FILE *fp; >> +char *line = NULL; >> +size_t n; >> +char check; >> +unsigned int devmajor, devminor; >> +int ret, dir_s, dir_e, type_s, type_e, dev_s, dev_e; >> + >> +fp = fopen(mountinfo, "r"); >> +if (!
Re: [Qemu-devel] [PATCH v4 2/2] qga: Add guest-get-fsinfo command
On 6/20/14 11:21 , "Eric Blake" wrote: >On 06/19/2014 06:34 PM, Tomoki Sekiyama wrote: > >>>> +} >>>> +if (S_ISBLK(st.st_mode)) { >>>> +*devmajor = major(st.st_rdev); >>>> +*devminor = minor(st.st_rdev); >>> >>> major() and minor() are not POSIX functions. While they work on Linux, >>> and appear to have BSD origins, I still wonder if you need to be more >>> careful on guarding their use. >> >> This function is guarded by '#if defined(__linux__)' (and also >> '#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)' ), >> so I believe it is ok here. > >I take it the function gracefully fails on non-Linux. But that's not >very nice to management functions - they learn that the function exists, >but have to call it to see if it actually works. It might be nicer to >conditionally expose the command only if it will work, so that querying >the list of commands makes it obvious whether the agent supports subset >freezing. I think hiding unsupported commands from 'guest-info' is reasonable. Currently the list is auto-generated from qapi-schema.json and all commands are listed even though some of them just returns QERR_ UNSUPPORTED on some platforms(like guest-fstrim and guest-network- get-interfaces etc. on non-Linux platform). We may need a new mechanism to unregister them from the list, or to mark them "unsupported", or to extend the generator so that we can omit them from the list on unsupported platforms. (And that should be done in another patch series.) >>>> +while (getline(&line, &n, fp) != -1) { >>>> +ret = sscanf(line, >>>> + "%*u %*u %u:%u %*s %n%*s%n %*s %*s %*s %n%*s%n >>>> %n%*s%n%c", >>>> + &devmajor, &devminor, &dir_s, &dir_e, &type_s, >>>> &type_e, >>> >>> I'm not a huge fan of sscanf("%u") - it has undefined behavior on >>> integer overflow. But the alternative of avoiding sscanf and >>> open-coding your parser is so much bulkier, that I tend to look the >>> other way. >> >> Hmm, '%*u' can be simply replaced by '%*s' then. >> For '%u:%u', maybe we can catch this part with '%s' or '%n%*s%n' >> and convert them into integers later by strtoul(). >> Does it sound good to you? > >As I said, the cost of properly parsing a row of integers explodes into >so much more code that I'm just fine looking the other way if you want >to use sscanf for compactness - after all, this is a kernel file we're >supposed to be reading, and if that interface has been corrupted to give >us bogus data that doesn't parse correctly, then we're probably already >hurting in other ways. Right... then I'm going to keep sscanf here then. Thanks, Tomoki Sekiyama
[Qemu-devel] [PATCH v5 0/3] qga: Add guest-fsfreeze-freeze-list command
Hi, This is v5 patch for qemu-ga to add functions to freeze specific file systems mounted in a guest. Changes since v4: - PATCH 2: fix coding styles (spaces around operators) make decode_mntname() more generic rename functions to avoid leading '__' improve compatibility with older Linux - PATCH 3 (new in v5): disable unsupported commands by default (v4: http://lists.gnu.org/archive/html/qemu-devel/2014-06/msg01357.html) --- Tomoki Sekiyama (3): qga: Add guest-fsfreeze-freeze-list command qga: Add guest-get-fsinfo command qga: Disable unsupported commands by default qga/commands-posix.c | 508 qga/commands-win32.c | 47 qga/guest-agent-core.h |1 qga/main.c |1 qga/qapi-schema.json | 96 + 5 files changed, 650 insertions(+), 3 deletions(-) -- Regards, Tomoki Sekiyama
[Qemu-devel] [PATCH v5 1/3] qga: Add guest-fsfreeze-freeze-list command
If an array of mount point paths is specified as 'mountpoints' argument of guest-fsfreeze-freeze-list, qemu-ga will only freeze the file systems mounted on specified paths in Linux guests. Otherwise, it works as the same way as guest-fsfreeze-freeze. This would be useful when the host wants to create partial disk snapshots. Signed-off-by: Tomoki Sekiyama Reviewed-by: Eric Blake --- qga/commands-posix.c | 32 +++- qga/commands-win32.c |9 + qga/qapi-schema.json | 17 + 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 34ddba0..212988f 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -710,13 +710,21 @@ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) return GUEST_FSFREEZE_STATUS_THAWED; } +int64_t qmp_guest_fsfreeze_freeze(Error **errp) +{ +return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); +} + /* * Walk list of mounted file systems in the guest, and freeze the ones which * are real local file systems. */ -int64_t qmp_guest_fsfreeze_freeze(Error **errp) +int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, + strList *mountpoints, + Error **errp) { int ret = 0, i = 0; +strList *list; FsMountList mounts; struct FsMount *mount; Error *local_err = NULL; @@ -741,6 +749,19 @@ int64_t qmp_guest_fsfreeze_freeze(Error **errp) ga_set_frozen(ga_state); QTAILQ_FOREACH_REVERSE(mount, &mounts, FsMountList, next) { +/* To issue fsfreeze in the reverse order of mounts, check if the + * mount is listed in the list here */ +if (has_mountpoints) { +for (list = mountpoints; list; list = list->next) { +if (strcmp(list->value, mount->dirname) == 0) { +break; +} +} +if (!list) { +continue; +} +} + fd = qemu_open(mount->dirname, O_RDONLY); if (fd == -1) { error_setg_errno(errp, errno, "failed to open %s", mount->dirname); @@ -1474,6 +1495,15 @@ int64_t qmp_guest_fsfreeze_freeze(Error **errp) return 0; } +int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, + strList *mountpoints, + Error **errp) +{ +error_set(errp, QERR_UNSUPPORTED); + +return 0; +} + int64_t qmp_guest_fsfreeze_thaw(Error **errp) { error_set(errp, QERR_UNSUPPORTED); diff --git a/qga/commands-win32.c b/qga/commands-win32.c index e769396..94877e9 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -206,6 +206,15 @@ error: return 0; } +int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, + strList *mountpoints, + Error **errp) +{ +error_set(errp, QERR_UNSUPPORTED); + +return 0; +} + /* * Thaw local file systems using Volume Shadow-copy Service. */ diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index a8cdcb3..caa4612 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -387,6 +387,23 @@ 'returns': 'int' } ## +# @guest-fsfreeze-freeze-list: +# +# Sync and freeze specified guest filesystems +# +# @mountpoints: #optional an array of mountpoints of filesystems to be frozen. +# If omitted, every mounted filesystem is frozen. +# +# Returns: Number of file systems currently frozen. On error, all filesystems +# will be thawed. +# +# Since: 2.1 +## +{ 'command': 'guest-fsfreeze-freeze-list', + 'data':{ '*mountpoints': ['str'] }, + 'returns': 'int' } + +## # @guest-fsfreeze-thaw: # # Unfreeze all frozen guest filesystems
[Qemu-devel] [PATCH v5 2/3] qga: Add guest-get-fsinfo command
Add command to get mounted filesystems information in the guest. The returned value contains a list of mountpoint paths and corresponding disks info such as disk bus type, drive address, and the disk controllers' PCI addresses, so that management layer such as libvirt can resolve the disk backends. For example, when `lsblk' result is: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdb 8:16 01G 0 disk `-sdb1 8:17 0 1024M 0 part `-vg0-lv0253:10 1.4G 0 lvm /mnt/test sdc 8:32 01G 0 disk `-sdc1 8:33 0 512M 0 part `-vg0-lv0253:10 1.4G 0 lvm /mnt/test vda252:00 25G 0 disk `-vda1 252:10 25G 0 part / where sdb is a SCSI disk with PCI controller :00:0a.0 and ID=1, sdc is an IDE disk with PCI controller :00:01.1, and vda is a virtio-blk disk with PCI device :00:06.0, guest-get-fsinfo command will return the following result: {"return": [{"name":"dm-1", "mountpoint":"/mnt/test", "disk":[ {"bus-type":"scsi","bus":0,"unit":1,"target":0, "pci-controller":{"bus":0,"slot":10,"domain":0,"function":0}}, {"bus-type":"ide","bus":0,"unit":0,"target":0, "pci-controller":{"bus":0,"slot":1,"domain":0,"function":1}}], "type":"xfs"}, {"name":"vda1", "mountpoint":"/", "disk":[ {"bus-type":"virtio","bus":0,"unit":0,"target":0, "pci-controller":{"bus":0,"slot":6,"domain":0,"function":0}}], "type":"ext4"}]} In Linux guest, the disk information is resolved from sysfs. So far, it only supports virtio-blk, virtio-scsi, IDE, SATA, SCSI disks on x86 hosts, and "disk" parameter may be empty for unsupported disk types. Signed-off-by: Tomoki Sekiyama --- qga/commands-posix.c | 438 ++ qga/commands-win32.c |6 + qga/qapi-schema.json | 79 + 3 files changed, 522 insertions(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 212988f..9198b9f 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -575,6 +576,7 @@ static void guest_file_init(void) typedef struct FsMount { char *dirname; char *devtype; +unsigned int devmajor, devminor; QTAILQ_ENTRY(FsMount) next; } FsMount; @@ -596,15 +598,40 @@ static void free_fs_mount_list(FsMountList *mounts) } } +static int dev_major_minor(const char *devpath, + unsigned int *devmajor, unsigned int *devminor) +{ +struct stat st; + +*devmajor = 0; +*devminor = 0; + +if (stat(devpath, &st) < 0) { +slog("failed to stat device file '%s': %s", devpath, strerror(errno)); +return -1; +} +if (S_ISDIR(st.st_mode)) { +/* It is bind mount */ +return -2; +} +if (S_ISBLK(st.st_mode)) { +*devmajor = major(st.st_rdev); +*devminor = minor(st.st_rdev); +return 0; +} +return -1; +} + /* * Walk the mount table and build a list of local file systems */ -static void build_fs_mount_list(FsMountList *mounts, Error **errp) +static void build_fs_mount_list_from_mtab(FsMountList *mounts, Error **errp) { struct mntent *ment; FsMount *mount; char const *mtab = "/proc/self/mounts"; FILE *fp; +unsigned int devmajor, devminor; fp = setmntent(mtab, "r"); if (!fp) { @@ -624,20 +651,423 @@ static void build_fs_mount_list(FsMountList *mounts, Error **errp) (strcmp(ment->mnt_type, "cifs") == 0)) { continue; } +if (dev_major_minor(ment->mnt_fsname, &devmajor, &devminor) == -2) { +/* Skip bind mounts */ +continue; +} mount = g_malloc0(sizeof(FsMount)); mount->dirname = g_strdup(ment->mnt_dir); mount->devtype = g_strdup(ment->mnt_type); +mount->devmajor = devmajor; +mount->devminor = devminor; QTAILQ_INSERT_TAIL(mounts, mount, next); } endmntent(fp); } + +static void decode_mntname(char *name, int len) +{ +int i, j = 0; +for (i = 0; i <= len; i++) { +if (name[i] != '\\') { +name[j++] = name[i]; +} else if (name[i + 1] == '
Re: [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL
; +hEventThaw = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_THAW); >> +if (hEventThaw == INVALID_HANDLE_VALUE) { >> +CloseHandle(hEventFrozen); >> +return E_FAIL; >> +} >> + >> +/* Send event to qemu-ga to notify filesystem is frozen */ >> +SetEvent(hEventFrozen); >> + >> +/* Wait until the snapshot is taken by the host. */ >> +if (WaitForSingleObject(hEventThaw, VSS_TIMEOUT_MSEC) != >>WAIT_OBJECT_0) { >> +hr = E_ABORT; >> +} > >I see that we approximate both the 10 second fsfreeze and 60s writer >freeze timeouts using local event timeouts, but I think there's a chance >for some races there. > >We could maybe lower the timeouts a bit to be safe, but i don't really >like the sound of that...would be nice if there was some way to > >a) ideally, guarantee the guest-fsfreeze-thaw will return an error if > the fsfreeze timed out before it was called, or >b) guarantee at least that it will return an error if the vss writer > freeze timed out. When the writer freeze timeout is exceeded, VSS service will automatically abort the snapshot sequence and report an error (E_VSS_WRITES_TIMEOUT) to the requester, even if the provider is still sleeping. This behavior guarantees the following guest-fsfreeze-thaw return the following error: {"error": {"class": "GenericError", "desc": "couldn't hold writes: fsfreeze is limited up to 10 seconds: (error:80042314)"}} VSS_TIMEOUT_MSEC here is just not to freeze the provider forever if the guest-fsfreeze-thaw is not issued. However, if the provider returns the E_ABORT by timeout, VSS reports VSS_E_UNEXPECTED_PROVIDER_ERROR, and it results in different error message returned to the host. (Possibly your comment below about overwritten error intended to address this issue?) To ensure we get the E_VSS_WRITES_TIMEOUT on VSS timeout, the timeout could be longer (e.g., 120 seconds). >> diff --git a/qga/vss-win32/requester.cpp b/qga/vss-win32/requester.cpp >> new file mode 100644 >> index 000..1b91ca5 >> --- /dev/null >> +++ b/qga/vss-win32/requester.cpp >> +/* Need to call QueryStatus several times to make VSS provider >>progress */ >> +for (i = 0; i < VSS_TIMEOUT_FREEZE_MSEC/VSS_TIMEOUT_EVENT_MSEC; >>i++) { >> +HRESULT hr2 = vss_ctx.pAsyncSnapshot->QueryStatus(&hr, NULL); >> +if (FAILED(hr2)) { >> +err_set(errset, hr, "failed to do snapshot set"); >> +goto out; >> +} >> +if (hr != VSS_S_ASYNC_PENDING) { >> +err_set(errset, E_FAIL, >> +"DoSnapshotSet exited without Frozen event"); >> +goto out; >> +} >> +wait_status = WaitForSingleObject(vss_ctx.hEventFrozen, >> + VSS_TIMEOUT_EVENT_MSEC); >> +if (wait_status != WAIT_TIMEOUT) { >> +break; >> + } >> +} >> +if (wait_status != WAIT_OBJECT_0) { >> +err_set(errset, E_FAIL, >> +"Couldn't receive Frozen event from VSS provider"); >> +goto out; >> +} > >One small issue I noticed was that this error will get overwritten >with the VSS writer timeout error if we wait longer than 60s before >calling guest-fsfreeze-thaw. It might give some users false assurances >about what aspects of their snapshot may be volatile so it's >probably worth addressing. This is an error returned against guest-fsfreeze-freeze, when the writers or filesystems take more than 60s to quiesce. (CQGAVssProvider::CommitSnapshots that issues FrozenEvent is called after this quiescing succeeded.) The VSS sequence is aborted at "out:". If this happens, as the system remains thawed state, the following guest-fsfreeze-thaw will just return 0. >> diff --git a/qga/vss-win32/requester.h b/qga/vss-win32/requester.h >> new file mode 100644 >> index 000..ccd197c >> --- /dev/null >> +++ b/qga/vss-win32/requester.h >> +typedef void (*QGAVSSReuqesterFunc)(int *, ErrorSet *); > >Should be QGAVSSRequesterFunc Oops, thank you for catching this. Will fix these typo in the next version. Thanks, -- Tomoki Sekiyama
Re: [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL
On 7/30/13 15:35 , "Michael Roth" wrote: >>>One small issue I noticed was that this error will get overwritten >>>with the VSS writer timeout error if we wait longer than 60s before >>>calling guest-fsfreeze-thaw. It might give some users false assurances >>>about what aspects of their snapshot may be volatile so it's >>>probably worth addressing. >>This is an error returned against guest-fsfreeze-freeze, when the >>writers or filesystems take more than 60s to quiesce. >>(CQGAVssProvider::CommitSnapshots that issues FrozenEvent is >>called after this quiescing succeeded.) The VSS sequence is aborted >>at "out:". If this happens, as the system remains thawed state, the >>following guest-fsfreeze-thaw will just return 0. > >This is the example I'm referring to: > >{'execute':'guest-fsfreeze-freeze'} >{"return": 2} >/* wait 10+ seconds */ >{'execute':'guest-fsfreeze-thaw'} >{"error": {"class": "GenericError", "desc": "couldn't hold writes: >fsfreeze is limited up to 10 seconds: (error: 80042314)"}} >{'execute':'guest-fsfreeze-freeze'} >{"return": 2} >/* wait 60+ seconds */ >{'execute':'guest-fsfreeze-thaw'} >{"error": {"class": "GenericError", "desc": "failed to do snapshot set: >(error: 8004230f)"}} > >It this seems to be because CommitSnapshot returns in the latter instance >due >to VSS_TIMEOUT_MSEC wait and it's E_ABORT error message overwrites the >VSS_E_HOLD_WRITES_TIMEOUT from earlier. Perhaps we could just have >CommitSnapshot return VSS_E_HOLD_WRITES_TIMEOUT if it doesn't get the thaw >event in time? I think that error message is much more informative for >users. Agreed. How about modifying the provider to return S_OK instead of E_ABORT when it exceeds VSS_TIMEOUT_MSEC? As VSS_TIMEOUT_MSEC is larger than 10 seconds fsfreeze timeout, CommitSnapshot will return VSS_E_HOLD_WRITES_TIMEOUT on provider's timeout, and give "fsfreeze is limited up to 10 seconds" message to users. The writers are also automatically thawed by 60 seconds timeout anyway, this wouldn't break anything. The waiting code in CQGAVssProvider::CommitSnapshots would be like this: ... /* Wait until the snapshot is taken by the host. */ wait = WaitForSingleObject(hEventThaw, VSS_TIMEOUT_MSEC); switch (wait) { case WAIT_TIMEOUT: /* * We return S_OK, but the qemu-ga will get E_VSS_HOLD_WRITES_TIMEOUT * because 10 seconds fsfreeze timeout is exceeded. (If we return some * error here, it results in VSS_E_UNEXPECTED_PROVIDER_ERROR that can * be caused by the other reasons.) */ case WAIT_OBJECT_0: hr = S_OK; break; default: hr = E_ABORT; } ... Thanks, Tomoki Sekiyama
Re: [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL
On 7/30/13 18:24 , "Michael Roth" wrote: >Quoting Tomoki Sekiyama (2013-07-30 15:54:05) >>On 7/30/13 15:35 , "Michael Roth" wrote: >>>>>One small issue I noticed was that this error will get overwritten >>>>>with the VSS writer timeout error if we wait longer than 60s before >>>>>calling guest-fsfreeze-thaw. It might give some users false assurances >>>>>about what aspects of their snapshot may be volatile so it's >>>>>probably worth addressing. >>>>This is an error returned against guest-fsfreeze-freeze, when the >>>>writers or filesystems take more than 60s to quiesce. >>>>(CQGAVssProvider::CommitSnapshots that issues FrozenEvent is >>>>called after this quiescing succeeded.) The VSS sequence is aborted >>>>at "out:". If this happens, as the system remains thawed state, the >>>>following guest-fsfreeze-thaw will just return 0. >>> >>>This is the example I'm referring to: >>> >>>{'execute':'guest-fsfreeze-freeze'} >>>{"return": 2} >>>/* wait 10+ seconds */ >>>{'execute':'guest-fsfreeze-thaw'} >>>{"error": {"class": "GenericError", "desc": "couldn't hold writes: >>>fsfreeze is limited up to 10 seconds: (error: 80042314)"}} >>>{'execute':'guest-fsfreeze-freeze'} >>>{"return": 2} >>>/* wait 60+ seconds */ >>>{'execute':'guest-fsfreeze-thaw'} >>>{"error": {"class": "GenericError", "desc": "failed to do snapshot set: >>>(error: 8004230f)"}} >>> >>>It this seems to be because CommitSnapshot returns in the latter >>>instance >>>due >>>to VSS_TIMEOUT_MSEC wait and it's E_ABORT error message overwrites the >>>VSS_E_HOLD_WRITES_TIMEOUT from earlier. Perhaps we could just have >>>CommitSnapshot return VSS_E_HOLD_WRITES_TIMEOUT if it doesn't get the >>>thaw >>>event in time? I think that error message is much more informative for >>>users. >>Agreed. >>How about modifying the provider to return S_OK instead of E_ABORT >>when it exceeds VSS_TIMEOUT_MSEC? >>As VSS_TIMEOUT_MSEC is larger than 10 seconds fsfreeze timeout, >>CommitSnapshot will return VSS_E_HOLD_WRITES_TIMEOUT on provider's >>timeout, >>and give "fsfreeze is limited up to 10 seconds" message to users. >>The writers are also automatically thawed by 60 seconds timeout anyway, >>this wouldn't break anything. > >Hmm, it seems like it would work, but I'm a bit worried about returning >S_OK and hoping VSS still produces an error. Probably really unlikely, but >I could imagine a really strange timing issue where the 60 second timeout >for whatever reason gets triggered before the 10 second one (maybe because >one vcpu is being starved for whatever reason, don't know enough about >windows timekeeping mechanisms to know how plausible this is, but I'd >rather not rely on it not happening). > >One way you could maybe do it would be maybe introducing a hEventTimeout >that CommitSnapshots will set if it times out. That way we can poll >it to see if the event is set when we get VSS_E_UNEXPECTED_PROVIDER_ERROR >in the requester. If it's set we know a timeout occurred on provider side, >and return the E_VSS_HOLD_WRITES_TIMEOUT error. OK, this sounds more reliable. I will take this way. Thanks, Tomoki Sekiyama
[Qemu-devel] [PATCH v9 06/10] error: Add error_set_win32 and error_setg_win32
These functions help maintaining homogeneous formatting of error messages with Windows error code and description (generated by g_win32_error_message()). Signed-off-by: Tomoki Sekiyama Reviewed-by: Michael Roth --- include/qapi/error.h | 13 + util/error.c | 35 +++ 2 files changed, 48 insertions(+) diff --git a/include/qapi/error.h b/include/qapi/error.h index ffd1cea..7d4c696 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -36,6 +36,15 @@ void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ */ void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5); +#ifdef _WIN32 +/** + * Set an indirect pointer to an error given a ErrorClass value and a + * printf-style human message, followed by a g_win32_error_message() string if + * @win32_err is not zero. + */ +void error_set_win32(Error **err, int win32_err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5); +#endif + /** * Same as error_set(), but sets a generic error */ @@ -43,6 +52,10 @@ void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) #define error_setg_errno(err, os_error, fmt, ...) \ error_set_errno(err, os_error, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) +#ifdef _WIN32 +#define error_setg_win32(err, win32_err, fmt, ...) \ +error_set_win32(err, win32_err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) +#endif /** * Helper for open() errors diff --git a/util/error.c b/util/error.c index 53b0435..ec0faa6 100644 --- a/util/error.c +++ b/util/error.c @@ -76,6 +76,41 @@ void error_setg_file_open(Error **errp, int os_errno, const char *filename) error_setg_errno(errp, os_errno, "Could not open '%s'", filename); } +#ifdef _WIN32 + +void error_set_win32(Error **errp, int win32_err, ErrorClass err_class, + const char *fmt, ...) +{ +Error *err; +char *msg1; +va_list ap; + +if (errp == NULL) { +return; +} +assert(*errp == NULL); + +err = g_malloc0(sizeof(*err)); + +va_start(ap, fmt); +msg1 = g_strdup_vprintf(fmt, ap); +if (win32_err != 0) { +char *msg2 = g_win32_error_message(win32_err); +err->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2, + (unsigned)win32_err); +g_free(msg2); +g_free(msg1); +} else { +err->msg = msg1; +} +va_end(ap); +err->err_class = err_class; + +*errp = err; +} + +#endif + Error *error_copy(const Error *err) { Error *err_new;
[Qemu-devel] [PATCH v9 01/10] configure: Support configuring C++ compiler
Add configuration for C++ compiler in configure and Makefiles. The C++ compiler is choosed as following: - ${CXX}, if it is specified. - ${cross_prefix}g++, if ${cross_prefix} is specified. - Otherwise, c++ is used. Currently, usage of C++ language is only for access to Windows VSS using COM+ services in qemu-guest-agent for Windows. Signed-off-by: Tomoki Sekiyama Reviewed-by: Laszlo Ersek Reviewed-by: Micael Roth --- configure | 13 + rules.mak |9 - 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/configure b/configure index f0761ea..94cff69 100755 --- a/configure +++ b/configure @@ -252,6 +252,8 @@ for opt do ;; --cc=*) CC="$optarg" ;; + --cxx=*) CXX="$optarg" + ;; --source-path=*) source_path="$optarg" ;; --cpu=*) cpu="$optarg" @@ -282,6 +284,12 @@ else cc="${CC-${cross_prefix}gcc}" fi +if test -z "${CXX}${cross_prefix}"; then + cxx="c++" +else + cxx="${CXX-${cross_prefix}g++}" +fi + ar="${AR-${cross_prefix}ar}" as="${AS-${cross_prefix}as}" cpp="${CPP-$cc -E}" @@ -622,6 +630,8 @@ for opt do ;; --host-cc=*) host_cc="$optarg" ;; + --cxx=*) + ;; --objcc=*) objcc="$optarg" ;; --make=*) make="$optarg" @@ -1023,6 +1033,7 @@ echo " --cross-prefix=PREFIXuse PREFIX for compile tools [$cross_prefix]" echo " --cc=CC use C compiler CC [$cc]" echo " --host-cc=CC use C compiler CC [$host_cc] for code run at" echo " build time" +echo " --cxx=CXXuse C++ compiler CXX [$cxx]" echo " --objcc=OBJCCuse Objective-C compiler OBJCC [$objcc]" echo " --extra-cflags=CFLAGSappend extra C compiler flags QEMU_CFLAGS" echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS" @@ -3517,6 +3528,7 @@ fi echo "Source path $source_path" echo "C compiler$cc" echo "Host C compiler $host_cc" +echo "C++ compiler $cxx" echo "Objective-C compiler $objcc" echo "CFLAGS$CFLAGS" echo "QEMU_CFLAGS $QEMU_CFLAGS" @@ -4098,6 +4110,7 @@ echo "PYTHON=$python" >> $config_host_mak echo "CC=$cc" >> $config_host_mak echo "CC_I386=$cc_i386" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak +echo "CXX=$cxx" >> $config_host_mak echo "OBJCC=$objcc" >> $config_host_mak echo "AR=$ar" >> $config_host_mak echo "AS=$as" >> $config_host_mak diff --git a/rules.mak b/rules.mak index 4499745..abc2e84 100644 --- a/rules.mak +++ b/rules.mak @@ -8,9 +8,13 @@ MAKEFLAGS += -rR %.d: %.h: %.c: +%.cpp: %.m: %.mak: +# Flags for C++ compilation +QEMU_CXXFLAGS = -D__STDC_LIMIT_MACROS $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls, $(QEMU_CFLAGS)) + # Flags for dependency generation QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d @@ -50,6 +54,9 @@ endif %.o: %.asm $(call quiet-command,$(AS) $(ASFLAGS) -o $@ $<," AS $(TARGET_DIR)$@") +%.o: %.cpp + $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CXX $(TARGET_DIR)$@") + %.o: %.m $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@") @@ -70,7 +77,7 @@ quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1)) cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \ >/dev/null 2>&1 && echo OK), $2, $3) -VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.sh %.rc +VPATH_SUFFIXES = %.c %.h %.S %.cpp %.m %.mak %.texi %.sh %.rc set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) # find-in-path
[Qemu-devel] [PATCH v9 10/10] QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command
guest-fsfreeze-freeze command can take longer than 3 seconds when heavy disk I/O is running. To avoid unexpected timeout, this changes the timeout to 60 seconds (timeout of pre-commit phase of VSS). Signed-off-by: Tomoki Sekiyama Reviewed-by: Paolo Bonzini Reviewed-by: Laszlo Ersek Reviewed-by: Michael Roth --- QMP/qemu-ga-client |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/QMP/qemu-ga-client b/QMP/qemu-ga-client index 46676c3..b5f7e7c 100755 --- a/QMP/qemu-ga-client +++ b/QMP/qemu-ga-client @@ -267,7 +267,9 @@ def main(address, cmd, args): print('Hint: qemu is not running?') sys.exit(1) -if cmd != 'ping': +if cmd == 'fsfreeze' and args[0] == 'freeze': +client.sync(60) +elif cmd != 'ping': client.sync() globals()['_cmd_' + cmd](client, args)
[Qemu-devel] [PATCH v9 05/10] qemu-ga: Add configure options to specify path to Windows/VSS SDK
To enable VSS support in qemu-ga for Windows, header files included in VSS SDK are required. The VSS support is enabled by the configure option like below: ./configure --with-vss-sdk="/path/to/VSS SDK" If the path is omitted, it tries to search the headers from default paths and VSS support is enabled only if the SDK is found. VSS support is disabled if --without-vss-sdk or --with-vss-sdk=no is specified. VSS SDK is available from: http://www.microsoft.com/en-us/download/details.aspx?id=23490 To cross-compile using mingw, you need to setup the SDK on Windows environments to extract headers. You can also extract the SDK headers on POSIX environments using scripts/extract-vss-headers and msitools. In addition, --with-win-sdk="/path/to/Windows SDK" option is also added to specify path to Windows SDK, which may be used for native-compile of .tlb file of qemu-ga VSS provider. However, this is usually unnecessary because pre-compiled .tlb file is included. Signed-off-by: Tomoki Sekiyama Reviewed-by: Laszlo Ersek Reviewed-by: Michael Roth --- .gitignore |1 + Makefile |1 + configure | 78 3 files changed, 80 insertions(+) diff --git a/.gitignore b/.gitignore index 0fe114d..02d15f0 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ fsdev/virtfs-proxy-helper.pod *.la *.pc .libs +.sdk *.swp *.orig .pc diff --git a/Makefile b/Makefile index 29f1043..0caf4fe 100644 --- a/Makefile +++ b/Makefile @@ -273,6 +273,7 @@ distclean: clean for d in $(TARGET_DIRS); do \ rm -rf $$d || exit 1 ; \ done + rm -Rf .sdk if test -f pixman/config.log; then make -C pixman distclean; fi if test -f dtc/version_gen.h; then make $(DTC_MAKE_ARGS) clean; fi diff --git a/configure b/configure index 94cff69..929c85f 100755 --- a/configure +++ b/configure @@ -232,6 +232,9 @@ usb_redir="" glx="" zlib="yes" guest_agent="yes" +guest_agent_with_vss="no" +vss_win32_sdk="" +win_sdk="no" want_tools="yes" libiscsi="" coroutine="" @@ -923,6 +926,18 @@ for opt do ;; --disable-guest-agent) guest_agent="no" ;; + --with-vss-sdk) vss_win32_sdk="" + ;; + --with-vss-sdk=*) vss_win32_sdk="$optarg" + ;; + --without-vss-sdk) vss_win32_sdk="no" + ;; + --with-win-sdk) win_sdk="" + ;; + --with-win-sdk=*) win_sdk="$optarg" + ;; + --without-win-sdk) win_sdk="no" + ;; --enable-tools) want_tools="yes" ;; --disable-tools) want_tools="no" @@ -1159,6 +1174,8 @@ echo " --disable-usb-redir disable usb network redirection support" echo " --enable-usb-redir enable usb network redirection support" echo " --disable-guest-agentdisable building of the QEMU Guest Agent" echo " --enable-guest-agent enable building of the QEMU Guest Agent" +echo " --with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent" +echo " --with-win-sdk=SDK-path path to Windows Platform SDK (to build VSS .tlb)" echo " --disable-seccompdisable seccomp support" echo " --enable-seccomp enables seccomp support" echo " --with-coroutine=BACKEND coroutine backend. Supported options:" @@ -3093,6 +3110,61 @@ if test "$usb_redir" != "no" ; then fi ## +# check if we have VSS SDK headers for win + +if test "$mingw32" = "yes" -a "$guest_agent" = "yes" -a "$vss_win32_sdk" != "no" ; then + case "$vss_win32_sdk" in +"") vss_win32_include="-I$source_path" ;; +*\ *) # The SDK is installed in "Program Files" by default, but we cannot + # handle path with spaces. So we symlink the headers into ".sdk/vss". + vss_win32_include="-I$source_path/.sdk/vss" + symlink "$vss_win32_sdk/inc" "$source_path/.sdk/vss/inc" + ;; +*)vss_win32_include="-I$vss_win32_sdk" + esac + cat > $TMPC << EOF +#define __MIDL_user_allocate_free_DEFINED__ +#include +int main(void) { return VSS_CTX_BACKUP; } +EOF + if compile_prog "$vss_win32_include" "" ; then +guest_agent_with_vss="yes" +QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include" +libs_qga="-lole32 -loleaut32 -lshlwapi -luuid -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga" + else +if test "$vss_win32_sdk" != "" ; then + echo "ERROR: Please download and install Microsoft VSS SDK:" + echo "ERROR: http://www.microsoft.com/en-us/download/details.aspx?id=23490"; + ec
[Qemu-devel] [PATCH v9 00/10] qemu-ga: fsfreeze on Windows using VSS
Hi, This is v9 of patch series to add fsfreeze for Windows qemu-guest-agent. changes from v8: - Add hEventTimeout to improve timeout error message (patch 07, see below) - Build qga-vss.tlb if configure'd --with-win-sdk (patch 05, 07) - Use "qga-vss-dll-obj-$(CONFIG_QGA_VSS)" in Makefile.objs (patch 07) - Fix typo in QGAVSSRequesterFunc (patch 07, 08) v8: http://lists.gnu.org/archive/html/qemu-devel/2013-07/msg04070.html * Improvement of timeout error message According to discussion in v8(*), the timeout error message is more informative and consistent in this version when guest-fsfreeze-thaw is issued after 60 seconds since guest-fsfreeze-freeze. (*) http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg05924.html For example: {'execute':'guest-fsfreeze-freeze'} {"return": 2} /* wait 10+ seconds */ {'execute':'guest-fsfreeze-thaw'} {"error": {"class": "GenericError", "desc": "couldn't hold writes: fsfreeze is limited up to 10 seconds: (error: 80042314)"}} {'execute':'guest-fsfreeze-freeze'} {"return": 2} /* wait 60+ seconds */ {'execute':'guest-fsfreeze-thaw'} {"error": {"class": "GenericError", "desc": "couldn't hold writes: fsfreeze is limited up to 10 seconds: (error: 8004230f)"}} /* In v8, "desc": "failed to do snapshot set" due to provider timeout */ * Description In Windows, VSS (Volume Shadow Copy Service) provides a facility to quiesce filesystems and applications before disk snapshots are taken. This patch series implements "fsfreeze" command of qemu-ga using VSS. * How to build & run qemu-ga with VSS support - Download Microsoft VSS SDK from: http://www.microsoft.com/en-us/download/details.aspx?id=23490 - Setup the SDK scripts/extract-vsssdk-headers setup.exe (on POSIX-systems) - Specify installed SDK directory to configure option as: ./configure -with-vss-sdk="path/to/VSS SDK" --cross-prefix=i686-w64-mingw32- - make qemu-ga.exe qga/vss-win32/qga-vss.{dll,tlb} - Install qemu-ga.exe, qga/vss-win32/qga-vss.{dll,tlb}, and the other required mingw libraries into the same directory in guests - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests Any feedback are appreciated. --- Tomoki Sekiyama (10): configure: Support configuring C++ compiler Add c++ keywords to QAPI helper script checkpatch.pl: Check .cpp files Add a script to extract VSS SDK headers on POSIX system qemu-ga: Add configure options to specify path to Windows/VSS SDK error: Add error_set_win32 and error_setg_win32 qemu-ga: Add Windows VSS provider and requester as DLL qemu-ga: Call Windows VSS requester in fsfreeze command handler qemu-ga: Install Windows VSS provider on `qemu-ga -s install' QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command .gitignore |1 Makefile |3 Makefile.objs |2 QMP/qemu-ga-client |4 configure | 96 +++ hmp.c |2 hw/pci/pci.c |2 include/qapi/error.h | 13 + qga/Makefile.objs |3 qga/commands-win32.c | 82 ++ qga/main.c | 10 + qga/vss-win32.c| 166 + qga/vss-win32.h| 27 ++ qga/vss-win32/Makefile.objs| 23 ++ qga/vss-win32/install.cpp | 458 +++ qga/vss-win32/provider.cpp | 523 qga/vss-win32/qga-vss.def | 13 + qga/vss-win32/qga-vss.idl | 20 ++ qga/vss-win32/qga-vss.tlb | Bin qga/vss-win32/requester.cpp| 507 +++ qga/vss-win32/requester.h | 42 +++ qga/vss-win32/vss-common.h | 129 ++ rules.mak |9 + scripts/checkpatch.pl | 34 ++- scripts/extract-vsssdk-headers | 35 +++ scripts/qapi.py| 12 + util/error.c | 35 +++ 27 files changed, 2229 insertions(+), 22 deletions(-) create mode 100644 qga/vss-win32.c create mode 100644 qga/vss-win32.h create mode 100644 qga/vss-win32/Makefile.objs create mode 100644 qga/vss-win32/install.cpp create mode 100644 qga/vss-win32/provider.cpp create mode 100644 qga/vss-win32/qga-vss.def create mode 100644 qga/vss-win32/qga-vss.idl create mode 100644 qga/vss-win32/qga-vss.tlb create mode 100644 qga/vss-win32/requester.cpp create mode 100644 qga/vss-win32/requester.h create mode 100644 qga/vss-win32/vss-common.h create mode 100755 scripts/extract-vsssdk-headers
[Qemu-devel] [PATCH v9 02/10] Add c++ keywords to QAPI helper script
Add c++ keywords to avoid errors in compiling with c++ compiler. This also renames class member of PciDeviceInfo to q_class. Signed-off-by: Tomoki Sekiyama Reviewed-by: Laszlo Ersek Reviewed-by: Michael Roth --- hmp.c |2 +- hw/pci/pci.c|2 +- scripts/qapi.py | 12 +++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/hmp.c b/hmp.c index c45514b..79931d2 100644 --- a/hmp.c +++ b/hmp.c @@ -528,7 +528,7 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) if (dev->class_info.has_desc) { monitor_printf(mon, "%s", dev->class_info.desc); } else { -monitor_printf(mon, "Class %04" PRId64, dev->class_info.class); +monitor_printf(mon, "Class %04" PRId64, dev->class_info.q_class); } monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n", diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 4c004f5..25d08eb 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1466,7 +1466,7 @@ static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus, info->function = PCI_FUNC(dev->devfn); class = pci_get_word(dev->config + PCI_CLASS_DEVICE); -info->class_info.class = class; +info->class_info.q_class = class; desc = get_class_desc(class); if (desc->desc) { info->class_info.has_desc = true; diff --git a/scripts/qapi.py b/scripts/qapi.py index 0ebea94..d0a92df 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -236,9 +236,19 @@ def c_var(name, protect=True): # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html # excluding _.* gcc_words = set(['asm', 'typeof']) +# C++ ISO/IEC 14882:2003 2.11 +cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete', + 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable', + 'namespace', 'new', 'operator', 'private', 'protected', + 'public', 'reinterpret_cast', 'static_cast', 'template', + 'this', 'throw', 'true', 'try', 'typeid', 'typename', + 'using', 'virtual', 'wchar_t', + # alternative representations + 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not', + 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq']) # namespace pollution: polluted_words = set(['unix']) -if protect and (name in c89_words | c99_words | c11_words | gcc_words | polluted_words): +if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words): return "q_" + name return name.replace('-', '_').lstrip("*")
[Qemu-devel] [PATCH v9 04/10] Add a script to extract VSS SDK headers on POSIX system
VSS SDK(*) setup.exe is only runnable on Windows. This adds a script to extract VSS SDK headers on POSIX-systems using msitools. * http://www.microsoft.com/en-us/download/details.aspx?id=23490 From: Paolo Bonzini Signed-off-by: Paolo Bonzini Signed-off-by: Tomoki Sekiyama Reviewed-by: Laszlo Ersek Reviewed-by: Michael Roth --- scripts/extract-vsssdk-headers | 35 +++ 1 file changed, 35 insertions(+) create mode 100755 scripts/extract-vsssdk-headers diff --git a/scripts/extract-vsssdk-headers b/scripts/extract-vsssdk-headers new file mode 100755 index 000..9e38510 --- /dev/null +++ b/scripts/extract-vsssdk-headers @@ -0,0 +1,35 @@ +#! /bin/bash + +# extract-vsssdk-headers +# Author: Paolo Bonzini + +set -e +if test $# != 1 || ! test -f "$1"; then + echo 'Usage: extract-vsssdk-headers /path/to/setup.exe' >&2 + exit 1 +fi + +if ! command -v msiextract > /dev/null; then + echo 'msiextract not found. Please install msitools.' >&2 + exit 1 +fi + +if test -e inc; then + echo '"inc" already exists.' >&2 + exit 1 +fi + +# Extract .MSI file in the .exe, looking for the OLE compound +# document signature. Extra data at the end does not matter. +export LC_ALL=C +MAGIC=$'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1' +offset=$(grep -abom1 "$MAGIC" "$1" | sed -n 's/:/\n/; P') +tmpdir=$(mktemp -d) +trap 'rm -fr -- "$tmpdir" vsssdk.msi' EXIT HUP INT QUIT ALRM TERM +tail -c +$(($offset+1)) -- "$1" > vsssdk.msi + +# Now extract the files. +msiextract -C $tmpdir vsssdk.msi +mv "$tmpdir/Program Files/Microsoft/VSSSDK72/inc" inc +echo 'Extracted SDK headers into "inc" directory.' +exit 0
[Qemu-devel] [PATCH v9 08/10] qemu-ga: Call Windows VSS requester in fsfreeze command handler
Support guest-fsfreeze-freeze and guest-fsfreeze-thaw commands for Windows guests. When fsfreeze command is issued, it calls the VSS requester to freeze filesystems and applications. On thaw command, it again tells the VSS requester to thaw them. This also adds calling of initialize functions for the VSS requester. Signed-off-by: Tomoki Sekiyama Reviewed-by: Michael Roth --- qga/Makefile.objs|1 qga/commands-win32.c | 82 ++--- qga/vss-win32.c | 141 ++ qga/vss-win32.h | 24 + 4 files changed, 240 insertions(+), 8 deletions(-) create mode 100644 qga/vss-win32.c create mode 100644 qga/vss-win32.h diff --git a/qga/Makefile.objs b/qga/Makefile.objs index c4bd151..1c5986c 100644 --- a/qga/Makefile.objs +++ b/qga/Makefile.objs @@ -1,6 +1,7 @@ qga-obj-y = commands.o guest-agent-command-state.o main.o qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o +qga-obj-$(CONFIG_WIN32) += vss-win32.o qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o qga-obj-y += qapi-generated/qga-qmp-marshal.o diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 24e4ad0..7a37f5c 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -15,6 +15,7 @@ #include #include #include "qga/guest-agent-core.h" +#include "qga/vss-win32.h" #include "qga-qmp-commands.h" #include "qapi/qmp/qerror.h" @@ -156,27 +157,89 @@ void qmp_guest_file_flush(int64_t handle, Error **err) */ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) { -error_set(err, QERR_UNSUPPORTED); -return 0; +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +if (ga_is_frozen(ga_state)) { +return GUEST_FSFREEZE_STATUS_FROZEN; +} + +return GUEST_FSFREEZE_STATUS_THAWED; } /* - * Walk list of mounted file systems in the guest, and freeze the ones which - * are real local file systems. + * Freeze local file systems using Volume Shadow-copy Service. + * The frozen state is limited for up to 10 seconds by VSS. */ int64_t qmp_guest_fsfreeze_freeze(Error **err) { -error_set(err, QERR_UNSUPPORTED); +int i; +Error *local_err = NULL; + +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +slog("guest-fsfreeze called"); + +/* cannot risk guest agent blocking itself on a write in this state */ +ga_set_frozen(ga_state); + +qga_vss_fsfreeze(&i, err, true); +if (error_is_set(err)) { +goto error; +} + +return i; + +error: +qmp_guest_fsfreeze_thaw(&local_err); +if (error_is_set(&local_err)) { +g_debug("cleanup thaw: %s", error_get_pretty(local_err)); +error_free(local_err); +} return 0; } /* - * Walk list of frozen file systems in the guest, and thaw them. + * Thaw local file systems using Volume Shadow-copy Service. */ int64_t qmp_guest_fsfreeze_thaw(Error **err) { -error_set(err, QERR_UNSUPPORTED); -return 0; +int i; + +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +qga_vss_fsfreeze(&i, err, false); + +ga_unset_frozen(ga_state); +return i; +} + +static void guest_fsfreeze_cleanup(void) +{ +Error *err = NULL; + +if (!vss_initialized()) { +return; +} + +if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { +qmp_guest_fsfreeze_thaw(&err); +if (err) { +slog("failed to clean up frozen filesystems: %s", + error_get_pretty(err)); +error_free(err); +} +} + +vss_deinit(true); } /* @@ -354,4 +417,7 @@ int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) /* register init/cleanup routines for stateful command groups */ void ga_command_state_init(GAState *s, GACommandState *cs) { +if (vss_init(true)) { +ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); +} } diff --git a/qga/vss-win32.c b/qga/vss-win32.c new file mode 100644 index 000..89c0f3b --- /dev/null +++ b/qga/vss-win32.c @@ -0,0 +1,141 @@ +/* + * QEMU Guest Agent VSS utility functions + * + * Copyright Hitachi Data Systems Corp. 2013 + * + * Authors: + * Tomoki Sekiyama + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include "qga/guest-agent-core.h" +#include "qga/vss-win32.h" +#include "qga/vss-win32/requester.h" + +#define QGA_VSS_DLL "qga-vss.dll" + +static HMODULE provider_lib; + +/* Call a function in qga-vss.dll with the specified name */ +static HRESULT call_vss_provider_func(const
[Qemu-devel] [PATCH v9 03/10] checkpatch.pl: Check .cpp files
Enable checkpatch.pl to apply the same checks as C source files for C++ files with .cpp extensions. It also adds some exceptions for C++ sources to suppress errors for: - <> used in C++ template arguments (e.g. template ) - :: used to represent namespaces (e.g. SomeClass::method()) - : used in class declaration (e.g. class T : public Super) - ~ used in destructor method name (e.g. T::~T()) - spacing around 'catch'(e.g. catch (...)) Signed-off-by: Tomoki Sekiyama Reviewed-by: Michael Roth --- scripts/checkpatch.pl | 34 -- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index ec0aa4c..9d46e5a 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1363,7 +1363,7 @@ sub process { # Check for incorrect file permissions if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { my $permhere = $here . "FILE: $realfile\n"; - if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) { + if ($realfile =~ /(Makefile|Kconfig|\.c|\.cpp|\.h|\.S|\.tmpl)$/) { ERROR("do not set execute permissions for source files\n" . $permhere); } } @@ -1460,7 +1460,7 @@ sub process { } # check we are in a valid source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/); + next if ($realfile !~ /\.(h|c|cpp|s|S|pl|sh)$/); #80 column limit if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ && @@ -1495,7 +1495,7 @@ sub process { } # check we are in a valid source file C or perl if not then ignore this hunk - next if ($realfile !~ /\.(h|c|pl)$/); + next if ($realfile !~ /\.(h|c|cpp|pl)$/); # in QEMU, no tabs are allowed if ($rawline =~ /^\+.*\t/) { @@ -1505,7 +1505,7 @@ sub process { } # check we are in a valid C source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c)$/); + next if ($realfile !~ /\.(h|c|cpp)$/); # check for RCS/CVS revision markers if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { @@ -1969,6 +1969,9 @@ sub process { asm|__asm__)$/x) { + # Ignore 'catch (...)' in C++ + } elsif ($name =~ /^catch$/ && $realfile =~ /(\.cpp|\.h)$/) { + # cpp #define statements have non-optional spaces, ie # if there is a space between the name and the open # parenthesis it is simply not a parameter group. @@ -1992,7 +1995,7 @@ sub process { \+=|-=|\*=|\/=|%=|\^=|\|=|&=| =>|->|<<|>>|<|>|=|!|~| &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| - \?|: + \?|::|: }x; my @elements = split(/($ops|;)/, $opline); my $off = 0; @@ -2062,6 +2065,10 @@ sub process { # // is a comment } elsif ($op eq '//') { + # Ignore : used in class declaration in C++ + } elsif ($opv eq ':B' && $ctx =~ /Wx[WE]/ && +$line =~ /class/ && $realfile =~ /(\.cpp|\.h)$/) { + # No spaces for: # -> # : when part of a bitfield @@ -2088,7 +2095,10 @@ sub process { } elsif ($op eq '!' || $op eq '~' || $opv eq '*U' || $opv eq '-U' || $opv eq '&U' || $opv eq '&&U') { - if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { + if ($op eq '~' && $ca =~ /::$/ && $realfile =~ /(\.cpp|\.h)$/) { + # '~' used as a name of Destructor + + } elsif ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { ERROR("space required before that '$op' $at\n" . $hereptr); }
[Qemu-devel] [PATCH v9 09/10] qemu-ga: Install Windows VSS provider on `qemu-ga -s install'
Register QGA VSS provider library into Windows when qemu-ga is installed as Windows service ('-s install' option). It is deregistered when the service is uninstalled ('-s uninstall' option). Signed-off-by: Tomoki Sekiyama Reviewed-by: Michael Roth --- qga/main.c | 10 +- qga/vss-win32.c | 25 + qga/vss-win32.h |3 +++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/qga/main.c b/qga/main.c index 0e04e73..6c746c8 100644 --- a/qga/main.c +++ b/qga/main.c @@ -34,6 +34,7 @@ #include "qemu/bswap.h" #ifdef _WIN32 #include "qga/service-win32.h" +#include "qga/vss-win32.h" #include #endif #ifdef __linux__ @@ -1031,8 +1032,15 @@ int main(int argc, char **argv) fixed_state_dir = (state_dir == dfl_pathnames.state_dir) ? NULL : state_dir; -return ga_install_service(path, log_filepath, fixed_state_dir); +if (ga_install_vss_provider()) { +return EXIT_FAILURE; +} +if (ga_install_service(path, log_filepath, fixed_state_dir)) { +return EXIT_FAILURE; +} +return 0; } else if (strcmp(service, "uninstall") == 0) { +ga_uninstall_vss_provider(); return ga_uninstall_service(); } else { printf("Unknown service command.\n"); diff --git a/qga/vss-win32.c b/qga/vss-win32.c index 89c0f3b..24c4288 100644 --- a/qga/vss-win32.c +++ b/qga/vss-win32.c @@ -119,6 +119,31 @@ bool vss_initialized(void) return !!provider_lib; } +int ga_install_vss_provider(void) +{ +HRESULT hr; + +if (!vss_init(false)) { +fprintf(stderr, "Installation of VSS provider is skipped. " +"fsfreeze will be disabled.\n"); +return 0; +} +hr = call_vss_provider_func("COMRegister"); +vss_deinit(false); + +return SUCCEEDED(hr) ? 0 : EXIT_FAILURE; +} + +void ga_uninstall_vss_provider(void) +{ +if (!vss_init(false)) { +fprintf(stderr, "Removal of VSS provider is skipped.\n"); +return; +} +call_vss_provider_func("COMUnregister"); +vss_deinit(false); +} + /* Call VSS requester and freeze/thaw filesystems and applications */ void qga_vss_fsfreeze(int *nr_volume, Error **err, bool freeze) { diff --git a/qga/vss-win32.h b/qga/vss-win32.h index eac669c..db8fbe5 100644 --- a/qga/vss-win32.h +++ b/qga/vss-win32.h @@ -19,6 +19,9 @@ bool vss_init(bool init_requester); void vss_deinit(bool deinit_requester); bool vss_initialized(void); +int ga_install_vss_provider(void); +void ga_uninstall_vss_provider(void); + void qga_vss_fsfreeze(int *nr_volume, Error **err, bool freeze); #endif
[Qemu-devel] [PATCH v10 01/10] configure: Support configuring C++ compiler
Add configuration for C++ compiler in configure and Makefiles. The C++ compiler is choosed as following: - ${CXX}, if it is specified. - ${cross_prefix}g++, if ${cross_prefix} is specified. - Otherwise, c++ is used. Currently, usage of C++ language is only for access to Windows VSS using COM+ services in qemu-guest-agent for Windows. Signed-off-by: Tomoki Sekiyama Reviewed-by: Laszlo Ersek Reviewed-by: Micael Roth --- configure | 13 + rules.mak |9 - 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 18fa608..eabd8e5 100755 --- a/configure +++ b/configure @@ -252,6 +252,8 @@ for opt do ;; --cc=*) CC="$optarg" ;; + --cxx=*) CXX="$optarg" + ;; --source-path=*) source_path="$optarg" ;; --cpu=*) cpu="$optarg" @@ -282,6 +284,12 @@ else cc="${CC-${cross_prefix}gcc}" fi +if test -z "${CXX}${cross_prefix}"; then + cxx="c++" +else + cxx="${CXX-${cross_prefix}g++}" +fi + ar="${AR-${cross_prefix}ar}" as="${AS-${cross_prefix}as}" cpp="${CPP-$cc -E}" @@ -622,6 +630,8 @@ for opt do ;; --host-cc=*) host_cc="$optarg" ;; + --cxx=*) + ;; --objcc=*) objcc="$optarg" ;; --make=*) make="$optarg" @@ -1023,6 +1033,7 @@ echo " --cross-prefix=PREFIXuse PREFIX for compile tools [$cross_prefix]" echo " --cc=CC use C compiler CC [$cc]" echo " --host-cc=CC use C compiler CC [$host_cc] for code run at" echo " build time" +echo " --cxx=CXXuse C++ compiler CXX [$cxx]" echo " --objcc=OBJCCuse Objective-C compiler OBJCC [$objcc]" echo " --extra-cflags=CFLAGSappend extra C compiler flags QEMU_CFLAGS" echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS" @@ -3522,6 +3533,7 @@ fi echo "Source path $source_path" echo "C compiler$cc" echo "Host C compiler $host_cc" +echo "C++ compiler $cxx" echo "Objective-C compiler $objcc" echo "CFLAGS$CFLAGS" echo "QEMU_CFLAGS $QEMU_CFLAGS" @@ -4103,6 +4115,7 @@ echo "PYTHON=$python" >> $config_host_mak echo "CC=$cc" >> $config_host_mak echo "CC_I386=$cc_i386" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak +echo "CXX=$cxx" >> $config_host_mak echo "OBJCC=$objcc" >> $config_host_mak echo "AR=$ar" >> $config_host_mak echo "AS=$as" >> $config_host_mak diff --git a/rules.mak b/rules.mak index 4499745..abc2e84 100644 --- a/rules.mak +++ b/rules.mak @@ -8,9 +8,13 @@ MAKEFLAGS += -rR %.d: %.h: %.c: +%.cpp: %.m: %.mak: +# Flags for C++ compilation +QEMU_CXXFLAGS = -D__STDC_LIMIT_MACROS $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls, $(QEMU_CFLAGS)) + # Flags for dependency generation QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d @@ -50,6 +54,9 @@ endif %.o: %.asm $(call quiet-command,$(AS) $(ASFLAGS) -o $@ $<," AS $(TARGET_DIR)$@") +%.o: %.cpp + $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CXX $(TARGET_DIR)$@") + %.o: %.m $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@") @@ -70,7 +77,7 @@ quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1)) cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \ >/dev/null 2>&1 && echo OK), $2, $3) -VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.sh %.rc +VPATH_SUFFIXES = %.c %.h %.S %.cpp %.m %.mak %.texi %.sh %.rc set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) # find-in-path
[Qemu-devel] [PATCH v10 03/10] checkpatch.pl: Check .cpp files
Enable checkpatch.pl to apply the same checks as C source files for C++ files with .cpp extensions. It also adds some exceptions for C++ sources to suppress errors for: - <> used in C++ template arguments (e.g. template ) - :: used to represent namespaces (e.g. SomeClass::method()) - : used in class declaration (e.g. class T : public Super) - ~ used in destructor method name (e.g. T::~T()) - spacing around 'catch'(e.g. catch (...)) Signed-off-by: Tomoki Sekiyama Reviewed-by: Michael Roth --- scripts/checkpatch.pl | 34 -- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index ec0aa4c..9d46e5a 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1363,7 +1363,7 @@ sub process { # Check for incorrect file permissions if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { my $permhere = $here . "FILE: $realfile\n"; - if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) { + if ($realfile =~ /(Makefile|Kconfig|\.c|\.cpp|\.h|\.S|\.tmpl)$/) { ERROR("do not set execute permissions for source files\n" . $permhere); } } @@ -1460,7 +1460,7 @@ sub process { } # check we are in a valid source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/); + next if ($realfile !~ /\.(h|c|cpp|s|S|pl|sh)$/); #80 column limit if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ && @@ -1495,7 +1495,7 @@ sub process { } # check we are in a valid source file C or perl if not then ignore this hunk - next if ($realfile !~ /\.(h|c|pl)$/); + next if ($realfile !~ /\.(h|c|cpp|pl)$/); # in QEMU, no tabs are allowed if ($rawline =~ /^\+.*\t/) { @@ -1505,7 +1505,7 @@ sub process { } # check we are in a valid C source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c)$/); + next if ($realfile !~ /\.(h|c|cpp)$/); # check for RCS/CVS revision markers if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { @@ -1969,6 +1969,9 @@ sub process { asm|__asm__)$/x) { + # Ignore 'catch (...)' in C++ + } elsif ($name =~ /^catch$/ && $realfile =~ /(\.cpp|\.h)$/) { + # cpp #define statements have non-optional spaces, ie # if there is a space between the name and the open # parenthesis it is simply not a parameter group. @@ -1992,7 +1995,7 @@ sub process { \+=|-=|\*=|\/=|%=|\^=|\|=|&=| =>|->|<<|>>|<|>|=|!|~| &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| - \?|: + \?|::|: }x; my @elements = split(/($ops|;)/, $opline); my $off = 0; @@ -2062,6 +2065,10 @@ sub process { # // is a comment } elsif ($op eq '//') { + # Ignore : used in class declaration in C++ + } elsif ($opv eq ':B' && $ctx =~ /Wx[WE]/ && +$line =~ /class/ && $realfile =~ /(\.cpp|\.h)$/) { + # No spaces for: # -> # : when part of a bitfield @@ -2088,7 +2095,10 @@ sub process { } elsif ($op eq '!' || $op eq '~' || $opv eq '*U' || $opv eq '-U' || $opv eq '&U' || $opv eq '&&U') { - if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { + if ($op eq '~' && $ca =~ /::$/ && $realfile =~ /(\.cpp|\.h)$/) { + # '~' used as a name of Destructor + + } elsif ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { ERROR("space required before that '$op' $at\n" . $hereptr); }
[Qemu-devel] [PATCH v10 08/10] qemu-ga: Call Windows VSS requester in fsfreeze command handler
Support guest-fsfreeze-freeze and guest-fsfreeze-thaw commands for Windows guests. When fsfreeze command is issued, it calls the VSS requester to freeze filesystems and applications. On thaw command, it again tells the VSS requester to thaw them. This also adds calling of initialize functions for the VSS requester. Signed-off-by: Tomoki Sekiyama Reviewed-by: Michael Roth --- qga/Makefile.objs|1 qga/commands-win32.c | 82 ++--- qga/vss-win32.c | 141 ++ qga/vss-win32.h | 24 + 4 files changed, 240 insertions(+), 8 deletions(-) create mode 100644 qga/vss-win32.c create mode 100644 qga/vss-win32.h diff --git a/qga/Makefile.objs b/qga/Makefile.objs index c4bd151..1c5986c 100644 --- a/qga/Makefile.objs +++ b/qga/Makefile.objs @@ -1,6 +1,7 @@ qga-obj-y = commands.o guest-agent-command-state.o main.o qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o +qga-obj-$(CONFIG_WIN32) += vss-win32.o qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o qga-obj-y += qapi-generated/qga-qmp-marshal.o diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 24e4ad0..7a37f5c 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -15,6 +15,7 @@ #include #include #include "qga/guest-agent-core.h" +#include "qga/vss-win32.h" #include "qga-qmp-commands.h" #include "qapi/qmp/qerror.h" @@ -156,27 +157,89 @@ void qmp_guest_file_flush(int64_t handle, Error **err) */ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) { -error_set(err, QERR_UNSUPPORTED); -return 0; +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +if (ga_is_frozen(ga_state)) { +return GUEST_FSFREEZE_STATUS_FROZEN; +} + +return GUEST_FSFREEZE_STATUS_THAWED; } /* - * Walk list of mounted file systems in the guest, and freeze the ones which - * are real local file systems. + * Freeze local file systems using Volume Shadow-copy Service. + * The frozen state is limited for up to 10 seconds by VSS. */ int64_t qmp_guest_fsfreeze_freeze(Error **err) { -error_set(err, QERR_UNSUPPORTED); +int i; +Error *local_err = NULL; + +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +slog("guest-fsfreeze called"); + +/* cannot risk guest agent blocking itself on a write in this state */ +ga_set_frozen(ga_state); + +qga_vss_fsfreeze(&i, err, true); +if (error_is_set(err)) { +goto error; +} + +return i; + +error: +qmp_guest_fsfreeze_thaw(&local_err); +if (error_is_set(&local_err)) { +g_debug("cleanup thaw: %s", error_get_pretty(local_err)); +error_free(local_err); +} return 0; } /* - * Walk list of frozen file systems in the guest, and thaw them. + * Thaw local file systems using Volume Shadow-copy Service. */ int64_t qmp_guest_fsfreeze_thaw(Error **err) { -error_set(err, QERR_UNSUPPORTED); -return 0; +int i; + +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +qga_vss_fsfreeze(&i, err, false); + +ga_unset_frozen(ga_state); +return i; +} + +static void guest_fsfreeze_cleanup(void) +{ +Error *err = NULL; + +if (!vss_initialized()) { +return; +} + +if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { +qmp_guest_fsfreeze_thaw(&err); +if (err) { +slog("failed to clean up frozen filesystems: %s", + error_get_pretty(err)); +error_free(err); +} +} + +vss_deinit(true); } /* @@ -354,4 +417,7 @@ int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) /* register init/cleanup routines for stateful command groups */ void ga_command_state_init(GAState *s, GACommandState *cs) { +if (vss_init(true)) { +ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); +} } diff --git a/qga/vss-win32.c b/qga/vss-win32.c new file mode 100644 index 000..89c0f3b --- /dev/null +++ b/qga/vss-win32.c @@ -0,0 +1,141 @@ +/* + * QEMU Guest Agent VSS utility functions + * + * Copyright Hitachi Data Systems Corp. 2013 + * + * Authors: + * Tomoki Sekiyama + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include "qga/guest-agent-core.h" +#include "qga/vss-win32.h" +#include "qga/vss-win32/requester.h" + +#define QGA_VSS_DLL "qga-vss.dll" + +static HMODULE provider_lib; + +/* Call a function in qga-vss.dll with the specified name */ +static HRESULT call_vss_provider_func(const
[Qemu-devel] [PATCH v10 05/10] qemu-ga: Add configure options to specify path to Windows/VSS SDK
To enable VSS support in qemu-ga for Windows, header files included in VSS SDK are required. The VSS support is enabled by the configure option like below: ./configure --with-vss-sdk="/path/to/VSS SDK" If the path is omitted, it tries to search the headers from default paths and VSS support is enabled only if the SDK is found. VSS support is disabled if --without-vss-sdk or --with-vss-sdk=no is specified. VSS SDK is available from: http://www.microsoft.com/en-us/download/details.aspx?id=23490 To cross-compile using mingw, you need to setup the SDK on Windows environments to extract headers. You can also extract the SDK headers on POSIX environments using scripts/extract-vss-headers and msitools. In addition, --with-win-sdk="/path/to/Windows SDK" option is also added to specify path to Windows SDK, which may be used for native-compile of .tlb file of qemu-ga VSS provider. However, this is usually unnecessary because pre-compiled .tlb file is included. Signed-off-by: Tomoki Sekiyama Reviewed-by: Laszlo Ersek Reviewed-by: Michael Roth --- .gitignore |1 + Makefile |1 + configure | 78 3 files changed, 80 insertions(+) diff --git a/.gitignore b/.gitignore index 0fe114d..02d15f0 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ fsdev/virtfs-proxy-helper.pod *.la *.pc .libs +.sdk *.swp *.orig .pc diff --git a/Makefile b/Makefile index 29f1043..0caf4fe 100644 --- a/Makefile +++ b/Makefile @@ -273,6 +273,7 @@ distclean: clean for d in $(TARGET_DIRS); do \ rm -rf $$d || exit 1 ; \ done + rm -Rf .sdk if test -f pixman/config.log; then make -C pixman distclean; fi if test -f dtc/version_gen.h; then make $(DTC_MAKE_ARGS) clean; fi diff --git a/configure b/configure index eabd8e5..137cfee 100755 --- a/configure +++ b/configure @@ -232,6 +232,9 @@ usb_redir="" glx="" zlib="yes" guest_agent="" +guest_agent_with_vss="no" +vss_win32_sdk="" +win_sdk="no" want_tools="yes" libiscsi="" coroutine="" @@ -923,6 +926,18 @@ for opt do ;; --disable-guest-agent) guest_agent="no" ;; + --with-vss-sdk) vss_win32_sdk="" + ;; + --with-vss-sdk=*) vss_win32_sdk="$optarg" + ;; + --without-vss-sdk) vss_win32_sdk="no" + ;; + --with-win-sdk) win_sdk="" + ;; + --with-win-sdk=*) win_sdk="$optarg" + ;; + --without-win-sdk) win_sdk="no" + ;; --enable-tools) want_tools="yes" ;; --disable-tools) want_tools="no" @@ -1159,6 +1174,8 @@ echo " --disable-usb-redir disable usb network redirection support" echo " --enable-usb-redir enable usb network redirection support" echo " --disable-guest-agentdisable building of the QEMU Guest Agent" echo " --enable-guest-agent enable building of the QEMU Guest Agent" +echo " --with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent" +echo " --with-win-sdk=SDK-path path to Windows Platform SDK (to build VSS .tlb)" echo " --disable-seccompdisable seccomp support" echo " --enable-seccomp enables seccomp support" echo " --with-coroutine=BACKEND coroutine backend. Supported options:" @@ -3093,6 +3110,61 @@ if test "$usb_redir" != "no" ; then fi ## +# check if we have VSS SDK headers for win + +if test "$mingw32" = "yes" -a "$guest_agent" != "no" -a "$vss_win32_sdk" != "no" ; then + case "$vss_win32_sdk" in +"") vss_win32_include="-I$source_path" ;; +*\ *) # The SDK is installed in "Program Files" by default, but we cannot + # handle path with spaces. So we symlink the headers into ".sdk/vss". + vss_win32_include="-I$source_path/.sdk/vss" + symlink "$vss_win32_sdk/inc" "$source_path/.sdk/vss/inc" + ;; +*)vss_win32_include="-I$vss_win32_sdk" + esac + cat > $TMPC << EOF +#define __MIDL_user_allocate_free_DEFINED__ +#include +int main(void) { return VSS_CTX_BACKUP; } +EOF + if compile_prog "$vss_win32_include" "" ; then +guest_agent_with_vss="yes" +QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include" +libs_qga="-lole32 -loleaut32 -lshlwapi -luuid -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga" + else +if test "$vss_win32_sdk" != "" ; then + echo "ERROR: Please download and install Microsoft VSS SDK:" + echo "ERROR: http://www.microsoft.com/en-us/download/details.aspx?id=23490"; + ec
[Qemu-devel] [PATCH v10 02/10] Add c++ keywords to QAPI helper script
Add c++ keywords to avoid errors in compiling with c++ compiler. This also renames class member of PciDeviceInfo to q_class. Signed-off-by: Tomoki Sekiyama Reviewed-by: Laszlo Ersek Reviewed-by: Michael Roth --- hmp.c |2 +- hw/pci/pci.c|2 +- scripts/qapi.py | 12 +++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/hmp.c b/hmp.c index c45514b..79931d2 100644 --- a/hmp.c +++ b/hmp.c @@ -528,7 +528,7 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) if (dev->class_info.has_desc) { monitor_printf(mon, "%s", dev->class_info.desc); } else { -monitor_printf(mon, "Class %04" PRId64, dev->class_info.class); +monitor_printf(mon, "Class %04" PRId64, dev->class_info.q_class); } monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n", diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 4c004f5..25d08eb 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1466,7 +1466,7 @@ static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus, info->function = PCI_FUNC(dev->devfn); class = pci_get_word(dev->config + PCI_CLASS_DEVICE); -info->class_info.class = class; +info->class_info.q_class = class; desc = get_class_desc(class); if (desc->desc) { info->class_info.has_desc = true; diff --git a/scripts/qapi.py b/scripts/qapi.py index 0ebea94..d0a92df 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -236,9 +236,19 @@ def c_var(name, protect=True): # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html # excluding _.* gcc_words = set(['asm', 'typeof']) +# C++ ISO/IEC 14882:2003 2.11 +cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete', + 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable', + 'namespace', 'new', 'operator', 'private', 'protected', + 'public', 'reinterpret_cast', 'static_cast', 'template', + 'this', 'throw', 'true', 'try', 'typeid', 'typename', + 'using', 'virtual', 'wchar_t', + # alternative representations + 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not', + 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq']) # namespace pollution: polluted_words = set(['unix']) -if protect and (name in c89_words | c99_words | c11_words | gcc_words | polluted_words): +if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words): return "q_" + name return name.replace('-', '_').lstrip("*")
[Qemu-devel] [PATCH v10 00/10] qemu-ga: fsfreeze on Windows using VSS
Hi, I rebased the patch series to add fsfreeze for Windows qemu-ga. changes from v9: - Fix conflict with commit e8ef31a3518c "qemu-ga: build it even if !system" changes from v8: - Add hEventTimeout to improve timeout error message (patch 07, see below) - Build qga-vss.tlb if configure'd --with-win-sdk (patch 05, 07) - Use "qga-vss-dll-obj-$(CONFIG_QGA_VSS)" in Makefile.objs (patch 07) - Fix typo in QGAVSSRequesterFunc (patch 07, 08) v9: http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg06071.html * Description In Windows, VSS (Volume Shadow Copy Service) provides a facility to quiesce filesystems and applications before disk snapshots are taken. This patch series implements "fsfreeze" command of qemu-ga using VSS. * How to build & run qemu-ga with VSS support - Download Microsoft VSS SDK from: http://www.microsoft.com/en-us/download/details.aspx?id=23490 - Setup the SDK scripts/extract-vsssdk-headers setup.exe (on POSIX-systems) - Specify installed SDK directory to configure option as: ./configure --cross-prefix=i686-w64-mingw32- \ --with-vss-sdk="path/to/VSS SDK" \ --without-systems --without-tools - make qemu-ga.exe qga/vss-win32/qga-vss.{dll,tlb} - Install qemu-ga.exe, qga/vss-win32/qga-vss.{dll,tlb}, and the other required mingw libraries into the same directory in guests - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests Any feedback are appreciated. --- Tomoki Sekiyama (10): configure: Support configuring C++ compiler Add c++ keywords to QAPI helper script checkpatch.pl: Check .cpp files Add a script to extract VSS SDK headers on POSIX system qemu-ga: Add configure options to specify path to Windows/VSS SDK error: Add error_set_win32 and error_setg_win32 qemu-ga: Add Windows VSS provider and requester as DLL qemu-ga: Call Windows VSS requester in fsfreeze command handler qemu-ga: Install Windows VSS provider on `qemu-ga -s install' QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command .gitignore |1 Makefile |3 Makefile.objs |2 QMP/qemu-ga-client |4 configure | 96 +++ hmp.c |2 hw/pci/pci.c |2 include/qapi/error.h | 13 + qga/Makefile.objs |3 qga/commands-win32.c | 82 ++ qga/main.c | 10 + qga/vss-win32.c| 166 + qga/vss-win32.h| 27 ++ qga/vss-win32/Makefile.objs| 23 ++ qga/vss-win32/install.cpp | 458 +++ qga/vss-win32/provider.cpp | 523 qga/vss-win32/qga-vss.def | 13 + qga/vss-win32/qga-vss.idl | 20 ++ qga/vss-win32/qga-vss.tlb | Bin qga/vss-win32/requester.cpp| 507 +++ qga/vss-win32/requester.h | 42 +++ qga/vss-win32/vss-common.h | 129 ++ rules.mak |9 + scripts/checkpatch.pl | 34 ++- scripts/extract-vsssdk-headers | 35 +++ scripts/qapi.py| 12 + util/error.c | 35 +++ 27 files changed, 2229 insertions(+), 22 deletions(-) create mode 100644 qga/vss-win32.c create mode 100644 qga/vss-win32.h create mode 100644 qga/vss-win32/Makefile.objs create mode 100644 qga/vss-win32/install.cpp create mode 100644 qga/vss-win32/provider.cpp create mode 100644 qga/vss-win32/qga-vss.def create mode 100644 qga/vss-win32/qga-vss.idl create mode 100644 qga/vss-win32/qga-vss.tlb create mode 100644 qga/vss-win32/requester.cpp create mode 100644 qga/vss-win32/requester.h create mode 100644 qga/vss-win32/vss-common.h create mode 100755 scripts/extract-vsssdk-headers
[Qemu-devel] [PATCH v10 06/10] error: Add error_set_win32 and error_setg_win32
These functions help maintaining homogeneous formatting of error messages with Windows error code and description (generated by g_win32_error_message()). Signed-off-by: Tomoki Sekiyama Reviewed-by: Michael Roth --- include/qapi/error.h | 13 + util/error.c | 35 +++ 2 files changed, 48 insertions(+) diff --git a/include/qapi/error.h b/include/qapi/error.h index ffd1cea..7d4c696 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -36,6 +36,15 @@ void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ */ void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5); +#ifdef _WIN32 +/** + * Set an indirect pointer to an error given a ErrorClass value and a + * printf-style human message, followed by a g_win32_error_message() string if + * @win32_err is not zero. + */ +void error_set_win32(Error **err, int win32_err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5); +#endif + /** * Same as error_set(), but sets a generic error */ @@ -43,6 +52,10 @@ void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) #define error_setg_errno(err, os_error, fmt, ...) \ error_set_errno(err, os_error, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) +#ifdef _WIN32 +#define error_setg_win32(err, win32_err, fmt, ...) \ +error_set_win32(err, win32_err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) +#endif /** * Helper for open() errors diff --git a/util/error.c b/util/error.c index 53b0435..ec0faa6 100644 --- a/util/error.c +++ b/util/error.c @@ -76,6 +76,41 @@ void error_setg_file_open(Error **errp, int os_errno, const char *filename) error_setg_errno(errp, os_errno, "Could not open '%s'", filename); } +#ifdef _WIN32 + +void error_set_win32(Error **errp, int win32_err, ErrorClass err_class, + const char *fmt, ...) +{ +Error *err; +char *msg1; +va_list ap; + +if (errp == NULL) { +return; +} +assert(*errp == NULL); + +err = g_malloc0(sizeof(*err)); + +va_start(ap, fmt); +msg1 = g_strdup_vprintf(fmt, ap); +if (win32_err != 0) { +char *msg2 = g_win32_error_message(win32_err); +err->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2, + (unsigned)win32_err); +g_free(msg2); +g_free(msg1); +} else { +err->msg = msg1; +} +va_end(ap); +err->err_class = err_class; + +*errp = err; +} + +#endif + Error *error_copy(const Error *err) { Error *err_new;
[Qemu-devel] [PATCH v10 04/10] Add a script to extract VSS SDK headers on POSIX system
VSS SDK(*) setup.exe is only runnable on Windows. This adds a script to extract VSS SDK headers on POSIX-systems using msitools. * http://www.microsoft.com/en-us/download/details.aspx?id=23490 From: Paolo Bonzini Signed-off-by: Paolo Bonzini Signed-off-by: Tomoki Sekiyama Reviewed-by: Laszlo Ersek Reviewed-by: Michael Roth --- scripts/extract-vsssdk-headers | 35 +++ 1 file changed, 35 insertions(+) create mode 100755 scripts/extract-vsssdk-headers diff --git a/scripts/extract-vsssdk-headers b/scripts/extract-vsssdk-headers new file mode 100755 index 000..9e38510 --- /dev/null +++ b/scripts/extract-vsssdk-headers @@ -0,0 +1,35 @@ +#! /bin/bash + +# extract-vsssdk-headers +# Author: Paolo Bonzini + +set -e +if test $# != 1 || ! test -f "$1"; then + echo 'Usage: extract-vsssdk-headers /path/to/setup.exe' >&2 + exit 1 +fi + +if ! command -v msiextract > /dev/null; then + echo 'msiextract not found. Please install msitools.' >&2 + exit 1 +fi + +if test -e inc; then + echo '"inc" already exists.' >&2 + exit 1 +fi + +# Extract .MSI file in the .exe, looking for the OLE compound +# document signature. Extra data at the end does not matter. +export LC_ALL=C +MAGIC=$'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1' +offset=$(grep -abom1 "$MAGIC" "$1" | sed -n 's/:/\n/; P') +tmpdir=$(mktemp -d) +trap 'rm -fr -- "$tmpdir" vsssdk.msi' EXIT HUP INT QUIT ALRM TERM +tail -c +$(($offset+1)) -- "$1" > vsssdk.msi + +# Now extract the files. +msiextract -C $tmpdir vsssdk.msi +mv "$tmpdir/Program Files/Microsoft/VSSSDK72/inc" inc +echo 'Extracted SDK headers into "inc" directory.' +exit 0
[Qemu-devel] [PATCH v10 10/10] QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command
guest-fsfreeze-freeze command can take longer than 3 seconds when heavy disk I/O is running. To avoid unexpected timeout, this changes the timeout to 60 seconds (timeout of pre-commit phase of VSS). Signed-off-by: Tomoki Sekiyama Reviewed-by: Paolo Bonzini Reviewed-by: Laszlo Ersek Reviewed-by: Michael Roth --- QMP/qemu-ga-client |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/QMP/qemu-ga-client b/QMP/qemu-ga-client index 46676c3..b5f7e7c 100755 --- a/QMP/qemu-ga-client +++ b/QMP/qemu-ga-client @@ -267,7 +267,9 @@ def main(address, cmd, args): print('Hint: qemu is not running?') sys.exit(1) -if cmd != 'ping': +if cmd == 'fsfreeze' and args[0] == 'freeze': +client.sync(60) +elif cmd != 'ping': client.sync() globals()['_cmd_' + cmd](client, args)
[Qemu-devel] [PATCH v10 09/10] qemu-ga: Install Windows VSS provider on `qemu-ga -s install'
Register QGA VSS provider library into Windows when qemu-ga is installed as Windows service ('-s install' option). It is deregistered when the service is uninstalled ('-s uninstall' option). Signed-off-by: Tomoki Sekiyama Reviewed-by: Michael Roth --- qga/main.c | 10 +- qga/vss-win32.c | 25 + qga/vss-win32.h |3 +++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/qga/main.c b/qga/main.c index 0e04e73..6c746c8 100644 --- a/qga/main.c +++ b/qga/main.c @@ -34,6 +34,7 @@ #include "qemu/bswap.h" #ifdef _WIN32 #include "qga/service-win32.h" +#include "qga/vss-win32.h" #include #endif #ifdef __linux__ @@ -1031,8 +1032,15 @@ int main(int argc, char **argv) fixed_state_dir = (state_dir == dfl_pathnames.state_dir) ? NULL : state_dir; -return ga_install_service(path, log_filepath, fixed_state_dir); +if (ga_install_vss_provider()) { +return EXIT_FAILURE; +} +if (ga_install_service(path, log_filepath, fixed_state_dir)) { +return EXIT_FAILURE; +} +return 0; } else if (strcmp(service, "uninstall") == 0) { +ga_uninstall_vss_provider(); return ga_uninstall_service(); } else { printf("Unknown service command.\n"); diff --git a/qga/vss-win32.c b/qga/vss-win32.c index 89c0f3b..24c4288 100644 --- a/qga/vss-win32.c +++ b/qga/vss-win32.c @@ -119,6 +119,31 @@ bool vss_initialized(void) return !!provider_lib; } +int ga_install_vss_provider(void) +{ +HRESULT hr; + +if (!vss_init(false)) { +fprintf(stderr, "Installation of VSS provider is skipped. " +"fsfreeze will be disabled.\n"); +return 0; +} +hr = call_vss_provider_func("COMRegister"); +vss_deinit(false); + +return SUCCEEDED(hr) ? 0 : EXIT_FAILURE; +} + +void ga_uninstall_vss_provider(void) +{ +if (!vss_init(false)) { +fprintf(stderr, "Removal of VSS provider is skipped.\n"); +return; +} +call_vss_provider_func("COMUnregister"); +vss_deinit(false); +} + /* Call VSS requester and freeze/thaw filesystems and applications */ void qga_vss_fsfreeze(int *nr_volume, Error **err, bool freeze) { diff --git a/qga/vss-win32.h b/qga/vss-win32.h index eac669c..db8fbe5 100644 --- a/qga/vss-win32.h +++ b/qga/vss-win32.h @@ -19,6 +19,9 @@ bool vss_init(bool init_requester); void vss_deinit(bool deinit_requester); bool vss_initialized(void); +int ga_install_vss_provider(void); +void ga_uninstall_vss_provider(void); + void qga_vss_fsfreeze(int *nr_volume, Error **err, bool freeze); #endif
Re: [Qemu-devel] [PATCH v2] qga: Add 'mountpoints' argument to guest-fsfreeze-freeze command
Any comments for this patch? Thanks, Tomoki Sekiyama On 4/28/14 11:25 , "Tomoki Sekiyama" wrote: >Hi, > >This is v2 patch for qemu-ga to add argument to specify which filesystems >to be frozen by guest-fsfreeze-freeze command. > >Changes to v1: > added documentation of the new field > (v1: http://lists.gnu.org/archive/html/qemu-devel/2014-04/msg04085.html) > >--- >Tomoki Sekiyama (1): > qga: Add 'mountpoints' argument to guest-fsfreeze-freeze command > > > qga/commands-posix.c | 17 - > qga/commands-win32.c |3 ++- > qga/qapi-schema.json |4 > 3 files changed, 22 insertions(+), 2 deletions(-) > >-- >Regards, >Tomoki Sekiyama
Re: [Qemu-devel] [PATCH v2] qga: Add 'mountpoints' argument to guest-fsfreeze-freeze command
> On 04/28/2014 09:25 AM, Tomoki Sekiyama wrote: >> When an array of mount point paths is specified as 'mountpoints' argument >> of guest-fsfreeze-freeze, qemu-ga with this patch will only freeze the file >> systems mounted on specified paths in Linux. > > How does the management application learn the set of valid mountpoints > arguments it can pass to this command? Shouldn't there be a query > counterpart that asks the guest to return the full list of mountpoints > that it can support freezing? In the case of guests that are > all-or-none, like Windows, the query command would return an empty list > to make it obvious there is no ability to freeze just a subset. > > In returning a list of mountpoint names, it might also be nice to > correlate which names map to which devices (it can be a many:many > mapping, thanks to things like RAID setups in the guest). I agree. The patch below is for the command to get filesystems list. === From: Tomoki Sekiyama qga: Add guest-get-fs-info command Add command to get mounted filesystems information in the guest. The returned value contains a list of mountpoint paths and corresponding disks info such as disk bus type, drive address, and the disk controllers' PCI addresses, so that management layer such as libvirt can resolve the disk backends. In Linux guest, the disk information is resolved from sysfs. For example, when `lsblk' result is: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdb 8:16 01G 0 disk `-sdb1 8:17 0 1024M 0 part `-vg0-lv0253:10 1.4G 0 lvm /mnt/test sdc 8:32 01G 0 disk `-sdc1 8:33 0 512M 0 part `-vg0-lv0253:10 1.4G 0 lvm /mnt/test vda252:00 25G 0 disk `-vda1 252:10 25G 0 part / where sdb is a SCSI disk with PCI controller :00:0a.0 and ID=1, sdc is an IDE disk with PCI controller :00:01.1, and vda is a virtio disk with PCI device :00:06.0, guest-get-fs-info command will return the following result: {"return": [{"name":"dm-1", "mountpoint":"/mnt/test", "disk":[ {"bus-type":"scsi","bus":0,"unit":1,"target":0, "pci-controller":{"bus":0,"slot":10,"domain":0,"function":0}}, {"bus-type":"ide","bus":0,"unit":0,"target":0, "pci-controller":{"bus":0,"slot":1,"domain":0,"function":1}}], "type":"xfs"}, {"name":"vda1", "mountpoint":"/", "disk":[ {"bus-type":"virtio","bus":0,"unit":0,"target":0, "pci-controller":{"bus":0,"slot":6,"domain":0,"function":0}}], "type":"ext4"}]} Signed-off-by: Tomoki Sekiyama --- qga/commands-posix.c | 420 ++- qga/qapi-schema.json | 77 ++ 2 files changed, 496 insertions(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 771f00c..212913a 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -575,6 +576,7 @@ static void guest_file_init(void) typedef struct FsMount { char *dirname; char *devtype; +unsigned int devmajor, devminor; QTAILQ_ENTRY(FsMount) next; } FsMount; @@ -596,15 +598,40 @@ static void free_fs_mount_list(FsMountList *mounts) } } +static int dev_major_minor(const char *devpath, + unsigned int *devmajor, unsigned int *devminor) +{ +struct stat st; + +*devmajor = 0; +*devminor = 0; + +if (stat(devpath, &st) < 0) { +slog("failed to stat device file '%s': %s", devpath, strerror(errno)); +return -1; +} +if (S_ISDIR(st.st_mode)) { +/* It is bind mount */ +return -2; +} +if (S_ISBLK(st.st_mode)) { +*devmajor = major(st.st_rdev); +*devminor = minor(st.st_rdev); +return 0; +} +return -1; +} + /* * Walk the mount table and build a list of local file systems */ -static void build_fs_mount_list(FsMountList *mounts, Error **errp) +static void build_fs_mount_list_from_mtab(FsMountList *mounts, Error **errp) { struct mntent *ment; FsMount *mount; char const *mtab = "/proc/self/mounts"; FILE *fp; +unsigned int devmajor, devminor; fp = setmntent(mtab, "r"); if (!fp) { @@ -624,20 +651,36
Re: [Qemu-devel] [PATCH v2] qga: Add 'mountpoints' argument to guest-fsfreeze-freeze command
> On 04/28/2014 09:25 AM, Tomoki Sekiyama wrote: >> When an array of mount point paths is specified as 'mountpoints' argument >> of guest-fsfreeze-freeze, qemu-ga with this patch will only freeze the file >> systems mounted on specified paths in Linux. > > How does the management application learn the set of valid mountpoints > arguments it can pass to this command? Shouldn't there be a query > counterpart that asks the guest to return the full list of mountpoints > that it can support freezing? In the case of guests that are > all-or-none, like Windows, the query command would return an empty list > to make it obvious there is no ability to freeze just a subset. > > In returning a list of mountpoint names, it might also be nice to > correlate which names map to which devices (it can be a many:many > mapping, thanks to things like RAID setups in the guest). I agree. The patch below is for the command to get filesystems list. === From: Tomoki Sekiyama qga: Add guest-get-fs-info command Add command to get mounted filesystems information in the guest. The returned value contains a list of mountpoint paths and corresponding disks info such as disk bus type, drive address, and the disk controllers' PCI addresses, so that management layer such as libvirt can resolve the disk backends. In Linux guest, the disk information is resolved from sysfs. For example, when `lsblk' result is: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdb 8:16 01G 0 disk `-sdb1 8:17 0 1024M 0 part `-vg0-lv0253:10 1.4G 0 lvm /mnt/test sdc 8:32 01G 0 disk `-sdc1 8:33 0 512M 0 part `-vg0-lv0253:10 1.4G 0 lvm /mnt/test vda252:00 25G 0 disk `-vda1 252:10 25G 0 part / where sdb is a SCSI disk with PCI controller :00:0a.0 and ID=1, sdc is an IDE disk with PCI controller :00:01.1, and vda is a virtio disk with PCI device :00:06.0, guest-get-fs-info command will return the following result: {"return": [{"name":"dm-1", "mountpoint":"/mnt/test", "disk":[ {"bus-type":"scsi","bus":0,"unit":1,"target":0, "pci-controller":{"bus":0,"slot":10,"domain":0,"function":0}}, {"bus-type":"ide","bus":0,"unit":0,"target":0, "pci-controller":{"bus":0,"slot":1,"domain":0,"function":1}}], "type":"xfs"}, {"name":"vda1", "mountpoint":"/", "disk":[ {"bus-type":"virtio","bus":0,"unit":0,"target":0, "pci-controller":{"bus":0,"slot":6,"domain":0,"function":0}}], "type":"ext4"}]} Signed-off-by: Tomoki Sekiyama --- qga/commands-posix.c | 420 ++- qga/qapi-schema.json | 77 ++ 2 files changed, 496 insertions(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 771f00c..212913a 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -575,6 +576,7 @@ static void guest_file_init(void) typedef struct FsMount { char *dirname; char *devtype; +unsigned int devmajor, devminor; QTAILQ_ENTRY(FsMount) next; } FsMount; @@ -596,15 +598,40 @@ static void free_fs_mount_list(FsMountList *mounts) } } +static int dev_major_minor(const char *devpath, + unsigned int *devmajor, unsigned int *devminor) +{ +struct stat st; + +*devmajor = 0; +*devminor = 0; + +if (stat(devpath, &st) < 0) { +slog("failed to stat device file '%s': %s", devpath, strerror(errno)); +return -1; +} +if (S_ISDIR(st.st_mode)) { +/* It is bind mount */ +return -2; +} +if (S_ISBLK(st.st_mode)) { +*devmajor = major(st.st_rdev); +*devminor = minor(st.st_rdev); +return 0; +} +return -1; +} + /* * Walk the mount table and build a list of local file systems */ -static void build_fs_mount_list(FsMountList *mounts, Error **errp) +static void build_fs_mount_list_from_mtab(FsMountList *mounts, Error **errp) { struct mntent *ment; FsMount *mount; char const *mtab = "/proc/self/mounts"; FILE *fp; +unsigned int devmajor, devminor; fp = setmntent(mtab, "r"); if (!fp) { @@ -624,20 +651,36
Re: [Qemu-devel] [PATCH v2] qga: Add 'mountpoints' argument to guest-fsfreeze-freeze command
Hi Eric, thank you for the comments. On 5/20/14 18:46 , "Eric Blake" wrote: >On 05/20/2014 04:01 PM, Tomoki Sekiyama wrote: >> The patch below is for the command to get filesystems list. >> >> === >> From: Tomoki Sekiyama > >You'll want to resend it as a series of patches as a top-level thread; >not everyone notices a patch buried as a reply. OK. I will resend as a series (with a fix below). >> >> qga: Add guest-get-fs-info command >> >> Add command to get mounted filesystems information in the guest. >> The returned value contains a list of mountpoint paths and >> corresponding disks info such as disk bus type, drive address, >> and the disk controllers' PCI addresses, so that management layer >> such as libvirt can resolve the disk backends. >> In Linux guest, the disk information is resolved from sysfs. >> >> guest-get-fs-info command will return the following result: >> >> {"return": >> [{"name":"dm-1", >>"mountpoint":"/mnt/test", >>"disk":[ >> {"bus-type":"scsi","bus":0,"unit":1,"target":0, >> "pci-controller":{"bus":0,"slot":10,"domain":0,"function":0}}, >> {"bus-type":"ide","bus":0,"unit":0,"target":0, >> "pci-controller":{"bus":0,"slot":1,"domain":0,"function":1}}], >>"type":"xfs"}, > >Definitely looks like a useful set of information. I have not reviewed >the patch closely, but it looks like you have a good API for Linux. I'm >a bit worried that it might be hard to translate this API into non-Linux >guests, but it still seems generic enough; and the argument also holds >that if this command is not implemented, the guest does not support >partial freezing. >>+++ b/qga/qapi-schema.json >> @@ -646,3 +646,80 @@ >> { 'command': 'guest-set-vcpus', >>'data':{'vcpus': ['GuestLogicalProcessor'] }, > >> + >> +## >> +# @GuestFilesystemInfo >> +# >> +# @name: disk name >> +# @mountpoint: mount point path >> +# @type: file system type string >> +# @disk: an array of disk hardware informations that the volume lies on > >s/informations/information/ Will fix it. >> +# >> +# Since: 2.1 >> +## >> +{ 'type': 'GuestFilesystemInfo', >> + 'data': {'name': 'str', 'mountpoint': 'str', 'type': 'str', >> + '*disk': ['GuestDiskAddress']} } > >Why is the array optional? Is it something where an empty array has >different meaning than omitting the array altogether? Not actually. Currently it omits the array when the disk type is not supported (non-PCI device like floppy disks or SD cards). But it can be replaced with an empty array if preferable. >>+ >> +## >> +# @guest-get-fs-info: >> +# >> +# Returns: The list of filesystems information mounted in the guest. >> +# The returned mountpoints may be specified to >>@guest-fsfreeze-freeze. >> +# Network filesystems (such as CIFS and NFS) are not listed. >> +# >> +# Since: 2.1 >> +## >> +{ 'command': 'guest-get-fs-info', >> + 'returns': ['GuestFilesystemInfo'] } > >Should this command support an optional input argument '*name':'str' >that filters the results to a one-element array about that one named >mountpoint? Hmm, I don't have specific use-cases for the name argument. As other commands like 'guest-network-get-interfaces' don't have a such filter, I don't have a reason to give a filter for this command. Anyway, the caller can easily filter the result by him/herself. Regards, Tomoki Sekiyama
[Qemu-devel] [PATCH v3 2/2] qga: Add guest-get-fs-info command
Add command to get mounted filesystems information in the guest. The returned value contains a list of mountpoint paths and corresponding disks info such as disk bus type, drive address, and the disk controllers' PCI addresses, so that management layer such as libvirt can resolve the disk backends. For example, when `lsblk' result is: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdb 8:16 01G 0 disk `-sdb1 8:17 0 1024M 0 part `-vg0-lv0253:10 1.4G 0 lvm /mnt/test sdc 8:32 01G 0 disk `-sdc1 8:33 0 512M 0 part `-vg0-lv0253:10 1.4G 0 lvm /mnt/test vda252:00 25G 0 disk `-vda1 252:10 25G 0 part / where sdb is a SCSI disk with PCI controller :00:0a.0 and ID=1, sdc is an IDE disk with PCI controller :00:01.1, and vda is a virtio-blk disk with PCI device :00:06.0, guest-get-fs-info command will return the following result: {"return": [{"name":"dm-1", "mountpoint":"/mnt/test", "disk":[ {"bus-type":"scsi","bus":0,"unit":1,"target":0, "pci-controller":{"bus":0,"slot":10,"domain":0,"function":0}}, {"bus-type":"ide","bus":0,"unit":0,"target":0, "pci-controller":{"bus":0,"slot":1,"domain":0,"function":1}}], "type":"xfs"}, {"name":"vda1", "mountpoint":"/", "disk":[ {"bus-type":"virtio","bus":0,"unit":0,"target":0, "pci-controller":{"bus":0,"slot":6,"domain":0,"function":0}}], "type":"ext4"}]} In Linux guest, the disk information is resolved from sysfs. So far, it only supports virtio-blk, virtio-scsi, IDE, SATA, SCSI disks on x86 hosts, and "disk" parameter may be empty for unsupported disk types. Signed-off-by: Tomoki Sekiyama --- qga/commands-posix.c | 420 ++ qga/qapi-schema.json | 78 + 2 files changed, 497 insertions(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 771f00c..c7a2c09 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -575,6 +576,7 @@ static void guest_file_init(void) typedef struct FsMount { char *dirname; char *devtype; +unsigned int devmajor, devminor; QTAILQ_ENTRY(FsMount) next; } FsMount; @@ -596,15 +598,40 @@ static void free_fs_mount_list(FsMountList *mounts) } } +static int dev_major_minor(const char *devpath, + unsigned int *devmajor, unsigned int *devminor) +{ +struct stat st; + +*devmajor = 0; +*devminor = 0; + +if (stat(devpath, &st) < 0) { +slog("failed to stat device file '%s': %s", devpath, strerror(errno)); +return -1; +} +if (S_ISDIR(st.st_mode)) { +/* It is bind mount */ +return -2; +} +if (S_ISBLK(st.st_mode)) { +*devmajor = major(st.st_rdev); +*devminor = minor(st.st_rdev); +return 0; +} +return -1; +} + /* * Walk the mount table and build a list of local file systems */ -static void build_fs_mount_list(FsMountList *mounts, Error **errp) +static void build_fs_mount_list_from_mtab(FsMountList *mounts, Error **errp) { struct mntent *ment; FsMount *mount; char const *mtab = "/proc/self/mounts"; FILE *fp; +unsigned int devmajor, devminor; fp = setmntent(mtab, "r"); if (!fp) { @@ -624,20 +651,368 @@ static void build_fs_mount_list(FsMountList *mounts, Error **errp) (strcmp(ment->mnt_type, "cifs") == 0)) { continue; } +if (dev_major_minor(ment->mnt_fsname, &devmajor, &devminor) == -2) { +/* Skip bind mounts */ +continue; +} mount = g_malloc0(sizeof(FsMount)); mount->dirname = g_strdup(ment->mnt_dir); mount->devtype = g_strdup(ment->mnt_type); +mount->devmajor = devmajor; +mount->devminor = devminor; QTAILQ_INSERT_TAIL(mounts, mount, next); } endmntent(fp); } + +static void decode_mntname(char *name, int len) +{ +int i, j = 0; +for (i = 0; i <= len; i++) { +if (name[i] != '\\') { +name[j++] = name[i]; +} else if (name[i+1] == '\\') { +
[Qemu-devel] [PATCH v3 1/2] qga: Add 'mountpoints' argument to guest-fsfreeze-freeze command
When an array of mount point paths is specified as 'mountpoints' argument of guest-fsfreeze-freeze, qemu-ga with this patch will only freeze the file systems mounted on specified paths in Linux. This would be useful when the host wants to create partial disk snapshots. Signed-off-by: Tomoki Sekiyama --- qga/commands-posix.c | 17 - qga/commands-win32.c |3 ++- qga/qapi-schema.json |4 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 34ddba0..771f00c 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -714,9 +714,11 @@ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) * Walk list of mounted file systems in the guest, and freeze the ones which * are real local file systems. */ -int64_t qmp_guest_fsfreeze_freeze(Error **errp) +int64_t qmp_guest_fsfreeze_freeze(bool has_mountpoints, strList *mountpoints, + Error **errp) { int ret = 0, i = 0; +strList *list; FsMountList mounts; struct FsMount *mount; Error *local_err = NULL; @@ -741,6 +743,19 @@ int64_t qmp_guest_fsfreeze_freeze(Error **errp) ga_set_frozen(ga_state); QTAILQ_FOREACH_REVERSE(mount, &mounts, FsMountList, next) { +/* To issue fsfreeze in the reverse order of mounts, check if the + * mount is listed in the list here */ +if (has_mountpoints) { +for (list = mountpoints; list; list = list->next) { +if (strcmp(list->value, mount->dirname) == 0) { +break; +} +} +if (!list) { +continue; +} +} + fd = qemu_open(mount->dirname, O_RDONLY); if (fd == -1) { error_setg_errno(errp, errno, "failed to open %s", mount->dirname); diff --git a/qga/commands-win32.c b/qga/commands-win32.c index d793dd0..0c6296d 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -171,7 +171,8 @@ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) * Freeze local file systems using Volume Shadow-copy Service. * The frozen state is limited for up to 10 seconds by VSS. */ -int64_t qmp_guest_fsfreeze_freeze(Error **errp) +int64_t qmp_guest_fsfreeze_freeze(bool has_mountpoints, strList *mountpoints, + Error **errp) { int i; Error *local_err = NULL; diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index a8cdcb3..31c0dc8 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -378,12 +378,16 @@ # # Sync and freeze all freezable, local guest filesystems # +# @mountpoints: #optional an array of mountpoints of filesystems to be frozen. +# If omitted, every mounted filesystem is frozen. (Since: 2.1) +# # Returns: Number of file systems currently frozen. On error, all filesystems # will be thawed. # # Since: 0.15.0 ## { 'command': 'guest-fsfreeze-freeze', + 'data':{ '*mountpoints': ['str'] }, 'returns': 'int' } ##
[Qemu-devel] [PATCH v3 0/2] qga: Add 'mountpoints' argument to guest-fsfreeze-freeze command
Hi, This is v3 patch for qemu-ga to add argument to specify which filesystems to be frozen by guest-fsfreeze-freeze command. Changes since v2: - new PATCH 2/2 to add a command 'guest-get-fs-info' get mounted filesysmtes information - rebased to latest master (v2: http://lists.gnu.org/archive/html/qemu-devel/2014-04/msg04433.html) --- Tomoki Sekiyama (2): qga: Add 'mountpoints' argument to guest-fsfreeze-freeze command qga: Add guest-get-fs-info command qga/commands-posix.c | 437 ++ qga/commands-win32.c |3 qga/qapi-schema.json | 82 + 3 files changed, 519 insertions(+), 3 deletions(-) -- Regards, Tomoki Sekiyama
[Qemu-devel] [PATCH 0/2] qga: vss-win32: Fix build failure
Hello, These patches are to fix recent build failures of qemu-guest-agent for Windows when fsfreeze using VSS is enabled by: ./configure --cross-prefix=i686-w64-mingw32- --with-vss-sdk=yes --- Tomoki Sekiyama (2): Makefile: add qga-vss-dll-obj-y to nested variables vss-win32: Fix build with mingw64-headers-3.1.0 Makefile |1 + qga/vss-win32/install.cpp |3 +++ 2 files changed, 4 insertions(+) -- Tomoki Sekiyama
[Qemu-devel] [PATCH 1/2] Makefile: add qga-vss-dll-obj-y to nested variables
The build rule for qga/vss-win32/qga-vss.dll is broken by commit ba1183da9a10b94611cad88c44a5c6df005f9b55, because it misses qga-vss-dll-obj-y in the list of nested variables. This fixes build of qga-vss.dll by adding qga-vss-dll-obj-y to the list. Signed-off-by: Tomoki Sekiyama --- Makefile |1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index ec74039..b6b09a9 100644 --- a/Makefile +++ b/Makefile @@ -133,6 +133,7 @@ dummy := $(call unnest-vars,, \ stub-obj-y \ util-obj-y \ qga-obj-y \ +qga-vss-dll-obj-y \ block-obj-y \ block-obj-m \ common-obj-y \
[Qemu-devel] [PATCH 2/2] vss-win32: Fix build with mingw64-headers-3.1.0
In mingw64-headers-3.1.0, definition of _com_issue_error() is added, which conflicts with definition in install.cpp. This adds version checking for mingw headers to disable the definition when the headers>=3.1 is used. Signed-off-by: Tomoki Sekiyama --- qga/vss-win32/install.cpp |3 +++ 1 file changed, 3 insertions(+) diff --git a/qga/vss-win32/install.cpp b/qga/vss-win32/install.cpp index b791a6c..b0e4426 100644 --- a/qga/vss-win32/install.cpp +++ b/qga/vss-win32/install.cpp @@ -75,10 +75,13 @@ static void errmsg_dialog(DWORD err, const char *text, const char *opt = "") #define chk(status) _chk(hr, status, "Failed to " #status, out) +#if !defined(__MINGW64_VERSION_MAJOR) || !defined(__MINGW64_VERSION_MINOR) || \ +__MINGW64_VERSION_MAJOR * 100 + __MINGW64_VERSION_MINOR < 301 void __stdcall _com_issue_error(HRESULT hr) { errmsg(hr, "Unexpected error in COM"); } +#endif template HRESULT put_Value(ICatalogObject *pObj, LPCWSTR name, T val)
[Qemu-devel] [PATCH 0/3] qga: vss-win32: Fix interference with other VSS requesters
Current functionarity of qemu-ga VSS provider is limited to implement filesystems freeze, and doesn't support the creation of shadow copies within the guest. However, when no other hardware snapshot provider is installed, VSS may choose qemu-ga VSS provider to create shadow copies and fail with VSS_E_UNEXPECTED_PROVIDER_ERROR. Similar issue occurs when the requester deletes shadow copies. This patchset fix this issue by telling VSS that the volume is not supported by qemu-ga VSS provider when it is kicked by other requesters. It also fixes wrong error handling around OpenEvent/CreateEvent WinAPI, which returns NULL instead of INVALID_HANDLE_VALUE on errors. https://bugzilla.redhat.com/show_bug.cgi?id=1036341 --- Tomoki Sekiyama (3): qga: vss-win32: Use NULL as an invalid pointer for OpenEvent and CreateEvent qga: vss-win32: Fix interference with snapshot creation by other VSS requesters qga: vss-win32: Fix interference with snapshot deletion by other VSS request qga/vss-win32/provider.cpp | 21 ++--- qga/vss-win32/requester.cpp | 70 --- 2 files changed, 49 insertions(+), 42 deletions(-) -- Tomoki Sekiyama
[Qemu-devel] [PATCH 2/3] qga: vss-win32: Fix interference with snapshot creation by other VSS requesters
When a VSS requester such as vshadow.exe or diskshadow.exe requests to create disk snapshots, Windows may choose qemu-ga VSS provider if it is only provider registered on the system. However, because it provides only a function to freeze the filesystem, the snapshotting fails. This patch adds a check into CQGAVssProvider::IsVolumeSupported() to reject the request from other VSS requesters, so that the other provider is chosen. The check of requester is done by confirming event channels between qemu-ga's requester and provider established. To ensure that the events are initialized when CQGAVssProvider::IsVolumeSupported() is called, it moves the initialization earlier. Signed-off-by: Tomoki Sekiyama --- qga/vss-win32/provider.cpp | 11 - qga/vss-win32/requester.cpp | 52 ++- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/qga/vss-win32/provider.cpp b/qga/vss-win32/provider.cpp index c3030d8..b233646 100644 --- a/qga/vss-win32/provider.cpp +++ b/qga/vss-win32/provider.cpp @@ -291,8 +291,17 @@ STDMETHODIMP CQGAVssProvider::BeginPrepareSnapshot( STDMETHODIMP CQGAVssProvider::IsVolumeSupported( VSS_PWSZ pwszVolumeName, BOOL *pbSupportedByThisProvider) { -*pbSupportedByThisProvider = TRUE; +HANDLE hEventFrozen; + +/* Check if a requester is qemu-ga by whether an event is created */ +hEventFrozen = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_FROZEN); +if (!hEventFrozen) { +*pbSupportedByThisProvider = FALSE; +return S_OK; +} +CloseHandle(hEventFrozen); +*pbSupportedByThisProvider = TRUE; return S_OK; } diff --git a/qga/vss-win32/requester.cpp b/qga/vss-win32/requester.cpp index 0a55447..922e74d 100644 --- a/qga/vss-win32/requester.cpp +++ b/qga/vss-win32/requester.cpp @@ -252,6 +252,32 @@ void requester_freeze(int *num_vols, ErrorSet *errset) CoInitialize(NULL); +/* Allow unrestricted access to events */ +InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); +SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); +sa.nLength = sizeof(sa); +sa.lpSecurityDescriptor = &sd; +sa.bInheritHandle = FALSE; + +vss_ctx.hEventFrozen = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_FROZEN); +if (!vss_ctx.hEventFrozen) { +err_set(errset, GetLastError(), "failed to create event %s", +EVENT_NAME_FROZEN); +goto out; +} +vss_ctx.hEventThaw = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_THAW); +if (!vss_ctx.hEventThaw) { +err_set(errset, GetLastError(), "failed to create event %s", +EVENT_NAME_THAW); +goto out; +} +vss_ctx.hEventTimeout = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_TIMEOUT); +if (!vss_ctx.hEventTimeout) { +err_set(errset, GetLastError(), "failed to create event %s", +EVENT_NAME_TIMEOUT); +goto out; +} + assert(pCreateVssBackupComponents != NULL); hr = pCreateVssBackupComponents(&vss_ctx.pVssbc); if (FAILED(hr)) { @@ -362,32 +388,6 @@ void requester_freeze(int *num_vols, ErrorSet *errset) goto out; } -/* Allow unrestricted access to events */ -InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); -SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); -sa.nLength = sizeof(sa); -sa.lpSecurityDescriptor = &sd; -sa.bInheritHandle = FALSE; - -vss_ctx.hEventFrozen = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_FROZEN); -if (!vss_ctx.hEventFrozen) { -err_set(errset, GetLastError(), "failed to create event %s", -EVENT_NAME_FROZEN); -goto out; -} -vss_ctx.hEventThaw = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_THAW); -if (!vss_ctx.hEventThaw) { -err_set(errset, GetLastError(), "failed to create event %s", -EVENT_NAME_THAW); -goto out; -} -vss_ctx.hEventTimeout = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_TIMEOUT); -if (!vss_ctx.hEventTimeout) { -err_set(errset, GetLastError(), "failed to create event %s", -EVENT_NAME_TIMEOUT); -goto out; -} - /* * Start VSS quiescing operations. * CQGAVssProvider::CommitSnapshots will kick vss_ctx.hEventFrozen
[Qemu-devel] [PATCH 1/3] qga: vss-win32: Use NULL as an invalid pointer for OpenEvent and CreateEvent
OpenEvent and CreateEvent WinAPI return NULL when failed to open/create events handles, instead of INVALID_HANDLE_VALUE (although their return types are HANDLE). This replaces INVALID_HANDLE_VALUE related to event handles with NULL. Signed-off-by: Tomoki Sekiyama --- qga/vss-win32/provider.cpp |6 +++--- qga/vss-win32/requester.cpp | 24 ++-- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/qga/vss-win32/provider.cpp b/qga/vss-win32/provider.cpp index bf42b5e..c3030d8 100644 --- a/qga/vss-win32/provider.cpp +++ b/qga/vss-win32/provider.cpp @@ -342,18 +342,18 @@ STDMETHODIMP CQGAVssProvider::CommitSnapshots(VSS_ID SnapshotSetId) HANDLE hEventFrozen, hEventThaw, hEventTimeout; hEventFrozen = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_FROZEN); -if (hEventFrozen == INVALID_HANDLE_VALUE) { +if (!hEventFrozen) { return E_FAIL; } hEventThaw = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_THAW); -if (hEventThaw == INVALID_HANDLE_VALUE) { +if (!hEventThaw) { CloseHandle(hEventFrozen); return E_FAIL; } hEventTimeout = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_TIMEOUT); -if (hEventTimeout == INVALID_HANDLE_VALUE) { +if (!hEventTimeout) { CloseHandle(hEventFrozen); CloseHandle(hEventThaw); return E_FAIL; diff --git a/qga/vss-win32/requester.cpp b/qga/vss-win32/requester.cpp index 1e8dd3d..0a55447 100644 --- a/qga/vss-win32/requester.cpp +++ b/qga/vss-win32/requester.cpp @@ -50,10 +50,6 @@ static struct QGAVSSContext { STDAPI requester_init(void) { -vss_ctx.hEventFrozen = INVALID_HANDLE_VALUE; -vss_ctx.hEventThaw = INVALID_HANDLE_VALUE; -vss_ctx.hEventTimeout = INVALID_HANDLE_VALUE; - COMInitializer initializer; /* to call CoInitializeSecurity */ HRESULT hr = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, @@ -94,17 +90,17 @@ STDAPI requester_init(void) static void requester_cleanup(void) { -if (vss_ctx.hEventFrozen != INVALID_HANDLE_VALUE) { +if (vss_ctx.hEventFrozen) { CloseHandle(vss_ctx.hEventFrozen); -vss_ctx.hEventFrozen = INVALID_HANDLE_VALUE; +vss_ctx.hEventFrozen = NULL; } -if (vss_ctx.hEventThaw != INVALID_HANDLE_VALUE) { +if (vss_ctx.hEventThaw) { CloseHandle(vss_ctx.hEventThaw); -vss_ctx.hEventThaw = INVALID_HANDLE_VALUE; +vss_ctx.hEventThaw = NULL; } -if (vss_ctx.hEventTimeout != INVALID_HANDLE_VALUE) { +if (vss_ctx.hEventTimeout) { CloseHandle(vss_ctx.hEventTimeout); -vss_ctx.hEventTimeout = INVALID_HANDLE_VALUE; +vss_ctx.hEventTimeout = NULL; } if (vss_ctx.pAsyncSnapshot) { vss_ctx.pAsyncSnapshot->Release(); @@ -374,19 +370,19 @@ void requester_freeze(int *num_vols, ErrorSet *errset) sa.bInheritHandle = FALSE; vss_ctx.hEventFrozen = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_FROZEN); -if (vss_ctx.hEventFrozen == INVALID_HANDLE_VALUE) { +if (!vss_ctx.hEventFrozen) { err_set(errset, GetLastError(), "failed to create event %s", EVENT_NAME_FROZEN); goto out; } vss_ctx.hEventThaw = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_THAW); -if (vss_ctx.hEventThaw == INVALID_HANDLE_VALUE) { +if (!vss_ctx.hEventThaw) { err_set(errset, GetLastError(), "failed to create event %s", EVENT_NAME_THAW); goto out; } vss_ctx.hEventTimeout = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_TIMEOUT); -if (vss_ctx.hEventTimeout == INVALID_HANDLE_VALUE) { +if (!vss_ctx.hEventTimeout) { err_set(errset, GetLastError(), "failed to create event %s", EVENT_NAME_TIMEOUT); goto out; @@ -443,7 +439,7 @@ void requester_thaw(int *num_vols, ErrorSet *errset) { COMPointer pAsync; -if (vss_ctx.hEventThaw == INVALID_HANDLE_VALUE) { +if (!vss_ctx.hEventThaw) { /* * In this case, DoSnapshotSet is aborted or not started, * and no volumes must be frozen. We return without an error.
[Qemu-devel] [PATCH 3/3] qga: vss-win32: Fix interference with snapshot deletion by other VSS request
When a VSS requester such as vshadow.exe or diskshadow.exe requests to delete snapshots, qemu-ga VSS provider's DeleteSnapshots() is also called and returns E_NOTIMPL, that makes the deletion fail. To avoid this issue, return S_OK and set values that represent no snapshots are deleted by qemu-ga VSS provider. Signed-off-by: Tomoki Sekiyama --- qga/vss-win32/provider.cpp |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qga/vss-win32/provider.cpp b/qga/vss-win32/provider.cpp index b233646..d5129f8 100644 --- a/qga/vss-win32/provider.cpp +++ b/qga/vss-win32/provider.cpp @@ -278,7 +278,9 @@ STDMETHODIMP CQGAVssProvider::DeleteSnapshots( VSS_ID SourceObjectId, VSS_OBJECT_TYPE eSourceObjectType, BOOL bForceDelete, LONG *plDeletedSnapshots, VSS_ID *pNondeletedSnapshotID) { -return E_NOTIMPL; +*plDeletedSnapshots = 0; +*pNondeletedSnapshotID = SourceObjectId; +return S_OK; } STDMETHODIMP CQGAVssProvider::BeginPrepareSnapshot(
Re: [Qemu-devel] [RFC PATCH v2 00/11] qemu-ga: fsfreeze on Windows using VSS
Hi, On 4/23/13 12:44 , "Tomoki Sekiyama" wrote: >>2 executing the command "{"execute":"guest-fsfreeze-freeze"}" >>failed,the output is: > >> {"execute":"guest-fsfreeze-freeze"} >> {"error": {"class": "GenericError", "desc": "Failed to >>pVssbc->SetContext. (Error: 8004231b) "}} >> >> Could you give me some advise to debug this problem ? I can provide more >>information if need. > >Is there any logs corresponding to the error in Event Viewer? > >And this might be caused by unsupported VSS_VOLSNAP_ATTR_* flags in >SetContext() >called from qga_vss_fsfreeze_freeze() at qga/vss-win32-requester.cpp, >but I couldn't find out flags not supported on Windows 7 from VSS >references. I'm investigating this issue. Some versions of Windows seem to ignore VSS_VOLSNAP_ATTR_NO_AUTORECOVERY, and to cause an error with VSS_VOLSNAP_ATTR_TRANSPORTABLE. In such cases, we cannot disable Auto-recovery that requires writable snapshots we don't yet support. Because of this, even if we remove TRANSPORTABLE flag, auto-recovery would be enabled and cause another error (VSS_E_OBJECT_NOT_FOUND) on thaw. The patch attached (to be applied after v2 patch) removes TRANSPORTABLE flag, and ignores the VSS_E_OBJECT_NOT_FOUND error on thaw. I think this should resolve the issue in Windows 7, and also works in the other versions of Windows. Could you try this? If it works, I will merge this into my path set and resend it as v3. Thanks, Tomoki Sekiyama ignore-notfound.patch Description: ignore-notfound.patch
[Qemu-devel] [RFC PATCH v3 02/11] Fix errors and warnings while compiling with c++ compilier
Add C++ keywords to avoid errors in compiling with c++ compiler. This also renames class member of PciDeviceInfo to q_class. Signed-off-by: Tomoki Sekiyama --- hmp.c |2 +- hw/pci/pci.c|2 +- scripts/qapi.py |9 - 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/hmp.c b/hmp.c index 4fb76ec..cb0ed3b 100644 --- a/hmp.c +++ b/hmp.c @@ -484,7 +484,7 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) if (dev->class_info.has_desc) { monitor_printf(mon, "%s", dev->class_info.desc); } else { -monitor_printf(mon, "Class %04" PRId64, dev->class_info.class); +monitor_printf(mon, "Class %04" PRId64, dev->class_info.q_class); } monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n", diff --git a/hw/pci/pci.c b/hw/pci/pci.c index d5257ed..a3eaf47 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1460,7 +1460,7 @@ static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus, info->function = PCI_FUNC(dev->devfn); class = pci_get_word(dev->config + PCI_CLASS_DEVICE); -info->class_info.class = class; +info->class_info.q_class = class; desc = get_class_desc(class); if (desc->desc) { info->class_info.has_desc = true; diff --git a/scripts/qapi.py b/scripts/qapi.py index afc5f32..b174acb 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -156,9 +156,16 @@ def c_var(name, protect=True): # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html # excluding _.* gcc_words = set(['asm', 'typeof']) +# C++ ISO/IEC 14882:2003 2.11 +cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete', + 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable', + 'namespace', 'new', 'operator', 'private', 'protected', + 'public', 'reinterpret_cast', 'static_cast', 'template', + 'this', 'throw', 'true', 'try', 'typeid', 'typename', + 'using', 'virtual', 'wchar_t']) # namespace pollution: polluted_words = set(['unix']) -if protect and (name in c89_words | c99_words | c11_words | gcc_words | polluted_words): +if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words): return "q_" + name return name.replace('-', '_').lstrip("*")
[Qemu-devel] [RFC PATCH v3 01/11] configure: Support configuring c++ compiler
Add configuration for c++ compiler (${corss_prefix}g++ as default) in configure and Makefiles. Currently, usage of c++ language is only for access to Windows VSS using COM+ services in qemu-guest-agent for Windows. Signed-off-by: Tomoki Sekiyama --- configure |6 ++ rules.mak |9 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 5ae7e4a..1af2f37 100755 --- a/configure +++ b/configure @@ -280,6 +280,7 @@ else cc="${CC-${cross_prefix}gcc}" fi +cxx="${CXX-${cross_prefix}g++}" ar="${AR-${cross_prefix}ar}" as="${AS-${cross_prefix}as}" cpp="${CPP-$cc -E}" @@ -614,6 +615,8 @@ for opt do ;; --host-cc=*) host_cc="$optarg" ;; + --cxx=*) cxx="$optarg" + ;; --objcc=*) objcc="$optarg" ;; --make=*) make="$optarg" @@ -1069,6 +1072,7 @@ echo " --cross-prefix=PREFIXuse PREFIX for compile tools [$cross_prefix]" echo " --cc=CC use C compiler CC [$cc]" echo " --host-cc=CC use C compiler CC [$host_cc] for code run at" echo " build time" +echo " --cxx=CXXuse C++ compiler CXX [$cxx]" echo " --objcc=OBJCCuse Objective-C compiler OBJCC [$objcc]" echo " --extra-cflags=CFLAGSappend extra C compiler flags QEMU_CFLAGS" echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS" @@ -3496,6 +3500,7 @@ fi echo "Source path $source_path" echo "C compiler$cc" echo "Host C compiler $host_cc" +echo "C++ compiler $cxx" echo "Objective-C compiler $objcc" echo "CFLAGS$CFLAGS" echo "QEMU_CFLAGS $QEMU_CFLAGS" @@ -4069,6 +4074,7 @@ echo "PYTHON=$python" >> $config_host_mak echo "CC=$cc" >> $config_host_mak echo "CC_I386=$cc_i386" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak +echo "CXX=$cxx" >> $config_host_mak echo "OBJCC=$objcc" >> $config_host_mak echo "AR=$ar" >> $config_host_mak echo "AS=$as" >> $config_host_mak diff --git a/rules.mak b/rules.mak index 4499745..abc2e84 100644 --- a/rules.mak +++ b/rules.mak @@ -8,9 +8,13 @@ MAKEFLAGS += -rR %.d: %.h: %.c: +%.cpp: %.m: %.mak: +# Flags for C++ compilation +QEMU_CXXFLAGS = -D__STDC_LIMIT_MACROS $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls, $(QEMU_CFLAGS)) + # Flags for dependency generation QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d @@ -50,6 +54,9 @@ endif %.o: %.asm $(call quiet-command,$(AS) $(ASFLAGS) -o $@ $<," AS $(TARGET_DIR)$@") +%.o: %.cpp + $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CXX $(TARGET_DIR)$@") + %.o: %.m $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@") @@ -70,7 +77,7 @@ quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1)) cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \ >/dev/null 2>&1 && echo OK), $2, $3) -VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.sh %.rc +VPATH_SUFFIXES = %.c %.h %.S %.cpp %.m %.mak %.texi %.sh %.rc set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) # find-in-path
[Qemu-devel] [RFC PATCH v3 08/11] qemu-ga: install Windows VSS provider on `qemu-ga -s install'
Register QGA VSS provider library into Windows when qemu-ga is installed as Windows service ('-s install' option). It is deregistered when the service is uninstalled ('-s uninstall' option). Signed-off-by: Tomoki Sekiyama --- qga/main.c |8 1 file changed, 8 insertions(+) diff --git a/qga/main.c b/qga/main.c index 3ffba14..377b4be 100644 --- a/qga/main.c +++ b/qga/main.c @@ -1029,8 +1029,16 @@ int main(int argc, char **argv) case 's': service = optarg; if (strcmp(service, "install") == 0) { +#ifdef HAS_VSS_SDK +if (FAILED(COMRegister())) { +return EXIT_FAILURE; +} +#endif return ga_install_service(path, log_filepath); } else if (strcmp(service, "uninstall") == 0) { +#ifdef HAS_VSS_SDK +COMUnregister(); +#endif return ga_uninstall_service(); } else { printf("Unknown service command.\n");
[Qemu-devel] [RFC PATCH v3 10/11] QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command
guest-fsfreeze-freeze command can take longer than 3 seconds when heavy disk I/O is running. To avoid unexpected timeout, this changes the timeout to 30 seconds. Signed-off-by: Tomoki Sekiyama --- QMP/qemu-ga-client |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/QMP/qemu-ga-client b/QMP/qemu-ga-client index 46676c3..1f7011a 100755 --- a/QMP/qemu-ga-client +++ b/QMP/qemu-ga-client @@ -267,7 +267,9 @@ def main(address, cmd, args): print('Hint: qemu is not running?') sys.exit(1) -if cmd != 'ping': +if cmd == 'fsfreeze' and args[0] == 'freeze': +client.sync(30) +elif cmd != 'ping': client.sync() globals()['_cmd_' + cmd](client, args)
[Qemu-devel] [RFC PATCH v3 03/11] Add a script to extract VSS SDK headers on POSIX system
VSS SDK(*) setup.exe is only runnable on Windows. This adds a script to extract VSS SDK headers on POSIX-systems using msitools. * http://www.microsoft.com/en-us/download/details.aspx?id=23490 From: Paolo Bonzini Signed-off-by: Tomoki Sekiyama --- scripts/extract-vsssdk-headers | 25 + 1 file changed, 25 insertions(+) create mode 100755 scripts/extract-vsssdk-headers diff --git a/scripts/extract-vsssdk-headers b/scripts/extract-vsssdk-headers new file mode 100755 index 000..5877137 --- /dev/null +++ b/scripts/extract-vsssdk-headers @@ -0,0 +1,25 @@ +#! /bin/bash + +# extract-vsssdk-headers +# Author: Paolo Bonzini + +set -e +if test $# = 0 || ! test -f "$1"; then + echo 'Usage: extract-vsssdk-headers /path/to/setup.exe' + exit 1 +fi + +# Extract .MSI file in the .exe, looking for the OLE compound +# document signature. Extra data at the end does not matter. +export LC_ALL=C +MAGIC=$'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1' +offset=`grep -abom1 "$MAGIC" "$1" | sed -n 's/:/\n/; P' ` +(dd of=/dev/null skip=$offset bs=1 count=0; cat) < "$1" > vsssdk.msi + +# Now extract the files. +tmpdir=tmp$$ +mkdir $tmpdir +msiextract -C $tmpdir vsssdk.msi +mv "$tmpdir/Program Files/Microsoft/VSSSDK72/inc" inc +rm -rf $tmpdir vsssdk.msi +exit 0
[Qemu-devel] [RFC PATCH v3 07/11] qemu-ga: call Windows VSS requester in fsfreeze command handler
Support guest-fsfreeze-freeze and guest-fsfreeze-thaw commands for Windows guests. When fsfreeze command is issued, it calls the VSS requester to freeze filesystems and applications. On thaw command, it again tells the VSS requester to thaw them. This also adds calling of initialize functions for the VSS requester. Signed-off-by: Tomoki Sekiyama --- qga/commands-win32.c | 74 ++ qga/main.c | 33 ++ 2 files changed, 100 insertions(+), 7 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 24e4ad0..67dca60 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -15,6 +15,7 @@ #include #include #include "qga/guest-agent-core.h" +#include "qga/vss-win32-requester.h" #include "qga-qmp-commands.h" #include "qapi/qmp/qerror.h" @@ -151,34 +152,95 @@ void qmp_guest_file_flush(int64_t handle, Error **err) error_set(err, QERR_UNSUPPORTED); } +#ifdef HAS_VSS_SDK + /* * Return status of freeze/thaw */ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) { -error_set(err, QERR_UNSUPPORTED); -return 0; +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +if (ga_is_frozen(ga_state)) { +return GUEST_FSFREEZE_STATUS_FROZEN; +} + +return GUEST_FSFREEZE_STATUS_THAWED; } /* - * Walk list of mounted file systems in the guest, and freeze the ones which - * are real local file systems. + * Freeze local file systems using Volume Shadow-copy Service. + * The frozen state is limited for up to 10 seconds by VSS. */ int64_t qmp_guest_fsfreeze_freeze(Error **err) { -error_set(err, QERR_UNSUPPORTED); +int i; + +slog("guest-fsfreeze called"); + +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +/* cannot risk guest agent blocking itself on a write in this state */ +ga_set_frozen(ga_state); + +qga_vss_fsfreeze_freeze(&i, err); +if (error_is_set(err)) { +goto error; +} + +return i; + +error: +qmp_guest_fsfreeze_thaw(NULL); return 0; } /* - * Walk list of frozen file systems in the guest, and thaw them. + * Thaw local file systems using Volume Shadow-copy Service. */ int64_t qmp_guest_fsfreeze_thaw(Error **err) { +int i; + +if (!vss_initialized()) { +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +qga_vss_fsfreeze_thaw(&i, err); + +ga_unset_frozen(ga_state); +return i; +} + +#else + +GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) +{ +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +int64_t qmp_guest_fsfreeze_freeze(Error **err) +{ +error_set(err, QERR_UNSUPPORTED); +return 0; +} + +int64_t qmp_guest_fsfreeze_thaw(Error **err) +{ error_set(err, QERR_UNSUPPORTED); return 0; } +#endif + /* * Walk list of mounted file systems in the guest, and discard unused * areas. diff --git a/qga/main.c b/qga/main.c index 44a2836..3ffba14 100644 --- a/qga/main.c +++ b/qga/main.c @@ -34,6 +34,10 @@ #include "qemu/bswap.h" #ifdef _WIN32 #include "qga/service-win32.h" +#ifdef HAS_VSS_SDK +#include "qga/vss-win32-provider.h" +#include "qga/vss-win32-requester.h" +#endif #include #endif #ifdef __linux__ @@ -685,6 +689,25 @@ static gboolean channel_init(GAState *s, const gchar *method, const gchar *path) } #ifdef _WIN32 + +static gboolean vss_win32_init(void) +{ +#ifdef HAS_VSS_SDK +if (FAILED(vss_init())) { +g_critical("failed to initialize VSS"); +return false; +} +#endif +return true; +} + +static void vss_win32_deinit(void) +{ +#ifdef HAS_VSS_SDK +vss_deinit(); +#endif +} + DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data, LPVOID ctx) { @@ -727,8 +750,12 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[]) service->status.dwWaitHint = 0; SetServiceStatus(service->status_handle, &service->status); +if (!vss_win32_init()) { +goto out_bad; +} g_main_loop_run(ga_state->main_loop); - +vss_win32_deinit(); +out_bad: service->status.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(service->status_handle, &service->status); } @@ -1132,7 +1159,11 @@ int main(int argc, char **argv) { (char *)QGA_SERVICE_NAME, service_main }, { NULL, NULL } }; StartServiceCtrlDispatcher(service_table); } else { +if (!vss_win32_init()) { +goto out_bad; +} g_main_loop_run(ga_state->main_loop); +vss_win32_deinit(); } #endif
[Qemu-devel] [RFC PATCH v3 06/11] qemu-ga: Add Windows VSS requester to quisce applications and filesystems
Add VSS requester functions for to qemu-ga. This provides facility to request VSS service in Windows guest to quisce applications and filesystems. This function is only supported in Windows 2003 or later. In older guests, this function does nothing. In several versions of Windows which don't support attribute VSS_VOLSNAP_ATTR_NO_AUTORECOVERY, DoSnapshotSet fails with error VSS_E_OBJECT_NOT_FOUND. In this patch, we just ignore this error. To solve this fundamentally, we need a framework to handle mount writable snapshot on guests, which is required by VSS auto-recovery feature (a cleanup phase after snapshot is taken). Signed-off-by: Tomoki Sekiyama --- qga/Makefile.objs |3 qga/vss-win32-requester.cpp | 404 +++ qga/vss-win32-requester.h | 31 +++ 3 files changed, 437 insertions(+), 1 deletion(-) create mode 100644 qga/vss-win32-requester.cpp create mode 100644 qga/vss-win32-requester.h diff --git a/qga/Makefile.objs b/qga/Makefile.objs index 8d93866..f17a380 100644 --- a/qga/Makefile.objs +++ b/qga/Makefile.objs @@ -6,6 +6,7 @@ qga-obj-y += qapi-generated/qga-qmp-marshal.o ifeq ($(CONFIG_QGA_VSS),y) QEMU_CFLAGS += -DHAS_VSS_SDK -qga-obj-y += vss-win32-provider/ +qga-obj-y += vss-win32-provider/ vss-win32-requester.o qga-prv-obj-y += vss-win32-provider/ +$(obj)/vss-win32-requester.o: QEMU_CXXFLAGS += -Wno-unknown-pragmas endif diff --git a/qga/vss-win32-requester.cpp b/qga/vss-win32-requester.cpp new file mode 100644 index 000..5a4653a --- /dev/null +++ b/qga/vss-win32-requester.cpp @@ -0,0 +1,404 @@ +/* + * QEMU Guest Agent win32 VSS Requester implementations + * + * Copyright Hitachi Data Systems Corp. 2013 + * + * Authors: + * Tomoki Sekiyama + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +extern "C" { +#include "guest-agent-core.h" +} +#include "vss-win32-requester.h" +#include "vss-win32-provider.h" +#include "vss-win32.h" +#include "inc/win2003/vswriter.h" +#include "inc/win2003/vsbackup.h" + +/* Functions in VSSAPI.DLL */ +typedef HRESULT (STDAPICALLTYPE* t_CreateVssBackupComponents)(OUT IVssBackupComponents **); +typedef void (APIENTRY* t_VssFreeSnapshotProperties)(IN VSS_SNAPSHOT_PROP*); + +static t_CreateVssBackupComponents _CreateVssBackupComponents = NULL; +static t_VssFreeSnapshotProperties _VssFreeSnapshotProperties = NULL; +static IVssBackupComponents *pVssbc = NULL; +static IVssAsync *pAsyncSnapshot = NULL; +static HMODULE hLib = NULL; +static HANDLE hEvent = INVALID_HANDLE_VALUE, hEvent2 = INVALID_HANDLE_VALUE; +static int cFrozenVols = 0; + +GCC_FMT_ATTR(1, 2) +static void errmsg(const char *fmt, ...) +{ +va_list ap; +va_start(ap, fmt); +char *msg = g_strdup_vprintf(fmt, ap); +va_end(ap); +MessageBox(NULL, msg, "Error in QEMU guest agent", MB_OK | MB_ICONWARNING); +g_free(msg); +} + +static void error_set_win32(Error **errp, DWORD err, +ErrorClass eclass, const char *text) +{ +char *msg = NULL, *nul = strchr(text, '('); +int len = nul ? nul - text : -1; + +/* print error message in native encoding */ +FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (char *)&msg, 0, NULL); +printf("%.*s. (Error: %lx) %s\n", len, text, err, msg); +LocalFree(msg); + +/* set error message in UTF-8 encoding */ +msg = g_win32_error_message(err); +error_set(errp, eclass, "%.*s. (Error: %lx) %s", len, text, err, msg); +g_free(msg); +} +#define error_setg_win32(errp, err, text) \ +error_set_win32(errp, err, ERROR_CLASS_GENERIC_ERROR, text) + +#define _chk(status, text, errp, err_label)\ +do {\ +HRESULT __hr = (status);\ +if (FAILED(__hr)) { \ +error_setg_win32(errp, __hr, text); \ +goto err_label; \ +} \ +} while(0) + +#define chk(status) _chk(status, "Failed to " #status, err, out) + + +HRESULT WaitForAsync(IVssAsync *pAsync) +{ +HRESULT ret, hr; + +do { +hr = pAsync->Wait(); +if (FAILED(hr)) { +ret = hr; +break; +} +hr = pAsync->QueryStatus(&ret, NULL); +if (FAILED(hr)) { +ret = hr; +break; +} +} while (ret == VSS_S_ASYNC_PENDING); + +return ret; +} + +HRESULT vss_init(void) +{ +HRESULT hr; + +hr = VSSCheckOSVersion(); +if (hr == S_FALSE) { +return hr; +} + +hr = CoInitialize(NULL); +i
[Qemu-devel] [RFC PATCH v3 04/11] qemu-ga: Add an configure option to specify path to Windows VSS SDK
To enable VSS support in qemu-ga for Windows, header files included in VSS SDK is required. The VSS support is enabled when the option like below: ./configure --with-vss-sdk="/pass/to/VSS SDK" VSS SDK is available from: http://www.microsoft.com/en-us/download/details.aspx?id=23490 To cross-compilie using mingw32 for Linux, you need to setup the SDK on Windows environments to extract headers. You can also extract the SDK headers using scripts/extract-vss-headers, written by Paolo Bonzini. Signed-off-by: Tomoki Sekiyama --- .gitignore |1 + Makefile |1 + configure | 48 3 files changed, 50 insertions(+) diff --git a/.gitignore b/.gitignore index 64e9466..67facd3 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ fsdev/virtfs-proxy-helper.pod *.la *.pc .libs +.sdk *.swp *.orig .pc diff --git a/Makefile b/Makefile index 7dc0204..b87cc5a 100644 --- a/Makefile +++ b/Makefile @@ -272,6 +272,7 @@ distclean: clean for d in $(TARGET_DIRS); do \ rm -rf $$d || exit 1 ; \ done + rm -Rf .sdk if test -f pixman/config.log; then make -C pixman distclean; fi if test -f dtc/version_gen.h; then make $(DTC_MAKE_ARGS) clean; fi diff --git a/configure b/configure index 1af2f37..981561f 100755 --- a/configure +++ b/configure @@ -231,6 +231,8 @@ usb_redir="" glx="" zlib="yes" guest_agent="yes" +guest_agent_with_vss="no" +vss_win32_sdk="" want_tools="yes" libiscsi="" coroutine="" @@ -910,6 +912,12 @@ for opt do ;; --disable-guest-agent) guest_agent="no" ;; + --with-vss-sdk) vss_win32_sdk="" + ;; + --with-vss-sdk=*) vss_win32_sdk="$optarg" + ;; + --without-vss-sdk) vss_win32_sdk="no" + ;; --enable-tools) want_tools="yes" ;; --disable-tools) want_tools="no" @@ -1193,6 +1201,7 @@ echo " --disable-usb-redir disable usb network redirection support" echo " --enable-usb-redir enable usb network redirection support" echo " --disable-guest-agentdisable building of the QEMU Guest Agent" echo " --enable-guest-agent enable building of the QEMU Guest Agent" +echo " --with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent" echo " --disable-seccompdisable seccomp support" echo " --enable-seccomp enables seccomp support" echo " --with-coroutine=BACKEND coroutine backend. Supported options:" @@ -3098,6 +3107,41 @@ if test "$usb_redir" != "no" ; then fi ## +# check if we have VSS SDK headers for win + +if test "$mingw32" = "yes" -a "$guest_agent" = "yes" -a "$vss_win32_sdk" != "no" ; then + case "$vss_win32_sdk" in +"") vss_win32_include="-I$source_path" ;; +*\ *) # The SDK is installed in "Program Files" by default, but we cannot + # handle path with spaces. So we symlink the headers into ".sdk/vss". + vss_win32_include="-I$source_path/.sdk/vss" + symlink "$vss_win32_sdk/inc" "$source_path/.sdk/vss/inc" + ;; +*)vss_win32_include="-I$vss_win32_sdk" + esac + cat > $TMPC << EOF +#define __MIDL_user_allocate_free_DEFINED__ +#include +int main(void) { return VSS_CTX_BACKUP; } +EOF + if compile_prog "$vss_win32_include" "" ; then +guest_agent_with_vss="yes" +QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include" +libs_qga="-lole32 -loleaut32 -lshlwapi -luuid -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga" + else +if test "$vss_win32_sdk" != "" ; then + echo "ERROR: Please download and install Microsoft VSS SDK:" + echo "ERROR: http://www.microsoft.com/en-us/download/details.aspx?id=23490"; + echo "ERROR: On POSIX-systems, you can extract the SDK headers by:" + echo "ERROR: scripts/extract-vsssdk-headers setup.exe" + echo "ERROR: The headers are extracted in the directory \`inc'." + feature_not_found "VSS support" +fi +guest_agent_with_vss="no" + fi +fi + +## ## # check if we have fdatasync @@ -3581,6 +3625,7 @@ echo "usb net redir $usb_redir" echo "GLX support $glx" echo "libiscsi support $libiscsi" echo "build guest agent $guest_agent" +echo "QGA VSS support $guest_agent_with_vss" echo "seccomp support $seccomp" echo "coroutine backend $coroutine" echo "GlusterFS support $glusterfs" @@ -3654,6 +3699,9 @@ if test "$mingw32" = "yes" ; then version_micro=0 echo "CONFIG_FILEVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak echo "CONFIG_PRODUCTVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak + if test "$guest_agent_with_vss" = "yes" ; then +echo "CONFIG_QGA_VSS=y" >> $config_host_mak + fi else echo "CONFIG_POSIX=y" >> $config_host_mak fi
[Qemu-devel] [RFC PATCH v3 11/11] QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly
qemu-ga in Windows may return error message with multibyte characters when the guest OS language is set to other than English. To display such messages correctly, this encodes the message based on the locale settings. Signed-off-by: Tomoki Sekiyama --- QMP/qmp.py |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/QMP/qmp.py b/QMP/qmp.py index c551df1..ee21819 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -11,6 +11,7 @@ import json import errno import socket +import locale class QMPError(Exception): pass @@ -133,7 +134,8 @@ class QEMUMonitorProtocol: def command(self, cmd, **kwds): ret = self.cmd(cmd, kwds) if ret.has_key('error'): -raise Exception(ret['error']['desc']) +enc = locale.getpreferredencoding() +raise Exception(ret['error']['desc'].encode(enc)) return ret['return'] def pull_event(self, wait=False):
[Qemu-devel] [RFC PATCH v3 05/11] qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze
Implements a basic stub of software VSS provider. Currently, this modules only provides a relay function of events between qemu-guest-agent and Windows VSS when VSS finished filesystem freeze and when qemu snapshot is done. In the future, this module could be extended to support the other VSS functions, such as query for snapshot volumes and recovery. Signed-off-by: Tomoki Sekiyama --- Makefile.objs |2 configure |5 qga/Makefile.objs |6 qga/vss-win32-provider.h| 26 ++ qga/vss-win32-provider/Makefile.objs| 21 + qga/vss-win32-provider/install.cpp | 494 +++ qga/vss-win32-provider/provider.cpp | 474 ++ qga/vss-win32-provider/qga-provider.def | 10 + qga/vss-win32-provider/qga-provider.idl | 20 + qga/vss-win32.h | 85 + 10 files changed, 1142 insertions(+), 1 deletion(-) create mode 100644 qga/vss-win32-provider.h create mode 100644 qga/vss-win32-provider/Makefile.objs create mode 100644 qga/vss-win32-provider/install.cpp create mode 100644 qga/vss-win32-provider/provider.cpp create mode 100644 qga/vss-win32-provider/qga-provider.def create mode 100644 qga/vss-win32-provider/qga-provider.idl create mode 100644 qga/vss-win32.h diff --git a/Makefile.objs b/Makefile.objs index 286ce06..b6c1505 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -102,6 +102,7 @@ common-obj-y += disas/ # FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed # by libqemuutil.a. These should be moved to a separate .json schema. qga-obj-y = qga/ qapi-types.o qapi-visit.o +qga-prv-obj-y = qga/ vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) @@ -113,6 +114,7 @@ nested-vars += \ stub-obj-y \ util-obj-y \ qga-obj-y \ + qga-prv-obj-y \ block-obj-y \ common-obj-y dummy := $(call unnest-vars) diff --git a/configure b/configure index 981561f..6995bba 100755 --- a/configure +++ b/configure @@ -3503,9 +3503,12 @@ if test "$softmmu" = yes ; then virtfs=no fi fi - if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then + if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" -o "$mingw32" = "yes" ] ; then if [ "$guest_agent" = "yes" ]; then tools="qemu-ga\$(EXESUF) $tools" + if [ "$mingw32" = "yes" ]; then +tools="qga/vss-win32-provider/qga-provider.dll qga/vss-win32-provider/qga-provider.tlb $tools" + fi fi fi fi diff --git a/qga/Makefile.objs b/qga/Makefile.objs index b8d7cd0..8d93866 100644 --- a/qga/Makefile.objs +++ b/qga/Makefile.objs @@ -3,3 +3,9 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o qga-obj-y += qapi-generated/qga-qmp-marshal.o + +ifeq ($(CONFIG_QGA_VSS),y) +QEMU_CFLAGS += -DHAS_VSS_SDK +qga-obj-y += vss-win32-provider/ +qga-prv-obj-y += vss-win32-provider/ +endif diff --git a/qga/vss-win32-provider.h b/qga/vss-win32-provider.h new file mode 100644 index 000..a437e71 --- /dev/null +++ b/qga/vss-win32-provider.h @@ -0,0 +1,26 @@ +/* + * QEMU Guest Agent win32 VSS provider declarations + * + * Copyright Hitachi Data Systems Corp. 2013 + * + * Authors: + * Tomoki Sekiyama + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef VSS_WIN32_PROVIDER_H +#define VSS_WIN32_PROVIDER_H + +#include + +STDAPI VSSCheckOSVersion(void); + +STDAPI COMRegister(void); +STDAPI COMUnregister(void); + +STDAPI DllRegisterServer(void); +STDAPI DllUnregisterServer(void); + +#endif diff --git a/qga/vss-win32-provider/Makefile.objs b/qga/vss-win32-provider/Makefile.objs new file mode 100644 index 000..73ef752 --- /dev/null +++ b/qga/vss-win32-provider/Makefile.objs @@ -0,0 +1,21 @@ +# rules to build qga-provider.dll + +qga-obj-y += qga-provider.dll +qga-prv-obj-y += provider.o install.o + +obj-qga-prv-obj-y = $(addprefix $(obj)/, $(qga-prv-obj-y)) +$(obj-qga-prv-obj-y): QEMU_CXXFLAGS = $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls -fstack-protector-all, $(QEMU_CFLAGS)) -Wno-unknown-pragmas -Wno-delete-non-virtual-dtor + +$(obj)/qga-provider.dll: LDFLAGS = -shared -Wl,--add-stdcall-alias,--enable-stdcall-fixup -lole32 -loleaut32 -lshlwapi -luuid -static +$(obj)/qga-provider.dll: $(obj-qga-prv-obj-y) $(SRC_PATH)/$(obj)/qga-provider.def $(obj)/qga-provider.tlb + $(call quiet-command,$(CXX) -o $@ $(qga-prv-obj-y)
[Qemu-devel] [RFC PATCH v3 09/11] qemu-ga: Add VSS provider .tlb file in the repository
To build type library (.tlb) for qga-provider.dll from COM IDL (.idl), MIDL in VisualC++ and stdole2.tlb in Windows SDK are required. This patch adds pre-compiled .tlb file in the repository in order to enable cross-compile qemu-ga.exe for Windows with VSS support. Signed-off-by: Tomoki Sekiyama --- Makefile|2 +- qga/vss-win32-provider/Makefile.objs|4 qga/vss-win32-provider/qga-provider.tlb | Bin 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 qga/vss-win32-provider/qga-provider.tlb diff --git a/Makefile b/Makefile index b87cc5a..1652d3d 100644 --- a/Makefile +++ b/Makefile @@ -235,7 +235,7 @@ clean: rm -f qemu-options.def find . -name '*.[oda]' -type f -exec rm -f {} + find . -name '*.l[oa]' -type f -exec rm -f {} + - rm -f $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ + rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f qemu-img-cmds.h @# May not be present in GENERATED_HEADERS diff --git a/qga/vss-win32-provider/Makefile.objs b/qga/vss-win32-provider/Makefile.objs index 73ef752..698359b 100644 --- a/qga/vss-win32-provider/Makefile.objs +++ b/qga/vss-win32-provider/Makefile.objs @@ -18,4 +18,8 @@ MIDL=midl WINSDK="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include" $(obj)/qga-provider.tlb: $(SRC_PATH)/$(obj)/qga-provider.idl +ifeq ($(wildcard $(SRC_PATH)/$(obj)/qga-provider.tlb),) $(call quiet-command,$(MIDL) -m64 -o $@ -I $(WINSDK) $<," MIDL $(TARGET_DIR)$@") +else + $(call quiet-command,cp $(dir $<)qga-provider.tlb $@, " COPY $(TARGET_DIR)$@") +endif diff --git a/qga/vss-win32-provider/qga-provider.tlb b/qga/vss-win32-provider/qga-provider.tlb new file mode 100644 index ..226452a1861371ffe0cad1019cf90fdfdcd5ef49 GIT binary patch literal 1528 zcmeYbb_-!*U}OLRP8Kl5;0UB3A_y8H!@$4OPh6a(1_GM|T)fx!kz-UGh_rLWKC!yoBjb#vz`9Lwu4+R-SJ!kIOX4xLBUUGN9-NyTyP76j}@n z2f!qQ8-xepfXD+7rW+{SKz4&@7#qX~^1#sn3O|tFK>%ciE<&_Q3PuKoMqI)S5zj9Ngog_= gXfrXehlhjmFbIJB4$8MKU>*YlD1Z9^F{m5{03Vre%>V!Z literal 0 HcmV?d1
[Qemu-devel] [RFC PATCH v3 00/11] qemu-ga: fsfreeze on Windows using VSS
Hi, This patch series adds fsfreeze support for Windows qemu-guest-agent. changes from v2: - [06/11] Fix errors in Windows 7, reported by Li Baiqing (see below for details). changes from v1: - Fix out-tree build by stop using recursive Makefile - Added script to extract VSS SDK headers on POSIX systems using msitools (thanks Paolo) - Remove some unnecessary header files v2: http://lists.gnu.org/archive/html/qemu-devel/2013-04/msg02518.html * Description In Windows, VSS (Volume Shadow Copy Service) provides a facility to quiesce filesystems and applications before disk snapshots are taken. This patch series implements "fsfreeze" command of qemu-ga using VSS. * How to build & run qemu-ga with VSS support - Download Microsoft VSS SDK from: http://www.microsoft.com/en-us/download/details.aspx?id=23490 - Setup the SDK scripts/extract-vsssdk-headers setup.exe (on POSIX-systems) - Specify installed SDK directory to configure option as: ./configure -with-vss-sdk="path/to/VSS SDK" --cross-prefix=i686-w64-mingw32- - make qemu-ga.exe - Install qemu-ga.exe, qga/vss-win32-provider/qga-provider.{dll,tlb}, and the other required mingw libraries into the same directory in guests - Run `qemu-ga.exe -s install' and `net start qemu-ga' in the guests * About errors in Windows 7 with patch v2 VSS requires to write to snapshot volumes just before making them read-only at final commit phase. This feature is called `auto-recovery' (See http://msdn.microsoft.com/en-us/library/windows/desktop/aa384651(v=vs.85).aspx#base.vssgloss_auto_recoved_shadow_copy for details). Since qemu and libvirt don't have feature to handle writable snapshots, this patchset just disables auto-recovery by specifying VSS_VOLSNAP_ATTR_NO_AUTORECOVERY flag to SetContext. Unfortunately, this flag seems unsupported in Windows 7 or earlier. It tries to look up the snapshot volumes to write and fails in VSS_E_OBJECT_NOT_FOUND. For fundamental resolution we need a framework for guests to query snapshots and to mount them as writable snapshots, but we just ignore the error in this patchset. Any feedback are appliciated. --- Tomoki Sekiyama (11): configure: Support configuring c++ compiler Fix errors and warnings while compiling with c++ compilier Add a script to extract VSS SDK headers on POSIX system qemu-ga: Add an configure option to specify path to Windows VSS SDK qemu-ga: Add Windows VSS provider to quiesce applications on fsfreeze qemu-ga: Add Windows VSS requester to quisce applications and filesystems qemu-ga: call Windows VSS requester in fsfreeze command handler qemu-ga: install Windows VSS provider on `qemu-ga -s install' qemu-ga: Add VSS provider .tlb file in the repository QMP/qemu-ga-client: make timeout longer for guest-fsfreeze-freeze command QMP/qmp.py: set locale for exceptions to display non-ascii messages correctly .gitignore |1 Makefile|3 Makefile.objs |2 QMP/qemu-ga-client |4 QMP/qmp.py |4 configure | 59 hmp.c |2 hw/pci/pci.c|2 qga/Makefile.objs |7 qga/commands-win32.c| 74 - qga/main.c | 41 +++ qga/vss-win32-provider.h| 26 ++ qga/vss-win32-provider/Makefile.objs| 25 ++ qga/vss-win32-provider/install.cpp | 494 +++ qga/vss-win32-provider/provider.cpp | 474 ++ qga/vss-win32-provider/qga-provider.def | 10 + qga/vss-win32-provider/qga-provider.idl | 20 + qga/vss-win32-provider/qga-provider.tlb | Bin qga/vss-win32-requester.cpp | 404 + qga/vss-win32-requester.h | 31 ++ qga/vss-win32.h | 85 + rules.mak |9 + scripts/extract-vsssdk-headers | 25 ++ scripts/qapi.py |9 + 24 files changed, 1796 insertions(+), 15 deletions(-) create mode 100644 qga/vss-win32-provider.h create mode 100644 qga/vss-win32-provider/Makefile.objs create mode 100644 qga/vss-win32-provider/install.cpp create mode 100644 qga/vss-win32-provider/provider.cpp create mode 100644 qga/vss-win32-provider/qga-provider.def create mode 100644 qga/vss-win32-provider/qga-provider.idl create mode 100644 qga/vss-win32-provider/qga-provider.tlb create mode 100644 qga/vss-win32-requester.cpp create mode 100644 qga/vss-win32-requester.h create mode 100644 qga/vss-win32.h create mode 100755 scripts/extract-vsssdk-headers
Re: [Qemu-devel] [RFC PATCH v3 01/11] configure: Support configuring c++ compiler
Hi Peter, On 5/21/13 12:56 , "Peter Maydell" wrote: >On 21 May 2013 16:33, Tomoki Sekiyama wrote: >> Add configuration for c++ compiler (${corss_prefix}g++ as default) in >> configure and Makefiles. > >I think you should follow the same logic we use for picking >the C compiler, so that we use 'c++' rather than 'g++' if >cross_prefix isn't specified. Otherwise we'll end up on MacOSX >with the odd effect of using clang for C and some ancient >compiler for C++... > >> Currently, usage of c++ language is only for access to Windows VSS >> using COM+ services in qemu-guest-agent for Windows. > >...which isn't important for this use, but I'm sure once configure >has support for C++ it'll spread to other uses later. > >thanks >-- PMM OK, I will follow the logic for C compiler in the next version. Thanks, -- Tomoki Sekiyama
Re: [Qemu-devel] [RFC PATCH v3 03/11] Add a script to extract VSS SDK headers on POSIX system
On 5/21/13 12:48 , "Eric Blake" wrote: >On 05/21/2013 09:33 AM, Tomoki Sekiyama wrote: >> VSS SDK(*) setup.exe is only runnable on Windows. This adds a script >> to extract VSS SDK headers on POSIX-systems using msitools. >> >> * http://www.microsoft.com/en-us/download/details.aspx?id=23490 >> >> From: Paolo Bonzini >> Signed-off-by: Tomoki Sekiyama >> --- >> scripts/extract-vsssdk-headers | 25 + >> 1 file changed, 25 insertions(+) >> create mode 100755 scripts/extract-vsssdk-headers >> > >> +#! /bin/bash > >Since you are using bash... > >> + >> +# extract-vsssdk-headers >> +# Author: Paolo Bonzini >> + >> +set -e >> +if test $# = 0 || ! test -f "$1"; then > >Why reject 0 arguments but not 2? Shouldn't the first check be test $# >!= 1? I agree, will fix this. >> + echo 'Usage: extract-vsssdk-headers /path/to/setup.exe' >> + exit 1 >> +fi >> + >> +# Extract .MSI file in the .exe, looking for the OLE compound >> +# document signature. Extra data at the end does not matter. >> +export LC_ALL=C >> +MAGIC=$'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1' >> +offset=`grep -abom1 "$MAGIC" "$1" | sed -n 's/:/\n/; P' ` > >...I'd prefer $() over ``. OK. >> +(dd of=/dev/null skip=$offset bs=1 count=0; cat) < "$1" > vsssdk.msi >> + >> +# Now extract the files. >> +tmpdir=tmp$$ >> +mkdir $tmpdir > >...also, this name is rather predictable; adding a $RANDOM might help >improve its quality. I will add $RANDOM here. >> +msiextract -C $tmpdir vsssdk.msi >> +mv "$tmpdir/Program Files/Microsoft/VSSSDK72/inc" inc >> +rm -rf $tmpdir vsssdk.msi > >What, no trap, to guarantee clean up of the temp directory even if you >Ctrl-C the script in the middle of a potentially long-running msiextract? OK, I will add some trap here. Maybe it also should have an additional check and a message to install Msitools for the case msiextract isn't exectable. Thanks, -- Tomoki Sekiyama
Re: [Qemu-devel] [RFC PATCH v3 01/11] configure: Support configuring c++ compiler
Hi Eric, Thank you for the review. On 5/21/13 12:42 , "Eric Blake" wrote: >On 05/21/2013 09:33 AM, Tomoki Sekiyama wrote: >> Add configuration for c++ compiler (${corss_prefix}g++ as default) in > >s/corss/cross/ Oops, I'll fix this in next version... (with a fix for logic to configure c++ compiler, pointed out on Peter's mail) >> configure and Makefiles. >> >> Currently, usage of c++ language is only for access to Windows VSS >> using COM+ services in qemu-guest-agent for Windows. Thanks, -- Tomoki Sekiyama
Re: [Qemu-devel] [RFC PATCH v3 04/11] qemu-ga: Add an configure option to specify path to Windows VSS SDK
On 5/21/13 12:53 , "Eric Blake" wrote: >On 05/21/2013 09:33 AM, Tomoki Sekiyama wrote: >> To enable VSS support in qemu-ga for Windows, header files included in >> VSS SDK is required. >> The VSS support is enabled when the option like below: >> ./configure --with-vss-sdk="/pass/to/VSS SDK" >> >> VSS SDK is available from: >> http://www.microsoft.com/en-us/download/details.aspx?id=23490 >> >> To cross-compilie using mingw32 for Linux, you need to setup the SDK on > >s/compilie/compile/ > >There are two mingw projects: mingw (older, 32-bit only) and mingw64 >(newer, both 32- and 64-bit support). The name 'mingw32' is misleading, >as neither project uses it. Fedora uses mingw64. Ah, I should say just mingw here. >> Windows environments to extract headers. You can also extract the SDK >> headers using scripts/extract-vss-headers, written by Paolo Bonzini. > >I haven't downloaded the sdk to check for myself; are we breaking any >licensing restrictions by compiling against those files? I believe it is ok while the SDK is used for development of software running on Windows, and while the SDK is not redistributed.
Re: [Qemu-devel] [RFC PATCH v3 06/11] qemu-ga: Add Windows VSS requester to quisce applications and filesystems
On 5/21/13 12:56 , "Eric Blake" wrote: >On 05/21/2013 09:33 AM, Tomoki Sekiyama wrote: >> Add VSS requester functions for to qemu-ga. >> This provides facility to request VSS service in Windows guest to quisce > >s/quisce/quiesce/ Oops, thanks again. >> applications and filesystems. This function is only supported in Windows >> 2003 or later. In older guests, this function does nothing. >> >> In several versions of Windows which don't support attribute >> VSS_VOLSNAP_ATTR_NO_AUTORECOVERY, DoSnapshotSet fails with error >> VSS_E_OBJECT_NOT_FOUND. In this patch, we just ignore this error. >> To solve this fundamentally, we need a framework to handle mount >>writable >> snapshot on guests, which is required by VSS auto-recovery feature >> (a cleanup phase after snapshot is taken). > >I take it that such a framework may involve additional guest-agent >commands and management work (such as libvirt having to be aware of the >added framework). How important is this functionality? How frequently >does VSS even get us into that state? That is, are Windows guests going >to frequently hit our current first-round implementation limits that >fail to let them do auto-recovery? "Auto-recovery" is invoked every time after snapshots are taken by VSS (the name is misleading, but it is normal path...) to make the snapshot completely consistent state by rolling back incomplete transactions. VSS requesters can explicitly disable this, but this may remain some incomplete data in the snapshot when some applications which relying on this feature are running. However, I believe they can usually be recovered *after the snapshot is rolled back*. Full-support of VSS including auto-recovery may require the other channel between libvirt and guest-agent to conduct snapshot operation from guests. I think such interface can also enable various VSS feature such as partial- recovery from snapshots. It would be nice to have in the future version, but is overkill just to enable fsfreeze command so far Thanks, Tomoki Sekiyama