If user delete a VS and enum VSSD at the sametime, it may have chance
to report error, but actually it succeed just with some VS not found. Root
cause is race condition between libvirt API for get domain's name&count and
the API for get domain's xml.
This Patch fixed it. It will continue if found one VS is missing in enum.
v2:
Rebased and better document.
v3:
Rebased.
v4:
changed CU_DEBUG information when met error in instance_from_dom().
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
src/Virt_VSSD.c | 71 ++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/src/Virt_VSSD.c b/src/Virt_VSSD.c
index 499b157..0781c8f 100644
--- a/src/Virt_VSSD.c
+++ b/src/Virt_VSSD.c
@@ -36,6 +36,8 @@
#include "Virt_VSSD.h"
+#define VSSD_ERROR_RECOVERABLE (2)
+
const static CMPIBroker *_BROKER;
static CMPIStatus _set_fv_prop(const CMPIBroker *broker,
@@ -181,8 +183,18 @@ static int instance_from_dom(const CMPIBroker *broker,
struct domain *dominfo = NULL;
ret = get_dominfo(dom, &dominfo);
- if (!ret)
+ if (!ret) {
+ int active = virDomainIsActive(dom);
+ if (active < 0) {
+ /* ret > 1 indicate that it is recoverable */
+ CU_DEBUG("Failed to get dominfo, "
+ "domain may not be active anymore.");
+ ret = VSSD_ERROR_RECOVERABLE;
+ } else {
+ CU_DEBUG("Failed to get dominfo.");
+ }
goto out;
+ }
op = CMGetObjectPath(inst, NULL);
pfx = class_prefix_name(CLASSNAME(op));
@@ -246,6 +258,8 @@ static int instance_from_dom(const CMPIBroker *broker,
s = _set_fv_prop(broker, dominfo, inst);
if (s.rc != CMPI_RC_OK) {
ret = 0;
+ CU_DEBUG("Failed to set full virtual prop for %d
dom.",
+ dominfo->type);
goto out;
}
}
@@ -260,6 +274,7 @@ static int instance_from_dom(const CMPIBroker *broker,
if (asprintf(&vsid, "%s:%s", pfx, dominfo->name) == -1) {
ret = 0;
+ CU_DEBUG("Failed in asprintf vsid.");
goto out;
}
@@ -278,7 +293,8 @@ static CMPIInstance *_get_vssd(const CMPIBroker *broker,
const CMPIObjectPath *reference,
virConnectPtr conn,
virDomainPtr dom,
- CMPIStatus *s)
+ CMPIStatus *s,
+ int *error_below)
{
CMPIInstance *inst = NULL;
@@ -294,10 +310,18 @@ static CMPIInstance *_get_vssd(const CMPIBroker *broker,
goto out;
}
- if (instance_from_dom(broker, dom, inst) != 1) {
- cu_statusf(broker, s,
- CMPI_RC_ERR_FAILED,
- "Unable to get VSSD instance from Domain");
+ *error_below = instance_from_dom(broker, dom, inst);
+ if (*error_below != 1) {
+ if (*error_below == VSSD_ERROR_RECOVERABLE) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get VSSD instance from Domain, "
+ "Domain may not exist at this moment.");
+ } else {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get VSSD instance from Domain");
+ }
}
out:
@@ -312,6 +336,7 @@ static CMPIStatus return_enum_vssd(const CMPIObjectPath *reference,
virDomainPtr *list;
int count;
int i;
+ int error_below;
CMPIStatus s = {CMPI_RC_OK, NULL};
conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
@@ -327,14 +352,33 @@ static CMPIStatus return_enum_vssd(const CMPIObjectPath *reference,
} else if (count == 0)
goto out;
+ int fail_count = 0;
for (i = 0; i < count; i++) {
CMPIInstance *inst = NULL;
-
- inst = _get_vssd(_BROKER, reference, conn, list[i], &s);
-
+
+ inst = _get_vssd(_BROKER, reference, conn, list[i],
+ &s, &error_below);
+
virDomainFree(list[i]);
- if (inst == NULL)
- continue;
+
+ if ((inst == NULL) || (s.rc != CMPI_RC_OK)) {
+ fail_count++;
+ CU_DEBUG("VSSD got %d fail instance, total %d,"
+ " error %d.",
+ fail_count, count, error_below);
+ if (error_below == VSSD_ERROR_RECOVERABLE) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_OK,
+ "%d/%d VSSD not got,"
+ " some VS may not exist now",
+ fail_count, count);
+ CU_DEBUG("Continue to next VSSD for enum.");
+ continue;
+ } else {
+ CU_DEBUG("Met unrecoverable error.");
+ break;
+ }
+ }
if (names_only)
cu_return_instance_name(results, inst);
@@ -358,7 +402,8 @@ CMPIStatus get_vssd_by_name(const CMPIBroker *broker,
virDomainPtr dom;
CMPIStatus s = {CMPI_RC_OK, NULL};
CMPIInstance *inst = NULL;
-
+ int error_below;
+
conn = connect_by_classname(broker, CLASSNAME(reference), &s);
if (conn == NULL) {
cu_statusf(broker, &s,
@@ -377,7 +422,7 @@ CMPIStatus get_vssd_by_name(const CMPIBroker *broker,
goto out;
}
- inst = _get_vssd(broker, reference, conn, dom, &s);
+ inst = _get_vssd(broker, reference, conn, dom, &s, &error_below);
virDomainFree(dom);
--
1.7.1