aboutsummaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-02-25 10:50:11 +0000
committerPeter Maydell <peter.maydell@linaro.org>2014-02-25 10:50:11 +0000
commite7a1d6c52a3ac6e76e5653c830b2545e0a4043d3 (patch)
treec79235495674ca3dceded77db7224e54419f6f61 /util
parentc58e291591dbc1c846fa152d4792554803405ebb (diff)
parent6141f3bd6904df7cf9519c6444a14a608b9874c4 (diff)
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block patches # gpg: Signature made Fri 21 Feb 2014 21:42:24 GMT using RSA key ID C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" * remotes/kevin/tags/for-upstream: (54 commits) iotests: Mixed quorum child device specifications quorum: Simplify quorum_open() quorum: Add unit test. quorum: Add quorum_open() and quorum_close(). quorum: Implement recursive .bdrv_recurse_is_first_non_filter in quorum. quorum: Add quorum_co_flush(). quorum: Add quorum_invalidate_cache(). quorum: Add quorum_getlength(). quorum: Add quorum mechanism. quorum: Add quorum_aio_readv. blkverify: Extract qemu_iovec_clone() and qemu_iovec_compare() from blkverify. quorum: Add quorum_aio_writev and its dependencies. quorum: Create BDRVQuorumState and BlkDriver and do init. quorum: Create quorum.c, add QuorumChildRequest and QuorumAIOCB. check-qdict: Test termination of qdict_array_split() check-qdict: Adjust test for qdict_array_split() qdict: Extract non-QDicts in qdict_array_split() qemu-config: Sections must consist of keys qemu-iotests: Check qemu-img command line parsing qemu-img: Allow -o help with incomplete argument list ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'util')
-rw-r--r--util/iov.c106
-rw-r--r--util/qemu-config.c6
-rw-r--r--util/qemu-option.c49
3 files changed, 161 insertions, 0 deletions
diff --git a/util/iov.c b/util/iov.c
index bb46c04e4d..03934da74d 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -378,6 +378,112 @@ size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes);
}
+/**
+ * Check that I/O vector contents are identical
+ *
+ * The IO vectors must have the same structure (same length of all parts).
+ * A typical usage is to compare vectors created with qemu_iovec_clone().
+ *
+ * @a: I/O vector
+ * @b: I/O vector
+ * @ret: Offset to first mismatching byte or -1 if match
+ */
+ssize_t qemu_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
+{
+ int i;
+ ssize_t offset = 0;
+
+ assert(a->niov == b->niov);
+ for (i = 0; i < a->niov; i++) {
+ size_t len = 0;
+ uint8_t *p = (uint8_t *)a->iov[i].iov_base;
+ uint8_t *q = (uint8_t *)b->iov[i].iov_base;
+
+ assert(a->iov[i].iov_len == b->iov[i].iov_len);
+ while (len < a->iov[i].iov_len && *p++ == *q++) {
+ len++;
+ }
+
+ offset += len;
+
+ if (len != a->iov[i].iov_len) {
+ return offset;
+ }
+ }
+ return -1;
+}
+
+typedef struct {
+ int src_index;
+ struct iovec *src_iov;
+ void *dest_base;
+} IOVectorSortElem;
+
+static int sortelem_cmp_src_base(const void *a, const void *b)
+{
+ const IOVectorSortElem *elem_a = a;
+ const IOVectorSortElem *elem_b = b;
+
+ /* Don't overflow */
+ if (elem_a->src_iov->iov_base < elem_b->src_iov->iov_base) {
+ return -1;
+ } else if (elem_a->src_iov->iov_base > elem_b->src_iov->iov_base) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int sortelem_cmp_src_index(const void *a, const void *b)
+{
+ const IOVectorSortElem *elem_a = a;
+ const IOVectorSortElem *elem_b = b;
+
+ return elem_a->src_index - elem_b->src_index;
+}
+
+/**
+ * Copy contents of I/O vector
+ *
+ * The relative relationships of overlapping iovecs are preserved. This is
+ * necessary to ensure identical semantics in the cloned I/O vector.
+ */
+void qemu_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src, void *buf)
+{
+ IOVectorSortElem sortelems[src->niov];
+ void *last_end;
+ int i;
+
+ /* Sort by source iovecs by base address */
+ for (i = 0; i < src->niov; i++) {
+ sortelems[i].src_index = i;
+ sortelems[i].src_iov = &src->iov[i];
+ }
+ qsort(sortelems, src->niov, sizeof(sortelems[0]), sortelem_cmp_src_base);
+
+ /* Allocate buffer space taking into account overlapping iovecs */
+ last_end = NULL;
+ for (i = 0; i < src->niov; i++) {
+ struct iovec *cur = sortelems[i].src_iov;
+ ptrdiff_t rewind = 0;
+
+ /* Detect overlap */
+ if (last_end && last_end > cur->iov_base) {
+ rewind = last_end - cur->iov_base;
+ }
+
+ sortelems[i].dest_base = buf - rewind;
+ buf += cur->iov_len - MIN(rewind, cur->iov_len);
+ last_end = MAX(cur->iov_base + cur->iov_len, last_end);
+ }
+
+ /* Sort by source iovec index and build destination iovec */
+ qsort(sortelems, src->niov, sizeof(sortelems[0]), sortelem_cmp_src_index);
+ for (i = 0; i < src->niov; i++) {
+ qemu_iovec_add(dest, sortelems[i].dest_base, src->iov[i].iov_len);
+ }
+}
+
size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt,
size_t bytes)
{
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 797df71569..f6101012c0 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -413,6 +413,12 @@ static void config_parse_qdict_section(QDict *options, QemuOptsList *opts,
QDict *section = qobject_to_qdict(qlist_entry_obj(list_entry));
char *opt_name;
+ if (!section) {
+ error_setg(errp, "[%s] section (index %u) does not consist of "
+ "keys", opts->name, i);
+ goto out;
+ }
+
opt_name = g_strdup_printf("%s.%u", opts->name, i++);
subopts = qemu_opts_create(opts, opt_name, 1, &local_err);
g_free(opt_name);
diff --git a/util/qemu-option.c b/util/qemu-option.c
index fd76cd2ada..9d898af443 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -450,6 +450,55 @@ fail:
return NULL;
}
+bool has_help_option(const char *param)
+{
+ size_t buflen = strlen(param) + 1;
+ char *buf = g_malloc0(buflen);
+ const char *p = param;
+ bool result = false;
+
+ while (*p) {
+ p = get_opt_value(buf, buflen, p);
+ if (*p) {
+ p++;
+ }
+
+ if (is_help_option(buf)) {
+ result = true;
+ goto out;
+ }
+ }
+
+out:
+ free(buf);
+ return result;
+}
+
+bool is_valid_option_list(const char *param)
+{
+ size_t buflen = strlen(param) + 1;
+ char *buf = g_malloc0(buflen);
+ const char *p = param;
+ bool result = true;
+
+ while (*p) {
+ p = get_opt_value(buf, buflen, p);
+ if (*p && !*++p) {
+ result = false;
+ goto out;
+ }
+
+ if (!*buf || *buf == ',') {
+ result = false;
+ goto out;
+ }
+ }
+
+out:
+ free(buf);
+ return result;
+}
+
/*
* Prints all options of a list that have a value to stdout
*/