block: enhance QEMUIOVector structure

Add a possibility of embedded iovec, for cases when we need only one
local iov.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-id: 20190218140926.333779-2-vsementsov@virtuozzo.com
Message-Id: <20190218140926.333779-2-vsementsov@virtuozzo.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Vladimir Sementsov-Ogievskiy 2019-02-18 17:09:10 +03:00 committed by Stefan Hajnoczi
parent fc3dbb90f2
commit a1ca3ed5ec

View File

@ -133,10 +133,70 @@ size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt,
typedef struct QEMUIOVector {
struct iovec *iov;
int niov;
int nalloc;
size_t size;
/*
* For external @iov (qemu_iovec_init_external()) or allocated @iov
* (qemu_iovec_init()), @size is the cumulative size of iovecs and
* @local_iov is invalid and unused.
*
* For embedded @iov (QEMU_IOVEC_INIT_BUF() or qemu_iovec_init_buf()),
* @iov is equal to &@local_iov, and @size is valid, as it has same
* offset and type as @local_iov.iov_len, which is guaranteed by
* static assertion below.
*
* @nalloc is always valid and is -1 both for embedded and external
* cases. It is included in the union only to ensure the padding prior
* to the @size field will not result in a 0-length array.
*/
union {
struct {
int nalloc;
struct iovec local_iov;
};
struct {
char __pad[sizeof(int) + offsetof(struct iovec, iov_len)];
size_t size;
};
};
} QEMUIOVector;
QEMU_BUILD_BUG_ON(offsetof(QEMUIOVector, size) !=
offsetof(QEMUIOVector, local_iov.iov_len));
#define QEMU_IOVEC_INIT_BUF(self, buf, len) \
{ \
.iov = &(self).local_iov, \
.niov = 1, \
.nalloc = -1, \
.local_iov = { \
.iov_base = (void *)(buf), /* cast away const */ \
.iov_len = (len), \
}, \
}
/*
* qemu_iovec_init_buf
*
* Initialize embedded QEMUIOVector.
*
* Note: "const" is used over @buf pointer to make it simple to pass
* const pointers, appearing in read functions. Then this "const" is
* cast away by QEMU_IOVEC_INIT_BUF().
*/
static inline void qemu_iovec_init_buf(QEMUIOVector *qiov,
const void *buf, size_t len)
{
*qiov = (QEMUIOVector) QEMU_IOVEC_INIT_BUF(*qiov, buf, len);
}
static inline void *qemu_iovec_buf(QEMUIOVector *qiov)
{
/* Only supports embedded iov */
assert(qiov->nalloc == -1 && qiov->iov == &qiov->local_iov);
return qiov->local_iov.iov_base;
}
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);