]> xenbits.xensource.com Git - libvirt.git/commitdiff
lib: Replace qsort() with g_qsort_with_data()
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 22 Nov 2023 13:58:49 +0000 (14:58 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 24 Nov 2023 08:53:14 +0000 (09:53 +0100)
While glibc provides qsort(), which usually is just a mergesort,
until sorting arrays so huge that temporary array used by
mergesort would not fit into physical memory (which in our case
is never), we are not guaranteed it'll use mergesort. The
advantage of mergesort is clear - it's stable. IOW, if we have an
array of values parsed from XML, qsort() it and produce some
output based on those values, we can then compare the output with
some expected output, line by line.

But with newer glibc this is all history. After [1], qsort() is
no longer mergesort but introsort instead, which is not stable.
This is suboptimal, because in some cases we want to preserve
order of equal items. For instance, in ebiptablesApplyNewRules(),
nwfilter rules are sorted by their priority. But if two rules
have the same priority, we want to keep them in the order they
appear in the XML. Since it's hard/needless work to identify
places where stable or unstable sorting is needed, let's just
play it safe and use stable sorting everywhere.

Fortunately, glib provides g_qsort_with_data() which indeed
implement mergesort and it's a drop in replacement for qsort(),
almost. It accepts fifth argument (pointer to opaque data), that
is passed to comparator function, which then accepts three
arguments.

We have to keep one occurance of qsort() though - in NSS module
which deliberately does not link with glib.

1: https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=03bf8357e8291857a435afcc3048e0b697b6cc04
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
30 files changed:
build-aux/Makefile.nonreentrant
build-aux/syntax-check.mk
src/conf/capabilities.c
src/conf/domain_conf.c
src/cpu/cpu.c
src/cpu/cpu_x86.c
src/lxc/lxc_container.c
src/nwfilter/nwfilter_ebiptables_driver.c
src/qemu/qemu_monitor_json.c
src/qemu/qemu_process.c
src/security/security_manager.c
src/util/virfile.c
src/util/virhash.c
src/util/virresctrl.c
src/util/virstring.c
src/util/virstring.h
src/util/virtypedparam.c
tests/commandhelper.c
tests/virstringtest.c
tools/virsh-checkpoint.c
tools/virsh-domain-monitor.c
tools/virsh-host.c
tools/virsh-interface.c
tools/virsh-network.c
tools/virsh-nodedev.c
tools/virsh-nwfilter.c
tools/virsh-pool.c
tools/virsh-secret.c
tools/virsh-snapshot.c
tools/virsh-volume.c

index 729f395e9d9863c2229e4668db7df43ef821a277..4ecd694b2fe6a9a096ea2e589b296d21a8c729a1 100644 (file)
 #  nm -D --defined-only --without-symbol-versions /lib64/libc.so.6 \
 #      | grep '_r$' \
 #      | awk '{print $3}' \
-#      | grep -v -e '^_' -e 'qsort' -e 'readdir' \
+#      | grep -v -e '^_' -e 'readdir' \
 #      | sort -u \
 #      | sed -s 's/_r$//'
 #
-# qsort() is safe because we don't need to pass extra args to qsort comparator,
 # readdir*() is safe as long as each DIR * instance is only used by one thread.
 #
 # Also manually add in all inet_* functions some of which
index 53dcf11a067805b50b5fc0672206a0c2b02d637a..309ca0c29a9be4c2a1bda1ef615e3c47c0c5698f 100644 (file)
@@ -380,7 +380,7 @@ sc_prohibit_unsigned_pid:
 # Many of the function names below came from this filter:
 # git grep -B2 '\<_('|grep -E '\.c- *[[:alpha:]_][[:alnum:]_]* ?\(.*[,;]$' \
 # |sed 's/.*\.c-  *//'|perl -pe 's/ ?\(.*//'|sort -u \
-# |grep -vE '^(qsort|if|close|assert|fputc|free|N_|vir.*GetName|.*Unlock|virNodeListDevices|virHashRemoveEntry|freeaddrinfo|.*[fF]ree|xdrmem_create|xmlXPathFreeObject|virUUIDFormat|openvzSetProgramSentinal|polkit_action_unref)$'
+# |grep -vE '^(if|close|assert|fputc|free|N_|vir.*GetName|.*Unlock|virNodeListDevices|virHashRemoveEntry|freeaddrinfo|.*[fF]ree|xdrmem_create|xmlXPathFreeObject|virUUIDFormat|openvzSetProgramSentinal|polkit_action_unref)$'
 
 msg_gen_function =
 msg_gen_function += VIR_ERROR
index 34f04cb7d3ed8dfbb5aa6801eb928d71f94f782c..32badee7b3da9ed6e4be3590c0dfe461cc66e61a 100644 (file)
@@ -2073,7 +2073,8 @@ virCapsHostCacheBankFree(virCapsHostCacheBank *ptr)
 
 static int
 virCapsHostCacheBankSorter(const void *a,
-                           const void *b)
+                           const void *b,
+                           void *opaque G_GNUC_UNUSED)
 {
     virCapsHostCacheBank *ca = *(virCapsHostCacheBank **)a;
     virCapsHostCacheBank *cb = *(virCapsHostCacheBank **)b;
@@ -2273,8 +2274,9 @@ virCapabilitiesInitCaches(virCaps *caps)
      * still traverse the directory instead of guessing names (in case there is
      * 'index1' and 'index3' but no 'index2'). */
     if (caps->host.cache.banks) {
-        qsort(caps->host.cache.banks, caps->host.cache.nbanks,
-              sizeof(*caps->host.cache.banks), virCapsHostCacheBankSorter);
+        g_qsort_with_data(caps->host.cache.banks, caps->host.cache.nbanks,
+                          sizeof(*caps->host.cache.banks),
+                          virCapsHostCacheBankSorter, NULL);
     }
 
     if (virCapabilitiesInitResctrlMemory(caps) < 0)
index 27f686206774a05350dedb8ac222ec2dbff5c858..f7d7244738d93dbdc72cd67eea0a60a5d2d0c89c 100644 (file)
@@ -15703,7 +15703,9 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
 }
 
 
-static int virDomainIdMapEntrySort(const void *a, const void *b)
+static int virDomainIdMapEntrySort(const void *a,
+                                   const void *b,
+                                   void *opaque G_GNUC_UNUSED)
 {
     const virDomainIdMapEntry *entrya = a;
     const virDomainIdMapEntry *entryb = b;
@@ -15746,7 +15748,7 @@ virDomainIdmapDefParseXML(xmlXPathContextPtr ctxt,
         }
     }
 
-    qsort(idmap, num, sizeof(idmap[0]), virDomainIdMapEntrySort);
+    g_qsort_with_data(idmap, num, sizeof(idmap[0]), virDomainIdMapEntrySort, NULL);
 
     return idmap;
 }
index bb5737e938aa9400e043b2c81d032f727f743dd4..bc43aa4e939f4b40af8cdab4d6d1189d55af0718 100644 (file)
@@ -1045,7 +1045,8 @@ virCPUConvertLegacy(virArch arch,
 
 static int
 virCPUFeatureCompare(const void *p1,
-                     const void *p2)
+                     const void *p2,
+                     void *opaque G_GNUC_UNUSED)
 {
     const virCPUFeatureDef *f1 = p1;
     const virCPUFeatureDef *f2 = p2;
@@ -1085,8 +1086,8 @@ virCPUExpandFeatures(virArch arch,
         driver->expandFeatures(cpu) < 0)
         return -1;
 
-    qsort(cpu->features, cpu->nfeatures, sizeof(*cpu->features),
-          virCPUFeatureCompare);
+    g_qsort_with_data(cpu->features, cpu->nfeatures, sizeof(*cpu->features),
+                      virCPUFeatureCompare, NULL);
 
     VIR_DEBUG("nfeatures=%zu", cpu->nfeatures);
     return 0;
index 7a7f3b409dd85f1af4208b9d42d7756ec6ba75a9..8d0e3947cef61e02b4a44660f800aaab4ce0aa68 100644 (file)
@@ -393,7 +393,9 @@ x86FeatureFindInternal(const char *name)
 
 
 static int
-virCPUx86DataSorter(const void *a, const void *b)
+virCPUx86DataSorter(const void *a,
+                    const void *b,
+                    void *opaque G_GNUC_UNUSED)
 {
     virCPUx86DataItem *da = (virCPUx86DataItem *) a;
     virCPUx86DataItem *db = (virCPUx86DataItem *) b;
@@ -437,7 +439,7 @@ static int
 virCPUx86DataItemCmp(const virCPUx86DataItem *item1,
                      const virCPUx86DataItem *item2)
 {
-    return virCPUx86DataSorter(item1, item2);
+    return virCPUx86DataSorter(item1, item2, NULL);
 }
 
 
@@ -541,8 +543,9 @@ virCPUx86DataAddItem(virCPUx86Data *data,
         VIR_APPEND_ELEMENT_COPY(data->items, data->len,
                                 *((virCPUx86DataItem *)item));
 
-        qsort(data->items, data->len,
-              sizeof(virCPUx86DataItem), virCPUx86DataSorter);
+        g_qsort_with_data(data->items, data->len,
+                          sizeof(virCPUx86DataItem),
+                          virCPUx86DataSorter, NULL);
     }
 
     return 0;
@@ -3465,8 +3468,8 @@ virCPUx86DataGetHost(void)
     }
 
     /* the rest of the code expects the function to be in order */
-    qsort(cpuid->data.x86.items, cpuid->data.x86.len,
-          sizeof(virCPUx86DataItem), virCPUx86DataSorter);
+    g_qsort_with_data(cpuid->data.x86.items, cpuid->data.x86.len,
+                      sizeof(virCPUx86DataItem), virCPUx86DataSorter, NULL);
 
     return cpuid;
 }
index 35a882171b5daa9f78a5caed911d86f735e8c521..652697890f8ce7ce3c02f437750d48a81504f7f7 100644 (file)
@@ -791,7 +791,8 @@ static int lxcContainerSetReadOnly(void)
     if (!mounts)
         return 0;
 
-    qsort(mounts, nmounts, sizeof(mounts[0]), virStringSortRevCompare);
+    g_qsort_with_data(mounts, nmounts,
+                      sizeof(mounts[0]), virStringSortRevCompare, NULL);
 
     /* turn 'mounts' into a proper GStrv */
     VIR_EXPAND_N(mounts, nmounts, 1);
index 1c5da2ae058b01e79c1ee2002d218f934995ff07..56bddb9097edc967d9ba99b8fc7a652ca1a6b27b 100644 (file)
@@ -3087,7 +3087,9 @@ virNWFilterRuleInstSort(const void *a, const void *b)
 
 
 static int
-virNWFilterRuleInstSortPtr(const void *a, const void *b)
+virNWFilterRuleInstSortPtr(const void *a,
+                           const void *b,
+                           void *opaque G_GNUC_UNUSED)
 {
     virNWFilterRuleInst * const *insta = a;
     virNWFilterRuleInst * const *instb = b;
@@ -3097,7 +3099,8 @@ virNWFilterRuleInstSortPtr(const void *a, const void *b)
 
 static int
 ebiptablesFilterOrderSort(const void *va,
-                          const void *vb)
+                          const void *vb,
+                          void *opaque G_GNUC_UNUSED)
 {
     const virHashKeyValuePair *a = va;
     const virHashKeyValuePair *b = vb;
@@ -3244,7 +3247,9 @@ struct _ebtablesSubChainInst {
 
 
 static int
-ebtablesSubChainInstSort(const void *a, const void *b)
+ebtablesSubChainInstSort(const void *a,
+                         const void *b,
+                         void *opaque G_GNUC_UNUSED)
 {
     const ebtablesSubChainInst **insta = (const ebtablesSubChainInst **)a;
     const ebtablesSubChainInst **instb = (const ebtablesSubChainInst **)b;
@@ -3268,7 +3273,8 @@ ebtablesGetSubChainInsts(GHashTable *chains,
     if (filter_names == NULL)
         return -1;
 
-    qsort(filter_names, nfilter_names, sizeof(*filter_names), ebiptablesFilterOrderSort);
+    g_qsort_with_data(filter_names, nfilter_names,
+                      sizeof(*filter_names), ebiptablesFilterOrderSort, NULL);
 
     for (i = 0; filter_names[i].key; i++) {
         g_autofree ebtablesSubChainInst *inst = NULL;
@@ -3306,9 +3312,10 @@ ebiptablesApplyNewRules(const char *ifname,
     size_t nsubchains = 0;
     int ret = -1;
 
-    if (nrules)
-        qsort(rules, nrules, sizeof(rules[0]),
-              virNWFilterRuleInstSortPtr);
+    if (nrules) {
+        g_qsort_with_data(rules, nrules, sizeof(rules[0]),
+                          virNWFilterRuleInstSortPtr, NULL);
+    }
 
     /* cleanup whatever may exist */
     virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
@@ -3388,9 +3395,11 @@ ebiptablesApplyNewRules(const char *ifname,
                 goto cleanup;
         }
 
-        if (nsubchains > 0)
-            qsort(subchains, nsubchains, sizeof(subchains[0]),
-                  ebtablesSubChainInstSort);
+        if (nsubchains > 0) {
+            g_qsort_with_data(subchains, nsubchains,
+                              sizeof(subchains[0]),
+                              ebtablesSubChainInstSort, NULL);
+        }
 
         for (i = 0, j = 0; i < nrules; i++) {
             if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) {
index 105d729d7cd4df2f3598c2bbe4863b0fbd360a51..6f1dffe8f79b7979dbb650f2114c5c4b6a54d16c 100644 (file)
@@ -7607,7 +7607,8 @@ qemuMonitorJSONProcessHotpluggableCpusReply(virJSONValue *vcpu,
 
 static int
 qemuMonitorQueryHotpluggableCpusEntrySort(const void *p1,
-                                          const void *p2)
+                                          const void *p2,
+                                          void *opaque G_GNUC_UNUSED)
 {
     const struct qemuMonitorQueryHotpluggableCpusEntry *a = p1;
     const struct qemuMonitorQueryHotpluggableCpusEntry *b = p2;
@@ -7659,7 +7660,8 @@ qemuMonitorJSONGetHotpluggableCPUs(qemuMonitor *mon,
             goto cleanup;
     }
 
-    qsort(info, ninfo, sizeof(*info), qemuMonitorQueryHotpluggableCpusEntrySort);
+    g_qsort_with_data(info, ninfo, sizeof(*info),
+                      qemuMonitorQueryHotpluggableCpusEntrySort, NULL);
 
     *entries = g_steal_pointer(&info);
     *nentries = ninfo;
index b9267d86994fec3f847f50cf8553c8041ddd51b6..f32e82bbd19fa092edc07347d0c7ad874a80a953 100644 (file)
@@ -6093,7 +6093,8 @@ qemuDomainHasHotpluggableStartupVcpus(virDomainDef *def)
 
 static int
 qemuProcessVcpusSortOrder(const void *a,
-                          const void *b)
+                          const void *b,
+                          void *opaque G_GNUC_UNUSED)
 {
     virDomainVcpuDef *vcpua = *((virDomainVcpuDef **)a);
     virDomainVcpuDef *vcpub = *((virDomainVcpuDef **)b);
@@ -6133,8 +6134,8 @@ qemuProcessSetupHotpluggableVcpus(virDomainObj *vm,
     if (nbootHotplug == 0)
         return 0;
 
-    qsort(bootHotplug, nbootHotplug, sizeof(*bootHotplug),
-          qemuProcessVcpusSortOrder);
+    g_qsort_with_data(bootHotplug, nbootHotplug,
+                      sizeof(*bootHotplug), qemuProcessVcpusSortOrder, NULL);
 
     if (virDomainCgroupEmulatorAllNodesAllow(priv->cgroup, &emulatorCgroup) < 0)
         goto cleanup;
index 5df0cd341954e9c988615677274b06d4ba8f07ee..afd41f1c203acbe8bc1aa1e650eb31e79126064f 100644 (file)
@@ -1247,7 +1247,9 @@ virSecurityManagerRestoreNetdevLabel(virSecurityManager *mgr,
 
 
 static int
-cmpstringp(const void *p1, const void *p2)
+cmpstringp(const void *p1,
+           const void *p2,
+           void *opaque G_GNUC_UNUSED)
 {
     const char *s1 = *(char * const *) p1;
     const char *s2 = *(char * const *) p2;
@@ -1303,8 +1305,9 @@ virSecurityManagerMetadataLock(virSecurityManager *mgr G_GNUC_UNUSED,
      * paths in the same order and thus no deadlock can occur.
      * Lastly, it makes searching for duplicate paths below
      * simpler. */
-    if (paths)
-        qsort(paths, npaths, sizeof(*paths), cmpstringp);
+    if (paths) {
+        g_qsort_with_data(paths, npaths, sizeof(*paths), cmpstringp, NULL);
+    }
 
     for (i = 0; i < npaths; i++) {
         const char *p = paths[i];
index 54708652fb8db9d6cd2a59794ce3bf6258e9bcc5..007b6cf51293234eb9f2da7d02cc1247cdfce855 100644 (file)
@@ -2193,9 +2193,11 @@ virFileGetMountSubtreeImpl(const char *mtabpath,
         mounts[nmounts - 2] = g_strdup(mntent.mnt_dir);
     }
 
-    if (mounts)
-        qsort(mounts, nmounts - 1, sizeof(mounts[0]),
-              reverse ? virStringSortRevCompare : virStringSortCompare);
+    if (mounts) {
+        g_qsort_with_data(mounts, nmounts - 1, sizeof(mounts[0]),
+                          reverse ? virStringSortRevCompare : virStringSortCompare,
+                          NULL);
+    }
 
     *mountsret = mounts;
     *nmountsret = nmounts ? nmounts - 1 : 0;
index 8365f51eb3672919e5e4a1904dfb7aa8c71c996d..19908c941244dcd038cbf76c9805cc1f77aebe46 100644 (file)
@@ -514,7 +514,8 @@ void *virHashSearch(GHashTable *table,
 
 static int
 virHashGetItemsKeySorter(const void *va,
-                         const void *vb)
+                         const void *vb,
+                         void *opaque G_GNUC_UNUSED)
 {
     const virHashKeyValuePair *a = va;
     const virHashKeyValuePair *b = vb;
@@ -552,8 +553,10 @@ virHashGetItems(GHashTable *table,
         i++;
     }
 
-    if (sortKeys)
-        qsort(items, *nitems, sizeof(*items), virHashGetItemsKeySorter);
+    if (sortKeys) {
+        g_qsort_with_data(items, *nitems,
+                          sizeof(*items), virHashGetItemsKeySorter, NULL);
+    }
 
     return items;
 }
index 8ca58f5d105000860c380d323e09c74bd0a8953b..30ae25c4872657caa6726aab45d34243fa521b48 100644 (file)
@@ -2522,7 +2522,8 @@ virResctrlMonitorRemove(virResctrlMonitor *monitor)
 
 static int
 virResctrlMonitorStatsSorter(const void *a,
-                             const void *b)
+                             const void *b,
+                             void *opaque G_GNUC_UNUSED)
 {
     return (*(virResctrlMonitorStats **)a)->id
         - (*(virResctrlMonitorStats **)b)->id;
@@ -2625,8 +2626,10 @@ virResctrlMonitorGetStats(virResctrlMonitor *monitor,
     }
 
     /* Sort in id's ascending order */
-    if (*nstats)
-        qsort(*stats, *nstats, sizeof(**stats), virResctrlMonitorStatsSorter);
+    if (*nstats) {
+        g_qsort_with_data(*stats, *nstats, sizeof(**stats),
+                          virResctrlMonitorStatsSorter, NULL);
+    }
 
     ret = 0;
  cleanup:
index 6b728ff047594b0fea76689fcaf82fdcfcc7cb6c..81c9aff3042eb1e0fba78a4aef569b1f3814cd25 100644 (file)
@@ -518,9 +518,11 @@ virStringIsEmpty(const char *str)
  * virStringSortCompare:
  *
  * A comparator function for sorting strings in
- * normal order with qsort().
+ * normal order with g_qsort_with_data().
  */
-int virStringSortCompare(const void *a, const void *b)
+int virStringSortCompare(const void *a,
+                         const void *b,
+                         void *opaque G_GNUC_UNUSED)
 {
     const char **sa = (const char**)a;
     const char **sb = (const char**)b;
@@ -532,9 +534,11 @@ int virStringSortCompare(const void *a, const void *b)
  * virStringSortRevCompare:
  *
  * A comparator function for sorting strings in
- * reverse order with qsort().
+ * reverse order with g_qsort_with_data().
  */
-int virStringSortRevCompare(const void *a, const void *b)
+int virStringSortRevCompare(const void *a,
+                            const void *b,
+                            void *opaque G_GNUC_UNUSED)
 {
     const char **sa = (const char**)a;
     const char **sb = (const char**)b;
index 16dcce98f42aef7b7b65ec50811d3fe493a5443f..8f9b1edc8fe524f355ad436c4ff0aacc0c5d1ed4 100644 (file)
@@ -83,8 +83,12 @@ bool virStringIsEmpty(const char *str);
 int virStrcpy(char *dest, const char *src, size_t destbytes);
 #define virStrcpyStatic(dest, src) virStrcpy((dest), (src), sizeof(dest))
 
-int virStringSortCompare(const void *a, const void *b);
-int virStringSortRevCompare(const void *a, const void *b);
+int virStringSortCompare(const void *a,
+                         const void *b,
+                         void *opaque);
+int virStringSortRevCompare(const void *a,
+                            const void *b,
+                            void *opaque);
 int virStringToUpper(char **dst, const char *src);
 
 ssize_t virStringSearch(const char *str,
index ef3b8052f6b5315c7e9096d2b3c6c445b9734035..1be249d855406a536d29fb1550e1145fdf658b91 100644 (file)
@@ -43,7 +43,9 @@ VIR_ENUM_IMPL(virTypedParameter,
 );
 
 static int
-virTypedParamsSortName(const void *left, const void *right)
+virTypedParamsSortName(const void *left,
+                       const void *right,
+                       void *opaque G_GNUC_UNUSED)
 {
     const virTypedParameter *param_left = left, *param_right = right;
     return strcmp(param_left->field, param_right->field);
@@ -78,7 +80,8 @@ virTypedParamsValidate(virTypedParameterPtr params, int nparams, ...)
 
     /* Here we intentionally don't copy values */
     memcpy(sorted, params, sizeof(*params) * nparams);
-    qsort(sorted, nparams, sizeof(*sorted), virTypedParamsSortName);
+    g_qsort_with_data(sorted, nparams,
+                      sizeof(*sorted), virTypedParamsSortName, NULL);
 
     name = va_arg(ap, const char *);
     while (name) {
@@ -102,7 +105,7 @@ virTypedParamsValidate(virTypedParameterPtr params, int nparams, ...)
 
     va_end(ap);
 
-    qsort(keys, nkeys, sizeof(*keys), virTypedParamsSortName);
+    g_qsort_with_data(keys, nkeys, sizeof(*keys), virTypedParamsSortName, NULL);
 
     for (i = 0, j = 0; i < nparams && j < nkeys;) {
         if (STRNEQ(sorted[i].field, keys[j].field)) {
index 334b02122c0caaafc25a52ae49caca25954711f6..d4629d824eddfbc7c13a8e551a37693660964c45 100644 (file)
@@ -129,7 +129,9 @@ static void printArguments(FILE *log, int argc, char** argv)
     }
 }
 
-static int envsort(const void *a, const void *b)
+static int envsort(const void *a,
+                   const void *b,
+                   void *opaque G_GNUC_UNUSED)
 {
     const char *astr = *(const char**)a;
     const char *bstr = *(const char**)b;
@@ -165,7 +167,7 @@ static int printEnvironment(FILE *log)
         newenv[i] = environ[i];
     }
 
-    qsort(newenv, length, sizeof(newenv[0]), envsort);
+    g_qsort_with_data(newenv, length, sizeof(newenv[0]), envsort, NULL);
 
     for (i = 0; i < length; i++) {
         /* Ignore the variables used to instruct the loader into
index 6e697cc240e68202271ea8702a85a64208142bfa..f4976890dbeb9f1d2af04fedc5dcbc22d93ad5f8 100644 (file)
@@ -89,10 +89,10 @@ testStringSortCompare(const void *opaque G_GNUC_UNUSED)
     };
     size_t i;
 
-    qsort(randlist, G_N_ELEMENTS(randlist), sizeof(randlist[0]),
-          virStringSortCompare);
-    qsort(randrlist, G_N_ELEMENTS(randrlist), sizeof(randrlist[0]),
-          virStringSortRevCompare);
+    g_qsort_with_data(randlist, G_N_ELEMENTS(randlist),
+                      sizeof(randlist[0]), virStringSortCompare, NULL);
+    g_qsort_with_data(randrlist, G_N_ELEMENTS(randrlist),
+                      sizeof(randrlist[0]), virStringSortRevCompare, NULL);
 
     for (i = 0; i < G_N_ELEMENTS(randlist); i++) {
         if (STRNEQ(randlist[i], sortlist[i])) {
index 727de34abbebefa24848a4769f3b24d8b6c07df0..34bae34f9a17357d0fb144de7d1fbc85a48c976c 100644 (file)
@@ -526,7 +526,8 @@ virshCheckpointListFree(struct virshCheckpointList *checkpointlist)
 
 static int
 virshChkSorter(const void *a,
-               const void *b)
+               const void *b,
+               void *opaque G_GNUC_UNUSED)
 {
     const struct virshChk *sa = a;
     const struct virshChk *sb = b;
@@ -594,9 +595,10 @@ virshCheckpointListCollect(vshControl *ctl,
     }
 
     if (!(orig_flags & VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL) &&
-        checkpointlist->chks)
-        qsort(checkpointlist->chks, checkpointlist->nchks,
-              sizeof(*checkpointlist->chks), virshChkSorter);
+        checkpointlist->chks) {
+        g_qsort_with_data(checkpointlist->chks, checkpointlist->nchks,
+                          sizeof(*checkpointlist->chks), virshChkSorter, NULL);
+    }
 
     ret = g_steal_pointer(&checkpointlist);
 
index 89fdc7a050a84f3ef434cd3e0be6e67c1975bac2..a2c56fc0900d6b658fb876e9f9c87678c0831299 100644 (file)
@@ -1483,7 +1483,9 @@ static const vshCmdInfo info_list[] = {
 
 /* compare domains, pack NULLed ones at the end */
 static int
-virshDomainSorter(const void *a, const void *b)
+virshDomainSorter(const void *a,
+                  const void *b,
+                  void *opaque G_GNUC_UNUSED)
 {
     virDomainPtr *da = (virDomainPtr *) a;
     virDomainPtr *db = (virDomainPtr *) b;
@@ -1741,9 +1743,10 @@ virshDomainListCollect(vshControl *ctl, unsigned int flags)
 
  finished:
     /* sort the list */
-    if (list->domains && list->ndomains)
-        qsort(list->domains, list->ndomains, sizeof(*list->domains),
-              virshDomainSorter);
+    if (list->domains && list->ndomains) {
+        g_qsort_with_data(list->domains, list->ndomains,
+                          sizeof(*list->domains), virshDomainSorter, NULL);
+    }
 
     /* truncate the list if filter simulation deleted entries */
     if (deleted)
index 411648197895aebf9b1acaad126bc6eabe8eb903..6c14be865f612db078ee71bd08f9e2a1f01496ef 100644 (file)
@@ -300,7 +300,9 @@ static const vshCmdOptDef opts_freepages[] = {
 };
 
 static int
-vshPageSizeSorter(const void *a, const void *b)
+vshPageSizeSorter(const void *a,
+                  const void *b,
+                  void *opaque G_GNUC_UNUSED)
 {
     unsigned int pa = *(unsigned int *)a;
     unsigned int pb = *(unsigned int *)b;
@@ -377,7 +379,8 @@ cmdFreepages(vshControl *ctl, const vshCmd *cmd)
              * @pagesize array will contain duplicates. We should
              * remove them otherwise not very nice output will be
              * produced. */
-            qsort(pagesize, nodes_cnt, sizeof(*pagesize), vshPageSizeSorter);
+            g_qsort_with_data(pagesize, nodes_cnt,
+                              sizeof(*pagesize), vshPageSizeSorter, NULL);
 
             for (i = 0; i < nodes_cnt - 1;) {
                 if (pagesize[i] == pagesize[i + 1]) {
index 77c0fff847740cd62cfa1dd57759b23d978036ac..09a3668438ac852fcc7c24e9e6fe7d627cde41c7 100644 (file)
@@ -141,7 +141,9 @@ cmdInterfaceEdit(vshControl *ctl, const vshCmd *cmd)
 }
 
 static int
-virshInterfaceSorter(const void *a, const void *b)
+virshInterfaceSorter(const void *a,
+                     const void *b,
+                     void *opaque G_GNUC_UNUSED)
 {
     virInterfacePtr *ia = (virInterfacePtr *) a;
     virInterfacePtr *ib = (virInterfacePtr *) b;
@@ -281,9 +283,10 @@ virshInterfaceListCollect(vshControl *ctl,
 
  finished:
     /* sort the list */
-    if (list->ifaces && list->nifaces)
-        qsort(list->ifaces, list->nifaces,
-              sizeof(*list->ifaces), virshInterfaceSorter);
+    if (list->ifaces && list->nifaces) {
+        g_qsort_with_data(list->ifaces, list->nifaces,
+                          sizeof(*list->ifaces), virshInterfaceSorter, NULL);
+    }
 
     /* truncate the list if filter simulation deleted entries */
     if (deleted)
index 998e7e15e32f6b992a863c2fa78b7e1b0c4ff3a1..68c75438635c15976a465cfbce553a57157f5a0b 100644 (file)
@@ -791,7 +791,9 @@ cmdNetworkInfo(vshControl *ctl, const vshCmd *cmd)
 }
 
 static int
-virshNetworkSorter(const void *a, const void *b)
+virshNetworkSorter(const void *a,
+                   const void *b,
+                   void *opaque G_GNUC_UNUSED)
 {
     virNetworkPtr *na = (virNetworkPtr *) a;
     virNetworkPtr *nb = (virNetworkPtr *) b;
@@ -982,9 +984,10 @@ virshNetworkListCollect(vshControl *ctl,
 
  finished:
     /* sort the list */
-    if (list->nets && list->nnets)
-        qsort(list->nets, list->nnets,
-              sizeof(*list->nets), virshNetworkSorter);
+    if (list->nets && list->nnets) {
+        g_qsort_with_data(list->nets, list->nnets,
+                          sizeof(*list->nets), virshNetworkSorter, NULL);
+    }
 
     /* truncate the list if filter simulation deleted entries */
     if (deleted)
@@ -1801,7 +1804,9 @@ static const vshCmdOptDef opts_network_dhcp_leases[] = {
 };
 
 static int
-virshNetworkDHCPLeaseSorter(const void *a, const void *b)
+virshNetworkDHCPLeaseSorter(const void *a,
+                            const void *b,
+                            void *opaque G_GNUC_UNUSED)
 {
     virNetworkDHCPLeasePtr *lease1 = (virNetworkDHCPLeasePtr *) a;
     virNetworkDHCPLeasePtr *lease2 = (virNetworkDHCPLeasePtr *) b;
@@ -1840,7 +1845,8 @@ cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd)
     }
 
     /* Sort the list according to MAC Address/IAID */
-    qsort(leases, nleases, sizeof(*leases), virshNetworkDHCPLeaseSorter);
+    g_qsort_with_data(leases, nleases,
+                      sizeof(*leases), virshNetworkDHCPLeaseSorter, NULL);
 
     table = vshTableNew(_("Expiry Time"), _("MAC address"), _("Protocol"),
                         _("IP address"), _("Hostname"), _("Client ID or DUID"),
@@ -2068,7 +2074,9 @@ cmdNetworkPortDelete(vshControl *ctl, const vshCmd *cmd)
 
 
 static int
-virshNetworkPortSorter(const void *a, const void *b)
+virshNetworkPortSorter(const void *a,
+                       const void *b,
+                       void *opaque G_GNUC_UNUSED)
 {
     virNetworkPortPtr *na = (virNetworkPortPtr *) a;
     virNetworkPortPtr *nb = (virNetworkPortPtr *) b;
@@ -2129,9 +2137,10 @@ virshNetworkPortListCollect(vshControl *ctl,
     list->nports = ret;
 
     /* sort the list */
-    if (list->ports && list->nports)
-        qsort(list->ports, list->nports,
-              sizeof(*list->ports), virshNetworkPortSorter);
+    if (list->ports && list->nports) {
+        g_qsort_with_data(list->ports, list->nports,
+                          sizeof(*list->ports), virshNetworkPortSorter, NULL);
+    }
 
     success = true;
 
index 82b8fb44fc533e12944a29ec483ec663eb7c4c72..fb38fd7fcc05fa12f2e927e6c93fa15530d42976 100644 (file)
@@ -183,7 +183,9 @@ virshNodeListLookup(int devid, bool parent, void *opaque)
 }
 
 static int
-virshNodeDeviceSorter(const void *a, const void *b)
+virshNodeDeviceSorter(const void *a,
+                      const void *b,
+                      void *opaque G_GNUC_UNUSED)
 {
     virNodeDevicePtr *na = (virNodeDevicePtr *) a;
     virNodeDevicePtr *nb = (virNodeDevicePtr *) b;
@@ -334,9 +336,10 @@ virshNodeDeviceListCollect(vshControl *ctl,
 
  finished:
     /* sort the list */
-    if (list->devices && list->ndevices)
-        qsort(list->devices, list->ndevices,
-              sizeof(*list->devices), virshNodeDeviceSorter);
+    if (list->devices && list->ndevices) {
+        g_qsort_with_data(list->devices, list->ndevices,
+                          sizeof(*list->devices), virshNodeDeviceSorter, NULL);
+    }
 
     /* truncate the list if filter simulation deleted entries */
     if (deleted)
index 92b2b7b3bca4a687eb8b38f375398f146fee311d..fa52d020e4df144c3b91cc9a955c7fabf071f117 100644 (file)
@@ -220,7 +220,9 @@ cmdNWFilterDumpXML(vshControl *ctl, const vshCmd *cmd)
 }
 
 static int
-virshNWFilterSorter(const void *a, const void *b)
+virshNWFilterSorter(const void *a,
+                    const void *b,
+                    void *opaque G_GNUC_UNUSED)
 {
     virNWFilterPtr *fa = (virNWFilterPtr *) a;
     virNWFilterPtr *fb = (virNWFilterPtr *) b;
@@ -323,9 +325,10 @@ virshNWFilterListCollect(vshControl *ctl,
 
  finished:
     /* sort the list */
-    if (list->filters && list->nfilters)
-        qsort(list->filters, list->nfilters,
-              sizeof(*list->filters), virshNWFilterSorter);
+    if (list->filters && list->nfilters) {
+        g_qsort_with_data(list->filters, list->nfilters,
+                          sizeof(*list->filters), virshNWFilterSorter, NULL);
+    }
 
     /* truncate the list for not found filter objects */
     if (deleted)
@@ -644,7 +647,9 @@ cmdNWFilterBindingDumpXML(vshControl *ctl, const vshCmd *cmd)
 
 
 static int
-virshNWFilterBindingSorter(const void *a, const void *b)
+virshNWFilterBindingSorter(const void *a,
+                           const void *b,
+                           void *opaque G_GNUC_UNUSED)
 {
     virNWFilterBindingPtr *fa = (virNWFilterBindingPtr *) a;
     virNWFilterBindingPtr *fb = (virNWFilterBindingPtr *) b;
@@ -702,9 +707,10 @@ virshNWFilterBindingListCollect(vshControl *ctl,
     list->nbindings = ret;
 
     /* sort the list */
-    if (list->bindings && list->nbindings > 1)
-        qsort(list->bindings, list->nbindings,
-              sizeof(*list->bindings), virshNWFilterBindingSorter);
+    if (list->bindings && list->nbindings > 1) {
+        g_qsort_with_data(list->bindings, list->nbindings,
+                          sizeof(*list->bindings), virshNWFilterBindingSorter, NULL);
+    }
 
     success = true;
 
index 5803530d7938addfce59007189a988b5e9ae1bb4..36f00cf643053f46d70475c02a84c09c5c5efc57 100644 (file)
@@ -814,7 +814,9 @@ cmdPoolDumpXML(vshControl *ctl, const vshCmd *cmd)
 }
 
 static int
-virshStoragePoolSorter(const void *a, const void *b)
+virshStoragePoolSorter(const void *a,
+                       const void *b,
+                       void *opaque G_GNUC_UNUSED)
 {
     virStoragePoolPtr *pa = (virStoragePoolPtr *) a;
     virStoragePoolPtr *pb = (virStoragePoolPtr *) b;
@@ -1005,9 +1007,10 @@ virshStoragePoolListCollect(vshControl *ctl,
 
  finished:
     /* sort the list */
-    if (list->pools && list->npools)
-        qsort(list->pools, list->npools,
-              sizeof(*list->pools), virshStoragePoolSorter);
+    if (list->pools && list->npools) {
+        g_qsort_with_data(list->pools, list->npools,
+                          sizeof(*list->pools), virshStoragePoolSorter, NULL);
+    }
 
     /* truncate the list if filter simulation deleted entries */
     if (deleted)
index 694e16c5cb15244baed8d6a254b8555a7c0f86cd..e54712ba786ff3162550435e34f18130d5340cac 100644 (file)
@@ -399,7 +399,9 @@ cmdSecretUndefine(vshControl *ctl, const vshCmd *cmd)
 }
 
 static int
-virshSecretSorter(const void *a, const void *b)
+virshSecretSorter(const void *a,
+                  const void *b,
+                  void *opaque G_GNUC_UNUSED)
 {
     virSecretPtr *sa = (virSecretPtr *) a;
     virSecretPtr *sb = (virSecretPtr *) b;
@@ -509,9 +511,10 @@ virshSecretListCollect(vshControl *ctl,
 
  finished:
     /* sort the list */
-    if (list->secrets && list->nsecrets)
-        qsort(list->secrets, list->nsecrets,
-              sizeof(*list->secrets), virshSecretSorter);
+    if (list->secrets && list->nsecrets) {
+        g_qsort_with_data(list->secrets, list->nsecrets,
+                          sizeof(*list->secrets), virshSecretSorter, NULL);
+    }
 
     /* truncate the list for not found secret objects */
     if (deleted)
index c85258c09ae15c273f5f5b5eac3b28a6fe1a70ad..2049872322e56bc50623c3c17144deed8a3bd430 100644 (file)
@@ -982,7 +982,9 @@ virshSnapshotListFree(struct virshSnapshotList *snaplist)
 }
 
 static int
-virshSnapSorter(const void *a, const void *b)
+virshSnapSorter(const void *a,
+                const void *b,
+                void *opaque G_GNUC_UNUSED)
 {
     const struct virshSnap *sa = a;
     const struct virshSnap *sb = b;
@@ -1232,7 +1234,7 @@ virshSnapshotListCollect(vshControl *ctl, virDomainPtr dom,
          * still in list.  We mark known descendants by clearing
          * snaps[i].parents.  Sorry, this is O(n^3) - hope your
          * hierarchy isn't huge.  XXX Is it worth making O(n^2 log n)
-         * by using qsort and bsearch?  */
+         * by using g_qsort_with_data and bsearch?  */
         if (start_index < 0) {
             vshError(ctl, _("snapshot %1$s disappeared from list"), fromname);
             goto cleanup;
@@ -1312,8 +1314,8 @@ virshSnapshotListCollect(vshControl *ctl, virDomainPtr dom,
     }
     if (!(orig_flags & VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL) &&
         snaplist->snaps && snaplist->nsnaps) {
-        qsort(snaplist->snaps, snaplist->nsnaps, sizeof(*snaplist->snaps),
-              virshSnapSorter);
+        g_qsort_with_data(snaplist->snaps, snaplist->nsnaps,
+                          sizeof(*snaplist->snaps), virshSnapSorter, NULL);
     }
     snaplist->nsnaps -= deleted;
 
index 9a2b21d3f356424ae01a999ab14d610fe3169cac..329ca3a66c29d6f5c9b32b12a2b90a850b694174 100644 (file)
@@ -1200,7 +1200,9 @@ cmdVolDumpXML(vshControl *ctl, const vshCmd *cmd)
 }
 
 static int
-virshStorageVolSorter(const void *a, const void *b)
+virshStorageVolSorter(const void *a,
+                      const void *b,
+                      void *opaque G_GNUC_UNUSED)
 {
     virStorageVolPtr *va = (virStorageVolPtr *) a;
     virStorageVolPtr *vb = (virStorageVolPtr *) b;
@@ -1299,8 +1301,10 @@ virshStorageVolListCollect(vshControl *ctl,
 
  finished:
     /* sort the list */
-    if (list->vols && list->nvols)
-        qsort(list->vols, list->nvols, sizeof(*list->vols), virshStorageVolSorter);
+    if (list->vols && list->nvols) {
+        g_qsort_with_data(list->vols, list->nvols,
+                          sizeof(*list->vols), virshStorageVolSorter, NULL);
+    }
 
     if (deleted)
         VIR_SHRINK_N(list->vols, list->nvols, deleted);