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>
This commit is contained in:
		
							parent
							
								
									58b3017f7f
								
							
						
					
					
						commit
						5f64089416
					
				| @ -33,8 +33,10 @@ typedef struct PRManagerClass { | ||||
| 
 | ||||
|     /* <public> */ | ||||
|     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, | ||||
|  | ||||
| @ -77,6 +77,34 @@ | ||||
| { 'struct': 'BlockdevSnapshotInternal', | ||||
|   '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: | ||||
| # | ||||
|  | ||||
| @ -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 = { | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Paolo Bonzini
						Paolo Bonzini