1 /* 2 * Persistent reservation manager abstract class 3 * 4 * Copyright (c) 2017 Red Hat, Inc. 5 * 6 * Author: Paolo Bonzini <pbonzini@redhat.com> 7 * 8 * This code is licensed under the LGPL. 9 * 10 */ 11 12 #include "qemu/osdep.h" 13 #include <scsi/sg.h> 14 15 #include "qapi/error.h" 16 #include "block/aio.h" 17 #include "block/thread-pool.h" 18 #include "scsi/pr-manager.h" 19 #include "trace.h" 20 21 typedef struct PRManagerData { 22 PRManager *pr_mgr; 23 struct sg_io_hdr *hdr; 24 int fd; 25 } PRManagerData; 26 27 static int pr_manager_worker(void *opaque) 28 { 29 PRManagerData *data = opaque; 30 PRManager *pr_mgr = data->pr_mgr; 31 PRManagerClass *pr_mgr_class = 32 PR_MANAGER_GET_CLASS(pr_mgr); 33 struct sg_io_hdr *hdr = data->hdr; 34 int fd = data->fd; 35 int r; 36 37 g_free(data); 38 trace_pr_manager_run(fd, hdr->cmdp[0], hdr->cmdp[1]); 39 40 /* The reference was taken in pr_manager_execute. */ 41 r = pr_mgr_class->run(pr_mgr, fd, hdr); 42 object_unref(OBJECT(pr_mgr)); 43 return r; 44 } 45 46 47 BlockAIOCB *pr_manager_execute(PRManager *pr_mgr, 48 AioContext *ctx, int fd, 49 struct sg_io_hdr *hdr, 50 BlockCompletionFunc *complete, 51 void *opaque) 52 { 53 PRManagerData *data = g_new(PRManagerData, 1); 54 ThreadPool *pool = aio_get_thread_pool(ctx); 55 56 trace_pr_manager_execute(fd, hdr->cmdp[0], hdr->cmdp[1], opaque); 57 data->pr_mgr = pr_mgr; 58 data->fd = fd; 59 data->hdr = hdr; 60 61 /* The matching object_unref is in pr_manager_worker. */ 62 object_ref(OBJECT(pr_mgr)); 63 return thread_pool_submit_aio(pool, pr_manager_worker, 64 data, complete, opaque); 65 } 66 67 static const TypeInfo pr_manager_info = { 68 .parent = TYPE_OBJECT, 69 .name = TYPE_PR_MANAGER, 70 .class_size = sizeof(PRManagerClass), 71 .abstract = true, 72 .interfaces = (InterfaceInfo[]) { 73 { TYPE_USER_CREATABLE }, 74 { } 75 } 76 }; 77 78 PRManager *pr_manager_lookup(const char *id, Error **errp) 79 { 80 Object *obj; 81 PRManager *pr_mgr; 82 83 obj = object_resolve_path_component(object_get_objects_root(), id); 84 if (!obj) { 85 error_setg(errp, "No persistent reservation manager with id '%s'", id); 86 return NULL; 87 } 88 89 pr_mgr = (PRManager *) 90 object_dynamic_cast(obj, 91 TYPE_PR_MANAGER); 92 if (!pr_mgr) { 93 error_setg(errp, 94 "Object with id '%s' is not a persistent reservation manager", 95 id); 96 return NULL; 97 } 98 99 return pr_mgr; 100 } 101 102 static void 103 pr_manager_register_types(void) 104 { 105 type_register_static(&pr_manager_info); 106 } 107 108 109 type_init(pr_manager_register_types); 110