direct-io.hg

changeset 10972:abd14c5c5496

[XENSTAT] Ignore domains that are being created/destroyed during get_info call.


Currently, xenstat_get_node exits with a failure and returns NULL if a
VM is deleted between the time the list of VMs is obtained and the time
it attempts to collect information about the VMs. This patch modifies xenstat
to ignore domains that transition during the call.

Signed-off-by: Simon Graham <Simon.Graham@stratus.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Aug 08 10:36:32 2006 +0100 (2006-08-08)
parents 986cf8354d11
children 857e7b864bb0
files tools/xenstat/libxenstat/src/xenstat.c
line diff
     1.1 --- a/tools/xenstat/libxenstat/src/xenstat.c	Tue Aug 08 10:29:58 2006 +0100
     1.2 +++ b/tools/xenstat/libxenstat/src/xenstat.c	Tue Aug 08 10:36:32 2006 +0100
     1.3 @@ -103,7 +103,10 @@ struct xenstat_vbd {
     1.4   * Data-collection types
     1.5   */
     1.6  /* Called to collect the information for the node and all the domains on
     1.7 - * it. When called, the domain information has already been collected. */
     1.8 + * it. When called, the domain information has already been collected. 
     1.9 + * Return status is 0 if fatal error occurs, 1 for success. Collectors
    1.10 + * may prune a domain from the list if it has been deleted between the
    1.11 + * time the list was setup and the time the colector is called */
    1.12  typedef int (*xenstat_collect_func)(xenstat_node * node);
    1.13  /* Called to free the information collected by the collect function.  The free
    1.14   * function will only be called on a xenstat_node if that node includes
    1.15 @@ -134,6 +137,7 @@ static void xenstat_uninit_networks(xens
    1.16  static void xenstat_uninit_xen_version(xenstat_handle * handle);
    1.17  static void xenstat_uninit_vbds(xenstat_handle * handle);
    1.18  static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id);
    1.19 +static void xenstat_prune_domain(xenstat_node *node, unsigned int entry);
    1.20  
    1.21  static xenstat_collector collectors[] = {
    1.22  	{ XENSTAT_VCPU, xenstat_collect_vcpus,
    1.23 @@ -208,7 +212,7 @@ xenstat_node *xenstat_get_node(xenstat_h
    1.24  	xenstat_node *node;
    1.25  	dom0_physinfo_t physinfo;
    1.26  	dom0_getdomaininfo_t domaininfo[DOMAIN_CHUNK_SIZE];
    1.27 -	unsigned int num_domains, new_domains;
    1.28 +	unsigned int new_domains;
    1.29  	unsigned int i;
    1.30  
    1.31  	/* Create the node */
    1.32 @@ -242,15 +246,17 @@ xenstat_node *xenstat_get_node(xenstat_h
    1.33  		return NULL;
    1.34  	}
    1.35  
    1.36 -	num_domains = 0;
    1.37 +	node->num_domains = 0;
    1.38  	do {
    1.39  		xenstat_domain *domain, *tmp;
    1.40  
    1.41  		new_domains = xc_domain_getinfolist(handle->xc_handle,
    1.42 -			num_domains, DOMAIN_CHUNK_SIZE, domaininfo);
    1.43 +						    node->num_domains, 
    1.44 +						    DOMAIN_CHUNK_SIZE, 
    1.45 +						    domaininfo);
    1.46  
    1.47  		tmp = realloc(node->domains,
    1.48 -			      (num_domains + new_domains)
    1.49 +			      (node->num_domains + new_domains)
    1.50  			      * sizeof(xenstat_domain));
    1.51  		if (tmp == NULL) {
    1.52  			free(node->domains);
    1.53 @@ -259,12 +265,29 @@ xenstat_node *xenstat_get_node(xenstat_h
    1.54  		}
    1.55  		node->domains = tmp;
    1.56  
    1.57 -		domain = node->domains + num_domains;
    1.58 +		domain = node->domains + node->num_domains;
    1.59 +
    1.60 +		/* zero out newly allocated memory in case error occurs below */
    1.61 +		memset(domain, 0, new_domains * sizeof(xenstat_domain));
    1.62  
    1.63  		for (i = 0; i < new_domains; i++) {
    1.64  			/* Fill in domain using domaininfo[i] */
    1.65  			domain->id = domaininfo[i].domain;
    1.66 -			domain->name = xenstat_get_domain_name(handle, domaininfo[i].domain);
    1.67 +			domain->name = xenstat_get_domain_name(handle, 
    1.68 +							       domain->id);
    1.69 +			if (domain->name == NULL) {
    1.70 +				if (errno == ENOMEM) {
    1.71 +					/* fatal error */
    1.72 +					xenstat_free_node(node);
    1.73 +					return NULL;
    1.74 +				}
    1.75 +				else {
    1.76 +					/* failed to get name -- this means the
    1.77 +					   domain is being destroyed so simply
    1.78 +					   ignore this entry */
    1.79 +					continue;
    1.80 +				}
    1.81 +			}
    1.82  			domain->state = domaininfo[i].flags;
    1.83  			domain->cpu_ns = domaininfo[i].cpu_time;
    1.84  			domain->num_vcpus = (domaininfo[i].max_vcpu_id+1);
    1.85 @@ -284,10 +307,9 @@ xenstat_node *xenstat_get_node(xenstat_h
    1.86  			domain->vbds = NULL;
    1.87  
    1.88  			domain++;
    1.89 +			node->num_domains++;
    1.90  		}
    1.91 -		num_domains += new_domains;
    1.92  	} while (new_domains == DOMAIN_CHUNK_SIZE);
    1.93 -	node->num_domains = num_domains;
    1.94  
    1.95  	/* Run all the extra data collectors requested */
    1.96  	node->flags = 0;
    1.97 @@ -495,10 +517,12 @@ xenstat_vbd *xenstat_domain_vbd(xenstat_
    1.98  /* Collect information about VCPUs */
    1.99  static int xenstat_collect_vcpus(xenstat_node * node)
   1.100  {
   1.101 -	unsigned int i, vcpu;
   1.102 +	unsigned int i, vcpu, inc_index;
   1.103  
   1.104  	/* Fill in VCPU information */
   1.105 -	for (i = 0; i < node->num_domains; i++) {
   1.106 +	for (i = 0; i < node->num_domains; i+=inc_index) {
   1.107 +		inc_index = 1; /* default is to increment to next domain */
   1.108 +
   1.109  		node->domains[i].vcpus = malloc(node->domains[i].num_vcpus
   1.110  						* sizeof(xenstat_vcpu));
   1.111  		if (node->domains[i].vcpus == NULL)
   1.112 @@ -509,11 +533,25 @@ static int xenstat_collect_vcpus(xenstat
   1.113  			dom0_getvcpuinfo_t info;
   1.114  
   1.115  			if (xc_vcpu_getinfo(node->handle->xc_handle,
   1.116 -				node->domains[i].id, vcpu, &info) != 0)
   1.117 -				return 0;
   1.118 +					    node->domains[i].id, vcpu, &info) != 0) {
   1.119 +				if (errno == ENOMEM) {
   1.120 +					/* fatal error */ 
   1.121 +					return 0;
   1.122 +				}
   1.123 +				else {
   1.124 +					/* domain is in transition - remove
   1.125 +					   from list */
   1.126 +					xenstat_prune_domain(node, i);
   1.127  
   1.128 -			node->domains[i].vcpus[vcpu].online = info.online;
   1.129 -			node->domains[i].vcpus[vcpu].ns = info.cpu_time;
   1.130 +					/* remember not to increment index! */
   1.131 +					inc_index = 0;
   1.132 +					break;
   1.133 +				}
   1.134 +			}
   1.135 +			else {
   1.136 +				node->domains[i].vcpus[vcpu].online = info.online;
   1.137 +				node->domains[i].vcpus[vcpu].ns = info.cpu_time;
   1.138 +			}
   1.139  		}
   1.140  	}
   1.141  	return 1;
   1.142 @@ -884,13 +922,30 @@ unsigned long long xenstat_vbd_wr_reqs(x
   1.143  static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id)
   1.144  {
   1.145  	char path[80];
   1.146 -	char *name;
   1.147  
   1.148  	snprintf(path, sizeof(path),"/local/domain/%i/name", domain_id);
   1.149  	
   1.150 -	name = xs_read(handle->xshandle, XBT_NULL, path, NULL);
   1.151 -	if (name == NULL)
   1.152 -		name = strdup(" ");
   1.153 +	return xs_read(handle->xshandle, XBT_NULL, path, NULL);
   1.154 +}	
   1.155 +
   1.156 +/* Remove specified entry from list of domains */
   1.157 +static void xenstat_prune_domain(xenstat_node *node, unsigned int entry)
   1.158 +{
   1.159 +	/* nothing to do if array is empty or entry is beyond end */
   1.160 +	if (node->num_domains == 0 || entry >= node->num_domains)
   1.161 +		return;
   1.162  
   1.163 -	return name;
   1.164 -}	
   1.165 +	/* decrement count of domains */
   1.166 +	node->num_domains--;
   1.167 +
   1.168 +	/* shift entries following specified entry up by one */
   1.169 +	if (entry < node->num_domains) {
   1.170 +		xenstat_domain *domain = &node->domains[entry];
   1.171 +		memmove(domain,domain+1,node->num_domains-entry);
   1.172 +	}
   1.173 +
   1.174 +	/* zero out original last entry from node -- not
   1.175 +	   strictly necessary but safer! */
   1.176 +	memset(&node->domains[node->num_domains], 0, sizeof(xenstat_domain)); 
   1.177 +}
   1.178 +