linux-aio: add IO_CMD_FDSYNC command support
Libaio defines IO_CMD_FDSYNC command to sync all outstanding asynchronous I/O operations, by flushing out file data to the disk storage. Enable linux-aio to submit such aio request. When using aio=native without fdsync() support, QEMU creates pthreads, and destroying these pthreads results in TLB flushes. In a real-time guest environment, TLB flushes cause a latency spike. This patch helps to avoid such spikes. Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> Message-ID: <20240425070412.37248-1-ppandit@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
10b1e09ed3
commit
24687abf23
@ -159,6 +159,7 @@ typedef struct BDRVRawState {
|
|||||||
bool has_discard:1;
|
bool has_discard:1;
|
||||||
bool has_write_zeroes:1;
|
bool has_write_zeroes:1;
|
||||||
bool use_linux_aio:1;
|
bool use_linux_aio:1;
|
||||||
|
bool has_laio_fdsync:1;
|
||||||
bool use_linux_io_uring:1;
|
bool use_linux_io_uring:1;
|
||||||
int page_cache_inconsistent; /* errno from fdatasync failure */
|
int page_cache_inconsistent; /* errno from fdatasync failure */
|
||||||
bool has_fallocate;
|
bool has_fallocate;
|
||||||
@ -718,6 +719,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (s->use_linux_aio) {
|
||||||
|
s->has_laio_fdsync = laio_has_fdsync(s->fd);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (s->use_linux_aio) {
|
if (s->use_linux_aio) {
|
||||||
error_setg(errp, "aio=native was specified, but is not supported "
|
error_setg(errp, "aio=native was specified, but is not supported "
|
||||||
@ -2598,6 +2602,11 @@ static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
|
|||||||
if (raw_check_linux_io_uring(s)) {
|
if (raw_check_linux_io_uring(s)) {
|
||||||
return luring_co_submit(bs, s->fd, 0, NULL, QEMU_AIO_FLUSH);
|
return luring_co_submit(bs, s->fd, 0, NULL, QEMU_AIO_FLUSH);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_LINUX_AIO
|
||||||
|
if (s->has_laio_fdsync && raw_check_linux_aio(s)) {
|
||||||
|
return laio_co_submit(s->fd, 0, NULL, QEMU_AIO_FLUSH, 0);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return raw_thread_pool_submit(handle_aiocb_flush, &acb);
|
return raw_thread_pool_submit(handle_aiocb_flush, &acb);
|
||||||
}
|
}
|
||||||
|
@ -384,6 +384,9 @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
|
|||||||
case QEMU_AIO_READ:
|
case QEMU_AIO_READ:
|
||||||
io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset);
|
io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset);
|
||||||
break;
|
break;
|
||||||
|
case QEMU_AIO_FLUSH:
|
||||||
|
io_prep_fdsync(iocbs, fd);
|
||||||
|
break;
|
||||||
/* Currently Linux kernel does not support other operations */
|
/* Currently Linux kernel does not support other operations */
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "%s: invalid AIO request type 0x%x.\n",
|
fprintf(stderr, "%s: invalid AIO request type 0x%x.\n",
|
||||||
@ -412,7 +415,7 @@ int coroutine_fn laio_co_submit(int fd, uint64_t offset, QEMUIOVector *qiov,
|
|||||||
AioContext *ctx = qemu_get_current_aio_context();
|
AioContext *ctx = qemu_get_current_aio_context();
|
||||||
struct qemu_laiocb laiocb = {
|
struct qemu_laiocb laiocb = {
|
||||||
.co = qemu_coroutine_self(),
|
.co = qemu_coroutine_self(),
|
||||||
.nbytes = qiov->size,
|
.nbytes = qiov ? qiov->size : 0,
|
||||||
.ctx = aio_get_linux_aio(ctx),
|
.ctx = aio_get_linux_aio(ctx),
|
||||||
.ret = -EINPROGRESS,
|
.ret = -EINPROGRESS,
|
||||||
.is_read = (type == QEMU_AIO_READ),
|
.is_read = (type == QEMU_AIO_READ),
|
||||||
@ -486,3 +489,19 @@ void laio_cleanup(LinuxAioState *s)
|
|||||||
}
|
}
|
||||||
g_free(s);
|
g_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool laio_has_fdsync(int fd)
|
||||||
|
{
|
||||||
|
struct iocb cb;
|
||||||
|
struct iocb *cbs[] = {&cb, NULL};
|
||||||
|
|
||||||
|
io_context_t ctx = 0;
|
||||||
|
io_setup(1, &ctx);
|
||||||
|
|
||||||
|
/* check if host kernel supports IO_CMD_FDSYNC */
|
||||||
|
io_prep_fdsync(&cb, fd);
|
||||||
|
int ret = io_submit(ctx, 1, cbs);
|
||||||
|
|
||||||
|
io_destroy(ctx);
|
||||||
|
return (ret == -EINVAL) ? false : true;
|
||||||
|
}
|
||||||
|
@ -60,6 +60,7 @@ void laio_cleanup(LinuxAioState *s);
|
|||||||
int coroutine_fn laio_co_submit(int fd, uint64_t offset, QEMUIOVector *qiov,
|
int coroutine_fn laio_co_submit(int fd, uint64_t offset, QEMUIOVector *qiov,
|
||||||
int type, uint64_t dev_max_batch);
|
int type, uint64_t dev_max_batch);
|
||||||
|
|
||||||
|
bool laio_has_fdsync(int);
|
||||||
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context);
|
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context);
|
||||||
void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context);
|
void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user