From nobody Wed Nov 5 14:49:31 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=126.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1535697775763545.0177946894412; Thu, 30 Aug 2018 23:42:55 -0700 (PDT) Received: from localhost ([::1]:52146 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fvd8w-0001yp-EX for importer@patchew.org; Fri, 31 Aug 2018 02:42:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36267) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fvd6k-0000DX-M9 for qemu-devel@nongnu.org; Fri, 31 Aug 2018 02:40:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fvcrW-0005t6-JE for qemu-devel@nongnu.org; Fri, 31 Aug 2018 02:24:57 -0400 Received: from m15-114.126.com ([220.181.15.114]:51146) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fvcrV-0005sJ-BM for qemu-devel@nongnu.org; Fri, 31 Aug 2018 02:24:54 -0400 Received: from localhost.localdomain (unknown [58.213.111.46]) by smtp7 (Coremail) with SMTP id DsmowADH_Lgm34hbKnPLIw--.17480S2; Fri, 31 Aug 2018 14:24:43 +0800 (CST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=126.com; s=s110527; h=From:Subject:Date:Message-Id; bh=oaXqpfoyyklN7yohYu R0miJQTNch2j1SSlYeZqDcfaI=; b=KwMa8nOScrVBkpKrK3qNda1tA8TsgVQhUS K0/60v+WDtvwTySIzb2KDfo2tVss105w8IHiYHuxiccU+oFuMmg4RLotDTnEkL86 fSZaWxTkuHCr6erYj04nizkoICo0b2BiAabtYRILGPGfrhEsevmJ7/BfFWwH3BJ6 smJaUYtZs= From: Chen Hanxiao To: mdroth@linux.vnet.ibm.com Date: Fri, 31 Aug 2018 14:22:50 +0800 Message-Id: <20180831062250.12425-1-chen_han_xiao@126.com> X-Mailer: git-send-email 2.17.1 X-CM-TRANSID: DsmowADH_Lgm34hbKnPLIw--.17480S2 X-Coremail-Antispam: 1Uf129KBjvJXoW3Jr4rZFyrtw43trykCw1DAwb_yoWfAw1DpF sxJrnakr40q3W7try8uw1xZFyfGFZ8Aa18Cw1vkrWUZ3Z5XF95AwsFya45uF18Aw4kX3yS va95trW8Za1Uur7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jLpnQUUUUU= X-Originating-IP: [58.213.111.46] X-CM-SenderInfo: xfkh0spkdqs5xldrqiyswou0bp/1tbikgyzrlpD6BprqAAAsr X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 220.181.15.114 Subject: [Qemu-devel] [PATCH v2] qga-win: add support for qmp_guest_fsfreeze_freeze_list X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org, Chen Hanxiao Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDMRC_1 RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Chen Hanxiao This patch add support for freeze specified fs. The valid mountpoints list member are [1]: The path of a mounted folder, for example, Y:\MountX\ A drive letter, for example, D:\ A volume GUID path of the form \\?\Volume{GUID}\, where GUID identifies the volume A UNC path that specifies a remote file share, for example, \\Clusterx\Share1\ [1] https://docs.microsoft.com/en-us/windows/desktop/api/vsbackup/nf-vsback= up-ivssbackupcomponents-addtosnapshotset Cc: Michael Roth Signed-off-by: Chen Hanxiao --- v2: optimize internal logic blocks qga/commands-win32.c | 21 ++++----- qga/main.c | 2 +- qga/vss-win32.c | 5 +- qga/vss-win32.h | 3 +- qga/vss-win32/requester.cpp | 92 ++++++++++++++++++++++++++----------- qga/vss-win32/requester.h | 13 ++++-- 6 files changed, 91 insertions(+), 45 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 98d9735389..1d627f73c1 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -776,6 +776,13 @@ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **= errp) * The frozen state is limited for up to 10 seconds by VSS. */ int64_t qmp_guest_fsfreeze_freeze(Error **errp) +{ + return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); +} + +int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, + strList *mountpoints, + Error **errp) { int i; Error *local_err =3D NULL; @@ -790,7 +797,7 @@ int64_t qmp_guest_fsfreeze_freeze(Error **errp) /* cannot risk guest agent blocking itself on a write in this state */ ga_set_frozen(ga_state); =20 - qga_vss_fsfreeze(&i, true, &local_err); + qga_vss_fsfreeze(&i, true, mountpoints, &local_err); if (local_err) { error_propagate(errp, local_err); goto error; @@ -808,15 +815,6 @@ error: return 0; } =20 -int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, - strList *mountpoints, - Error **errp) -{ - error_setg(errp, QERR_UNSUPPORTED); - - return 0; -} - /* * Thaw local file systems using Volume Shadow-copy Service. */ @@ -829,7 +827,7 @@ int64_t qmp_guest_fsfreeze_thaw(Error **errp) return 0; } =20 - qga_vss_fsfreeze(&i, false, errp); + qga_vss_fsfreeze(&i, false, NULL, errp); =20 ga_unset_frozen(ga_state); return i; @@ -1646,7 +1644,6 @@ GList *ga_command_blacklist_init(GList *blacklist) "guest-set-vcpus", "guest-get-memory-blocks", "guest-set-memory-blocks", "guest-get-memory-block-size", - "guest-fsfreeze-freeze-list", NULL}; char **p =3D (char **)list_unsupported; =20 diff --git a/qga/main.c b/qga/main.c index 6d70242d05..13bfff5f0a 100644 --- a/qga/main.c +++ b/qga/main.c @@ -151,7 +151,7 @@ static void quit_handler(int sig) WaitForSingleObject(hEventTimeout, 0); CloseHandle(hEventTimeout); } - qga_vss_fsfreeze(&i, false, &err); + qga_vss_fsfreeze(&i, false, NULL, &err); if (err) { g_debug("Error unfreezing filesystems prior to exiting: %s", error_get_pretty(err)); diff --git a/qga/vss-win32.c b/qga/vss-win32.c index a541f3ae01..f444a25a70 100644 --- a/qga/vss-win32.c +++ b/qga/vss-win32.c @@ -147,7 +147,8 @@ void ga_uninstall_vss_provider(void) } =20 /* Call VSS requester and freeze/thaw filesystems and applications */ -void qga_vss_fsfreeze(int *nr_volume, bool freeze, Error **errp) +void qga_vss_fsfreeze(int *nr_volume, bool freeze, + strList *mountpoints, Error **errp) { const char *func_name =3D freeze ? "requester_freeze" : "requester_tha= w"; QGAVSSRequesterFunc func; @@ -164,5 +165,5 @@ void qga_vss_fsfreeze(int *nr_volume, bool freeze, Erro= r **errp) return; } =20 - func(nr_volume, &errset); + func(nr_volume, mountpoints, &errset); } diff --git a/qga/vss-win32.h b/qga/vss-win32.h index 4f8e39aa5c..ce2abe5a72 100644 --- a/qga/vss-win32.h +++ b/qga/vss-win32.h @@ -22,6 +22,7 @@ bool vss_initialized(void); int ga_install_vss_provider(void); void ga_uninstall_vss_provider(void); =20 -void qga_vss_fsfreeze(int *nr_volume, bool freeze, Error **errp); +void qga_vss_fsfreeze(int *nr_volume, bool freeze, + strList *mountpints, Error **errp); =20 #endif diff --git a/qga/vss-win32/requester.cpp b/qga/vss-win32/requester.cpp index 3d9c9716c0..5378c55d23 100644 --- a/qga/vss-win32/requester.cpp +++ b/qga/vss-win32/requester.cpp @@ -234,7 +234,7 @@ out: } } =20 -void requester_freeze(int *num_vols, ErrorSet *errset) +void requester_freeze(int *num_vols, void *mountpoints, ErrorSet *errset) { COMPointer pAsync; HANDLE volume; @@ -246,6 +246,7 @@ void requester_freeze(int *num_vols, ErrorSet *errset) WCHAR short_volume_name[64], *display_name =3D short_volume_name; DWORD wait_status; int num_fixed_drives =3D 0, i; + int num_mount_points =3D 0; =20 if (vss_ctx.pVssbc) { /* already frozen */ *num_vols =3D 0; @@ -337,39 +338,73 @@ void requester_freeze(int *num_vols, ErrorSet *errset) goto out; } =20 - volume =3D FindFirstVolumeW(short_volume_name, sizeof(short_volume_nam= e)); - if (volume =3D=3D INVALID_HANDLE_VALUE) { - err_set(errset, hr, "failed to find first volume"); - goto out; - } - for (;;) { - if (GetDriveTypeW(short_volume_name) =3D=3D DRIVE_FIXED) { + if (mountpoints) { + PWCHAR volume_name_wchar; + for (volList *list =3D (volList *)mountpoints; list; list =3D list= ->next) { + size_t len =3D strlen(list->value) + 1; + size_t converted =3D 0; VSS_ID pid; - hr =3D vss_ctx.pVssbc->AddToSnapshotSet(short_volume_name, + + volume_name_wchar =3D new wchar_t[len]; + mbstowcs_s(&converted, volume_name_wchar, len, + list->value, _TRUNCATE); + + hr =3D vss_ctx.pVssbc->AddToSnapshotSet(volume_name_wchar, g_gProviderId, &pid); if (FAILED(hr)) { - WCHAR volume_path_name[PATH_MAX]; - if (GetVolumePathNamesForVolumeNameW( - short_volume_name, volume_path_name, - sizeof(volume_path_name), NULL) && *volume_path_na= me) { - display_name =3D volume_path_name; - } err_set(errset, hr, "failed to add %S to snapshot set", - display_name); - FindVolumeClose(volume); + volume_name_wchar); + delete volume_name_wchar; goto out; } - num_fixed_drives++; + num_mount_points++; + + delete volume_name_wchar; } - if (!FindNextVolumeW(volume, short_volume_name, - sizeof(short_volume_name))) { - FindVolumeClose(volume); - break; + + if (num_mount_points =3D=3D 0) { + /* If there is no valid mount points, just exit. */ + goto out; } } =20 - if (num_fixed_drives =3D=3D 0) { - goto out; /* If there is no fixed drive, just exit. */ + if (!mountpoints) { + volume =3D FindFirstVolumeW(short_volume_name, sizeof(short_volume= _name)); + if (volume =3D=3D INVALID_HANDLE_VALUE) { + err_set(errset, hr, "failed to find first volume"); + goto out; + } + + for (;;) { + if (GetDriveTypeW(short_volume_name) =3D=3D DRIVE_FIXED) { + VSS_ID pid; + hr =3D vss_ctx.pVssbc->AddToSnapshotSet(short_volume_name, + g_gProviderId, &pid); + if (FAILED(hr)) { + WCHAR volume_path_name[PATH_MAX]; + if (GetVolumePathNamesForVolumeNameW( + short_volume_name, volume_path_name, + sizeof(volume_path_name), NULL) && + *volume_path_name) { + display_name =3D volume_path_name; + } + err_set(errset, hr, "failed to add %S to snapshot set", + display_name); + FindVolumeClose(volume); + goto out; + } + num_fixed_drives++; + } + if (!FindNextVolumeW(volume, short_volume_name, + sizeof(short_volume_name))) { + FindVolumeClose(volume); + break; + } + } + + if (num_fixed_drives =3D=3D 0) { + goto out; /* If there is no fixed drive, just exit. */ + } } =20 hr =3D vss_ctx.pVssbc->PrepareForBackup(pAsync.replace()); @@ -435,7 +470,12 @@ void requester_freeze(int *num_vols, ErrorSet *errset) goto out; } =20 - *num_vols =3D vss_ctx.cFrozenVols =3D num_fixed_drives; + if (mountpoints) { + *num_vols =3D vss_ctx.cFrozenVols =3D num_mount_points; + } else { + *num_vols =3D vss_ctx.cFrozenVols =3D num_fixed_drives; + } + return; =20 out: @@ -449,7 +489,7 @@ out1: } =20 =20 -void requester_thaw(int *num_vols, ErrorSet *errset) +void requester_thaw(int *num_vols, void *mountpints, ErrorSet *errset) { COMPointer pAsync; =20 diff --git a/qga/vss-win32/requester.h b/qga/vss-win32/requester.h index 2a39d734a2..5a8e8faf0c 100644 --- a/qga/vss-win32/requester.h +++ b/qga/vss-win32/requester.h @@ -34,9 +34,16 @@ typedef struct ErrorSet { STDAPI requester_init(void); STDAPI requester_deinit(void); =20 -typedef void (*QGAVSSRequesterFunc)(int *, ErrorSet *); -void requester_freeze(int *num_vols, ErrorSet *errset); -void requester_thaw(int *num_vols, ErrorSet *errset); +typedef struct volList volList; + +struct volList { + volList *next; + char *value; +}; + +typedef void (*QGAVSSRequesterFunc)(int *, void *, ErrorSet *); +void requester_freeze(int *num_vols, void *volList, ErrorSet *errset); +void requester_thaw(int *num_vols, void *volList, ErrorSet *errset); =20 #ifdef __cplusplus } --=20 2.17.1