| /* |
| * Persistent reservation manager abstract class |
| * |
| * Copyright (c) 2017 Red Hat, Inc. |
| * |
| * Author: Paolo Bonzini <pbonzini@redhat.com> |
| * |
| * This code is licensed under the LGPL. |
| * |
| */ |
| |
| #include "qemu/osdep.h" |
| #include <scsi/sg.h> |
| |
| #include "qapi/error.h" |
| #include "block/aio.h" |
| #include "block/thread-pool.h" |
| #include "scsi/pr-manager.h" |
| #include "trace.h" |
| |
| typedef struct PRManagerData { |
| PRManager *pr_mgr; |
| struct sg_io_hdr *hdr; |
| int fd; |
| } PRManagerData; |
| |
| static int pr_manager_worker(void *opaque) |
| { |
| PRManagerData *data = opaque; |
| PRManager *pr_mgr = data->pr_mgr; |
| PRManagerClass *pr_mgr_class = |
| PR_MANAGER_GET_CLASS(pr_mgr); |
| struct sg_io_hdr *hdr = data->hdr; |
| int fd = data->fd; |
| int r; |
| |
| g_free(data); |
| trace_pr_manager_run(fd, hdr->cmdp[0], hdr->cmdp[1]); |
| |
| /* The reference was taken in pr_manager_execute. */ |
| r = pr_mgr_class->run(pr_mgr, fd, hdr); |
| object_unref(OBJECT(pr_mgr)); |
| return r; |
| } |
| |
| |
| BlockAIOCB *pr_manager_execute(PRManager *pr_mgr, |
| AioContext *ctx, int fd, |
| struct sg_io_hdr *hdr, |
| BlockCompletionFunc *complete, |
| void *opaque) |
| { |
| PRManagerData *data = g_new(PRManagerData, 1); |
| ThreadPool *pool = aio_get_thread_pool(ctx); |
| |
| trace_pr_manager_execute(fd, hdr->cmdp[0], hdr->cmdp[1], opaque); |
| data->pr_mgr = pr_mgr; |
| data->fd = fd; |
| data->hdr = hdr; |
| |
| /* The matching object_unref is in pr_manager_worker. */ |
| object_ref(OBJECT(pr_mgr)); |
| return thread_pool_submit_aio(pool, pr_manager_worker, |
| data, complete, opaque); |
| } |
| |
| static const TypeInfo pr_manager_info = { |
| .parent = TYPE_OBJECT, |
| .name = TYPE_PR_MANAGER, |
| .class_size = sizeof(PRManagerClass), |
| .abstract = true, |
| .interfaces = (InterfaceInfo[]) { |
| { TYPE_USER_CREATABLE }, |
| { } |
| } |
| }; |
| |
| PRManager *pr_manager_lookup(const char *id, Error **errp) |
| { |
| Object *obj; |
| PRManager *pr_mgr; |
| |
| obj = object_resolve_path_component(object_get_objects_root(), id); |
| if (!obj) { |
| error_setg(errp, "No persistent reservation manager with id '%s'", id); |
| return NULL; |
| } |
| |
| pr_mgr = (PRManager *) |
| object_dynamic_cast(obj, |
| TYPE_PR_MANAGER); |
| if (!pr_mgr) { |
| error_setg(errp, |
| "Object with id '%s' is not a persistent reservation manager", |
| id); |
| return NULL; |
| } |
| |
| return pr_mgr; |
| } |
| |
| static void |
| pr_manager_register_types(void) |
| { |
| type_register_static(&pr_manager_info); |
| } |
| |
| |
| type_init(pr_manager_register_types); |