Hi Michael,
Thank you for the review.

>>-  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
>
>It looks like this hasn't been updated to reflect the change in directory
>and
>tlb/dll filenames from an earlier version.
>
>Also, when CONFIG_QGA_VSS=n, we shouldn't make the dll/tlb dependencies of
>$tools, else we'll get a build error.
>
>The following changes seem to fix things for me:
>
>-      if [ "$mingw32" = "yes" ]; then
>-        tools="qga/vss-win32-provider/qga-provider.dll
>qga/vss-win32-provider/qga-provider.tlb $tools"
>+      if [ "$mingw32" = "yes" -a "$guest_agent_with_vss" = "yes" ]; then
>+        tools="qga/vss-win32/qga-vss.dll qga/vss-win32/qga-vss.tlb
>$tools"

Ah, thanks for pointing this out. I will fix into this.

>>+
>>+ifeq ($(CONFIG_QGA_VSS),y)
>>+qga-vss-dll-obj-y += vss-win32/
>>+endif
>
>Small nit, but I think we generally prefer this form in qemu:
>
>qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32

OK.

>> diff --git a/qga/vss-win32/Makefile.objs b/qga/vss-win32/Makefile.objs
>> new file mode 100644
>> index 0000000..4dad964
>> --- /dev/null
>> +++ b/qga/vss-win32/Makefile.objs
>> @@ -0,0 +1,23 @@
>> +# rules to build qga-vss.dll
>> +
>> +qga-vss-dll-obj-y += requester.o provider.o install.o
>> +
>> +obj-qga-vss-dll-obj-y = $(addprefix $(obj)/, $(qga-vss-dll-obj-y))
>> +$(obj-qga-vss-dll-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-vss.dll: LDFLAGS = -shared
>>-Wl,--add-stdcall-alias,--enable-stdcall-fixup -lole32 -loleaut32
>>-lshlwapi -luuid -static
>> +$(obj)/qga-vss.dll: $(obj-qga-vss-dll-obj-y)
>>$(SRC_PATH)/$(obj)/qga-vss.def
>> +       $(call quiet-command,$(CXX) -o $@ $(qga-vss-dll-obj-y)
>>$(SRC_PATH)/qga/vss-win32/qga-vss.def $(CXXFLAGS) $(LDFLAGS),"  LINK
>>$(TARGET_DIR)$@")
>> +
>> +
>> +# rules to build qga-provider.tlb
>> +# Currently, only native build is supported because building .tlb
>> +# (TypeLibrary) from .idl requires WindowsSDK and MIDL (and cl.exe in
>>VC++).
>> +MIDL=$(WIN_SDK)/Bin/midl
>> +
>> +$(obj)/qga-vss.tlb: $(SRC_PATH)/$(obj)/qga-vss.idl
>> +ifeq ($(wildcard $(SRC_PATH)/$(obj)/qga-vss.tlb),)
>> +       $(call quiet-command,$(MIDL) -tlb $@ -I $(WIN_SDK)/Include $<,"
>> MIDL  $(TARGET_DIR)$@")
>
>Is the only way to execute this to delete qga-vss.tlb from the source
>directory? Not a big deal, but seems a bit awkward for users/builders.
>
>It looks like WIN_SDK exists only for this purpose, so perhaps just
>default
>WIN_SDK to "no". Then if they specify --with-win-sdk with no parameters,
>we do
>the current defaults in configure, and if they specify it explicitly we
>use that
>path. Basically the same thing we do for --with-vss-sdk/--without-vss-sdk
>currently.
>
>Then we do something like:
>
>  $(obj)/qga-vss.tlb: $(SRC_PATH)/$(obj)/qga-vss.idl
>  ifeq ($(WIN_SDK),)
>         $(call quiet-command,cp $(dir $<)qga-vss.tlb $@, "  COPY
>$(TARGET_DIR)$@")
>  else
>         $(call quiet-command,$(MIDL) -tlb $@ -I $(WIN_SDK)/Include $<,"
>MIDL  $(TARGET_DIR)$@")
>  Endif

OK, I will take this way.


>> diff --git a/qga/vss-win32/provider.cpp b/qga/vss-win32/provider.cpp
>> new file mode 100644
>> index 0000000..e39526a
>> --- /dev/null
>> +++ b/qga/vss-win32/provider.cpp
<snip>
>> +STDMETHODIMP CQGAVssProvider::CommitSnapshots(VSS_ID SnapshotSetId)
>> +{
>> +    HRESULT hr = S_OK;
>> +    HANDLE hEventFrozen, hEventThaw;
>> +
>> +    hEventFrozen = OpenEvent(EVENT_ALL_ACCESS, FALSE,
>>EVENT_NAME_FROZEN);
>> +    if (hEventFrozen == INVALID_HANDLE_VALUE) {
>> +        return E_FAIL;
>> +    }
>> +
>> +    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 0000000..1b91ca5
>> --- /dev/null
>> +++ b/qga/vss-win32/requester.cpp
<snip>
>> +    /* 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.


<snip>
>> diff --git a/qga/vss-win32/requester.h b/qga/vss-win32/requester.h
>> new file mode 100644
>> index 0000000..ccd197c
>> --- /dev/null
>> +++ b/qga/vss-win32/requester.h
<snip>
>> +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


Reply via email to