X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=iothread.c;h=beeb8705344071e9198510a3a99a1291e9a15523;hb=577d8c9a811fc697b4cc68fbbe5c509b028e0768;hp=bd7034481123849fa3bb0a2cbfca72a87a54bbd4;hpb=5ff06787d4921579192e1becfedb9b1954f9bc0d;p=mirror_qemu.git diff --git a/iothread.c b/iothread.c index bd70344811..beeb870534 100644 --- a/iothread.c +++ b/iothread.c @@ -30,6 +30,12 @@ typedef ObjectClass IOThreadClass; #define IOTHREAD_CLASS(klass) \ OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD) +/* Benchmark results from 2016 on NVMe SSD drives show max polling times around + * 16-32 microseconds yield IOPS improvements for both iodepth=1 and iodepth=32 + * workloads. + */ +#define IOTHREAD_POLL_MAX_NS_DEFAULT 32768ULL + static __thread IOThread *my_iothread; AioContext *qemu_get_current_aio_context(void) @@ -71,6 +77,13 @@ static int iothread_stop(Object *object, void *opaque) return 0; } +static void iothread_instance_init(Object *obj) +{ + IOThread *iothread = IOTHREAD(obj); + + iothread->poll_max_ns = IOTHREAD_POLL_MAX_NS_DEFAULT; +} + static void iothread_instance_finalize(Object *obj) { IOThread *iothread = IOTHREAD(obj); @@ -98,6 +111,18 @@ static void iothread_complete(UserCreatable *obj, Error **errp) return; } + aio_context_set_poll_params(iothread->ctx, + iothread->poll_max_ns, + iothread->poll_grow, + iothread->poll_shrink, + &local_error); + if (local_error) { + error_propagate(errp, local_error); + aio_context_unref(iothread->ctx); + iothread->ctx = NULL; + return; + } + qemu_mutex_init(&iothread->init_done_lock); qemu_cond_init(&iothread->init_done_cond); @@ -120,10 +145,82 @@ static void iothread_complete(UserCreatable *obj, Error **errp) qemu_mutex_unlock(&iothread->init_done_lock); } +typedef struct { + const char *name; + ptrdiff_t offset; /* field's byte offset in IOThread struct */ +} PollParamInfo; + +static PollParamInfo poll_max_ns_info = { + "poll-max-ns", offsetof(IOThread, poll_max_ns), +}; +static PollParamInfo poll_grow_info = { + "poll-grow", offsetof(IOThread, poll_grow), +}; +static PollParamInfo poll_shrink_info = { + "poll-shrink", offsetof(IOThread, poll_shrink), +}; + +static void iothread_get_poll_param(Object *obj, Visitor *v, + const char *name, void *opaque, Error **errp) +{ + IOThread *iothread = IOTHREAD(obj); + PollParamInfo *info = opaque; + int64_t *field = (void *)iothread + info->offset; + + visit_type_int64(v, name, field, errp); +} + +static void iothread_set_poll_param(Object *obj, Visitor *v, + const char *name, void *opaque, Error **errp) +{ + IOThread *iothread = IOTHREAD(obj); + PollParamInfo *info = opaque; + int64_t *field = (void *)iothread + info->offset; + Error *local_err = NULL; + int64_t value; + + visit_type_int64(v, name, &value, &local_err); + if (local_err) { + goto out; + } + + if (value < 0) { + error_setg(&local_err, "%s value must be in range [0, %"PRId64"]", + info->name, INT64_MAX); + goto out; + } + + *field = value; + + if (iothread->ctx) { + aio_context_set_poll_params(iothread->ctx, + iothread->poll_max_ns, + iothread->poll_grow, + iothread->poll_shrink, + &local_err); + } + +out: + error_propagate(errp, local_err); +} + static void iothread_class_init(ObjectClass *klass, void *class_data) { UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass); ucc->complete = iothread_complete; + + object_class_property_add(klass, "poll-max-ns", "int", + iothread_get_poll_param, + iothread_set_poll_param, + NULL, &poll_max_ns_info, &error_abort); + object_class_property_add(klass, "poll-grow", "int", + iothread_get_poll_param, + iothread_set_poll_param, + NULL, &poll_grow_info, &error_abort); + object_class_property_add(klass, "poll-shrink", "int", + iothread_get_poll_param, + iothread_set_poll_param, + NULL, &poll_shrink_info, &error_abort); } static const TypeInfo iothread_info = { @@ -131,6 +228,7 @@ static const TypeInfo iothread_info = { .parent = TYPE_OBJECT, .class_init = iothread_class_init, .instance_size = sizeof(IOThread), + .instance_init = iothread_instance_init, .instance_finalize = iothread_instance_finalize, .interfaces = (InterfaceInfo[]) { {TYPE_USER_CREATABLE}, @@ -170,6 +268,9 @@ static int query_one_iothread(Object *object, void *opaque) info = g_new0(IOThreadInfo, 1); info->id = iothread_get_id(iothread); info->thread_id = iothread->thread_id; + info->poll_max_ns = iothread->poll_max_ns; + info->poll_grow = iothread->poll_grow; + info->poll_shrink = iothread->poll_shrink; elem = g_new0(IOThreadInfoList, 1); elem->value = info;