From e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Fri, 28 Aug 2015 09:58:54 +0800 Subject: Add qemu 2.4.0 Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5 Signed-off-by: Yang Zhang --- qemu/fsdev/virtio-9p-marshal.c | 323 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 qemu/fsdev/virtio-9p-marshal.c (limited to 'qemu/fsdev/virtio-9p-marshal.c') diff --git a/qemu/fsdev/virtio-9p-marshal.c b/qemu/fsdev/virtio-9p-marshal.c new file mode 100644 index 000000000..20f308b76 --- /dev/null +++ b/qemu/fsdev/virtio-9p-marshal.c @@ -0,0 +1,323 @@ +/* + * Virtio 9p backend + * + * Copyright IBM, Corp. 2010 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qemu/compiler.h" +#include "virtio-9p-marshal.h" +#include "qemu/bswap.h" + +void v9fs_string_free(V9fsString *str) +{ + g_free(str->data); + str->data = NULL; + str->size = 0; +} + +void v9fs_string_null(V9fsString *str) +{ + v9fs_string_free(str); +} + +void GCC_FMT_ATTR(2, 3) +v9fs_string_sprintf(V9fsString *str, const char *fmt, ...) +{ + va_list ap; + + v9fs_string_free(str); + + va_start(ap, fmt); + str->size = g_vasprintf(&str->data, fmt, ap); + va_end(ap); +} + +void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs) +{ + v9fs_string_free(lhs); + v9fs_string_sprintf(lhs, "%s", rhs->data); +} + + +static ssize_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count, + size_t offset, size_t size, int pack) +{ + int i = 0; + size_t copied = 0; + size_t req_size = size; + + + for (i = 0; size && i < sg_count; i++) { + size_t len; + if (offset >= sg[i].iov_len) { + /* skip this sg */ + offset -= sg[i].iov_len; + continue; + } else { + len = MIN(sg[i].iov_len - offset, size); + if (pack) { + memcpy(sg[i].iov_base + offset, addr, len); + } else { + memcpy(addr, sg[i].iov_base + offset, len); + } + size -= len; + copied += len; + addr += len; + if (size) { + offset = 0; + continue; + } + } + } + if (copied < req_size) { + /* + * We copied less that requested size. error out + */ + return -ENOBUFS; + } + return copied; +} + +static ssize_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num, + size_t offset, size_t size) +{ + return v9fs_packunpack(dst, out_sg, out_num, offset, size, 0); +} + +ssize_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset, + const void *src, size_t size) +{ + return v9fs_packunpack((void *)src, in_sg, in_num, offset, size, 1); +} + +ssize_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, + int bswap, const char *fmt, ...) +{ + int i; + va_list ap; + ssize_t copied = 0; + size_t old_offset = offset; + + va_start(ap, fmt); + for (i = 0; fmt[i]; i++) { + switch (fmt[i]) { + case 'b': { + uint8_t *valp = va_arg(ap, uint8_t *); + copied = v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp)); + break; + } + case 'w': { + uint16_t val, *valp; + valp = va_arg(ap, uint16_t *); + copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); + if (bswap) { + *valp = le16_to_cpu(val); + } else { + *valp = val; + } + break; + } + case 'd': { + uint32_t val, *valp; + valp = va_arg(ap, uint32_t *); + copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); + if (bswap) { + *valp = le32_to_cpu(val); + } else { + *valp = val; + } + break; + } + case 'q': { + uint64_t val, *valp; + valp = va_arg(ap, uint64_t *); + copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); + if (bswap) { + *valp = le64_to_cpu(val); + } else { + *valp = val; + } + break; + } + case 's': { + V9fsString *str = va_arg(ap, V9fsString *); + copied = v9fs_unmarshal(out_sg, out_num, offset, bswap, + "w", &str->size); + if (copied > 0) { + offset += copied; + str->data = g_malloc(str->size + 1); + copied = v9fs_unpack(str->data, out_sg, out_num, offset, + str->size); + if (copied > 0) { + str->data[str->size] = 0; + } else { + v9fs_string_free(str); + } + } + break; + } + case 'Q': { + V9fsQID *qidp = va_arg(ap, V9fsQID *); + copied = v9fs_unmarshal(out_sg, out_num, offset, bswap, "bdq", + &qidp->type, &qidp->version, &qidp->path); + break; + } + case 'S': { + V9fsStat *statp = va_arg(ap, V9fsStat *); + copied = v9fs_unmarshal(out_sg, out_num, offset, bswap, + "wwdQdddqsssssddd", + &statp->size, &statp->type, &statp->dev, + &statp->qid, &statp->mode, &statp->atime, + &statp->mtime, &statp->length, + &statp->name, &statp->uid, &statp->gid, + &statp->muid, &statp->extension, + &statp->n_uid, &statp->n_gid, + &statp->n_muid); + break; + } + case 'I': { + V9fsIattr *iattr = va_arg(ap, V9fsIattr *); + copied = v9fs_unmarshal(out_sg, out_num, offset, bswap, + "ddddqqqqq", + &iattr->valid, &iattr->mode, + &iattr->uid, &iattr->gid, &iattr->size, + &iattr->atime_sec, &iattr->atime_nsec, + &iattr->mtime_sec, &iattr->mtime_nsec); + break; + } + default: + break; + } + if (copied < 0) { + va_end(ap); + return copied; + } + offset += copied; + } + va_end(ap); + + return offset - old_offset; +} + +ssize_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, + int bswap, const char *fmt, ...) +{ + int i; + va_list ap; + ssize_t copied = 0; + size_t old_offset = offset; + + va_start(ap, fmt); + for (i = 0; fmt[i]; i++) { + switch (fmt[i]) { + case 'b': { + uint8_t val = va_arg(ap, int); + copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); + break; + } + case 'w': { + uint16_t val; + if (bswap) { + cpu_to_le16w(&val, va_arg(ap, int)); + } else { + val = va_arg(ap, int); + } + copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); + break; + } + case 'd': { + uint32_t val; + if (bswap) { + cpu_to_le32w(&val, va_arg(ap, uint32_t)); + } else { + val = va_arg(ap, uint32_t); + } + copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); + break; + } + case 'q': { + uint64_t val; + if (bswap) { + cpu_to_le64w(&val, va_arg(ap, uint64_t)); + } else { + val = va_arg(ap, uint64_t); + } + copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); + break; + } + case 's': { + V9fsString *str = va_arg(ap, V9fsString *); + copied = v9fs_marshal(in_sg, in_num, offset, bswap, + "w", str->size); + if (copied > 0) { + offset += copied; + copied = v9fs_pack(in_sg, in_num, offset, str->data, str->size); + } + break; + } + case 'Q': { + V9fsQID *qidp = va_arg(ap, V9fsQID *); + copied = v9fs_marshal(in_sg, in_num, offset, bswap, "bdq", + qidp->type, qidp->version, qidp->path); + break; + } + case 'S': { + V9fsStat *statp = va_arg(ap, V9fsStat *); + copied = v9fs_marshal(in_sg, in_num, offset, bswap, + "wwdQdddqsssssddd", + statp->size, statp->type, statp->dev, + &statp->qid, statp->mode, statp->atime, + statp->mtime, statp->length, &statp->name, + &statp->uid, &statp->gid, &statp->muid, + &statp->extension, statp->n_uid, + statp->n_gid, statp->n_muid); + break; + } + case 'A': { + V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *); + copied = v9fs_marshal(in_sg, in_num, offset, bswap, + "qQdddqqqqqqqqqqqqqqq", + statp->st_result_mask, + &statp->qid, statp->st_mode, + statp->st_uid, statp->st_gid, + statp->st_nlink, statp->st_rdev, + statp->st_size, statp->st_blksize, + statp->st_blocks, statp->st_atime_sec, + statp->st_atime_nsec, statp->st_mtime_sec, + statp->st_mtime_nsec, statp->st_ctime_sec, + statp->st_ctime_nsec, statp->st_btime_sec, + statp->st_btime_nsec, statp->st_gen, + statp->st_data_version); + break; + } + default: + break; + } + if (copied < 0) { + va_end(ap); + return copied; + } + offset += copied; + } + va_end(ap); + + return offset - old_offset; +} -- cgit 1.2.3-korg