]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Bail out vmtoolsd early when there are RPC errors.
authorOliver Kurth <okurth@vmware.com>
Tue, 29 Jan 2019 22:03:19 +0000 (14:03 -0800)
committerOliver Kurth <okurth@vmware.com>
Tue, 29 Jan 2019 22:03:19 +0000 (14:03 -0800)
VMX state machine could give up quiescing operation for various
reasons when vmtoolsd is busy performing necessary state transitions.
Once VMX gives up quiescing operation, there is no point in
vmtoolsd continuing with it. vmtoolsd should also give up the
operation asap. vmtoolsd can detect VMX state machine change
when it gets errors sending VMBACKUP_PROTOCOL_EVENT_SET RPC.

RPC errors are only used as a trigger to abort the operation.
We ignore the RPC errors that might occur after aborting the
operation.

open-vm-tools/services/plugins/vmbackup/stateMachine.c
open-vm-tools/services/plugins/vmbackup/vmBackupInt.h

index d435cb66d675e915160fc80f95233880724a6e13..2d136082d954a5f44357bab28ac1bea6a88b4ba1 100644 (file)
@@ -224,6 +224,7 @@ VmBackup_SendEvent(const char *event,
    if (gBackupState->keepAlive != NULL) {
       g_source_destroy(gBackupState->keepAlive);
       g_source_unref(gBackupState->keepAlive);
+      gBackupState->keepAlive = NULL;
    }
 
    msg = g_strdup_printf(VMBACKUP_PROTOCOL_EVENT_SET" %s %u %s",
@@ -267,19 +268,27 @@ VmBackup_SendEvent(const char *event,
                              &result, &resultLen);
 #endif
 
-   if (!success) {
+   if (success) {
+      ASSERT(gBackupState->keepAlive == NULL);
+      gBackupState->keepAlive =
+         g_timeout_source_new(VMBACKUP_KEEP_ALIVE_PERIOD / 2);
+      VMTOOLSAPP_ATTACH_SOURCE(gBackupState->ctx,
+                               gBackupState->keepAlive,
+                               VmBackupKeepAliveCallback,
+                               NULL,
+                               NULL);
+   } else {
       g_warning("Failed to send vmbackup event: %s, result: %s.\n",
                 msg, result);
+      if (gBackupState->rpcState != VMBACKUP_RPC_STATE_IGNORE) {
+         g_debug("Changing rpcState from %d to %d\n",
+                 gBackupState->rpcState, VMBACKUP_RPC_STATE_ERROR);
+         gBackupState->rpcState = VMBACKUP_RPC_STATE_ERROR;
+      }
    }
    vm_free(result);
    g_free(msg);
 
-   gBackupState->keepAlive = g_timeout_source_new(VMBACKUP_KEEP_ALIVE_PERIOD / 2);
-   VMTOOLSAPP_ATTACH_SOURCE(gBackupState->ctx,
-                            gBackupState->keepAlive,
-                            VmBackupKeepAliveCallback,
-                            NULL,
-                            NULL);
    return success;
 }
 
@@ -440,6 +449,12 @@ VmBackupDoAbort(void)
 {
    g_debug("*** %s\n", __FUNCTION__);
    ASSERT(gBackupState != NULL);
+
+   /*
+    * Once we abort the operation, we don't care about RPC state.
+    */
+   gBackupState->rpcState = VMBACKUP_RPC_STATE_IGNORE;
+
    if (gBackupState->machineState != VMBACKUP_MSTATE_SCRIPT_ERROR &&
        gBackupState->machineState != VMBACKUP_MSTATE_SYNC_ERROR) {
       const char *eventMsg = "Quiesce aborted.";
@@ -623,6 +638,17 @@ VmBackupAsyncCallback(void *clientData)
       if (opPending) {
          goto exit;
       }
+
+      /*
+       * VMX state might have changed when we were processing
+       * currentOp. This is usually detected by failures in
+       * sending backup event to the host.
+       */
+      if (gBackupState->rpcState == VMBACKUP_RPC_STATE_ERROR) {
+         g_warning("Aborting backup operation due to RPC errors.");
+         VmBackupDoAbort();
+         goto exit;
+      }
    }
 
    switch (gBackupState->machineState) {
@@ -958,6 +984,7 @@ VmBackupStartCommon(RpcInData *data,
    gBackupState->enableNullDriver = VMBACKUP_CONFIG_GET_BOOL(ctx->config,
                                                              "enableNullDriver",
                                                              TRUE);
+   gBackupState->rpcState = VMBACKUP_RPC_STATE_NORMAL;
 
    g_debug("Using quiesceApps = %d, quiesceFS = %d, allowHWProvider = %d,"
            " execScripts = %d, scriptArg = %s, timeout = %u,"
index 44e4f64cd08bca5f29f0efa4621098e3f33fa3ea..fd076b0d6d35c162207d058c6707f2c03bc80724 100644 (file)
@@ -72,6 +72,12 @@ typedef enum {
    VMBACKUP_MSTATE_SYNC_ERROR
 } VmBackupMState;
 
+typedef enum {
+   VMBACKUP_RPC_STATE_NORMAL,
+   VMBACKUP_RPC_STATE_ERROR,
+   VMBACKUP_RPC_STATE_IGNORE
+} VmBackupRpcState;
+
 /**
  * This is a "base struct" for asynchronous operations monitored by the
  * state machine. Each implementation should provide these three functions
@@ -138,6 +144,7 @@ typedef struct VmBackupState {
    Bool           vssBootableSystemState;
    Bool           vssPartialFileSupport;
    Bool           vssUseDefault;
+   VmBackupRpcState rpcState;
 } VmBackupState;
 
 typedef Bool (*VmBackupCallback)(VmBackupState *);