Add the helper qemu_sort_opts() to allow in-place sorting of QemuOptsList. The function can be specified in the form defined as qemu_opts_pri_fn(), where it takes a QemuOpts pointer and generates a number showing the priority of this QemuOpts entry.
Signed-off-by: Peter Xu <pet...@redhat.com> --- include/qemu/config-file.h | 4 ++++ util/qemu-config.c | 48 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h index f605423321..ce50a72985 100644 --- a/include/qemu/config-file.h +++ b/include/qemu/config-file.h @@ -3,8 +3,12 @@ typedef void QEMUConfigCB(const char *group, QDict *qdict, void *opaque, Error **errp); +/* Returns the priority for a QemuOpts */ +typedef int (*qemu_opts_pri_fn)(QemuOpts *opt); + void qemu_load_module_for_opts(const char *group); QemuOptsList *qemu_find_opts(const char *group); +void qemu_sort_opts(const char *group, qemu_opts_pri_fn fn); QemuOptsList *qemu_find_opts_err(const char *group, Error **errp); QemuOpts *qemu_find_opts_singleton(const char *group); diff --git a/util/qemu-config.c b/util/qemu-config.c index 436ab63b16..e882dc948b 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -7,6 +7,7 @@ #include "qapi/qmp/qlist.h" #include "qemu/error-report.h" #include "qemu/option.h" +#include "qemu/option_int.h" #include "qemu/config-file.h" static QemuOptsList *vm_config_groups[48]; @@ -41,6 +42,53 @@ QemuOptsList *qemu_find_opts(const char *group) return ret; } +struct QemuOptsSortEntry { + QemuOpts *opts; + int priority; +} __attribute__ ((__aligned__(sizeof(void *)))); +typedef struct QemuOptsSortEntry QemuOptsSortEntry; + +static int qemu_opts_cmp_fn(const void *opts_1, const void *opts_2) +{ + QemuOptsSortEntry *entry1, *entry2; + + entry1 = (QemuOptsSortEntry *)opts_1; + entry2 = (QemuOptsSortEntry *)opts_2; + + return entry1->priority - entry2->priority; +} + +void qemu_sort_opts(const char *group, qemu_opts_pri_fn fn) +{ + QemuOptsSortEntry *entries, *entry; + QemuOpts *opts, *next_opts; + int i = 0, count = 0; + QemuOptsList *list; + + list = find_list(vm_config_groups, group, &error_abort); + + QTAILQ_FOREACH(opts, &list->head, next) { + count++; + } + + entries = g_new0(QemuOptsSortEntry, count); + QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) { + entry = &entries[i++]; + entry->opts = opts; + entry->priority = fn(opts); + /* Temporarily remove them; will add them back later */ + QTAILQ_REMOVE(&list->head, opts, next); + } + + qsort(entries, count, sizeof(QemuOptsSortEntry), qemu_opts_cmp_fn); + + for (i = 0; i < count; i++) { + QTAILQ_INSERT_TAIL(&list->head, entries[i].opts, next); + } + + g_free(entries); +} + QemuOpts *qemu_find_opts_singleton(const char *group) { QemuOptsList *list; -- 2.31.1