qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

pr-manager.c (3585B)


      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 #include "qapi/qapi-types-block.h"
     21 #include "qemu/module.h"
     22 #include "qapi/qapi-commands-block.h"
     23 
     24 #define PR_MANAGER_PATH     "/objects"
     25 
     26 typedef struct PRManagerData {
     27     PRManager *pr_mgr;
     28     struct sg_io_hdr *hdr;
     29     int fd;
     30 } PRManagerData;
     31 
     32 static int pr_manager_worker(void *opaque)
     33 {
     34     PRManagerData *data = opaque;
     35     PRManager *pr_mgr = data->pr_mgr;
     36     PRManagerClass *pr_mgr_class =
     37         PR_MANAGER_GET_CLASS(pr_mgr);
     38     struct sg_io_hdr *hdr = data->hdr;
     39     int fd = data->fd;
     40     int r;
     41 
     42     trace_pr_manager_run(fd, hdr->cmdp[0], hdr->cmdp[1]);
     43 
     44     /* The reference was taken in pr_manager_execute.  */
     45     r = pr_mgr_class->run(pr_mgr, fd, hdr);
     46     object_unref(OBJECT(pr_mgr));
     47     return r;
     48 }
     49 
     50 
     51 int coroutine_fn pr_manager_execute(PRManager *pr_mgr, AioContext *ctx, int fd,
     52                                     struct sg_io_hdr *hdr)
     53 {
     54     ThreadPool *pool = aio_get_thread_pool(ctx);
     55     PRManagerData data = {
     56         .pr_mgr = pr_mgr,
     57         .fd     = fd,
     58         .hdr    = hdr,
     59     };
     60 
     61     trace_pr_manager_execute(fd, hdr->cmdp[0], hdr->cmdp[1]);
     62 
     63     /* The matching object_unref is in pr_manager_worker.  */
     64     object_ref(OBJECT(pr_mgr));
     65     return thread_pool_submit_co(pool, pr_manager_worker, &data);
     66 }
     67 
     68 bool pr_manager_is_connected(PRManager *pr_mgr)
     69 {
     70     PRManagerClass *pr_mgr_class =
     71         PR_MANAGER_GET_CLASS(pr_mgr);
     72 
     73     return !pr_mgr_class->is_connected || pr_mgr_class->is_connected(pr_mgr);
     74 }
     75 
     76 static const TypeInfo pr_manager_info = {
     77     .parent = TYPE_OBJECT,
     78     .name = TYPE_PR_MANAGER,
     79     .class_size = sizeof(PRManagerClass),
     80     .abstract = true,
     81     .interfaces = (InterfaceInfo[]) {
     82         { TYPE_USER_CREATABLE },
     83         { }
     84     }
     85 };
     86 
     87 PRManager *pr_manager_lookup(const char *id, Error **errp)
     88 {
     89     Object *obj;
     90     PRManager *pr_mgr;
     91 
     92     obj = object_resolve_path_component(object_get_objects_root(), id);
     93     if (!obj) {
     94         error_setg(errp, "No persistent reservation manager with id '%s'", id);
     95         return NULL;
     96     }
     97 
     98     pr_mgr = (PRManager *)
     99         object_dynamic_cast(obj,
    100                             TYPE_PR_MANAGER);
    101     if (!pr_mgr) {
    102         error_setg(errp,
    103                    "Object with id '%s' is not a persistent reservation manager",
    104                    id);
    105         return NULL;
    106     }
    107 
    108     return pr_mgr;
    109 }
    110 
    111 static void
    112 pr_manager_register_types(void)
    113 {
    114     type_register_static(&pr_manager_info);
    115 }
    116 
    117 static int query_one_pr_manager(Object *object, void *opaque)
    118 {
    119     PRManagerInfoList ***tail = opaque;
    120     PRManagerInfo *info;
    121     PRManager *pr_mgr;
    122 
    123     pr_mgr = (PRManager *)object_dynamic_cast(object, TYPE_PR_MANAGER);
    124     if (!pr_mgr) {
    125         return 0;
    126     }
    127 
    128     info = g_new0(PRManagerInfo, 1);
    129     info->id = g_strdup(object_get_canonical_path_component(object));
    130     info->connected = pr_manager_is_connected(pr_mgr);
    131     QAPI_LIST_APPEND(*tail, info);
    132     return 0;
    133 }
    134 
    135 PRManagerInfoList *qmp_query_pr_managers(Error **errp)
    136 {
    137     PRManagerInfoList *head = NULL;
    138     PRManagerInfoList **prev = &head;
    139     Object *container = container_get(object_get_root(), PR_MANAGER_PATH);
    140 
    141     object_child_foreach(container, query_one_pr_manager, &prev);
    142     return head;
    143 }
    144 
    145 type_init(pr_manager_register_types);