From 91fa5e18d2ac6e376901a71f3f44343761fde012 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 6 Jul 2018 17:56:55 +0200 Subject: [PATCH 21/89] pr-manager: add query-pr-managers QMP command RH-Author: Paolo Bonzini Message-id: <20180706175659.30615-6-pbonzini@redhat.com> Patchwork-id: 81251 O-Subject: [RHEL7.6 qemu-kvm-rhev PATCH 5/9] pr-manager: add query-pr-managers QMP command Bugzilla: 1533158 RH-Acked-by: Laurent Vivier RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Michal Privoznik This command lets you query the connection status of each pr-manager-helper object. Signed-off-by: Paolo Bonzini (cherry picked from commit 5f64089416f0d77c87683401838f064c51a292ed) [RHEL: no allow-preconfig yet, so don't specify it] Signed-off-by: Miroslav Rezanina --- include/scsi/pr-manager.h | 2 ++ qapi/block.json | 27 +++++++++++++++++++++++++++ scsi/pr-manager-helper.c | 13 +++++++++++++ scsi/pr-manager-stub.c | 6 ++++++ scsi/pr-manager.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+) diff --git a/include/scsi/pr-manager.h b/include/scsi/pr-manager.h index 71971ae..50a77b0 100644 --- a/include/scsi/pr-manager.h +++ b/include/scsi/pr-manager.h @@ -33,8 +33,10 @@ typedef struct PRManagerClass { /* */ int (*run)(PRManager *pr_mgr, int fd, struct sg_io_hdr *hdr); + bool (*is_connected)(PRManager *pr_mgr); } PRManagerClass; +bool pr_manager_is_connected(PRManager *pr_mgr); BlockAIOCB *pr_manager_execute(PRManager *pr_mgr, AioContext *ctx, int fd, struct sg_io_hdr *hdr, diff --git a/qapi/block.json b/qapi/block.json index 48c732f..c636354 100644 --- a/qapi/block.json +++ b/qapi/block.json @@ -78,6 +78,33 @@ 'data': { 'device': 'str', 'name': 'str' } } ## +# @PRManagerInfo: +# +# Information about a persistent reservation manager +# +# @id: the identifier of the persistent reservation manager +# +# @connected: true if the persistent reservation manager is connected to +# the underlying storage or helper +# +# Since: 3.0 +## +{ 'struct': 'PRManagerInfo', + 'data': {'id': 'str', 'connected': 'bool'} } + +## +# @query-pr-managers: +# +# Returns a list of information about each persistent reservation manager. +# +# Returns: a list of @PRManagerInfo for each persistent reservation manager +# +# Since: 3.0 +## +{ 'command': 'query-pr-managers', 'returns': ['PRManagerInfo'] } + + +## # @blockdev-snapshot-internal-sync: # # Synchronously take an internal snapshot of a block device, when the diff --git a/scsi/pr-manager-helper.c b/scsi/pr-manager-helper.c index 0c0fe38..b11481b 100644 --- a/scsi/pr-manager-helper.c +++ b/scsi/pr-manager-helper.c @@ -235,6 +235,18 @@ out: return ret; } +static bool pr_manager_helper_is_connected(PRManager *p) +{ + PRManagerHelper *pr_mgr = PR_MANAGER_HELPER(p); + bool result; + + qemu_mutex_lock(&pr_mgr->lock); + result = (pr_mgr->ioc != NULL); + qemu_mutex_unlock(&pr_mgr->lock); + + return result; +} + static void pr_manager_helper_complete(UserCreatable *uc, Error **errp) { PRManagerHelper *pr_mgr = PR_MANAGER_HELPER(uc); @@ -284,6 +296,7 @@ static void pr_manager_helper_class_init(ObjectClass *klass, &error_abort); uc_klass->complete = pr_manager_helper_complete; prmgr_klass->run = pr_manager_helper_run; + prmgr_klass->is_connected = pr_manager_helper_is_connected; } static const TypeInfo pr_manager_helper_info = { diff --git a/scsi/pr-manager-stub.c b/scsi/pr-manager-stub.c index 632f17c..738b6d7 100644 --- a/scsi/pr-manager-stub.c +++ b/scsi/pr-manager-stub.c @@ -22,3 +22,9 @@ PRManager *pr_manager_lookup(const char *id, Error **errp) error_setg(errp, "No persistent reservation manager with id '%s'", id); return NULL; } + + +PRManagerInfoList *qmp_query_pr_managers(Error **errp) +{ + return NULL; +} diff --git a/scsi/pr-manager.c b/scsi/pr-manager.c index 87c45db..2a8f300 100644 --- a/scsi/pr-manager.c +++ b/scsi/pr-manager.c @@ -17,6 +17,10 @@ #include "block/thread-pool.h" #include "scsi/pr-manager.h" #include "trace.h" +#include "qapi/qapi-types-block.h" +#include "qapi/qapi-commands-block.h" + +#define PR_MANAGER_PATH "/objects" typedef struct PRManagerData { PRManager *pr_mgr; @@ -64,6 +68,14 @@ BlockAIOCB *pr_manager_execute(PRManager *pr_mgr, data, complete, opaque); } +bool pr_manager_is_connected(PRManager *pr_mgr) +{ + PRManagerClass *pr_mgr_class = + PR_MANAGER_GET_CLASS(pr_mgr); + + return !pr_mgr_class->is_connected || pr_mgr_class->is_connected(pr_mgr); +} + static const TypeInfo pr_manager_info = { .parent = TYPE_OBJECT, .name = TYPE_PR_MANAGER, @@ -105,5 +117,38 @@ pr_manager_register_types(void) type_register_static(&pr_manager_info); } +static int query_one_pr_manager(Object *object, void *opaque) +{ + PRManagerInfoList ***prev = opaque; + PRManagerInfoList *elem; + PRManagerInfo *info; + PRManager *pr_mgr; + + pr_mgr = (PRManager *)object_dynamic_cast(object, TYPE_PR_MANAGER); + if (!pr_mgr) { + return 0; + } + + elem = g_new0(PRManagerInfoList, 1); + info = g_new0(PRManagerInfo, 1); + info->id = object_get_canonical_path_component(object); + info->connected = pr_manager_is_connected(pr_mgr); + elem->value = info; + elem->next = NULL; + + **prev = elem; + *prev = &elem->next; + return 0; +} + +PRManagerInfoList *qmp_query_pr_managers(Error **errp) +{ + PRManagerInfoList *head = NULL; + PRManagerInfoList **prev = &head; + Object *container = container_get(object_get_root(), PR_MANAGER_PATH); + + object_child_foreach(container, query_one_pr_manager, &prev); + return head; +} type_init(pr_manager_register_types); -- 1.8.3.1