Skip to content

Commit 5f64089

Browse files
committed
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 <[email protected]>
1 parent 58b3017 commit 5f64089

File tree

5 files changed

+94
-0
lines changed

5 files changed

+94
-0
lines changed

include/scsi/pr-manager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ typedef struct PRManagerClass {
3333

3434
/* <public> */
3535
int (*run)(PRManager *pr_mgr, int fd, struct sg_io_hdr *hdr);
36+
bool (*is_connected)(PRManager *pr_mgr);
3637
} PRManagerClass;
3738

39+
bool pr_manager_is_connected(PRManager *pr_mgr);
3840
BlockAIOCB *pr_manager_execute(PRManager *pr_mgr,
3941
AioContext *ctx, int fd,
4042
struct sg_io_hdr *hdr,

qapi/block.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,34 @@
7777
{ 'struct': 'BlockdevSnapshotInternal',
7878
'data': { 'device': 'str', 'name': 'str' } }
7979

80+
##
81+
# @PRManagerInfo:
82+
#
83+
# Information about a persistent reservation manager
84+
#
85+
# @id: the identifier of the persistent reservation manager
86+
#
87+
# @connected: true if the persistent reservation manager is connected to
88+
# the underlying storage or helper
89+
#
90+
# Since: 3.0
91+
##
92+
{ 'struct': 'PRManagerInfo',
93+
'data': {'id': 'str', 'connected': 'bool'} }
94+
95+
##
96+
# @query-pr-managers:
97+
#
98+
# Returns a list of information about each persistent reservation manager.
99+
#
100+
# Returns: a list of @PRManagerInfo for each persistent reservation manager
101+
#
102+
# Since: 3.0
103+
##
104+
{ 'command': 'query-pr-managers', 'returns': ['PRManagerInfo'],
105+
'allow-preconfig': true }
106+
107+
80108
##
81109
# @blockdev-snapshot-internal-sync:
82110
#

scsi/pr-manager-helper.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,18 @@ static int pr_manager_helper_run(PRManager *p,
235235
return ret;
236236
}
237237

238+
static bool pr_manager_helper_is_connected(PRManager *p)
239+
{
240+
PRManagerHelper *pr_mgr = PR_MANAGER_HELPER(p);
241+
bool result;
242+
243+
qemu_mutex_lock(&pr_mgr->lock);
244+
result = (pr_mgr->ioc != NULL);
245+
qemu_mutex_unlock(&pr_mgr->lock);
246+
247+
return result;
248+
}
249+
238250
static void pr_manager_helper_complete(UserCreatable *uc, Error **errp)
239251
{
240252
PRManagerHelper *pr_mgr = PR_MANAGER_HELPER(uc);
@@ -284,6 +296,7 @@ static void pr_manager_helper_class_init(ObjectClass *klass,
284296
&error_abort);
285297
uc_klass->complete = pr_manager_helper_complete;
286298
prmgr_klass->run = pr_manager_helper_run;
299+
prmgr_klass->is_connected = pr_manager_helper_is_connected;
287300
}
288301

289302
static const TypeInfo pr_manager_helper_info = {

scsi/pr-manager-stub.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,9 @@ PRManager *pr_manager_lookup(const char *id, Error **errp)
2222
error_setg(errp, "No persistent reservation manager with id '%s'", id);
2323
return NULL;
2424
}
25+
26+
27+
PRManagerInfoList *qmp_query_pr_managers(Error **errp)
28+
{
29+
return NULL;
30+
}

scsi/pr-manager.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
#include "block/thread-pool.h"
1818
#include "scsi/pr-manager.h"
1919
#include "trace.h"
20+
#include "qapi/qapi-types-block.h"
21+
#include "qapi/qapi-commands-block.h"
22+
23+
#define PR_MANAGER_PATH "/objects"
2024

2125
typedef struct PRManagerData {
2226
PRManager *pr_mgr;
@@ -64,6 +68,14 @@ BlockAIOCB *pr_manager_execute(PRManager *pr_mgr,
6468
data, complete, opaque);
6569
}
6670

71+
bool pr_manager_is_connected(PRManager *pr_mgr)
72+
{
73+
PRManagerClass *pr_mgr_class =
74+
PR_MANAGER_GET_CLASS(pr_mgr);
75+
76+
return !pr_mgr_class->is_connected || pr_mgr_class->is_connected(pr_mgr);
77+
}
78+
6779
static const TypeInfo pr_manager_info = {
6880
.parent = TYPE_OBJECT,
6981
.name = TYPE_PR_MANAGER,
@@ -105,5 +117,38 @@ pr_manager_register_types(void)
105117
type_register_static(&pr_manager_info);
106118
}
107119

120+
static int query_one_pr_manager(Object *object, void *opaque)
121+
{
122+
PRManagerInfoList ***prev = opaque;
123+
PRManagerInfoList *elem;
124+
PRManagerInfo *info;
125+
PRManager *pr_mgr;
126+
127+
pr_mgr = (PRManager *)object_dynamic_cast(object, TYPE_PR_MANAGER);
128+
if (!pr_mgr) {
129+
return 0;
130+
}
131+
132+
elem = g_new0(PRManagerInfoList, 1);
133+
info = g_new0(PRManagerInfo, 1);
134+
info->id = object_get_canonical_path_component(object);
135+
info->connected = pr_manager_is_connected(pr_mgr);
136+
elem->value = info;
137+
elem->next = NULL;
138+
139+
**prev = elem;
140+
*prev = &elem->next;
141+
return 0;
142+
}
143+
144+
PRManagerInfoList *qmp_query_pr_managers(Error **errp)
145+
{
146+
PRManagerInfoList *head = NULL;
147+
PRManagerInfoList **prev = &head;
148+
Object *container = container_get(object_get_root(), PR_MANAGER_PATH);
149+
150+
object_child_foreach(container, query_one_pr_manager, &prev);
151+
return head;
152+
}
108153

109154
type_init(pr_manager_register_types);

0 commit comments

Comments
 (0)