|
|
43fe83 |
From 48d8b3b8088178e6b77e40379facbfd23f3154e8 Mon Sep 17 00:00:00 2001
|
|
|
43fe83 |
Message-Id: <48d8b3b8088178e6b77e40379facbfd23f3154e8.1377873640.git.jdenemar@redhat.com>
|
|
|
43fe83 |
From: Peter Krempa <pkrempa@redhat.com>
|
|
|
43fe83 |
Date: Wed, 21 Aug 2013 12:43:31 +0200
|
|
|
43fe83 |
Subject: [PATCH] virsh: Don't leak list of volumes when undefining domain with
|
|
|
43fe83 |
storage
|
|
|
43fe83 |
|
|
|
43fe83 |
https://bugzilla.redhat.com/show_bug.cgi?id=999057 [7.0]
|
|
|
43fe83 |
|
|
|
43fe83 |
Use the new semantics of vshStringToArray to avoid leaking the array of
|
|
|
43fe83 |
volumes to be deleted. The array would be leaked in case the first
|
|
|
43fe83 |
volume was found in the domain definition. Also refactor the code a bit
|
|
|
43fe83 |
to sanitize naming of variables hoding arrays and dimensions of the
|
|
|
43fe83 |
arrays.
|
|
|
43fe83 |
|
|
|
43fe83 |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=996050 [6.6]
|
|
|
43fe83 |
(cherry picked from commit 04898f60d2b509c4d106bf7e1ee269acc240b93d)
|
|
|
43fe83 |
---
|
|
|
43fe83 |
tools/virsh-domain.c | 134 +++++++++++++++++++++++++--------------------------
|
|
|
43fe83 |
1 file changed, 65 insertions(+), 69 deletions(-)
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
|
|
|
43fe83 |
index e2e4409..f35a3c5 100644
|
|
|
43fe83 |
--- a/tools/virsh-domain.c
|
|
|
43fe83 |
+++ b/tools/virsh-domain.c
|
|
|
43fe83 |
@@ -2928,24 +2928,23 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
|
|
|
43fe83 |
int rc = -1;
|
|
|
43fe83 |
int running;
|
|
|
43fe83 |
/* list of volumes to remove along with this domain */
|
|
|
43fe83 |
- vshUndefineVolume *vlist = NULL;
|
|
|
43fe83 |
- int nvols = 0;
|
|
|
43fe83 |
- const char *volumes = NULL;
|
|
|
43fe83 |
- char **volume_tokens = NULL;
|
|
|
43fe83 |
- char *volume_tok = NULL;
|
|
|
43fe83 |
- int nvolume_tokens = 0;
|
|
|
43fe83 |
- char *def = NULL;
|
|
|
43fe83 |
+ const char *vol_string = NULL; /* string containing volumes to delete */
|
|
|
43fe83 |
+ char **vol_list = NULL; /* tokenized vol_string */
|
|
|
43fe83 |
+ int nvol_list = 0;
|
|
|
43fe83 |
+ vshUndefineVolume *vols = NULL; /* info about the volumes to delete*/
|
|
|
43fe83 |
+ size_t nvols = 0;
|
|
|
43fe83 |
+ char *def = NULL; /* domain def */
|
|
|
43fe83 |
+ xmlDocPtr doc = NULL;
|
|
|
43fe83 |
+ xmlXPathContextPtr ctxt = NULL;
|
|
|
43fe83 |
+ xmlNodePtr *vol_nodes = NULL; /* XML nodes of volumes of the guest */
|
|
|
43fe83 |
+ int nvol_nodes;
|
|
|
43fe83 |
char *source = NULL;
|
|
|
43fe83 |
char *target = NULL;
|
|
|
43fe83 |
size_t i;
|
|
|
43fe83 |
size_t j;
|
|
|
43fe83 |
- xmlDocPtr doc = NULL;
|
|
|
43fe83 |
- xmlXPathContextPtr ctxt = NULL;
|
|
|
43fe83 |
- xmlNodePtr *vol_nodes = NULL;
|
|
|
43fe83 |
- int nvolumes = 0;
|
|
|
43fe83 |
- bool vol_not_found = false;
|
|
|
43fe83 |
|
|
|
43fe83 |
- ignore_value(vshCommandOptString(cmd, "storage", &volumes));
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ ignore_value(vshCommandOptString(cmd, "storage", &vol_string));
|
|
|
43fe83 |
|
|
|
43fe83 |
if (managed_save) {
|
|
|
43fe83 |
flags |= VIR_DOMAIN_UNDEFINE_MANAGED_SAVE;
|
|
|
43fe83 |
@@ -3013,14 +3012,17 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
/* Stash domain description for later use */
|
|
|
43fe83 |
- if (volumes || remove_all_storage) {
|
|
|
43fe83 |
+ if (vol_string || remove_all_storage) {
|
|
|
43fe83 |
if (running) {
|
|
|
43fe83 |
- vshError(ctl, _("Storage volume deletion is supported only on stopped domains"));
|
|
|
43fe83 |
+ vshError(ctl,
|
|
|
43fe83 |
+ _("Storage volume deletion is supported only on "
|
|
|
43fe83 |
+ "stopped domains"));
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
- if (volumes && remove_all_storage) {
|
|
|
43fe83 |
- vshError(ctl, _("Specified both --storage and --remove-all-storage"));
|
|
|
43fe83 |
+ if (vol_string && remove_all_storage) {
|
|
|
43fe83 |
+ vshError(ctl,
|
|
|
43fe83 |
+ _("Specified both --storage and --remove-all-storage"));
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -3034,20 +3036,17 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
|
|
|
43fe83 |
goto error;
|
|
|
43fe83 |
|
|
|
43fe83 |
/* tokenize the string from user and save it's parts into an array */
|
|
|
43fe83 |
- if (volumes) {
|
|
|
43fe83 |
- if ((nvolume_tokens = vshStringToArray(volumes, &volume_tokens)) < 0)
|
|
|
43fe83 |
- goto cleanup;
|
|
|
43fe83 |
- }
|
|
|
43fe83 |
-
|
|
|
43fe83 |
- if ((nvolumes = virXPathNodeSet("./devices/disk", ctxt,
|
|
|
43fe83 |
- &vol_nodes)) < 0)
|
|
|
43fe83 |
+ if (vol_string &&
|
|
|
43fe83 |
+ (nvol_list = vshStringToArray(vol_string, &vol_list)) < 0)
|
|
|
43fe83 |
goto error;
|
|
|
43fe83 |
|
|
|
43fe83 |
- if (nvolumes > 0)
|
|
|
43fe83 |
- vlist = vshCalloc(ctl, nvolumes, sizeof(*vlist));
|
|
|
43fe83 |
+ if ((nvol_nodes = virXPathNodeSet("./devices/disk", ctxt,
|
|
|
43fe83 |
+ &vol_nodes)) < 0)
|
|
|
43fe83 |
+ goto error;
|
|
|
43fe83 |
|
|
|
43fe83 |
- for (i = 0; i < nvolumes; i++) {
|
|
|
43fe83 |
+ for (i = 0; i < nvol_nodes; i++) {
|
|
|
43fe83 |
ctxt->node = vol_nodes[i];
|
|
|
43fe83 |
+ vshUndefineVolume vol;
|
|
|
43fe83 |
VIR_FREE(source);
|
|
|
43fe83 |
VIR_FREE(target);
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -3059,56 +3058,53 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
|
|
|
43fe83 |
"./source/@file|"
|
|
|
43fe83 |
"./source/@dir|"
|
|
|
43fe83 |
"./source/@name|"
|
|
|
43fe83 |
- "./source/@dev)", ctxt))) {
|
|
|
43fe83 |
- if (last_error && last_error->code != VIR_ERR_OK)
|
|
|
43fe83 |
- goto error;
|
|
|
43fe83 |
- else
|
|
|
43fe83 |
- continue;
|
|
|
43fe83 |
- }
|
|
|
43fe83 |
+ "./source/@dev)", ctxt)))
|
|
|
43fe83 |
+ continue;
|
|
|
43fe83 |
|
|
|
43fe83 |
/* lookup if volume was selected by user */
|
|
|
43fe83 |
- if (volumes) {
|
|
|
43fe83 |
- volume_tok = NULL;
|
|
|
43fe83 |
- for (j = 0; j < nvolume_tokens; j++) {
|
|
|
43fe83 |
- if (volume_tokens[j] &&
|
|
|
43fe83 |
- (STREQ(volume_tokens[j], target) ||
|
|
|
43fe83 |
- STREQ(volume_tokens[j], source))) {
|
|
|
43fe83 |
- volume_tok = volume_tokens[j];
|
|
|
43fe83 |
- volume_tokens[j] = NULL;
|
|
|
43fe83 |
+ if (vol_list) {
|
|
|
43fe83 |
+ bool found = false;
|
|
|
43fe83 |
+ for (j = 0; j < nvol_list; j++) {
|
|
|
43fe83 |
+ if (STREQ_NULLABLE(vol_list[j], target) ||
|
|
|
43fe83 |
+ STREQ_NULLABLE(vol_list[j], source)) {
|
|
|
43fe83 |
+ VIR_FREE(vol_list[j]);
|
|
|
43fe83 |
+ found = true;
|
|
|
43fe83 |
break;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
}
|
|
|
43fe83 |
- if (!volume_tok)
|
|
|
43fe83 |
+ if (!found)
|
|
|
43fe83 |
continue;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
- if (!(vlist[nvols].vol = virStorageVolLookupByPath(ctl->conn,
|
|
|
43fe83 |
- source))) {
|
|
|
43fe83 |
+ if (!(vol.vol = virStorageVolLookupByPath(ctl->conn, source))) {
|
|
|
43fe83 |
vshPrint(ctl,
|
|
|
43fe83 |
_("Storage volume '%s'(%s) is not managed by libvirt. "
|
|
|
43fe83 |
"Remove it manually.\n"), target, source);
|
|
|
43fe83 |
vshResetLibvirtError();
|
|
|
43fe83 |
continue;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
- vlist[nvols].source = source;
|
|
|
43fe83 |
- vlist[nvols].target = target;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ vol.source = source;
|
|
|
43fe83 |
+ vol.target = target;
|
|
|
43fe83 |
source = NULL;
|
|
|
43fe83 |
target = NULL;
|
|
|
43fe83 |
- nvols++;
|
|
|
43fe83 |
+ if (VIR_APPEND_ELEMENT(vols, nvols, vol) < 0)
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
/* print volumes specified by user that were not found in domain definition */
|
|
|
43fe83 |
- if (volumes) {
|
|
|
43fe83 |
- for (j = 0; j < nvolume_tokens; j++) {
|
|
|
43fe83 |
- if (volume_tokens[j]) {
|
|
|
43fe83 |
- vshError(ctl, _("Volume '%s' was not found in domain's "
|
|
|
43fe83 |
- "definition.\n"),
|
|
|
43fe83 |
- volume_tokens[j]);
|
|
|
43fe83 |
- vol_not_found = true;
|
|
|
43fe83 |
+ if (vol_list) {
|
|
|
43fe83 |
+ bool found = false;
|
|
|
43fe83 |
+ for (i = 0; i < nvol_list; i++) {
|
|
|
43fe83 |
+ if (vol_list[i]) {
|
|
|
43fe83 |
+ vshError(ctl,
|
|
|
43fe83 |
+ _("Volume '%s' was not found in domain's "
|
|
|
43fe83 |
+ "definition.\n"), vol_list[i]);
|
|
|
43fe83 |
+ found = true;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
- if (vol_not_found)
|
|
|
43fe83 |
+ if (found)
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
}
|
|
|
43fe83 |
@@ -3169,9 +3165,9 @@ out:
|
|
|
43fe83 |
for (i = 0; i < nvols; i++) {
|
|
|
43fe83 |
if (wipe_storage) {
|
|
|
43fe83 |
vshPrint(ctl, _("Wiping volume '%s'(%s) ... "),
|
|
|
43fe83 |
- vlist[i].target, vlist[i].source);
|
|
|
43fe83 |
+ vols[i].target, vols[i].source);
|
|
|
43fe83 |
fflush(stdout);
|
|
|
43fe83 |
- if (virStorageVolWipe(vlist[i].vol, 0) < 0) {
|
|
|
43fe83 |
+ if (virStorageVolWipe(vols[i].vol, 0) < 0) {
|
|
|
43fe83 |
vshError(ctl, _("Failed! Volume not removed."));
|
|
|
43fe83 |
ret = false;
|
|
|
43fe83 |
continue;
|
|
|
43fe83 |
@@ -3181,13 +3177,13 @@ out:
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
/* delete the volume */
|
|
|
43fe83 |
- if (virStorageVolDelete(vlist[i].vol, 0) < 0) {
|
|
|
43fe83 |
+ if (virStorageVolDelete(vols[i].vol, 0) < 0) {
|
|
|
43fe83 |
vshError(ctl, _("Failed to remove storage volume '%s'(%s)"),
|
|
|
43fe83 |
- vlist[i].target, vlist[i].source);
|
|
|
43fe83 |
+ vols[i].target, vols[i].source);
|
|
|
43fe83 |
ret = false;
|
|
|
43fe83 |
} else {
|
|
|
43fe83 |
vshPrint(ctl, _("Volume '%s'(%s) removed.\n"),
|
|
|
43fe83 |
- vlist[i].target, vlist[i].source);
|
|
|
43fe83 |
+ vols[i].target, vols[i].source);
|
|
|
43fe83 |
}
|
|
|
43fe83 |
}
|
|
|
43fe83 |
}
|
|
|
43fe83 |
@@ -3196,17 +3192,17 @@ cleanup:
|
|
|
43fe83 |
VIR_FREE(source);
|
|
|
43fe83 |
VIR_FREE(target);
|
|
|
43fe83 |
for (i = 0; i < nvols; i++) {
|
|
|
43fe83 |
- VIR_FREE(vlist[i].source);
|
|
|
43fe83 |
- VIR_FREE(vlist[i].target);
|
|
|
43fe83 |
- if (vlist[i].vol)
|
|
|
43fe83 |
- virStorageVolFree(vlist[i].vol);
|
|
|
43fe83 |
+ VIR_FREE(vols[i].source);
|
|
|
43fe83 |
+ VIR_FREE(vols[i].target);
|
|
|
43fe83 |
+ if (vols[i].vol)
|
|
|
43fe83 |
+ virStorageVolFree(vols[i].vol);
|
|
|
43fe83 |
}
|
|
|
43fe83 |
- VIR_FREE(vlist);
|
|
|
43fe83 |
+ VIR_FREE(vols);
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ for (i = 0; i < nvol_list; i++)
|
|
|
43fe83 |
+ VIR_FREE(vol_list[i]);
|
|
|
43fe83 |
+ VIR_FREE(vol_list);
|
|
|
43fe83 |
|
|
|
43fe83 |
- if (volume_tokens) {
|
|
|
43fe83 |
- VIR_FREE(*volume_tokens);
|
|
|
43fe83 |
- VIR_FREE(volume_tokens);
|
|
|
43fe83 |
- }
|
|
|
43fe83 |
VIR_FREE(def);
|
|
|
43fe83 |
VIR_FREE(vol_nodes);
|
|
|
43fe83 |
xmlFreeDoc(doc);
|
|
|
43fe83 |
--
|
|
|
43fe83 |
1.8.3.2
|
|
|
43fe83 |
|