-----BEGIN PGP SIGNATURE-----

iQIcBAABAgAGBQJYsHFRAAoJEL2+eyfA3jBXs60P/jM8nXsUODyfbI4oFm338QPn
 TG8qU808qFWKTjc7ILAE3/xPwlM4E9IIU14cjPZgPn15JI/sROUQiJCGtkcOZhWj
 7YjG5XqYAUPXqYG3uKnL89bPTAxFMFpoQVcem+fkl3ZCyCoi4sjlQYjEo2sdxHiY
 PaRKYJWTeakZ7/5woV1tfLOAAG1cOKwEeQO2uCGbSeoeSSIrV6LdQbttNBMse3NZ
 iu7RA9qjeZp7VhHJAqnx9JvJmWLINHXcmO/BDtWVJGEKmUqDbphFKFxrN2ABv8fF
 93Hjm4nRku7xbzlFiyeG9L5unqlO6t7Sdyom8wqAhHSB5zNuoE0MhM9MEFgLkD7Y
 /+mIz/d43h0LnzOouWGQSUY99jCyYCwo2o09pSlOQH+prnp9XfJzK3F8I6zlRkhE
 oRMg60FdndKNwmSnpIQg6WdJIdwYqEm03AszMDU9GJ2mmX2fg0vgNOXY3G0TBXwh
 ca1zQmE59UoDblVzzOp5pL5K55ELfOYJsTZYpNsC3xbfWsQJ3wHD/+luP9WKOKi3
 JR3zhsY6Y78Osmd++Dxfc37QWk+OPKow8r6tQ2ds07xC/r9kaJv2G5qGrIUppvT0
 ppk0Np8lHS5L6ehJqHOajG1GkJ25lfevjHt1OO/MaaDxz+8bvKacxatbHKIWJf2u
 DGPWBT606gnkeH+UJbzT
 =1daa
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/cody/tags/block-pull-request' into staging

# gpg: Signature made Fri 24 Feb 2017 17:45:53 GMT
# gpg:                using RSA key 0xBDBE7B27C0DE3057
# gpg: Good signature from "Jeffrey Cody <jcody@redhat.com>"
# gpg:                 aka "Jeffrey Cody <jeff@codyprime.org>"
# gpg:                 aka "Jeffrey Cody <codyprime@gmail.com>"
# Primary key fingerprint: 9957 4B4D 3474 90E7 9D98  D624 BDBE 7B27 C0DE 3057

* remotes/cody/tags/block-pull-request:
  RBD: Add support readv,writev for rbd
  block/nfs: try to avoid the bounce buffer in pwritev
  block/nfs: convert to preadv / pwritev

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-02-26 11:47:00 +00:00
commit 6528a4c1f2
2 changed files with 84 additions and 46 deletions

View File

@ -263,9 +263,9 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
nfs_co_generic_bh_cb, task); nfs_co_generic_bh_cb, task);
} }
static int coroutine_fn nfs_co_readv(BlockDriverState *bs, static int coroutine_fn nfs_co_preadv(BlockDriverState *bs, uint64_t offset,
int64_t sector_num, int nb_sectors, uint64_t bytes, QEMUIOVector *iov,
QEMUIOVector *iov) int flags)
{ {
NFSClient *client = bs->opaque; NFSClient *client = bs->opaque;
NFSRPC task; NFSRPC task;
@ -274,9 +274,7 @@ static int coroutine_fn nfs_co_readv(BlockDriverState *bs,
task.iov = iov; task.iov = iov;
if (nfs_pread_async(client->context, client->fh, if (nfs_pread_async(client->context, client->fh,
sector_num * BDRV_SECTOR_SIZE, offset, bytes, nfs_co_generic_cb, &task) != 0) {
nb_sectors * BDRV_SECTOR_SIZE,
nfs_co_generic_cb, &task) != 0) {
return -ENOMEM; return -ENOMEM;
} }
@ -297,28 +295,34 @@ static int coroutine_fn nfs_co_readv(BlockDriverState *bs,
return 0; return 0;
} }
static int coroutine_fn nfs_co_writev(BlockDriverState *bs, static int coroutine_fn nfs_co_pwritev(BlockDriverState *bs, uint64_t offset,
int64_t sector_num, int nb_sectors, uint64_t bytes, QEMUIOVector *iov,
QEMUIOVector *iov) int flags)
{ {
NFSClient *client = bs->opaque; NFSClient *client = bs->opaque;
NFSRPC task; NFSRPC task;
char *buf = NULL; char *buf = NULL;
bool my_buffer = false;
nfs_co_init_task(bs, &task); nfs_co_init_task(bs, &task);
buf = g_try_malloc(nb_sectors * BDRV_SECTOR_SIZE); if (iov->niov != 1) {
if (nb_sectors && buf == NULL) { buf = g_try_malloc(bytes);
return -ENOMEM; if (bytes && buf == NULL) {
return -ENOMEM;
}
qemu_iovec_to_buf(iov, 0, buf, bytes);
my_buffer = true;
} else {
buf = iov->iov[0].iov_base;
} }
qemu_iovec_to_buf(iov, 0, buf, nb_sectors * BDRV_SECTOR_SIZE);
if (nfs_pwrite_async(client->context, client->fh, if (nfs_pwrite_async(client->context, client->fh,
sector_num * BDRV_SECTOR_SIZE, offset, bytes, buf,
nb_sectors * BDRV_SECTOR_SIZE, nfs_co_generic_cb, &task) != 0) {
buf, nfs_co_generic_cb, &task) != 0) { if (my_buffer) {
g_free(buf); g_free(buf);
}
return -ENOMEM; return -ENOMEM;
} }
@ -327,9 +331,11 @@ static int coroutine_fn nfs_co_writev(BlockDriverState *bs,
qemu_coroutine_yield(); qemu_coroutine_yield();
} }
g_free(buf); if (my_buffer) {
g_free(buf);
}
if (task.ret != nb_sectors * BDRV_SECTOR_SIZE) { if (task.ret != bytes) {
return task.ret < 0 ? task.ret : -EIO; return task.ret < 0 ? task.ret : -EIO;
} }
@ -861,8 +867,8 @@ static BlockDriver bdrv_nfs = {
.bdrv_create = nfs_file_create, .bdrv_create = nfs_file_create,
.bdrv_reopen_prepare = nfs_reopen_prepare, .bdrv_reopen_prepare = nfs_reopen_prepare,
.bdrv_co_readv = nfs_co_readv, .bdrv_co_preadv = nfs_co_preadv,
.bdrv_co_writev = nfs_co_writev, .bdrv_co_pwritev = nfs_co_pwritev,
.bdrv_co_flush_to_disk = nfs_co_flush, .bdrv_co_flush_to_disk = nfs_co_flush,
.bdrv_detach_aio_context = nfs_detach_aio_context, .bdrv_detach_aio_context = nfs_detach_aio_context,

View File

@ -62,6 +62,13 @@
#define RBD_MAX_SNAP_NAME_SIZE 128 #define RBD_MAX_SNAP_NAME_SIZE 128
#define RBD_MAX_SNAPS 100 #define RBD_MAX_SNAPS 100
/* The LIBRBD_SUPPORTS_IOVEC is defined in librbd.h */
#ifdef LIBRBD_SUPPORTS_IOVEC
#define LIBRBD_USE_IOVEC 1
#else
#define LIBRBD_USE_IOVEC 0
#endif
typedef enum { typedef enum {
RBD_AIO_READ, RBD_AIO_READ,
RBD_AIO_WRITE, RBD_AIO_WRITE,
@ -310,6 +317,17 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf,
return ret; return ret;
} }
static void qemu_rbd_memset(RADOSCB *rcb, int64_t offs)
{
if (LIBRBD_USE_IOVEC) {
RBDAIOCB *acb = rcb->acb;
iov_memset(acb->qiov->iov, acb->qiov->niov, offs, 0,
acb->qiov->size - offs);
} else {
memset(rcb->buf + offs, 0, rcb->size - offs);
}
}
static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
{ {
Error *local_err = NULL; Error *local_err = NULL;
@ -426,11 +444,11 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
} }
} else { } else {
if (r < 0) { if (r < 0) {
memset(rcb->buf, 0, rcb->size); qemu_rbd_memset(rcb, 0);
acb->ret = r; acb->ret = r;
acb->error = 1; acb->error = 1;
} else if (r < rcb->size) { } else if (r < rcb->size) {
memset(rcb->buf + r, 0, rcb->size - r); qemu_rbd_memset(rcb, r);
if (!acb->error) { if (!acb->error) {
acb->ret = rcb->size; acb->ret = rcb->size;
} }
@ -441,10 +459,13 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
g_free(rcb); g_free(rcb);
if (acb->cmd == RBD_AIO_READ) { if (!LIBRBD_USE_IOVEC) {
qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size); if (acb->cmd == RBD_AIO_READ) {
qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size);
}
qemu_vfree(acb->bounce);
} }
qemu_vfree(acb->bounce);
acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret)); acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
qemu_aio_unref(acb); qemu_aio_unref(acb);
@ -655,7 +676,6 @@ static BlockAIOCB *rbd_start_aio(BlockDriverState *bs,
RBDAIOCB *acb; RBDAIOCB *acb;
RADOSCB *rcb = NULL; RADOSCB *rcb = NULL;
rbd_completion_t c; rbd_completion_t c;
char *buf;
int r; int r;
BDRVRBDState *s = bs->opaque; BDRVRBDState *s = bs->opaque;
@ -664,27 +684,29 @@ static BlockAIOCB *rbd_start_aio(BlockDriverState *bs,
acb->cmd = cmd; acb->cmd = cmd;
acb->qiov = qiov; acb->qiov = qiov;
assert(!qiov || qiov->size == size); assert(!qiov || qiov->size == size);
if (cmd == RBD_AIO_DISCARD || cmd == RBD_AIO_FLUSH) {
acb->bounce = NULL; rcb = g_new(RADOSCB, 1);
} else {
acb->bounce = qemu_try_blockalign(bs, qiov->size); if (!LIBRBD_USE_IOVEC) {
if (acb->bounce == NULL) { if (cmd == RBD_AIO_DISCARD || cmd == RBD_AIO_FLUSH) {
goto failed; acb->bounce = NULL;
} else {
acb->bounce = qemu_try_blockalign(bs, qiov->size);
if (acb->bounce == NULL) {
goto failed;
}
} }
if (cmd == RBD_AIO_WRITE) {
qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
}
rcb->buf = acb->bounce;
} }
acb->ret = 0; acb->ret = 0;
acb->error = 0; acb->error = 0;
acb->s = s; acb->s = s;
if (cmd == RBD_AIO_WRITE) {
qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
}
buf = acb->bounce;
rcb = g_new(RADOSCB, 1);
rcb->acb = acb; rcb->acb = acb;
rcb->buf = buf;
rcb->s = acb->s; rcb->s = acb->s;
rcb->size = size; rcb->size = size;
r = rbd_aio_create_completion(rcb, (rbd_callback_t) rbd_finish_aiocb, &c); r = rbd_aio_create_completion(rcb, (rbd_callback_t) rbd_finish_aiocb, &c);
@ -694,10 +716,18 @@ static BlockAIOCB *rbd_start_aio(BlockDriverState *bs,
switch (cmd) { switch (cmd) {
case RBD_AIO_WRITE: case RBD_AIO_WRITE:
r = rbd_aio_write(s->image, off, size, buf, c); #ifdef LIBRBD_SUPPORTS_IOVEC
r = rbd_aio_writev(s->image, qiov->iov, qiov->niov, off, c);
#else
r = rbd_aio_write(s->image, off, size, rcb->buf, c);
#endif
break; break;
case RBD_AIO_READ: case RBD_AIO_READ:
r = rbd_aio_read(s->image, off, size, buf, c); #ifdef LIBRBD_SUPPORTS_IOVEC
r = rbd_aio_readv(s->image, qiov->iov, qiov->niov, off, c);
#else
r = rbd_aio_read(s->image, off, size, rcb->buf, c);
#endif
break; break;
case RBD_AIO_DISCARD: case RBD_AIO_DISCARD:
r = rbd_aio_discard_wrapper(s->image, off, size, c); r = rbd_aio_discard_wrapper(s->image, off, size, c);
@ -712,14 +742,16 @@ static BlockAIOCB *rbd_start_aio(BlockDriverState *bs,
if (r < 0) { if (r < 0) {
goto failed_completion; goto failed_completion;
} }
return &acb->common; return &acb->common;
failed_completion: failed_completion:
rbd_aio_release(c); rbd_aio_release(c);
failed: failed:
g_free(rcb); g_free(rcb);
qemu_vfree(acb->bounce); if (!LIBRBD_USE_IOVEC) {
qemu_vfree(acb->bounce);
}
qemu_aio_unref(acb); qemu_aio_unref(acb);
return NULL; return NULL;
} }