pr-manager: add query-pr-managers QMP command
This command lets you query the connection status of each pr-manager-helper object. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>stable-3.0
parent
58b3017f7f
commit
5f64089416
|
@ -33,8 +33,10 @@ typedef struct PRManagerClass {
|
||||||
|
|
||||||
/* <public> */
|
/* <public> */
|
||||||
int (*run)(PRManager *pr_mgr, int fd, struct sg_io_hdr *hdr);
|
int (*run)(PRManager *pr_mgr, int fd, struct sg_io_hdr *hdr);
|
||||||
|
bool (*is_connected)(PRManager *pr_mgr);
|
||||||
} PRManagerClass;
|
} PRManagerClass;
|
||||||
|
|
||||||
|
bool pr_manager_is_connected(PRManager *pr_mgr);
|
||||||
BlockAIOCB *pr_manager_execute(PRManager *pr_mgr,
|
BlockAIOCB *pr_manager_execute(PRManager *pr_mgr,
|
||||||
AioContext *ctx, int fd,
|
AioContext *ctx, int fd,
|
||||||
struct sg_io_hdr *hdr,
|
struct sg_io_hdr *hdr,
|
||||||
|
|
|
@ -77,6 +77,34 @@
|
||||||
{ 'struct': 'BlockdevSnapshotInternal',
|
{ 'struct': 'BlockdevSnapshotInternal',
|
||||||
'data': { 'device': 'str', 'name': 'str' } }
|
'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'],
|
||||||
|
'allow-preconfig': true }
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# @blockdev-snapshot-internal-sync:
|
# @blockdev-snapshot-internal-sync:
|
||||||
#
|
#
|
||||||
|
|
|
@ -235,6 +235,18 @@ out:
|
||||||
return ret;
|
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)
|
static void pr_manager_helper_complete(UserCreatable *uc, Error **errp)
|
||||||
{
|
{
|
||||||
PRManagerHelper *pr_mgr = PR_MANAGER_HELPER(uc);
|
PRManagerHelper *pr_mgr = PR_MANAGER_HELPER(uc);
|
||||||
|
@ -284,6 +296,7 @@ static void pr_manager_helper_class_init(ObjectClass *klass,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
uc_klass->complete = pr_manager_helper_complete;
|
uc_klass->complete = pr_manager_helper_complete;
|
||||||
prmgr_klass->run = pr_manager_helper_run;
|
prmgr_klass->run = pr_manager_helper_run;
|
||||||
|
prmgr_klass->is_connected = pr_manager_helper_is_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo pr_manager_helper_info = {
|
static const TypeInfo pr_manager_helper_info = {
|
||||||
|
|
|
@ -22,3 +22,9 @@ PRManager *pr_manager_lookup(const char *id, Error **errp)
|
||||||
error_setg(errp, "No persistent reservation manager with id '%s'", id);
|
error_setg(errp, "No persistent reservation manager with id '%s'", id);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PRManagerInfoList *qmp_query_pr_managers(Error **errp)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
#include "block/thread-pool.h"
|
#include "block/thread-pool.h"
|
||||||
#include "scsi/pr-manager.h"
|
#include "scsi/pr-manager.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
#include "qapi/qapi-types-block.h"
|
||||||
|
#include "qapi/qapi-commands-block.h"
|
||||||
|
|
||||||
|
#define PR_MANAGER_PATH "/objects"
|
||||||
|
|
||||||
typedef struct PRManagerData {
|
typedef struct PRManagerData {
|
||||||
PRManager *pr_mgr;
|
PRManager *pr_mgr;
|
||||||
|
@ -64,6 +68,14 @@ BlockAIOCB *pr_manager_execute(PRManager *pr_mgr,
|
||||||
data, complete, opaque);
|
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 = {
|
static const TypeInfo pr_manager_info = {
|
||||||
.parent = TYPE_OBJECT,
|
.parent = TYPE_OBJECT,
|
||||||
.name = TYPE_PR_MANAGER,
|
.name = TYPE_PR_MANAGER,
|
||||||
|
@ -105,5 +117,38 @@ pr_manager_register_types(void)
|
||||||
type_register_static(&pr_manager_info);
|
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);
|
type_init(pr_manager_register_types);
|
||||||
|
|
Loading…
Reference in New Issue