debuggers.hg

view tools/xenstat/libxenstat/src/xenstat.c @ 21042:401c0012b827

xentop: tmem: no stats for non-tmem domains

In xentop, don't re-use and print stale data of previous tmem
domain for subsequent non-tmem domain.

Signed-off-by: Dan Magenheimer <dan.magenheimer@oracle.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Mar 03 17:40:48 2010 +0000 (2010-03-03)
parents 9e9746e635f9
children 779c0ef9682c
line source
1 /* libxenstat: statistics-collection library for Xen
2 * Copyright (C) International Business Machines Corp., 2005
3 * Authors: Josh Triplett <josh@kernel.org>
4 * Judy Fischbach <jfisch@cs.pdx.edu>
5 * David Hendricks <cro_marmot@comcast.net>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 */
18 /*
19 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
20 * Use is subject to license terms.
21 */
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <unistd.h>
28 #include "xenstat_priv.h"
30 /*
31 * Data-collection types
32 */
33 /* Called to collect the information for the node and all the domains on
34 * it. When called, the domain information has already been collected.
35 * Return status is 0 if fatal error occurs, 1 for success. Collectors
36 * may prune a domain from the list if it has been deleted between the
37 * time the list was setup and the time the colector is called */
38 typedef int (*xenstat_collect_func)(xenstat_node * node);
39 /* Called to free the information collected by the collect function. The free
40 * function will only be called on a xenstat_node if that node includes
41 * information collected by the corresponding collector. */
42 typedef void (*xenstat_free_func)(xenstat_node * node);
43 /* Called to free any information stored in the handle. Note the lack of a
44 * matching init function; the collect functions should initialize on first
45 * use. Also, the uninit function must handle the case that the collector has
46 * never been initialized. */
47 typedef void (*xenstat_uninit_func)(xenstat_handle * handle);
48 typedef struct xenstat_collector {
49 unsigned int flag;
50 xenstat_collect_func collect;
51 xenstat_free_func free;
52 xenstat_uninit_func uninit;
53 } xenstat_collector;
55 static int xenstat_collect_vcpus(xenstat_node * node);
56 static int xenstat_collect_xen_version(xenstat_node * node);
57 static void xenstat_free_vcpus(xenstat_node * node);
58 static void xenstat_free_networks(xenstat_node * node);
59 static void xenstat_free_xen_version(xenstat_node * node);
60 static void xenstat_free_vbds(xenstat_node * node);
61 static void xenstat_uninit_vcpus(xenstat_handle * handle);
62 static void xenstat_uninit_xen_version(xenstat_handle * handle);
63 static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id);
64 static void xenstat_prune_domain(xenstat_node *node, unsigned int entry);
66 static xenstat_collector collectors[] = {
67 { XENSTAT_VCPU, xenstat_collect_vcpus,
68 xenstat_free_vcpus, xenstat_uninit_vcpus },
69 { XENSTAT_NETWORK, xenstat_collect_networks,
70 xenstat_free_networks, xenstat_uninit_networks },
71 { XENSTAT_XEN_VERSION, xenstat_collect_xen_version,
72 xenstat_free_xen_version, xenstat_uninit_xen_version },
73 { XENSTAT_VBD, xenstat_collect_vbds,
74 xenstat_free_vbds, xenstat_uninit_vbds }
75 };
77 #define NUM_COLLECTORS (sizeof(collectors)/sizeof(xenstat_collector))
79 /*
80 * libxenstat API
81 */
82 xenstat_handle *xenstat_init(void)
83 {
84 xenstat_handle *handle;
86 handle = (xenstat_handle *) calloc(1, sizeof(xenstat_handle));
87 if (handle == NULL)
88 return NULL;
90 #if defined(PAGESIZE)
91 handle->page_size = PAGESIZE;
92 #elif defined(PAGE_SIZE)
93 handle->page_size = PAGE_SIZE;
94 #else
95 handle->page_size = sysconf(_SC_PAGE_SIZE);
96 if (handle->page_size < 0) {
97 perror("Failed to retrieve page size.");
98 free(handle);
99 return NULL;
100 }
101 #endif
103 handle->xc_handle = xc_interface_open();
104 if (handle->xc_handle == -1) {
105 perror("xc_interface_open");
106 free(handle);
107 return NULL;
108 }
110 handle->xshandle = xs_daemon_open_readonly(); /* open handle to xenstore*/
111 if (handle->xshandle == NULL) {
112 perror("unable to open xenstore");
113 xc_interface_close(handle->xc_handle);
114 free(handle);
115 return NULL;
116 }
118 return handle;
119 }
121 void xenstat_uninit(xenstat_handle * handle)
122 {
123 unsigned int i;
124 if (handle) {
125 for (i = 0; i < NUM_COLLECTORS; i++)
126 collectors[i].uninit(handle);
127 xc_interface_close(handle->xc_handle);
128 xs_daemon_close(handle->xshandle);
129 free(handle->priv);
130 free(handle);
131 }
132 }
134 static inline unsigned long long parse(char *s, char *match)
135 {
136 char *s1 = strstr(s,match);
137 unsigned long long ret;
139 if ( s1 == NULL )
140 return 0LL;
141 s1 += 2;
142 if ( *s1++ != ':' )
143 return 0LL;
144 sscanf(s1,"%llu",&ret);
145 return ret;
146 }
148 void domain_get_tmem_stats(xenstat_handle * handle, xenstat_domain * domain)
149 {
150 char buffer[4096];
152 if (xc_tmem_control(handle->xc_handle,-1,TMEMC_LIST,domain->id,
153 sizeof(buffer),-1,-1,buffer) < 0)
154 return;
155 domain->tmem_stats.curr_eph_pages = parse(buffer,"Ec");
156 domain->tmem_stats.succ_eph_gets = parse(buffer,"Ge");
157 domain->tmem_stats.succ_pers_puts = parse(buffer,"Pp");
158 domain->tmem_stats.succ_pers_gets = parse(buffer,"Gp");
159 }
161 xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags)
162 {
163 #define DOMAIN_CHUNK_SIZE 256
164 xenstat_node *node;
165 xc_physinfo_t physinfo = { 0 };
166 xc_domaininfo_t domaininfo[DOMAIN_CHUNK_SIZE];
167 unsigned int new_domains;
168 unsigned int i;
170 /* Create the node */
171 node = (xenstat_node *) calloc(1, sizeof(xenstat_node));
172 if (node == NULL)
173 return NULL;
175 /* Store the handle in the node for later access */
176 node->handle = handle;
178 /* Get information about the physical system */
179 if (xc_physinfo(handle->xc_handle, &physinfo) < 0) {
180 free(node);
181 return NULL;
182 }
185 node->cpu_hz = ((unsigned long long)physinfo.cpu_khz) * 1000ULL;
186 node->num_cpus = physinfo.nr_cpus;
187 node->tot_mem = ((unsigned long long)physinfo.total_pages)
188 * handle->page_size;
189 node->free_mem = ((unsigned long long)physinfo.free_pages)
190 * handle->page_size;
192 node->freeable_mb = (long)xc_tmem_control(handle->xc_handle, -1,
193 TMEMC_QUERY_FREEABLE_MB, -1, 0, 0, 0, NULL);
195 /* malloc(0) is not portable, so allocate a single domain. This will
196 * be resized below. */
197 node->domains = malloc(sizeof(xenstat_domain));
198 if (node->domains == NULL) {
199 free(node);
200 return NULL;
201 }
203 node->num_domains = 0;
204 do {
205 xenstat_domain *domain, *tmp;
207 new_domains = xc_domain_getinfolist(handle->xc_handle,
208 node->num_domains,
209 DOMAIN_CHUNK_SIZE,
210 domaininfo);
212 tmp = realloc(node->domains,
213 (node->num_domains + new_domains)
214 * sizeof(xenstat_domain));
215 if (tmp == NULL) {
216 free(node->domains);
217 free(node);
218 return NULL;
219 }
220 node->domains = tmp;
222 domain = node->domains + node->num_domains;
224 /* zero out newly allocated memory in case error occurs below */
225 memset(domain, 0, new_domains * sizeof(xenstat_domain));
227 for (i = 0; i < new_domains; i++) {
228 /* Fill in domain using domaininfo[i] */
229 domain->id = domaininfo[i].domain;
230 domain->name = xenstat_get_domain_name(handle,
231 domain->id);
232 if (domain->name == NULL) {
233 if (errno == ENOMEM) {
234 /* fatal error */
235 xenstat_free_node(node);
236 return NULL;
237 }
238 else {
239 /* failed to get name -- this means the
240 domain is being destroyed so simply
241 ignore this entry */
242 continue;
243 }
244 }
245 domain->state = domaininfo[i].flags;
246 domain->cpu_ns = domaininfo[i].cpu_time;
247 domain->num_vcpus = (domaininfo[i].max_vcpu_id+1);
248 domain->vcpus = NULL;
249 domain->cur_mem =
250 ((unsigned long long)domaininfo[i].tot_pages)
251 * handle->page_size;
252 domain->max_mem =
253 domaininfo[i].max_pages == UINT_MAX
254 ? (unsigned long long)-1
255 : (unsigned long long)(domaininfo[i].max_pages
256 * handle->page_size);
257 domain->ssid = domaininfo[i].ssidref;
258 domain->num_networks = 0;
259 domain->networks = NULL;
260 domain->num_vbds = 0;
261 domain->vbds = NULL;
262 domain_get_tmem_stats(handle,domain);
264 domain++;
265 node->num_domains++;
266 }
267 } while (new_domains == DOMAIN_CHUNK_SIZE);
270 /* Run all the extra data collectors requested */
271 node->flags = 0;
272 for (i = 0; i < NUM_COLLECTORS; i++) {
273 if ((flags & collectors[i].flag) == collectors[i].flag) {
274 node->flags |= collectors[i].flag;
275 if(collectors[i].collect(node) == 0) {
276 xenstat_free_node(node);
277 return NULL;
278 }
279 }
280 }
282 return node;
283 }
285 void xenstat_free_node(xenstat_node * node)
286 {
287 int i;
289 if (node) {
290 if (node->domains) {
291 for (i = 0; i < node->num_domains; i++)
292 free(node->domains[i].name);
294 for (i = 0; i < NUM_COLLECTORS; i++)
295 if((node->flags & collectors[i].flag)
296 == collectors[i].flag)
297 collectors[i].free(node);
298 free(node->domains);
299 }
300 free(node);
301 }
302 }
304 xenstat_domain *xenstat_node_domain(xenstat_node * node, unsigned int domid)
305 {
306 unsigned int i;
308 /* FIXME: binary search */
309 /* Find the appropriate domain entry in the node struct. */
310 for (i = 0; i < node->num_domains; i++) {
311 if (node->domains[i].id == domid)
312 return &(node->domains[i]);
313 }
314 return NULL;
315 }
317 xenstat_domain *xenstat_node_domain_by_index(xenstat_node * node,
318 unsigned int index)
319 {
320 if (0 <= index && index < node->num_domains)
321 return &(node->domains[index]);
322 return NULL;
323 }
325 const char *xenstat_node_xen_version(xenstat_node * node)
326 {
327 return node->handle->xen_version;
328 }
330 unsigned long long xenstat_node_tot_mem(xenstat_node * node)
331 {
332 return node->tot_mem;
333 }
335 unsigned long long xenstat_node_free_mem(xenstat_node * node)
336 {
337 return node->free_mem;
338 }
340 long xenstat_node_freeable_mb(xenstat_node * node)
341 {
342 return node->freeable_mb;
343 }
345 unsigned int xenstat_node_num_domains(xenstat_node * node)
346 {
347 return node->num_domains;
348 }
350 unsigned int xenstat_node_num_cpus(xenstat_node * node)
351 {
352 return node->num_cpus;
353 }
355 /* Get information about the CPU speed */
356 unsigned long long xenstat_node_cpu_hz(xenstat_node * node)
357 {
358 return node->cpu_hz;
359 }
361 /* Get the domain ID for this domain */
362 unsigned xenstat_domain_id(xenstat_domain * domain)
363 {
364 return domain->id;
365 }
367 /* Get the domain name for the domain */
368 char *xenstat_domain_name(xenstat_domain * domain)
369 {
370 return domain->name;
371 }
373 /* Get information about how much CPU time has been used */
374 unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain)
375 {
376 return domain->cpu_ns;
377 }
379 /* Find the number of VCPUs for a domain */
380 unsigned int xenstat_domain_num_vcpus(xenstat_domain * domain)
381 {
382 return domain->num_vcpus;
383 }
385 xenstat_vcpu *xenstat_domain_vcpu(xenstat_domain * domain, unsigned int vcpu)
386 {
387 if (0 <= vcpu && vcpu < domain->num_vcpus)
388 return &(domain->vcpus[vcpu]);
389 return NULL;
390 }
392 /* Find the current memory reservation for this domain */
393 unsigned long long xenstat_domain_cur_mem(xenstat_domain * domain)
394 {
395 return domain->cur_mem;
396 }
398 /* Find the maximum memory reservation for this domain */
399 unsigned long long xenstat_domain_max_mem(xenstat_domain * domain)
400 {
401 return domain->max_mem;
402 }
404 /* Find the domain's SSID */
405 unsigned int xenstat_domain_ssid(xenstat_domain * domain)
406 {
407 return domain->ssid;
408 }
410 /* Get domain states */
411 unsigned int xenstat_domain_dying(xenstat_domain * domain)
412 {
413 return (domain->state & XEN_DOMINF_dying) == XEN_DOMINF_dying;
414 }
416 unsigned int xenstat_domain_crashed(xenstat_domain * domain)
417 {
418 return ((domain->state & XEN_DOMINF_shutdown) == XEN_DOMINF_shutdown)
419 && (((domain->state >> XEN_DOMINF_shutdownshift)
420 & XEN_DOMINF_shutdownmask) == SHUTDOWN_crash);
421 }
423 unsigned int xenstat_domain_shutdown(xenstat_domain * domain)
424 {
425 return ((domain->state & XEN_DOMINF_shutdown) == XEN_DOMINF_shutdown)
426 && (((domain->state >> XEN_DOMINF_shutdownshift)
427 & XEN_DOMINF_shutdownmask) != SHUTDOWN_crash);
428 }
430 unsigned int xenstat_domain_paused(xenstat_domain * domain)
431 {
432 return (domain->state & XEN_DOMINF_paused) == XEN_DOMINF_paused;
433 }
435 unsigned int xenstat_domain_blocked(xenstat_domain * domain)
436 {
437 return (domain->state & XEN_DOMINF_blocked) == XEN_DOMINF_blocked;
438 }
440 unsigned int xenstat_domain_running(xenstat_domain * domain)
441 {
442 return (domain->state & XEN_DOMINF_running) == XEN_DOMINF_running;
443 }
445 /* Get the number of networks for a given domain */
446 unsigned int xenstat_domain_num_networks(xenstat_domain * domain)
447 {
448 return domain->num_networks;
449 }
451 /* Get the network handle to obtain network stats */
452 xenstat_network *xenstat_domain_network(xenstat_domain * domain,
453 unsigned int network)
454 {
455 if (domain->networks && 0 <= network && network < domain->num_networks)
456 return &(domain->networks[network]);
457 return NULL;
458 }
460 /* Get the number of VBDs for a given domain */
461 unsigned int xenstat_domain_num_vbds(xenstat_domain * domain)
462 {
463 return domain->num_vbds;
464 }
466 /* Get the VBD handle to obtain VBD stats */
467 xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain,
468 unsigned int vbd)
469 {
470 if (domain->vbds && 0 <= vbd && vbd < domain->num_vbds)
471 return &(domain->vbds[vbd]);
472 return NULL;
473 }
475 /*
476 * VCPU functions
477 */
478 /* Collect information about VCPUs */
479 static int xenstat_collect_vcpus(xenstat_node * node)
480 {
481 unsigned int i, vcpu, inc_index;
483 /* Fill in VCPU information */
484 for (i = 0; i < node->num_domains; i+=inc_index) {
485 inc_index = 1; /* default is to increment to next domain */
487 node->domains[i].vcpus = malloc(node->domains[i].num_vcpus
488 * sizeof(xenstat_vcpu));
489 if (node->domains[i].vcpus == NULL)
490 return 0;
492 for (vcpu = 0; vcpu < node->domains[i].num_vcpus; vcpu++) {
493 /* FIXME: need to be using a more efficient mechanism*/
494 xc_vcpuinfo_t info;
496 if (xc_vcpu_getinfo(node->handle->xc_handle,
497 node->domains[i].id, vcpu, &info) != 0) {
498 if (errno == ENOMEM) {
499 /* fatal error */
500 return 0;
501 }
502 else {
503 /* domain is in transition - remove
504 from list */
505 xenstat_prune_domain(node, i);
507 /* remember not to increment index! */
508 inc_index = 0;
509 break;
510 }
511 }
512 else {
513 node->domains[i].vcpus[vcpu].online = info.online;
514 node->domains[i].vcpus[vcpu].ns = info.cpu_time;
515 }
516 }
517 }
518 return 1;
519 }
521 /* Free VCPU information */
522 static void xenstat_free_vcpus(xenstat_node * node)
523 {
524 unsigned int i;
525 for (i = 0; i < node->num_domains; i++)
526 free(node->domains[i].vcpus);
527 }
529 /* Free VCPU information in handle - nothing to do */
530 static void xenstat_uninit_vcpus(xenstat_handle * handle)
531 {
532 }
534 /* Get VCPU online status */
535 unsigned int xenstat_vcpu_online(xenstat_vcpu * vcpu)
536 {
537 return vcpu->online;
538 }
540 /* Get VCPU usage */
541 unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu)
542 {
543 return vcpu->ns;
544 }
546 /*
547 * Network functions
548 */
550 /* Free network information */
551 static void xenstat_free_networks(xenstat_node * node)
552 {
553 unsigned int i;
554 for (i = 0; i < node->num_domains; i++)
555 free(node->domains[i].networks);
556 }
558 /* Get the network ID */
559 unsigned int xenstat_network_id(xenstat_network * network)
560 {
561 return network->id;
562 }
564 /* Get the number of receive bytes */
565 unsigned long long xenstat_network_rbytes(xenstat_network * network)
566 {
567 return network->rbytes;
568 }
570 /* Get the number of receive packets */
571 unsigned long long xenstat_network_rpackets(xenstat_network * network)
572 {
573 return network->rpackets;
574 }
576 /* Get the number of receive errors */
577 unsigned long long xenstat_network_rerrs(xenstat_network * network)
578 {
579 return network->rerrs;
580 }
582 /* Get the number of receive drops */
583 unsigned long long xenstat_network_rdrop(xenstat_network * network)
584 {
585 return network->rdrop;
586 }
588 /* Get the number of transmit bytes */
589 unsigned long long xenstat_network_tbytes(xenstat_network * network)
590 {
591 return network->tbytes;
592 }
594 /* Get the number of transmit packets */
595 unsigned long long xenstat_network_tpackets(xenstat_network * network)
596 {
597 return network->tpackets;
598 }
600 /* Get the number of transmit errors */
601 unsigned long long xenstat_network_terrs(xenstat_network * network)
602 {
603 return network->terrs;
604 }
606 /* Get the number of transmit dropped packets */
607 unsigned long long xenstat_network_tdrop(xenstat_network * network)
608 {
609 return network->tdrop;
610 }
612 /*
613 * Xen version functions
614 */
616 /* Collect Xen version information */
617 static int xenstat_collect_xen_version(xenstat_node * node)
618 {
619 long vnum = 0;
620 xen_extraversion_t version;
622 /* Collect Xen version information if not already collected */
623 if (node->handle->xen_version[0] == '\0') {
624 /* Get the Xen version number and extraversion string */
625 vnum = xc_version(node->handle->xc_handle,
626 XENVER_version, NULL);
628 if (vnum < 0)
629 return 0;
631 if (xc_version(node->handle->xc_handle, XENVER_extraversion,
632 &version) < 0)
633 return 0;
634 /* Format the version information as a string and store it */
635 snprintf(node->handle->xen_version, VERSION_SIZE, "%ld.%ld%s",
636 ((vnum >> 16) & 0xFFFF), vnum & 0xFFFF, version);
637 }
639 return 1;
640 }
642 /* Free Xen version information in node - nothing to do */
643 static void xenstat_free_xen_version(xenstat_node * node)
644 {
645 }
647 /* Free Xen version information in handle - nothing to do */
648 static void xenstat_uninit_xen_version(xenstat_handle * handle)
649 {
650 }
652 /*
653 * VBD functions
654 */
656 /* Free VBD information */
657 static void xenstat_free_vbds(xenstat_node * node)
658 {
659 unsigned int i;
660 for (i = 0; i < node->num_domains; i++)
661 free(node->domains[i].vbds);
662 }
664 /* Get the back driver type for Virtual Block Device */
665 unsigned int xenstat_vbd_type(xenstat_vbd * vbd)
666 {
667 return vbd->back_type;
668 }
670 /* Get the major number of VBD device */
671 unsigned int xenstat_vbd_dev(xenstat_vbd * vbd)
672 {
673 return vbd->dev;
674 }
676 /* Get the number of OO(Out of) requests */
677 unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd)
678 {
679 return vbd->oo_reqs;
680 }
682 /* Get the number of READ requests */
683 unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd)
684 {
685 return vbd->rd_reqs;
686 }
688 /* Get the number of WRITE requests */
689 unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd)
690 {
691 return vbd->wr_reqs;
692 }
694 /* Get the number of READ sectors */
695 unsigned long long xenstat_vbd_rd_sects(xenstat_vbd * vbd)
696 {
697 return vbd->rd_sects;
698 }
700 /* Get the number of WRITE sectors */
701 unsigned long long xenstat_vbd_wr_sects(xenstat_vbd * vbd)
702 {
703 return vbd->wr_sects;
704 }
706 /*
707 * Tmem functions
708 */
710 xenstat_tmem *xenstat_domain_tmem(xenstat_domain * domain)
711 {
712 return &domain->tmem_stats;
713 }
715 /* Get the current number of ephemeral pages */
716 unsigned long long xenstat_tmem_curr_eph_pages(xenstat_tmem *tmem)
717 {
718 return tmem->curr_eph_pages;
719 }
721 /* Get the number of successful ephemeral gets */
722 unsigned long long xenstat_tmem_succ_eph_gets(xenstat_tmem *tmem)
723 {
724 return tmem->succ_eph_gets;
725 }
727 /* Get the number of successful persistent puts */
728 unsigned long long xenstat_tmem_succ_pers_puts(xenstat_tmem *tmem)
729 {
730 return tmem->succ_pers_puts;
731 }
733 /* Get the number of successful persistent gets */
734 unsigned long long xenstat_tmem_succ_pers_gets(xenstat_tmem *tmem)
735 {
736 return tmem->succ_pers_gets;
737 }
740 static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id)
741 {
742 char path[80], *vmpath;
744 snprintf(path, sizeof(path),"/local/domain/%i/vm", domain_id);
746 vmpath = xs_read(handle->xshandle, XBT_NULL, path, NULL);
748 if (vmpath == NULL)
749 return NULL;
751 snprintf(path, sizeof(path),"%s/name", vmpath);
752 free(vmpath);
754 return xs_read(handle->xshandle, XBT_NULL, path, NULL);
755 }
757 /* Remove specified entry from list of domains */
758 static void xenstat_prune_domain(xenstat_node *node, unsigned int entry)
759 {
760 /* nothing to do if array is empty or entry is beyond end */
761 if (node->num_domains == 0 || entry >= node->num_domains)
762 return;
764 /* decrement count of domains */
765 node->num_domains--;
767 /* shift entries following specified entry up by one */
768 if (entry < node->num_domains) {
769 xenstat_domain *domain = &node->domains[entry];
770 memmove(domain,domain+1,(node->num_domains - entry) * sizeof(xenstat_domain) );
771 }
773 /* zero out original last entry from node -- not
774 strictly necessary but safer! */
775 memset(&node->domains[node->num_domains], 0, sizeof(xenstat_domain));
776 }