block: add aio_flush operation
Instead stalling the VCPU while serving a cache flush try to do it asynchronously. Use our good old helper thread pool to issue an asynchronous fdatasync for raw-posix. Note that while Linux AIO implements a fdatasync operation it is not useful for us because it isn't actually implement in asynchronous fashion. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
6f1953c4c1
commit
b2e12bc6e3
40
block.c
40
block.c
@ -54,6 +54,8 @@ static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
|
||||
static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
|
||||
uint8_t *buf, int nb_sectors);
|
||||
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
|
||||
@ -138,6 +140,10 @@ void bdrv_register(BlockDriver *bdrv)
|
||||
bdrv->bdrv_read = bdrv_read_em;
|
||||
bdrv->bdrv_write = bdrv_write_em;
|
||||
}
|
||||
|
||||
if (!bdrv->bdrv_aio_flush)
|
||||
bdrv->bdrv_aio_flush = bdrv_aio_flush_em;
|
||||
|
||||
bdrv->next = first_drv;
|
||||
first_drv = bdrv;
|
||||
}
|
||||
@ -1552,6 +1558,21 @@ fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
if (!drv)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Note that unlike bdrv_flush the driver is reponsible for flushing a
|
||||
* backing image if it exists.
|
||||
*/
|
||||
return drv->bdrv_aio_flush(bs, cb, opaque);
|
||||
}
|
||||
|
||||
void bdrv_aio_cancel(BlockDriverAIOCB *acb)
|
||||
{
|
||||
acb->pool->cancel(acb);
|
||||
@ -1642,6 +1663,25 @@ static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
|
||||
return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
|
||||
}
|
||||
|
||||
static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
BlockDriverAIOCBSync *acb;
|
||||
|
||||
acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
|
||||
acb->is_write = 1; /* don't bounce in the completion hadler */
|
||||
acb->qiov = NULL;
|
||||
acb->bounce = NULL;
|
||||
acb->ret = 0;
|
||||
|
||||
if (!acb->bh)
|
||||
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
|
||||
|
||||
bdrv_flush(bs);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
return &acb->common;
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
/* sync block device emulation */
|
||||
|
||||
|
2
block.h
2
block.h
@ -85,6 +85,8 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
QEMUIOVector *iov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
void bdrv_aio_cancel(BlockDriverAIOCB *acb);
|
||||
|
||||
typedef struct BlockRequest {
|
||||
|
@ -17,8 +17,9 @@
|
||||
#define QEMU_AIO_READ 0x0001
|
||||
#define QEMU_AIO_WRITE 0x0002
|
||||
#define QEMU_AIO_IOCTL 0x0004
|
||||
#define QEMU_AIO_FLUSH 0x0008
|
||||
#define QEMU_AIO_TYPE_MASK \
|
||||
(QEMU_AIO_READ|QEMU_AIO_WRITE|QEMU_AIO_IOCTL)
|
||||
(QEMU_AIO_READ|QEMU_AIO_WRITE|QEMU_AIO_IOCTL|QEMU_AIO_FLUSH)
|
||||
|
||||
/* AIO flags */
|
||||
#define QEMU_AIO_MISALIGNED 0x1000
|
||||
|
@ -574,6 +574,18 @@ static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
|
||||
cb, opaque, QEMU_AIO_WRITE);
|
||||
}
|
||||
|
||||
static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (fd_open(bs) < 0)
|
||||
return NULL;
|
||||
|
||||
return paio_submit(bs, s->aio_ctx, s->fd, 0, NULL, 0,
|
||||
cb, opaque, QEMU_AIO_FLUSH);
|
||||
}
|
||||
|
||||
static void raw_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
@ -749,6 +761,7 @@ static BlockDriver bdrv_raw = {
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
.bdrv_aio_writev = raw_aio_writev,
|
||||
.bdrv_aio_flush = raw_aio_flush,
|
||||
|
||||
.bdrv_truncate = raw_truncate,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
@ -1002,6 +1015,7 @@ static BlockDriver bdrv_host_device = {
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
.bdrv_aio_writev = raw_aio_writev,
|
||||
.bdrv_aio_flush = raw_aio_flush,
|
||||
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
@ -1096,6 +1110,7 @@ static BlockDriver bdrv_host_floppy = {
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
.bdrv_aio_writev = raw_aio_writev,
|
||||
.bdrv_aio_flush = raw_aio_flush,
|
||||
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
@ -1176,6 +1191,7 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
.bdrv_aio_writev = raw_aio_writev,
|
||||
.bdrv_aio_flush = raw_aio_flush,
|
||||
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
@ -1295,6 +1311,7 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
.bdrv_aio_writev = raw_aio_writev,
|
||||
.bdrv_aio_flush = raw_aio_flush,
|
||||
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
|
@ -69,6 +69,8 @@ struct BlockDriver {
|
||||
BlockDriverAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
BlockDriverAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
|
||||
int (*bdrv_aio_multiwrite)(BlockDriverState *bs, BlockRequest *reqs,
|
||||
int num_reqs);
|
||||
|
@ -134,6 +134,16 @@ static size_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb)
|
||||
return aiocb->aio_nbytes;
|
||||
}
|
||||
|
||||
static size_t handle_aiocb_flush(struct qemu_paiocb *aiocb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = fdatasync(aiocb->aio_fildes);
|
||||
if (ret == -1)
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PREADV
|
||||
|
||||
static ssize_t
|
||||
@ -330,6 +340,9 @@ static void *aio_thread(void *unused)
|
||||
case QEMU_AIO_WRITE:
|
||||
ret = handle_aiocb_rw(aiocb);
|
||||
break;
|
||||
case QEMU_AIO_FLUSH:
|
||||
ret = handle_aiocb_flush(aiocb);
|
||||
break;
|
||||
case QEMU_AIO_IOCTL:
|
||||
ret = handle_aiocb_ioctl(aiocb);
|
||||
break;
|
||||
@ -530,8 +543,10 @@ BlockDriverAIOCB *paio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
|
||||
acb->aio_type = type;
|
||||
acb->aio_fildes = fd;
|
||||
acb->ev_signo = SIGUSR2;
|
||||
acb->aio_iov = qiov->iov;
|
||||
acb->aio_niov = qiov->niov;
|
||||
if (qiov) {
|
||||
acb->aio_iov = qiov->iov;
|
||||
acb->aio_niov = qiov->niov;
|
||||
}
|
||||
acb->aio_nbytes = nb_sectors * 512;
|
||||
acb->aio_offset = sector_num * 512;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user