[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v8 08/10] qemu-ga: Call Windows VSS requester in
From: |
Michael Roth |
Subject: |
Re: [Qemu-devel] [PATCH v8 08/10] qemu-ga: Call Windows VSS requester in fsfreeze command handler |
Date: |
Tue, 30 Jul 2013 15:17:34 -0500 |
User-agent: |
alot/0.3.4 |
Quoting Tomoki Sekiyama (2013-07-23 17:45:58)
> 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 <address@hidden>
Other than s/Reqeuster/Requester/ typo mentioned in 7/10, looks good:
Reviewed-by: Michael Roth <address@hidden>
> ---
> 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 4891732..ae1c28b 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 <wtypes.h>
> #include <powrprof.h>
> #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 0000000..ef5f0df
> --- /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 <address@hidden>
> + *
> + * 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 <stdio.h>
> +#include <windows.h>
> +#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 char *func_name)
> +{
> + FARPROC WINAPI func;
> +
> + g_assert(provider_lib);
> +
> + func = GetProcAddress(provider_lib, func_name);
> + if (!func) {
> + char *msg;
> + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
> + FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
> + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
> + (char *)&msg, 0, NULL);
> + fprintf(stderr, "failed to load %s from %s: %s",
> + func_name, QGA_VSS_DLL, msg);
> + LocalFree(msg);
> + return E_FAIL;
> + }
> +
> + return func();
> +}
> +
> +/* Check whether this OS version supports VSS providers */
> +static bool vss_check_os_version(void)
> +{
> + OSVERSIONINFO OSver;
> +
> + OSver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
> + GetVersionEx(&OSver);
> + if ((OSver.dwMajorVersion == 5 && OSver.dwMinorVersion >= 2) ||
> + OSver.dwMajorVersion > 5) {
> + BOOL wow64 = false;
> +#ifndef _WIN64
> + /* Provider doesn't work under WOW64 (32bit agent on 64bit OS) */
> + if (!IsWow64Process(GetCurrentProcess(), &wow64)) {
> + fprintf(stderr, "failed to IsWow64Process (Error: %lx\n)\n",
> + GetLastError());
> + return false;
> + }
> + if (wow64) {
> + fprintf(stderr, "Warning: Running under WOW64\n");
> + }
> +#endif
> + return !wow64;
> + }
> + return false;
> +}
> +
> +/* Load qga-vss.dll */
> +bool vss_init(bool init_requester)
> +{
> + if (!vss_check_os_version()) {
> + /* Do nothing if OS doesn't support providers. */
> + fprintf(stderr, "VSS provider is not supported in this OS version: "
> + "fsfreeze is disabled.\n");
> + return false;
> + }
> +
> + provider_lib = LoadLibraryA(QGA_VSS_DLL);
> + if (!provider_lib) {
> + char *msg;
> + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
> + FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
> + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
> + (char *)&msg, 0, NULL);
> + fprintf(stderr, "failed to load %s: %sfsfreeze is disabled\n",
> + QGA_VSS_DLL, msg);
> + LocalFree(msg);
> + return false;
> + }
> +
> + if (init_requester) {
> + HRESULT hr = call_vss_provider_func("requester_init");
> + if (FAILED(hr)) {
> + fprintf(stderr, "fsfreeze is disabled.\n");
> + vss_deinit(false);
> + return false;
> + }
> + }
> +
> + return true;
> +}
> +
> +/* Unload qga-provider.dll */
> +void vss_deinit(bool deinit_requester)
> +{
> + if (deinit_requester) {
> + call_vss_provider_func("requester_deinit");
> + }
> + FreeLibrary(provider_lib);
> + provider_lib = NULL;
> +}
> +
> +bool vss_initialized(void)
> +{
> + return !!provider_lib;
> +}
> +
> +/* Call VSS requester and freeze/thaw filesystems and applications */
> +void qga_vss_fsfreeze(int *nr_volume, Error **err, bool freeze)
> +{
> + const char *func_name = freeze ? "requester_freeze" : "requester_thaw";
> + QGAVSSReuqesterFunc func;
> + ErrorSet errset = {
> + .error_set = (ErrorSetFunc)error_set_win32,
> + .errp = (void **)err,
> + .err_class = ERROR_CLASS_GENERIC_ERROR
> + };
> +
> + func = (QGAVSSReuqesterFunc)GetProcAddress(provider_lib, func_name);
> + if (!func) {
> + error_setg_win32(err, GetLastError(), "failed to load %s from %s",
> + func_name, QGA_VSS_DLL);
> + return;
> + }
> +
> + func(nr_volume, &errset);
> +}
> diff --git a/qga/vss-win32.h b/qga/vss-win32.h
> new file mode 100644
> index 0000000..eac669c
> --- /dev/null
> +++ b/qga/vss-win32.h
> @@ -0,0 +1,24 @@
> +/*
> + * QEMU Guest Agent VSS utility declarations
> + *
> + * Copyright Hitachi Data Systems Corp. 2013
> + *
> + * Authors:
> + * Tomoki Sekiyama <address@hidden>
> + *
> + * 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_H
> +#define VSS_WIN32_H
> +
> +#include "qapi/error.h"
> +
> +bool vss_init(bool init_requester);
> +void vss_deinit(bool deinit_requester);
> +bool vss_initialized(void);
> +
> +void qga_vss_fsfreeze(int *nr_volume, Error **err, bool freeze);
> +
> +#endif
- Re: [Qemu-devel] [PATCH v8 01/10] configure: Support configuring C++ compiler, (continued)
- [Qemu-devel] [PATCH v8 02/10] Add c++ keywords to QAPI helper script, Tomoki Sekiyama, 2013/07/23
- [Qemu-devel] [PATCH v8 03/10] checkpatch.pl: Check .cpp files, Tomoki Sekiyama, 2013/07/23
- [Qemu-devel] [PATCH v8 04/10] Add a script to extract VSS SDK headers on POSIX system, Tomoki Sekiyama, 2013/07/23
- [Qemu-devel] [PATCH v8 05/10] qemu-ga: Add configure options to specify path to Windows/VSS SDK, Tomoki Sekiyama, 2013/07/23
- [Qemu-devel] [PATCH v8 06/10] error: Add error_set_win32 and error_setg_win32, Tomoki Sekiyama, 2013/07/23
- [Qemu-devel] [PATCH v8 09/10] qemu-ga: Install Windows VSS provider on `qemu-ga -s install', Tomoki Sekiyama, 2013/07/23
- [Qemu-devel] [PATCH v8 08/10] qemu-ga: Call Windows VSS requester in fsfreeze command handler, Tomoki Sekiyama, 2013/07/23
- Re: [Qemu-devel] [PATCH v8 08/10] qemu-ga: Call Windows VSS requester in fsfreeze command handler,
Michael Roth <=
- [Qemu-devel] [PATCH v8 10/10] QMP/qemu-ga-client: Make timeout longer for guest-fsfreeze-freeze command, Tomoki Sekiyama, 2013/07/23
- [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL, Tomoki Sekiyama, 2013/07/23
- Re: [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL, Michael Roth, 2013/07/25
- Re: [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL, Michael Roth, 2013/07/26
- Re: [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL, Tomoki Sekiyama, 2013/07/29
- Re: [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL, Michael Roth, 2013/07/30
- Re: [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL, Tomoki Sekiyama, 2013/07/30
- Re: [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL, Michael Roth, 2013/07/30
- Re: [Qemu-devel] [PATCH v8 07/10] qemu-ga: Add Windows VSS provider and requester as DLL, Tomoki Sekiyama, 2013/07/30