[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] merge?
# HG changeset patch # User cl349@xxxxxxxxxxxxxxxxxxxx # Node ID 5f4724c130406fe7030a8cbe482441785010a6b1 # Parent 2d3a7be68ba35c3278225214a792587b0c2219e0 merge? diff -r 2d3a7be68ba3 -r 5f4724c13040 Config.mk --- a/Config.mk Tue Aug 23 08:40:50 2005 +++ b/Config.mk Tue Aug 23 08:40:58 2005 @@ -14,6 +14,7 @@ CC = $(CROSS_COMPILE)gcc CPP = $(CROSS_COMPILE)gcc -E AR = $(CROSS_COMPILE)ar +RANLIB = $(CROSS_COMPILE)ranlib NM = $(CROSS_COMPILE)nm STRIP = $(CROSS_COMPILE)strip OBJCOPY = $(CROSS_COMPILE)objcopy @@ -43,3 +44,7 @@ # ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY # ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY ACM_USE_SECURITY_POLICY ?= ACM_NULL_POLICY + +# Optional components +XENSTAT_XENTOP ?= y + diff -r 2d3a7be68ba3 -r 5f4724c13040 linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c Tue Aug 23 08:40:50 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c Tue Aug 23 08:40:58 2005 @@ -405,54 +405,6 @@ balloon_unlock(flags); } - -unsigned long allocate_empty_lowmem_region(unsigned long pages) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - unsigned long *pfn_array; - unsigned long vstart; - unsigned long i; - unsigned int order = get_order(pages*PAGE_SIZE); - - vstart = __get_free_pages(GFP_KERNEL, order); - if (vstart == 0) - return 0UL; - - scrub_pages(vstart, 1 << order); - - pfn_array = vmalloc((1<<order) * sizeof(*pfn_array)); - BUG_ON(pfn_array == NULL); - - for (i = 0; i < (1<<order); i++) { - pgd = pgd_offset_k( (vstart + (i*PAGE_SIZE))); - pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE))); - pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE))); - pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE))); - pfn_array[i] = pte_mfn(*pte); -#ifdef CONFIG_X86_64 - xen_l1_entry_update(pte, __pte(0)); -#else - BUG_ON(HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE), - __pte_ma(0), 0)); -#endif - phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] = - INVALID_P2M_ENTRY; - } - - flush_tlb_all(); - - balloon_put_pages(pfn_array, 1 << order); - - vfree(pfn_array); - - return vstart; -} - -EXPORT_SYMBOL(allocate_empty_lowmem_region); - /* * Local variables: * c-file-style: "linux" diff -r 2d3a7be68ba3 -r 5f4724c13040 linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c Tue Aug 23 08:40:50 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c Tue Aug 23 08:40:58 2005 @@ -368,35 +368,37 @@ EXPORT_SYMBOL(direct_remap_area_pages); +static int lookup_pte_fn( + pte_t *pte, struct page *pte_page, unsigned long addr, void *data) +{ + unsigned long *ptep = (unsigned long *)data; + if (ptep) + *ptep = (pfn_to_mfn(page_to_pfn(pte_page)) << + PAGE_SHIFT) | + ((unsigned long)pte & ~PAGE_MASK); + return 0; +} + int create_lookup_pte_addr(struct mm_struct *mm, unsigned long address, unsigned long *ptep) { - int f(pte_t *pte, struct page *pte_page, unsigned long addr, - void *data) { - unsigned long *ptep = (unsigned long *)data; - if (ptep) - *ptep = (pfn_to_mfn(page_to_pfn(pte_page)) << - PAGE_SHIFT) | - ((unsigned long)pte & ~PAGE_MASK); - return 0; - } - - return generic_page_range(mm, address, PAGE_SIZE, f, ptep); + return generic_page_range(mm, address, PAGE_SIZE, lookup_pte_fn, ptep); } EXPORT_SYMBOL(create_lookup_pte_addr); + +static int noop_fn( + pte_t *pte, struct page *pte_page, unsigned long addr, void *data) +{ + return 0; +} int touch_pte_range(struct mm_struct *mm, unsigned long address, unsigned long size) { - int f(pte_t *pte, struct page *pte_page, unsigned long addr, - void *data) { - return 0; - } - - return generic_page_range(mm, address, size, f, NULL); + return generic_page_range(mm, address, size, noop_fn, NULL); } EXPORT_SYMBOL(touch_pte_range); diff -r 2d3a7be68ba3 -r 5f4724c13040 linux-2.6-xen-sparse/arch/xen/x86_64/mm/ioremap.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/ioremap.c Tue Aug 23 08:40:50 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/ioremap.c Tue Aug 23 08:40:58 2005 @@ -465,33 +465,35 @@ EXPORT_SYMBOL(direct_remap_area_pages); +static int lookup_pte_fn( + pte_t *pte, struct page *pte_page, unsigned long addr, void *data) +{ + unsigned long *ptep = (unsigned long *)data; + if (ptep) *ptep = (pfn_to_mfn(page_to_pfn(pte_page)) << PAGE_SHIFT) + | ((unsigned long)pte & ~PAGE_MASK); + return 0; +} + int create_lookup_pte_addr(struct mm_struct *mm, unsigned long address, unsigned long *ptep) { - int f(pte_t *pte, struct page *pte_page, unsigned long addr, void *data) - { - unsigned long *ptep = (unsigned long *)data; - if (ptep) *ptep = (pfn_to_mfn(page_to_pfn(pte_page)) << PAGE_SHIFT) - | ((unsigned long)pte & ~PAGE_MASK); - return 0; - } - - return generic_page_range(mm, address, PAGE_SIZE, f, ptep); + return generic_page_range(mm, address, PAGE_SIZE, lookup_pte_fn, ptep); } EXPORT_SYMBOL(create_lookup_pte_addr); + +static int noop_fn( + pte_t *pte, struct page *pte_page, unsigned long addr, void *data) +{ + return 0; +} int touch_pte_range(struct mm_struct *mm, unsigned long address, unsigned long size) { - int f(pte_t *pte, struct page *pte_page, unsigned long addr, void *data) - { - return 0; - } - - return generic_page_range(mm, address, size, f, NULL); -} + return generic_page_range(mm, address, size, noop_fn, NULL); +} EXPORT_SYMBOL(touch_pte_range); diff -r 2d3a7be68ba3 -r 5f4724c13040 linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Tue Aug 23 08:40:50 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Tue Aug 23 08:40:58 2005 @@ -83,12 +83,15 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) /* Use the private and mapping fields of struct page as a list. */ -#define PAGE_TO_LIST(p) ( (struct list_head *)&p->private ) -#define LIST_TO_PAGE(l) ( list_entry( ((unsigned long *)l), \ - struct page, private ) ) -#define UNLIST_PAGE(p) do { list_del(PAGE_TO_LIST(p)); \ - p->mapping = NULL; \ - p->private = 0; } while(0) +#define PAGE_TO_LIST(p) ((struct list_head *)&p->private) +#define LIST_TO_PAGE(l) \ + (list_entry(((unsigned long *)l), struct page, private)) +#define UNLIST_PAGE(p) \ + do { \ + list_del(PAGE_TO_LIST(p)); \ + p->mapping = NULL; \ + p->private = 0; \ + } while(0) #else /* There's a dedicated list field in struct page we can use. */ #define PAGE_TO_LIST(p) ( &p->list ) @@ -104,56 +107,53 @@ #endif #define IPRINTK(fmt, args...) \ - printk(KERN_INFO "xen_mem: " fmt, ##args) + printk(KERN_INFO "xen_mem: " fmt, ##args) #define WPRINTK(fmt, args...) \ - printk(KERN_WARNING "xen_mem: " fmt, ##args) + printk(KERN_WARNING "xen_mem: " fmt, ##args) /* balloon_append: add the given page to the balloon. */ static void balloon_append(struct page *page) { - /* Low memory is re-populated first, so highmem pages go at list tail. */ - if ( PageHighMem(page) ) - { - list_add_tail(PAGE_TO_LIST(page), &ballooned_pages); - balloon_high++; - } - else - { - list_add(PAGE_TO_LIST(page), &ballooned_pages); - balloon_low++; - } + /* Lowmem is re-populated first, so highmem pages go at list tail. */ + if (PageHighMem(page)) { + list_add_tail(PAGE_TO_LIST(page), &ballooned_pages); + balloon_high++; + } else { + list_add(PAGE_TO_LIST(page), &ballooned_pages); + balloon_low++; + } } /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ static struct page *balloon_retrieve(void) { - struct page *page; - - if ( list_empty(&ballooned_pages) ) - return NULL; - - page = LIST_TO_PAGE(ballooned_pages.next); - UNLIST_PAGE(page); - - if ( PageHighMem(page) ) - balloon_high--; - else - balloon_low--; - - return page; + struct page *page; + + if (list_empty(&ballooned_pages)) + return NULL; + + page = LIST_TO_PAGE(ballooned_pages.next); + UNLIST_PAGE(page); + + if (PageHighMem(page)) + balloon_high--; + else + balloon_low--; + + return page; } static void balloon_alarm(unsigned long unused) { - schedule_work(&balloon_worker); + schedule_work(&balloon_worker); } static unsigned long current_target(void) { - unsigned long target = min(target_pages, hard_limit); - if ( target > (current_pages + balloon_low + balloon_high) ) - target = current_pages + balloon_low + balloon_high; - return target; + unsigned long target = min(target_pages, hard_limit); + if (target > (current_pages + balloon_low + balloon_high)) + target = current_pages + balloon_low + balloon_high; + return target; } /* @@ -164,161 +164,147 @@ */ static void balloon_process(void *unused) { - unsigned long *mfn_list, pfn, i, flags; - struct page *page; - long credit, debt, rc; - void *v; - - down(&balloon_mutex); + unsigned long *mfn_list, pfn, i, flags; + struct page *page; + long credit, debt, rc; + void *v; + + down(&balloon_mutex); retry: - mfn_list = NULL; - - if ( (credit = current_target() - current_pages) > 0 ) - { - mfn_list = (unsigned long *)vmalloc(credit * sizeof(*mfn_list)); - if ( mfn_list == NULL ) - goto out; - - balloon_lock(flags); - rc = HYPERVISOR_dom_mem_op( - MEMOP_increase_reservation, mfn_list, credit, 0); - balloon_unlock(flags); - if ( rc < credit ) - { - /* We hit the Xen hard limit: reprobe. */ - if ( HYPERVISOR_dom_mem_op( - MEMOP_decrease_reservation, mfn_list, rc, 0) != rc ) - BUG(); - hard_limit = current_pages + rc - driver_pages; - vfree(mfn_list); - goto retry; - } - - for ( i = 0; i < credit; i++ ) - { - if ( (page = balloon_retrieve()) == NULL ) - BUG(); - - pfn = page - mem_map; - if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY ) - BUG(); - - /* Update P->M and M->P tables. */ - phys_to_machine_mapping[pfn] = mfn_list[i]; - xen_machphys_update(mfn_list[i], pfn); + mfn_list = NULL; + + if ((credit = current_target() - current_pages) > 0) { + mfn_list = vmalloc(credit * sizeof(*mfn_list)); + if (mfn_list == NULL) + goto out; + + balloon_lock(flags); + rc = HYPERVISOR_dom_mem_op( + MEMOP_increase_reservation, mfn_list, credit, 0); + balloon_unlock(flags); + if (rc < credit) { + /* We hit the Xen hard limit: reprobe. */ + BUG_ON(HYPERVISOR_dom_mem_op( + MEMOP_decrease_reservation, + mfn_list, rc, 0) != rc); + hard_limit = current_pages + rc - driver_pages; + vfree(mfn_list); + goto retry; + } + + for (i = 0; i < credit; i++) { + page = balloon_retrieve(); + BUG_ON(page == NULL); + + pfn = page - mem_map; + if (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY) + BUG(); + + /* Update P->M and M->P tables. */ + phys_to_machine_mapping[pfn] = mfn_list[i]; + xen_machphys_update(mfn_list[i], pfn); - /* Link back into the page tables if it's not a highmem page. */ - if ( pfn < max_low_pfn ) - { - BUG_ON(HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - pfn_pte_ma(mfn_list[i], PAGE_KERNEL), 0)); - } - - /* Finally, relinquish the memory back to the system allocator. */ - ClearPageReserved(page); - set_page_count(page, 1); - __free_page(page); - } - - current_pages += credit; - } - else if ( credit < 0 ) - { - debt = -credit; - - mfn_list = (unsigned long *)vmalloc(debt * sizeof(*mfn_list)); - if ( mfn_list == NULL ) - goto out; - - for ( i = 0; i < debt; i++ ) - { - if ( (page = alloc_page(GFP_HIGHUSER)) == NULL ) - { - debt = i; - break; - } - - pfn = page - mem_map; - mfn_list[i] = phys_to_machine_mapping[pfn]; - - if ( !PageHighMem(page) ) - { - v = phys_to_virt(pfn << PAGE_SHIFT); - scrub_pages(v, 1); - BUG_ON(HYPERVISOR_update_va_mapping( - (unsigned long)v, __pte_ma(0), 0)); - } + /* Link back into the page tables if not highmem. */ + if (pfn < max_low_pfn) + BUG_ON(HYPERVISOR_update_va_mapping( + (unsigned long)__va(pfn << PAGE_SHIFT), + pfn_pte_ma(mfn_list[i], PAGE_KERNEL), + 0)); + + /* Relinquish the page back to the allocator. */ + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); + } + + current_pages += credit; + } else if (credit < 0) { + debt = -credit; + + mfn_list = vmalloc(debt * sizeof(*mfn_list)); + if (mfn_list == NULL) + goto out; + + for (i = 0; i < debt; i++) { + if ((page = alloc_page(GFP_HIGHUSER)) == NULL) { + debt = i; + break; + } + + pfn = page - mem_map; + mfn_list[i] = phys_to_machine_mapping[pfn]; + + if (!PageHighMem(page)) { + v = phys_to_virt(pfn << PAGE_SHIFT); + scrub_pages(v, 1); + BUG_ON(HYPERVISOR_update_va_mapping( + (unsigned long)v, __pte_ma(0), 0)); + } #ifdef CONFIG_XEN_SCRUB_PAGES - else - { - v = kmap(page); - scrub_pages(v, 1); - kunmap(page); - } + else { + v = kmap(page); + scrub_pages(v, 1); + kunmap(page); + } #endif - } - - /* Ensure that ballooned highmem pages don't have cached mappings. */ - kmap_flush_unused(); - flush_tlb_all(); - - /* No more mappings: invalidate pages in P2M and add to balloon. */ - for ( i = 0; i < debt; i++ ) - { - pfn = mfn_to_pfn(mfn_list[i]); - phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY; - balloon_append(pfn_to_page(pfn)); - } - - if ( HYPERVISOR_dom_mem_op( - MEMOP_decrease_reservation, mfn_list, debt, 0) != debt ) - BUG(); - - current_pages -= debt; - } + } + + /* Ensure that ballooned highmem pages don't have kmaps. */ + kmap_flush_unused(); + flush_tlb_all(); + + /* No more mappings: invalidate P2M and add to balloon. */ + for (i = 0; i < debt; i++) { + pfn = mfn_to_pfn(mfn_list[i]); + phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY; + balloon_append(pfn_to_page(pfn)); + } + + BUG_ON(HYPERVISOR_dom_mem_op( + MEMOP_decrease_reservation,mfn_list, debt, 0) != debt); + + current_pages -= debt; + } out: - if ( mfn_list != NULL ) - vfree(mfn_list); - - /* Schedule more work if there is some still to be done. */ - if ( current_target() != current_pages ) - mod_timer(&balloon_timer, jiffies + HZ); - - up(&balloon_mutex); + if (mfn_list != NULL) + vfree(mfn_list); + + /* Schedule more work if there is some still to be done. */ + if (current_target() != current_pages) + mod_timer(&balloon_timer, jiffies + HZ); + + up(&balloon_mutex); } /* Resets the Xen limit, sets new target, and kicks off processing. */ static void set_new_target(unsigned long target) { - /* No need for lock. Not read-modify-write updates. */ - hard_limit = ~0UL; - target_pages = target; - schedule_work(&balloon_worker); + /* No need for lock. Not read-modify-write updates. */ + hard_limit = ~0UL; + target_pages = target; + schedule_work(&balloon_worker); } static struct xenbus_watch target_watch = { - .node = "memory/target" + .node = "memory/target" }; /* React to a change in the target key */ static void watch_target(struct xenbus_watch *watch, const char *node) { - unsigned long new_target; - int err; - - err = xenbus_scanf("memory", "target", "%lu", &new_target); + unsigned long new_target; + int err; + + err = xenbus_scanf("memory", "target", "%lu", &new_target); + if (err != 1) { + printk(KERN_ERR "Unable to read memory/target\n"); + return; + } - if(err != 1) - { - printk(KERN_ERR "Unable to read memory/target\n"); - return; - } - - set_new_target(new_target >> PAGE_SHIFT); + set_new_target(new_target >> PAGE_SHIFT); } @@ -329,141 +315,185 @@ unsigned long event, void *data) { - int err; - - BUG_ON(down_trylock(&xenbus_lock) == 0); - - err = register_xenbus_watch(&target_watch); - - if (err) { - printk(KERN_ERR "Failed to set balloon watcher\n"); - } - - return NOTIFY_DONE; + int err; + + BUG_ON(down_trylock(&xenbus_lock) == 0); + + err = register_xenbus_watch(&target_watch); + if (err) + printk(KERN_ERR "Failed to set balloon watcher\n"); + + return NOTIFY_DONE; } static int balloon_write(struct file *file, const char __user *buffer, unsigned long count, void *data) { - char memstring[64], *endchar; - unsigned long long target_bytes; - - if ( !capable(CAP_SYS_ADMIN) ) - return -EPERM; - - if ( count <= 1 ) - return -EBADMSG; /* runt */ - if ( count > sizeof(memstring) ) - return -EFBIG; /* too long */ - - if ( copy_from_user(memstring, buffer, count) ) - return -EFAULT; - memstring[sizeof(memstring)-1] = '\0'; - - target_bytes = memparse(memstring, &endchar); - set_new_target(target_bytes >> PAGE_SHIFT); - - return count; + char memstring[64], *endchar; + unsigned long long target_bytes; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (count <= 1) + return -EBADMSG; /* runt */ + if (count > sizeof(memstring)) + return -EFBIG; /* too long */ + + if (copy_from_user(memstring, buffer, count)) + return -EFAULT; + memstring[sizeof(memstring)-1] = '\0'; + + target_bytes = memparse(memstring, &endchar); + set_new_target(target_bytes >> PAGE_SHIFT); + + return count; } static int balloon_read(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len; - - len = sprintf( - page, - "Current allocation: %8lu kB\n" - "Requested target: %8lu kB\n" - "Low-mem balloon: %8lu kB\n" - "High-mem balloon: %8lu kB\n" - "Xen hard limit: ", - PAGES2KB(current_pages), PAGES2KB(target_pages), - PAGES2KB(balloon_low), PAGES2KB(balloon_high)); - - if ( hard_limit != ~0UL ) - len += sprintf( - page + len, - "%8lu kB (inc. %8lu kB driver headroom)\n", - PAGES2KB(hard_limit), PAGES2KB(driver_pages)); - else - len += sprintf( - page + len, - " ??? kB\n"); - - *eof = 1; - return len; + int len; + + len = sprintf( + page, + "Current allocation: %8lu kB\n" + "Requested target: %8lu kB\n" + "Low-mem balloon: %8lu kB\n" + "High-mem balloon: %8lu kB\n" + "Xen hard limit: ", + PAGES2KB(current_pages), PAGES2KB(target_pages), + PAGES2KB(balloon_low), PAGES2KB(balloon_high)); + + if (hard_limit != ~0UL) { + len += sprintf( + page + len, + "%8lu kB (inc. %8lu kB driver headroom)\n", + PAGES2KB(hard_limit), PAGES2KB(driver_pages)); + } else { + len += sprintf( + page + len, + " ??? kB\n"); + } + + *eof = 1; + return len; } static struct notifier_block xenstore_notifier; static int __init balloon_init(void) { - unsigned long pfn; - struct page *page; - - IPRINTK("Initialising balloon driver.\n"); - - current_pages = min(xen_start_info.nr_pages, max_pfn); - target_pages = current_pages; - balloon_low = 0; - balloon_high = 0; - driver_pages = 0UL; - hard_limit = ~0UL; - - init_timer(&balloon_timer); - balloon_timer.data = 0; - balloon_timer.function = balloon_alarm; + unsigned long pfn; + struct page *page; + + IPRINTK("Initialising balloon driver.\n"); + + current_pages = min(xen_start_info.nr_pages, max_pfn); + target_pages = current_pages; + balloon_low = 0; + balloon_high = 0; + driver_pages = 0UL; + hard_limit = ~0UL; + + init_timer(&balloon_timer); + balloon_timer.data = 0; + balloon_timer.function = balloon_alarm; - if ( (balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL ) - { - WPRINTK("Unable to create /proc/xen/balloon.\n"); - return -1; - } - - balloon_pde->read_proc = balloon_read; - balloon_pde->write_proc = balloon_write; + if ((balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL) { + WPRINTK("Unable to create /proc/xen/balloon.\n"); + return -1; + } + + balloon_pde->read_proc = balloon_read; + balloon_pde->write_proc = balloon_write; - /* Initialise the balloon with excess memory space. */ - for ( pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++ ) - { - page = &mem_map[pfn]; - if ( !PageReserved(page) ) - balloon_append(page); - } - - target_watch.callback = watch_target; - xenstore_notifier.notifier_call = balloon_init_watcher; - - register_xenstore_notifier(&xenstore_notifier); + /* Initialise the balloon with excess memory space. */ + for (pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++) { + page = &mem_map[pfn]; + if (!PageReserved(page)) + balloon_append(page); + } + + target_watch.callback = watch_target; + xenstore_notifier.notifier_call = balloon_init_watcher; + + register_xenstore_notifier(&xenstore_notifier); - return 0; + return 0; } subsys_initcall(balloon_init); void balloon_update_driver_allowance(long delta) { - unsigned long flags; - balloon_lock(flags); - driver_pages += delta; /* non-atomic update */ - balloon_unlock(flags); -} - -void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns) -{ - unsigned long flags; - - balloon_lock(flags); - if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, - mfn_list, nr_mfns, 0) != nr_mfns ) - BUG(); - current_pages -= nr_mfns; /* non-atomic update */ - balloon_unlock(flags); - - schedule_work(&balloon_worker); + unsigned long flags; + balloon_lock(flags); + driver_pages += delta; /* non-atomic update */ + balloon_unlock(flags); +} + +static int dealloc_pte_fn( + pte_t *pte, struct page *pte_page, unsigned long addr, void *data) +{ + unsigned long mfn = pte_mfn(*pte); + set_pte(pte, __pte_ma(0)); + phys_to_machine_mapping[__pa(addr) >> PAGE_SHIFT] = + INVALID_P2M_ENTRY; + BUG_ON(HYPERVISOR_dom_mem_op( + MEMOP_decrease_reservation, &mfn, 1, 0) != 1); + return 0; +} + +struct page *balloon_alloc_empty_page_range(unsigned long nr_pages) +{ + unsigned long vstart, flags; + unsigned int order = get_order(nr_pages * PAGE_SIZE); + + vstart = __get_free_pages(GFP_KERNEL, order); + if (vstart == 0) + return NULL; + + scrub_pages(vstart, 1 << order); + + balloon_lock(flags); + BUG_ON(generic_page_range( + &init_mm, vstart, PAGE_SIZE << order, dealloc_pte_fn, NULL)); + current_pages -= 1UL << order; + balloon_unlock(flags); + + schedule_work(&balloon_worker); + + flush_tlb_all(); + + return virt_to_page(vstart); +} + +void balloon_dealloc_empty_page_range( + struct page *page, unsigned long nr_pages) +{ + unsigned long i, flags; + unsigned int order = get_order(nr_pages * PAGE_SIZE); + + balloon_lock(flags); + for (i = 0; i < (1UL << order); i++) + balloon_append(page + i); + balloon_unlock(flags); + + schedule_work(&balloon_worker); } EXPORT_SYMBOL(balloon_update_driver_allowance); -EXPORT_SYMBOL(balloon_put_pages); +EXPORT_SYMBOL(balloon_alloc_empty_page_range); +EXPORT_SYMBOL(balloon_dealloc_empty_page_range); + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 2d3a7be68ba3 -r 5f4724c13040 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Tue Aug 23 08:40:50 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Tue Aug 23 08:40:58 2005 @@ -569,6 +569,7 @@ static int __init blkif_init(void) { int i; + struct page *page; if ( !(xen_start_info.flags & SIF_INITDOMAIN) && !(xen_start_info.flags & SIF_BLK_BE_DOMAIN) ) @@ -576,8 +577,9 @@ blkif_interface_init(); - if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 ) - BUG(); + page = balloon_alloc_empty_page_range(MMAP_PAGES); + BUG_ON(page == NULL); + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); pending_cons = 0; pending_prod = MAX_PENDING_REQS; diff -r 2d3a7be68ba3 -r 5f4724c13040 linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c Tue Aug 23 08:40:50 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c Tue Aug 23 08:40:58 2005 @@ -775,9 +775,11 @@ int blktap_init(void) { int err, i, j; - - if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 ) - BUG(); + struct page *page; + + page = balloon_alloc_empty_page_range(MMAP_PAGES); + BUG_ON(page == NULL); + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); #ifdef CONFIG_XEN_BLKDEV_GRANT for (i=0; i<MAX_PENDING_REQS ; i++) diff -r 2d3a7be68ba3 -r 5f4724c13040 linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Aug 23 08:40:50 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Aug 23 08:40:58 2005 @@ -968,8 +968,9 @@ netif_interface_init(); - mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS); - BUG_ON(mmap_vstart == 0); + page = balloon_alloc_empty_page_range(MAX_PENDING_REQS); + BUG_ON(page == NULL); + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); for ( i = 0; i < MAX_PENDING_REQS; i++ ) { diff -r 2d3a7be68ba3 -r 5f4724c13040 linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c --- a/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c Tue Aug 23 08:40:50 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c Tue Aug 23 08:40:58 2005 @@ -1027,13 +1027,15 @@ static int __init usbif_init(void) { int i; + struct page *page; if ( !(xen_start_info.flags & SIF_INITDOMAIN) && !(xen_start_info.flags & SIF_USB_BE_DOMAIN) ) return 0; - - if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 ) - BUG(); + + page = balloon_alloc_empty_page_range(MMAP_PAGES); + BUG_ON(page == NULL); + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); pending_cons = 0; pending_prod = MAX_PENDING_REQS; diff -r 2d3a7be68ba3 -r 5f4724c13040 linux-2.6-xen-sparse/include/asm-xen/balloon.h --- a/linux-2.6-xen-sparse/include/asm-xen/balloon.h Tue Aug 23 08:40:50 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/balloon.h Tue Aug 23 08:40:58 2005 @@ -35,10 +35,19 @@ * Inform the balloon driver that it should allow some slop for device-driver * memory activities. */ -extern void balloon_update_driver_allowance(long delta); +extern void +balloon_update_driver_allowance( + long delta); -/* Give up unmapped pages to the balloon driver. */ -extern void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns); +/* Allocate an empty low-memory page range. */ +extern struct page * +balloon_alloc_empty_page_range( + unsigned long nr_pages); + +/* Deallocate an empty page range, adding to the balloon. */ +extern void +balloon_dealloc_empty_page_range( + struct page *page, unsigned long nr_pages); /* * Prevent the balloon driver from changing the memory reservation during diff -r 2d3a7be68ba3 -r 5f4724c13040 linux-2.6-xen-sparse/include/asm-xen/hypervisor.h --- a/linux-2.6-xen-sparse/include/asm-xen/hypervisor.h Tue Aug 23 08:40:50 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/hypervisor.h Tue Aug 23 08:40:58 2005 @@ -137,9 +137,6 @@ void xen_create_contiguous_region(unsigned long vstart, unsigned int order); void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order); -/* Allocate a contiguous empty region of low memory. Return virtual start. */ -unsigned long allocate_empty_lowmem_region(unsigned long pages); - #include <asm/hypercall.h> #if defined(CONFIG_X86_64) diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/Makefile --- a/tools/Makefile Tue Aug 23 08:40:50 2005 +++ b/tools/Makefile Tue Aug 23 08:40:58 2005 @@ -14,6 +14,7 @@ SUBDIRS += firmware SUBDIRS += security SUBDIRS += console +SUBDIRS += xenstat .PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/Rules.mk --- a/tools/Rules.mk Tue Aug 23 08:40:50 2005 +++ b/tools/Rules.mk Tue Aug 23 08:40:58 2005 @@ -6,6 +6,7 @@ XEN_LIBXC = $(XEN_ROOT)/tools/libxc XEN_XCS = $(XEN_ROOT)/tools/xcs XEN_XENSTORE = $(XEN_ROOT)/tools/xenstore +XEN_LIBXENSTAT = $(XEN_ROOT)/tools/xenstat/libxenstat/src ifeq ($(XEN_TARGET_ARCH),x86_32) CFLAGS += -m32 -march=i686 diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Tue Aug 23 08:40:50 2005 +++ b/tools/python/xen/xm/main.py Tue Aug 23 08:40:58 2005 @@ -49,6 +49,7 @@ restore <File> create a domain from a saved state file save <DomId> <File> save domain state (and config) to file shutdown <DomId> shutdown a domain + top monitor system and domains in real-time unpause <DomId> unpause a paused domain For a complete list of subcommands run 'xm help --long' @@ -87,6 +88,7 @@ dmesg [--clear] read or clear Xen's message buffer info get information about the xen host log print the xend log + top monitor system and domains in real-time Scheduler Commands: bvt <options> set BVT scheduler parameters @@ -457,6 +459,9 @@ os.execvp('/usr/libexec/xen/xenconsole', cmd.split()) console = sxp.child(info, "console") +def xm_top(args): + os.execv('/usr/sbin/xentop', ['/usr/sbin/xentop']) + def xm_dmesg(args): gopts = Opts(use="""[-c|--clear] @@ -545,6 +550,8 @@ commands = { # console commands "console": xm_console, + # xenstat commands + "top": xm_top, # domain commands "domid": xm_domid, "domname": xm_domname, diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/Makefile --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/Makefile Tue Aug 23 08:40:58 2005 @@ -0,0 +1,13 @@ +XEN_ROOT = ../.. +include $(XEN_ROOT)/tools/Rules.mk + +SUBDIRS := +SUBDIRS += libxenstat +SUBDIRS += xentop + +.PHONY: all install clean + +all install clean: + @set -e; for subdir in $(SUBDIRS); do \ + $(MAKE) -C $$subdir $@; \ + done diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/libxenstat/COPYING --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/libxenstat/COPYING Tue Aug 23 08:40:58 2005 @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/libxenstat/Makefile --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/libxenstat/Makefile Tue Aug 23 08:40:58 2005 @@ -0,0 +1,142 @@ +# libxenstat: statistics-collection library for Xen +# Copyright (C) International Business Machines Corp., 2005 +# Author: Josh Triplett <josht@xxxxxxxxxx> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +XEN_ROOT=../../.. +include $(XEN_ROOT)/tools/Rules.mk +LINUX_ROOT := $(XEN_ROOT)/linux-2.6-xen-sparse + +INSTALL = install +INSTALL_PROG = $(INSTALL) -m0755 -D +INSTALL_DATA = $(INSTALL) -m0644 -D + +prefix=/usr +includedir=$(prefix)/include +libdir=$(prefix)/lib + +LDCONFIG=ldconfig +MAKE_LINK=ln -sf + +MAJOR=0 +MINOR=0 + +LIB=src/libxenstat.a +SHLIB=src/libxenstat.so.$(MAJOR).$(MINOR) +SHLIB_LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so +OBJECTS=src/xenstat.o src/xen-interface.o +SONAME_FLAGS=-Wl,-soname -Wl,libxenstat.so.$(MAJOR) + +WARN_FLAGS=-Wall -Werror + +CFLAGS+=-Isrc +CFLAGS+=-I$(XEN_ROOT)/xen/include/public +CFLAGS+=-I$(LINUX_ROOT)/include/asm-xen/linux-public/ +LDFLAGS+=-Lsrc + +all: $(LIB) + +$(LIB): $(OBJECTS) + $(AR) rc $@ $^ + $(RANLIB) $@ + +$(SHLIB): $(OBJECTS) + $(CC) $(LDFLAGS) $(SONAME_FLAGS) -shared -o $@ $(OBJECTS) + +src/xenstat.o: src/xenstat.c src/xenstat.h src/xen-interface.h + $(CC) $(CFLAGS) $(WARN_FLAGS) -c -o $@ $< + +src/xen-interface.o: src/xen-interface.c src/xen-interface.h + $(CC) $(CFLAGS) $(WARN_FLAGS) -c -o $@ $< + +src/libxenstat.so.$(MAJOR): $(LIB) + $(MAKE_LINK) $(<F) $@ + +src/libxenstat.so: src/libxenstat.so.$(MAJOR) + $(MAKE_LINK) $(<F) $@ + +install: all +#install: all +# $(INSTALL_DATA) src/xenstat.h $(DESTDIR)$(includedir)/xenstat.h +# $(INSTALL_PROG) $(LIB) $(DESTDIR)$(libdir)/libxenstat.a +# $(INSTALL_PROG) $(SHLIB) \ +# $(DESTDIR)$(libdir)/libxenstat.so.$(MAJOR).$(MINOR) +# $(MAKE_LINK) libxenstat.so.$(MAJOR).$(MINOR) \ +# $(DESTDIR)$(libdir)/libxenstat.so.$(MAJOR) +# $(MAKE_LINK) libxenstat.so.$(MAJOR) \ +# $(DESTDIR)$(libdir)/libxenstat.so +# -$(LDCONFIG) + +PYLIB=bindings/swig/python/_xenstat.so +PYMOD=bindings/swig/python/xenstat.py +PYSRC=bindings/swig/python/_xenstat.c +PERLLIB=bindings/swig/perl/xenstat.so +PERLMOD=bindings/swig/perl/xenstat.pm +PERLSRC=bindings/swig/perl/xenstat.c +BINDINGS=$(PYLIB) $(PYMOD) $(PERLLIB) $(PERLMOD) +BINDINGSRC=$(PYSRC) $(PERLSRC) + +# The all-bindings target builds all the language bindings +all-bindings: perl-bindings python-bindings + +# The install-bindings target installs all the language bindings +install-bindings: install-perl-bindings install-python-bindings + +$(BINDINGS): $(SHLIB) $(SHLIB_LINKS) src/xenstat.h + +SWIG_FLAGS=-module xenstat -Isrc + +# Python bindings +PYTHON_VERSION=2.3 +PYTHON_FLAGS=-I/usr/include/python$(PYTHON_VERSION) -lpython$(PYTHON_VERSION) +$(PYSRC) $(PYMOD): bindings/swig/xenstat.i + swig -python $(SWIG_FLAGS) -outdir $(@D) -o $(PYSRC) $< + +$(PYLIB): $(PYSRC) + $(CC) $(CFLAGS) $(LDFLAGS) $(PYTHON_FLAGS) -shared -lxenstat -o $@ $< + +python-bindings: $(PYLIB) $(PYMOD) + +pythonlibdir=$(prefix)/lib/python$(PYTHON_VERSION)/site-packages +install-python-bindings: $(PYLIB) $(PYMOD) + $(INSTALL_PROG) $(PYLIB) $(DESTDIR)$(pythonlibdir)/_xenstat.so + $(INSTALL_PROG) $(PYMOD) $(DESTDIR)$(pythonlibdir)/xenstat.py + +ifeq ($(XENSTAT_PYTHON_BINDINGS),y) +all: python-bindings +install: install-python-bindings +endif + +# Perl bindings +PERL_FLAGS=`perl -MConfig -e 'print "$$Config{ccflags} -I$$Config{archlib}/CORE";'` +$(PERLSRC) $(PERLMOD): bindings/swig/xenstat.i + swig -perl $(SWIG_FLAGS) -outdir $(@D) -o $(PERLSRC) $< + +$(PERLLIB): $(PERLSRC) + $(CC) $(CFLAGS) $(LDFLAGS) $(PERL_FLAGS) -shared -lxenstat -o $@ $< + +perl-bindings: $(PERLLIB) $(PERLMOD) + +perllibdir=$(prefix)/lib/perl5 +perlmoddir=$(prefix)/share/perl5 +install-perl-bindings: $(PERLLIB) $(PERLMOD) + $(INSTALL_PROG) $(PERLLIB) $(DESTDIR)$(perllibdir)/xenstat.so + $(INSTALL_PROG) $(PERLMOD) $(DESTDIR)$(perlmoddir)/xenstat.pm + +ifeq ($(XENSTAT_PERL_BINDINGS),y) +all: perl-bindings +install: install-perl-bindings +endif + +clean: + rm -f $(LIB) $(SHLIB) $(SHLIB_LINKS) $(OBJECTS) \ + $(BINDINGS) $(BINDINGSRC) diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/libxenstat/bindings/swig/perl/.empty --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/libxenstat/bindings/swig/perl/.empty Tue Aug 23 08:40:58 2005 @@ -0,0 +1,1 @@ +This directory is empty; this file is included to prevent version control systems from removing the directory. diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/libxenstat/bindings/swig/python/.empty --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/libxenstat/bindings/swig/python/.empty Tue Aug 23 08:40:58 2005 @@ -0,0 +1,1 @@ +This directory is empty; this file is included to prevent version control systems from removing the directory. diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/libxenstat/bindings/swig/xenstat.i --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/libxenstat/bindings/swig/xenstat.i Tue Aug 23 08:40:58 2005 @@ -0,0 +1,8 @@ +%module xenstat_swig +%{ +/* Includes the header in the wrapper code */ +#include "xenstat.h" +%} + +/* Parse the header file to generate wrappers */ +%include "xenstat.h" diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/libxenstat/src/xen-interface.c --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/libxenstat/src/xen-interface.c Tue Aug 23 08:40:58 2005 @@ -0,0 +1,144 @@ +/* xen-interface.c + * + * Copyright (C) International Business Machines Corp., 2005 + * Authors: Josh Triplett <josht@xxxxxxxxxx> + * Judy Fischbach <jfisch@xxxxxxxxxx> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#include "xen-interface.h" +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include "privcmd.h" +#include "xen.h" + +struct xi_handle { + int fd; +}; + +/* Initialize for xen-interface. Returns a handle to be used with subsequent + * calls to the xen-interface functions or NULL if an error occurs. */ +xi_handle *xi_init() +{ + xi_handle *handle; + + handle = (xi_handle *)calloc(1, sizeof(xi_handle)); + if (handle == NULL) + return NULL; + + handle->fd = open("/proc/xen/privcmd", O_RDWR); + if (handle->fd < 0) { + perror("Couldn't open /proc/xen/privcmd"); + free(handle); + return NULL; + } + + return handle; +} + +/* Release the handle to libxc, free resources, etc. */ +void xi_uninit(xi_handle *handle) +{ + close (handle->fd); + free (handle); +} + +/* Make Xen hypervisor call */ +int xi_make_dom0_op(xi_handle *handle, dom0_op_t *op, int opcode) +{ + privcmd_hypercall_t privcmd; + int ret = 0; + + /* set up for doing hypercall */ + privcmd.op = __HYPERVISOR_dom0_op; + privcmd.arg[0] = (unsigned long)op; + op->cmd = opcode; + op->interface_version = DOM0_INTERFACE_VERSION; + + if (mlock( &privcmd, sizeof(privcmd_hypercall_t)) < 0) { + perror("Failed to mlock privcmd structure"); + return -1; + } + + if (mlock( op, sizeof(dom0_op_t)) < 0) { + perror("Failed to mlock dom0_op structure"); + munlock( &privcmd, sizeof(privcmd_hypercall_t)); + return -1; + } + + if (ioctl( handle->fd, IOCTL_PRIVCMD_HYPERCALL, &privcmd) < 0) { + perror("Hypercall failed"); + ret = -1; + } + + munlock( &privcmd, sizeof(privcmd_hypercall_t)); + munlock( op, sizeof(dom0_op_t)); + + return ret; +} + +/* Obtain domain data from dom0 */ +int xi_get_physinfo(xi_handle *handle, dom0_physinfo_t *physinfo) +{ + dom0_op_t op; + + if (xi_make_dom0_op(handle, &op, DOM0_PHYSINFO) < 0) { + perror("DOM0_PHYSINFO Hypercall failed"); + return -1; + } + + *physinfo = op.u.physinfo; + return 0; +} + +/* Obtain domain data from dom0 */ +int xi_get_domaininfolist(xi_handle *handle, dom0_getdomaininfo_t *info, + unsigned int first_domain, unsigned int max_domains) +{ + dom0_op_t op; + op.u.getdomaininfolist.first_domain = first_domain; + op.u.getdomaininfolist.max_domains = max_domains; + op.u.getdomaininfolist.buffer = info; + + if (mlock( info, max_domains * sizeof(dom0_getdomaininfo_t)) < 0) { + perror("Failed to mlock domaininfo array"); + return -1; + } + + if (xi_make_dom0_op(handle, &op, DOM0_GETDOMAININFOLIST) < 0) { + perror("DOM0_GETDOMAININFOLIST Hypercall failed"); + return -1; + } + + return op.u.getdomaininfolist.num_domains; +} + +/* Returns cpu usage data from dom0 */ +long long xi_get_vcpu_usage(xi_handle *handle, unsigned int domain, + unsigned int vcpu) +{ + dom0_op_t op; + op.u.getvcpucontext.domain = domain; + op.u.getvcpucontext.vcpu = vcpu; + op.u.getvcpucontext.ctxt = NULL; + + if (xi_make_dom0_op(handle, &op, DOM0_GETVCPUCONTEXT) < 0) { + perror("DOM0_GETVCPUCONTEXT Hypercall failed"); + return -1; + } + + return op.u.getvcpucontext.cpu_time; +} diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/libxenstat/src/xen-interface.h --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/libxenstat/src/xen-interface.h Tue Aug 23 08:40:58 2005 @@ -0,0 +1,49 @@ +/* xen-interface.h + * + * Copyright (C) International Business Machines Corp., 2005 + * Authors: Josh Triplett <josht@xxxxxxxxxx> + * Judy Fischbach <jfisch@xxxxxxxxxx> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#include <stdint.h> + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +#include "dom0_ops.h" + +/* Opaque handles */ +typedef struct xi_handle xi_handle; + +/* Initialize for xen-interface. Returns a handle to be used with subsequent + * calls to the xen-interface functions or NULL if an error occurs. */ +xi_handle *xi_init(); + +/* Release the handle to libxc, free resources, etc. */ +void xi_uninit(xi_handle *handle); + +/* Obtain physinfo data from dom0 */ +int xi_get_physinfo(xi_handle *, dom0_physinfo_t *); + +/* Obtain domain data from dom0 */ +int xi_get_domaininfolist(xi_handle *, dom0_getdomaininfo_t *, unsigned int, + unsigned int); + +/* Returns cpu usage data from dom0 */ +long long xi_get_vcpu_usage(xi_handle *, unsigned int, unsigned int); diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/libxenstat/src/xenstat.c --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/libxenstat/src/xenstat.c Tue Aug 23 08:40:58 2005 @@ -0,0 +1,620 @@ +/* libxenstat: statistics-collection library for Xen + * Copyright (C) International Business Machines Corp., 2005 + * Authors: Josh Triplett <josht@xxxxxxxxxx> + * Judy Fischbach <jfisch@xxxxxxxxxx> + * David Hendricks <dhendrix@xxxxxxxxxx> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#include <limits.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <xen-interface.h> +#include "xenstat.h" + +/* + * Types + */ +struct xenstat_handle { + xi_handle *xihandle; + int page_size; + FILE *procnetdev; +}; + +struct xenstat_node { + unsigned int flags; + unsigned long long cpu_hz; + unsigned int num_cpus; + unsigned long long tot_mem; + unsigned long long free_mem; + unsigned int num_domains; + xenstat_domain *domains; /* Array of length num_domains */ +}; + +struct xenstat_domain { + unsigned int id; + unsigned int state; + unsigned long long cpu_ns; + unsigned int num_vcpus; + xenstat_vcpu *vcpus; /* Array of length num_vcpus */ + unsigned long long cur_mem; /* Current memory reservation */ + unsigned long long max_mem; /* Total memory allowed */ + unsigned int ssid; + unsigned int num_networks; + xenstat_network *networks; /* Array of length num_networks */ +}; + +struct xenstat_vcpu { + unsigned long long ns; +}; + +struct xenstat_network { + unsigned int id; + /* Received */ + unsigned long long rbytes; + unsigned long long rpackets; + unsigned long long rerrs; + unsigned long long rdrop; + /* Transmitted */ + unsigned long long tbytes; + unsigned long long tpackets; + unsigned long long terrs; + unsigned long long tdrop; +}; + +/* + * Data-collection types + */ +/* Called to collect the information for the node and all the domains on + * it. When called, the domain information has already been collected. */ +typedef int (*xenstat_collect_func)(xenstat_handle * handle, + xenstat_node * node); +/* Called to free the information collected by the collect function. The free + * function will only be called on a xenstat_node if that node includes + * information collected by the corresponding collector. */ +typedef void (*xenstat_free_func)(xenstat_node * node); +/* Called to free any information stored in the handle. Note the lack of a + * matching init function; the collect functions should initialize on first + * use. Also, the uninit function must handle the case that the collector has + * never been initialized. */ +typedef void (*xenstat_uninit_func)(xenstat_handle * handle); +typedef struct xenstat_collector { + unsigned int flag; + xenstat_collect_func collect; + xenstat_free_func free; + xenstat_uninit_func uninit; +} xenstat_collector; + +static int xenstat_collect_vcpus(xenstat_handle * handle, + xenstat_node * node); +static int xenstat_collect_networks(xenstat_handle * handle, + xenstat_node * node); +static void xenstat_free_vcpus(xenstat_node * node); +static void xenstat_free_networks(xenstat_node * node); +static void xenstat_uninit_vcpus(xenstat_handle * handle); +static void xenstat_uninit_networks(xenstat_handle * handle); + +static xenstat_collector collectors[] = { + { XENSTAT_VCPU, xenstat_collect_vcpus, + xenstat_free_vcpus, xenstat_uninit_vcpus }, + { XENSTAT_NETWORK, xenstat_collect_networks, + xenstat_free_networks, xenstat_uninit_networks } +}; + +#define NUM_COLLECTORS (sizeof(collectors)/sizeof(xenstat_collector)) + +/* + * libxenstat API + */ +xenstat_handle *xenstat_init() +{ + xenstat_handle *handle; + + handle = (xenstat_handle *) calloc(1, sizeof(xenstat_handle)); + if (handle == NULL) + return NULL; + +#if defined(PAGESIZE) + handle->page_size = PAGESIZE; +#elif defined(PAGE_SIZE) + handle->page_size = PAGE_SIZE; +#else + handle->page_size = sysconf(_SC_PAGE_SIZE); + if (handle->page_size < 0) { + perror("Failed to retrieve page size."); + free(handle); + return NULL; + } +#endif + + handle->xihandle = xi_init(); + if (handle->xihandle == NULL) { + perror("xi_init"); + free(handle); + return NULL; + } + + return handle; +} + +void xenstat_uninit(xenstat_handle * handle) +{ + unsigned int i; + if (handle) { + for (i = 0; i < NUM_COLLECTORS; i++) + collectors[i].uninit(handle); + xi_uninit(handle->xihandle); + free(handle); + } +} + +xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags) +{ +#define DOMAIN_CHUNK_SIZE 256 + xenstat_node *node; + dom0_physinfo_t physinfo; + dom0_getdomaininfo_t domaininfo[DOMAIN_CHUNK_SIZE]; + unsigned int num_domains, new_domains; + unsigned int i; + + /* Create the node */ + node = (xenstat_node *) calloc(1, sizeof(xenstat_node)); + if (node == NULL) + return NULL; + + /* Get information about the physical system */ + if (xi_get_physinfo(handle->xihandle, &physinfo) < 0) { + free(node); + return NULL; + } + + node->cpu_hz = ((unsigned long long)physinfo.cpu_khz) * 1000ULL; + node->num_cpus = + (physinfo.threads_per_core * physinfo.cores_per_socket * + physinfo.sockets_per_node * physinfo.nr_nodes); + node->tot_mem = ((unsigned long long)physinfo.total_pages) + * handle->page_size; + node->free_mem = ((unsigned long long)physinfo.free_pages) + * handle->page_size; + + /* malloc(0) is not portable, so allocate a single domain. This will + * be resized below. */ + node->domains = malloc(sizeof(xenstat_domain)); + if (node->domains == NULL) { + free(node); + return NULL; + } + + num_domains = 0; + do { + xenstat_domain *domain; + + new_domains = xi_get_domaininfolist(handle->xihandle, + domaininfo, num_domains, + DOMAIN_CHUNK_SIZE); + + node->domains = realloc(node->domains, + (num_domains + new_domains) + * sizeof(xenstat_domain)); + if (node->domains == NULL) { + free(node); + return NULL; + } + + domain = node->domains + num_domains; + + for (i = 0; i < new_domains; i++) { + /* Fill in domain using domaininfo[i] */ + domain->id = domaininfo[i].domain; + domain->state = domaininfo[i].flags; + domain->cpu_ns = domaininfo[i].cpu_time; + domain->num_vcpus = domaininfo[i].n_vcpu; + domain->vcpus = NULL; + domain->cur_mem = + ((unsigned long long)domaininfo[i].tot_pages) + * handle->page_size; + domain->max_mem = + domaininfo[i].max_pages == UINT_MAX + ? (unsigned long long)-1 + : (unsigned long long)(domaininfo[i].max_pages + * handle->page_size); + domain->ssid = domaininfo[i].ssidref; + domain->num_networks = 0; + domain->networks = NULL; + + domain++; + } + num_domains += new_domains; + } while (new_domains == DOMAIN_CHUNK_SIZE); + node->num_domains = num_domains; + + /* Run all the extra data collectors requested */ + node->flags = 0; + for (i = 0; i < NUM_COLLECTORS; i++) { + if ((flags & collectors[i].flag) == collectors[i].flag) { + node->flags |= collectors[i].flag; + if(collectors[i].collect(handle, node) == 0) { + xenstat_free_node(node); + return NULL; + } + } + } + + return node; +} + +void xenstat_free_node(xenstat_node * node) +{ + int i; + + if (node) { + if (node->domains) { + for (i = 0; i < NUM_COLLECTORS; i++) + if((node->flags & collectors[i].flag) + == collectors[i].flag) + collectors[i].free(node); + free(node->domains); + } + free(node); + } +} + +xenstat_domain *xenstat_node_domain(xenstat_node * node, unsigned int domid) +{ + unsigned int i; + + /* FIXME: binary search */ + /* Find the appropriate domain entry in the node struct. */ + for (i = 0; i < node->num_domains; i++) { + if (node->domains[i].id == domid) + return &(node->domains[i]); + } + return NULL; +} + +xenstat_domain *xenstat_node_domain_by_index(xenstat_node * node, + unsigned int index) +{ + if (0 <= index && index < node->num_domains) + return &(node->domains[index]); + return NULL; +} + +unsigned long long xenstat_node_tot_mem(xenstat_node * node) +{ + return node->tot_mem; +} + +unsigned long long xenstat_node_free_mem(xenstat_node * node) +{ + return node->free_mem; +} + +unsigned int xenstat_node_num_domains(xenstat_node * node) +{ + return node->num_domains; +} + +unsigned int xenstat_node_num_cpus(xenstat_node * node) +{ + return node->num_cpus; +} + +/* Get information about the CPU speed */ +unsigned long long xenstat_node_cpu_hz(xenstat_node * node) +{ + return node->cpu_hz; +} + +/* Get the domain ID for this domain */ +unsigned xenstat_domain_id(xenstat_domain * domain) +{ + return domain->id; +} + +/* Get information about how much CPU time has been used */ +unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain) +{ + return domain->cpu_ns; +} + +/* Find the number of VCPUs allocated to a domain */ +unsigned int xenstat_domain_num_vcpus(xenstat_domain * domain) +{ + return domain->num_vcpus; +} + +xenstat_vcpu *xenstat_domain_vcpu(xenstat_domain * domain, unsigned int vcpu) +{ + if (0 <= vcpu && vcpu < domain->num_vcpus) + return &(domain->vcpus[vcpu]); + return NULL; +} + +/* Find the current memory reservation for this domain */ +unsigned long long xenstat_domain_cur_mem(xenstat_domain * domain) +{ + return domain->cur_mem; +} + +/* Find the maximum memory reservation for this domain */ +unsigned long long xenstat_domain_max_mem(xenstat_domain * domain) +{ + return domain->max_mem; +} + +/* Find the domain's SSID */ +unsigned int xenstat_domain_ssid(xenstat_domain * domain) +{ + return domain->ssid; +} + +/* Get domain states */ +unsigned int xenstat_domain_dying(xenstat_domain * domain) +{ + return (domain->state & DOMFLAGS_DYING) == DOMFLAGS_DYING; +} + +unsigned int xenstat_domain_crashed(xenstat_domain * domain) +{ + return ((domain->state & DOMFLAGS_SHUTDOWN) == DOMFLAGS_SHUTDOWN) + && (((domain->state >> DOMFLAGS_SHUTDOWNSHIFT) + & DOMFLAGS_SHUTDOWNMASK) == SHUTDOWN_crash); +} + +unsigned int xenstat_domain_shutdown(xenstat_domain * domain) +{ + return ((domain->state & DOMFLAGS_SHUTDOWN) == DOMFLAGS_SHUTDOWN) + && (((domain->state >> DOMFLAGS_SHUTDOWNSHIFT) + & DOMFLAGS_SHUTDOWNMASK) != SHUTDOWN_crash); +} + +unsigned int xenstat_domain_paused(xenstat_domain * domain) +{ + return (domain->state & DOMFLAGS_PAUSED) == DOMFLAGS_PAUSED; +} + +unsigned int xenstat_domain_blocked(xenstat_domain * domain) +{ + return (domain->state & DOMFLAGS_BLOCKED) == DOMFLAGS_BLOCKED; +} + +unsigned int xenstat_domain_running(xenstat_domain * domain) +{ + return (domain->state & DOMFLAGS_RUNNING) == DOMFLAGS_RUNNING; +} + +/* Get the number of networks for a given domain */ +unsigned int xenstat_domain_num_networks(xenstat_domain * domain) +{ + return domain->num_networks; +} + +/* Get the network handle to obtain network stats */ +xenstat_network *xenstat_domain_network(xenstat_domain * domain, + unsigned int network) +{ + if (domain->networks && 0 <= network && network < domain->num_networks) + return &(domain->networks[network]); + return NULL; +} + +/* + * VCPU functions + */ +/* Collect information about VCPUs */ +static int xenstat_collect_vcpus(xenstat_handle * handle, xenstat_node * node) +{ + unsigned int i, vcpu; + /* Fill in VCPU information */ + for (i = 0; i < node->num_domains; i++) { + node->domains[i].vcpus = malloc(node->domains[i].num_vcpus + * sizeof(xenstat_vcpu)); + if (node->domains[i].vcpus == NULL) + return 0; + + for (vcpu = 0; vcpu < node->domains[i].num_vcpus; vcpu++) { + /* FIXME: need to be using a more efficient mechanism*/ + long long vcpu_time; + vcpu_time = + xi_get_vcpu_usage(handle->xihandle, + node->domains[i].id, + vcpu); + if (vcpu_time < 0) + return 0; + node->domains[i].vcpus[vcpu].ns = vcpu_time; + } + } + return 1; +} + +/* Free VCPU information */ +static void xenstat_free_vcpus(xenstat_node * node) +{ + unsigned int i; + for (i = 0; i < node->num_domains; i++) + free(node->domains[i].vcpus); +} + +/* Free VCPU information in handle - nothing to do */ +static void xenstat_uninit_vcpus(xenstat_handle * handle) +{ +} + +/* Get VCPU usage */ +unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu) +{ + return vcpu->ns; +} + +/* + * Network functions + */ + +/* Expected format of /proc/net/dev */ +static const char PROCNETDEV_HEADER[] = + "Inter-| Receive |" + " Transmit\n" + " face |bytes packets errs drop fifo frame compressed multicast|" + "bytes packets errs drop fifo colls carrier compressed\n"; + +/* Collect information about networks */ +static int xenstat_collect_networks(xenstat_handle * handle, + xenstat_node * node) +{ + /* Open and validate /proc/net/dev if we haven't already */ + if (handle->procnetdev == NULL) { + char header[sizeof(PROCNETDEV_HEADER)]; + handle->procnetdev = fopen("/proc/net/dev", "r"); + if (handle->procnetdev == NULL) { + perror("Error opening /proc/net/dev"); + return 1; + } + + /* Validate the format of /proc/net/dev */ + if (fread(header, sizeof(PROCNETDEV_HEADER) - 1, 1, + handle->procnetdev) != 1) { + perror("Error reading /proc/net/dev header"); + return 1; + } + header[sizeof(PROCNETDEV_HEADER) - 1] = '\0'; + if (strcmp(header, PROCNETDEV_HEADER) != 0) { + fprintf(stderr, + "Unexpected /proc/net/dev format\n"); + return 1; + } + } + + /* Fill in networks */ + /* FIXME: optimize this */ + fseek(handle->procnetdev, sizeof(PROCNETDEV_HEADER) - 1, SEEK_SET); + while (1) { + xenstat_domain *domain; + xenstat_network net; + unsigned int domid; + int ret = fscanf(handle->procnetdev, + "vif%u.%u:%llu%llu%llu%llu%*u%*u%*u%*u" + "%llu%llu%llu%llu%*u%*u%*u%*u", + &domid, &net.id, + &net.tbytes, &net.tpackets, &net.terrs, + &net.tdrop, + &net.rbytes, &net.rpackets, &net.rerrs, + &net.rdrop); + if (ret == EOF) + break; + if (ret != 10) { + unsigned int c; + do { + c = fgetc(handle->procnetdev); + } while (c != '\n' && c != EOF); + if (c == EOF) + break; + continue; + } + + /* FIXME: this does a search for the domid */ + domain = xenstat_node_domain(node, domid); + if (domain == NULL) { + fprintf(stderr, + "Found interface vif%u.%u but domain %u" + " does not exist.\n", domid, net.id, + domid); + continue; + } + if (domain->networks == NULL) { + domain->num_networks = 1; + domain->networks = malloc(sizeof(xenstat_network)); + } else { + domain->num_networks++; + domain->networks = + realloc(domain->networks, + domain->num_networks * + sizeof(xenstat_network)); + } + if (domain->networks == NULL) + return 1; + domain->networks[domain->num_networks - 1] = net; + } + + return 1; +} + +/* Free network information */ +static void xenstat_free_networks(xenstat_node * node) +{ + unsigned int i; + for (i = 0; i < node->num_domains; i++) + free(node->domains[i].networks); +} + +/* Free network information in handle */ +static void xenstat_uninit_networks(xenstat_handle * handle) +{ + if(handle->procnetdev) + fclose(handle->procnetdev); +} + +/* Get the network ID */ +unsigned int xenstat_network_id(xenstat_network * network) +{ + return network->id; +} + +/* Get the number of receive bytes */ +unsigned long long xenstat_network_rbytes(xenstat_network * network) +{ + return network->rbytes; +} + +/* Get the number of receive packets */ +unsigned long long xenstat_network_rpackets(xenstat_network * network) +{ + return network->rpackets; +} + +/* Get the number of receive errors */ +unsigned long long xenstat_network_rerrs(xenstat_network * network) +{ + return network->rerrs; +} + +/* Get the number of receive drops */ +unsigned long long xenstat_network_rdrop(xenstat_network * network) +{ + return network->rdrop; +} + +/* Get the number of transmit bytes */ +unsigned long long xenstat_network_tbytes(xenstat_network * network) +{ + return network->tbytes; +} + +/* Get the number of transmit packets */ +unsigned long long xenstat_network_tpackets(xenstat_network * network) +{ + return network->tpackets; +} + +/* Get the number of transmit errors */ +unsigned long long xenstat_network_terrs(xenstat_network * network) +{ + return network->terrs; +} + +/* Get the number of transmit dropped packets */ +unsigned long long xenstat_network_tdrop(xenstat_network * network) +{ + return network->tdrop; +} diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/libxenstat/src/xenstat.h --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/libxenstat/src/xenstat.h Tue Aug 23 08:40:58 2005 @@ -0,0 +1,148 @@ +/* libxenstat: statistics-collection library for Xen + * Copyright (C) International Business Machines Corp., 2005 + * Authors: Josh Triplett <josht@xxxxxxxxxx> + * Judy Fischbach <jfisch@xxxxxxxxxx> + * David Hendricks <dhendrix@xxxxxxxxxx> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +/* libxenstat API */ + +/* Opaque handles */ +typedef struct xenstat_handle xenstat_handle; +typedef struct xenstat_domain xenstat_domain; +typedef struct xenstat_node xenstat_node; +typedef struct xenstat_vcpu xenstat_vcpu; +typedef struct xenstat_network xenstat_network; + +/* Initialize the xenstat library. Returns a handle to be used with + * subsequent calls to the xenstat library, or NULL if an error occurs. */ +xenstat_handle *xenstat_init(); + +/* Release the handle to libxc, free resources, etc. */ +void xenstat_uninit(xenstat_handle * handle); + +/* Get all available information about a node */ +#define XENSTAT_VCPU 0x1 +#define XENSTAT_NETWORK 0x2 +#define XENSTAT_ALL (XENSTAT_VCPU|XENSTAT_NETWORK) +xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags); + +/* Free the information */ +void xenstat_free_node(xenstat_node * node); + +/* + * Node functions - extract information from a xenstat_node + */ + +/* Get information about the domain with the given domain ID */ +xenstat_domain *xenstat_node_domain(xenstat_node * node, + unsigned int domid); + +/* Get the domain with the given index; used to loop over all domains. */ +xenstat_domain *xenstat_node_domain_by_index(xenstat_node * node, + unsigned index); + +/* Get amount of total memory on a node */ +unsigned long long xenstat_node_tot_mem(xenstat_node * node); + +/* Get amount of free memory on a node */ +unsigned long long xenstat_node_free_mem(xenstat_node * node); + +/* Find the number of domains existing on a node */ +unsigned int xenstat_node_num_domains(xenstat_node * node); + +/* Find the number of CPUs existing on a node */ +unsigned int xenstat_node_num_cpus(xenstat_node * node); + +/* Get information about the CPU speed */ +unsigned long long xenstat_node_cpu_hz(xenstat_node * node); + +/* + * Domain functions - extract information from a xenstat_domain + */ + +/* Get the domain ID for this domain */ +unsigned xenstat_domain_id(xenstat_domain * domain); + +/* Get information about how much CPU time has been used */ +unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain); + +/* Find the number of VCPUs allocated to a domain */ +unsigned int xenstat_domain_num_vcpus(xenstat_domain * domain); + +/* Get the VCPU handle to obtain VCPU stats */ +xenstat_vcpu *xenstat_domain_vcpu(xenstat_domain * domain, + unsigned int vcpu); + +/* Find the current memory reservation for this domain */ +unsigned long long xenstat_domain_cur_mem(xenstat_domain * domain); + +/* Find the maximum memory reservation for this domain */ +unsigned long long xenstat_domain_max_mem(xenstat_domain * domain); + +/* Find the domain's SSID */ +unsigned int xenstat_domain_ssid(xenstat_domain * domain); + +/* Get domain states */ +unsigned int xenstat_domain_dying(xenstat_domain * domain); +unsigned int xenstat_domain_crashed(xenstat_domain * domain); +unsigned int xenstat_domain_shutdown(xenstat_domain * domain); +unsigned int xenstat_domain_paused(xenstat_domain * domain); +unsigned int xenstat_domain_blocked(xenstat_domain * domain); +unsigned int xenstat_domain_running(xenstat_domain * domain); + +/* Get the number of networks for a given domain */ +unsigned int xenstat_domain_num_networks(xenstat_domain *); + +/* Get the network handle to obtain network stats */ +xenstat_network *xenstat_domain_network(xenstat_domain * domain, + unsigned int network); + +/* + * VCPU functions - extract information from a xenstat_vcpu + */ + +/* Get VCPU usage */ +unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu); + + +/* + * Network functions - extract information from a xenstat_network + */ + +/* Get the ID for this network */ +unsigned int xenstat_network_id(xenstat_network * network); + +/* Get the number of receive bytes for this network */ +unsigned long long xenstat_network_rbytes(xenstat_network * network); + +/* Get the number of receive packets for this network */ +unsigned long long xenstat_network_rpackets(xenstat_network * network); + +/* Get the number of receive errors for this network */ +unsigned long long xenstat_network_rerrs(xenstat_network * network); + +/* Get the number of receive drops for this network */ +unsigned long long xenstat_network_rdrop(xenstat_network * network); + +/* Get the number of transmit bytes for this network */ +unsigned long long xenstat_network_tbytes(xenstat_network * network); + +/* Get the number of transmit packets for this network */ +unsigned long long xenstat_network_tpackets(xenstat_network * network); + +/* Get the number of transmit errors for this network */ +unsigned long long xenstat_network_terrs(xenstat_network * network); + +/* Get the number of transmit drops for this network */ +unsigned long long xenstat_network_tdrop(xenstat_network * network); diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/xentop/Makefile --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/xentop/Makefile Tue Aug 23 08:40:58 2005 @@ -0,0 +1,44 @@ +# Copyright (C) International Business Machines Corp., 2005 +# Author: Josh Triplett <josht@xxxxxxxxxx> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; under version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +XEN_ROOT=../../.. +include $(XEN_ROOT)/tools/Rules.mk + +ifneq ($(XENSTAT_XENTOP),y) +all install xentop: +else + +INSTALL = install +INSTALL_PROG = $(INSTALL) -m0755 -D +INSTALL_DATA = $(INSTALL) -m0644 -D + +prefix=/usr +mandir=$(prefix)/share/man +man1dir=$(mandir)/man1 +sbindir=$(prefix)/sbin + +CFLAGS += -DGCC_PRINTF -Wall -Werror -I$(XEN_LIBXENSTAT) +LDFLAGS += -L$(XEN_LIBXENSTAT) +LDLIBS += -lxenstat -lcurses + +all: xentop + +xentop: xentop.o + +install: xentop xentop.1 + $(INSTALL_PROG) xentop $(DESTDIR)$(sbindir)/xentop + $(INSTALL_DATA) xentop.1 $(DESTDIR)$(man1dir)/xentop.1 + +endif + +clean: + rm -f xentop xentop.o diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/xentop/TODO --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/xentop/TODO Tue Aug 23 08:40:58 2005 @@ -0,0 +1,34 @@ +Display error messages on the help line after bad input at a prompt. +Fractional delay times +Use prompting to search for domains +Better line editing? + +* Make CPU in % more accurate +* Domain total network TX % and RX % + +Like Top, f feature, field select of domain columns, toggle the display of +field by typing the letter associated with field, if displayed it shows in +bold and the letter is Capitalized along with a leading asterisk for the +field, if not selected for display letter is lowercase, no leading asterisk +and field is not bolded. + +Like Top, ordering of domain columns, o feature Capital letter shifts left, +lowercase letter shifts right? + +Color +Full management: pause, destroy, create domains + +Add support for Virtual Block Devices (vbd) + +To think about: +Support for one than one node display (distributed monitoring +from any node of all other nodes in a cluster) +Bottom line option (Switch node, Search node [tab completion?]) + +Capture/Logging of resource information generated during a time interval. +-b batch mode dump snapshots to standard output (used with -n) +-n number of iterations to dump to standard output (unlimited if not specified) +-d monitor DomIDs as -dD1,-dD2 or -dD1,D2... + Monitor only domains with specified domain IDs +-m monitor nodeIDs as -mN1,-mN2 or -mN1,N2... + Monitor only domains with specified node IDs diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/xentop/xentop.1 --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/xentop/xentop.1 Tue Aug 23 08:40:58 2005 @@ -0,0 +1,88 @@ +.\" Copyright (C) International Business Machines Corp., 2005 +.\" Author: Josh Triplett <josht@xxxxxxxxxx> +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; under version 2 of the License. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +.TH xentop 1 "August 2005" +.SH NAME +\fBxentop\fR \- displays real-time information about a Xen system and domains + +.SH SYNOPSIS +.B xentop +[\fB\-h\fR] +[\fB\-V\fR] +[\fB\-d\fRSECONDS] +[\fB\-n\fR] +[\fB\-r\fR] +[\fB\-v\fR] + +.SH DESCRIPTION +\fBxentop\fR displays information about the Xen system and domains, in a +continually-updating manner. Command-line options and interactive commands +can change the detail and format of the information displayed by \fBxentop\fR. + +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +display help and exit +.TP +\fB\-V\fR, \fB\-\-version\fR +output version information and exit +.TP +\fB\-d\fR, \fB\-\-delay\fR=\fISECONDS\fR +seconds between updates (default 1) +.TP +\fB\-n\fR, \fB\-\-networks\fR +output network information +.TP +\fB\-r\fR, \fB\-\-repeat\-header\fR +repeat table header before each domain +.TP +\fB\-v\fR, \fB\-\-vcpus\fR +output VCPU data + +.SH "INTERACTIVE COMMANDS" +All interactive commands are case-insensitive. +.TP +.B D +set delay between updates +.TP +.B N +toggle display of network information +.TP +.B Q, Esc +quit +.TP +.B R +toggle table header before each domain +.TP +.B S +cycle sort order +.TP +.B V +toggle display of VCPU information +.TP +.B Arrows +scroll domain display + +.SH AUTHORS +Written by Judy Fischbach, David Hendricks, and Josh Triplett + +.SH "REPORTING BUGS" +Report bugs to <dsteklof@xxxxxxxxxx>. + +.SH COPYRIGHT +Copyright \(co 2005 International Business Machines Corp +.br +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff -r 2d3a7be68ba3 -r 5f4724c13040 tools/xenstat/xentop/xentop.c --- /dev/null Tue Aug 23 08:40:50 2005 +++ b/tools/xenstat/xentop/xentop.c Tue Aug 23 08:40:58 2005 @@ -0,0 +1,876 @@ +/* + * Copyright (C) International Business Machines Corp., 2005 + * Author(s): Judy Fischbach <jfisch@xxxxxxxxxx> + * David Hendricks <dhendrix@xxxxxxxxxx> + * Josh Triplett <josht@xxxxxxxxxx> + * based on code from Anthony Liguori <aliguori@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <curses.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> + +#include <xenstat.h> + +#define XENTOP_VERSION "1.0" + +#define XENTOP_DISCLAIMER \ +"Copyright (C) 2005 International Business Machines Corp\n"\ +"This is free software; see the source for copying conditions.There is NO\n"\ +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" +#define XENTOP_BUGSTO "Report bugs to <dsteklof@xxxxxxxxxx>.\n" + +#define _GNU_SOURCE +#include <getopt.h> + +#if !defined(__GNUC__) && !defined(__GNUG__) +#define __attribute__(arg) /* empty */ +#endif + +#define KEY_ESCAPE '\x1B' + +/* + * Function prototypes + */ +/* Utility functions */ +static void usage(const char *); +static void version(void); +static void cleanup(void); +static void fail(const char *); +static int current_row(void); +static int lines(void); +static void print(const char *, ...) __attribute__((format(printf,1,2))); +static void attr_addstr(int attr, const char *str); +static void set_delay(char *value); +static void set_prompt(char *new_prompt, void (*func)(char *)); +static int handle_key(int); +static int compare(unsigned long long, unsigned long long); +static int compare_domains(xenstat_domain **, xenstat_domain **); +static unsigned long long tot_net_bytes( xenstat_domain *, int); + +/* Field functions */ +static int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_domid(xenstat_domain *domain); +static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_state(xenstat_domain *domain); +static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_cpu(xenstat_domain *domain); +static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_cpu_pct(xenstat_domain *domain); +static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_mem(xenstat_domain *domain); +static void print_mem_pct(xenstat_domain *domain); +static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_maxmem(xenstat_domain *domain); +static void print_max_pct(xenstat_domain *domain); +static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_vcpus(xenstat_domain *domain); +static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_nets(xenstat_domain *domain); +static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_net_tx(xenstat_domain *domain); +static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_net_rx(xenstat_domain *domain); +static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_ssid(xenstat_domain *domain); + +/* Section printing functions */ +static void do_summary(void); +static void do_header(void); +static void do_bottom_line(void); +static void do_domain(xenstat_domain *); +static void do_vcpu(xenstat_domain *); +static void do_network(xenstat_domain *); +static void top(void); + +/* Field types */ +typedef enum field_id { + FIELD_DOMID, + FIELD_STATE, + FIELD_CPU, + FIELD_CPU_PCT, + FIELD_MEM, + FIELD_MEM_PCT, + FIELD_MAXMEM, + FIELD_MAX_PCT, + FIELD_VCPUS, + FIELD_NETS, + FIELD_NET_TX, + FIELD_NET_RX, + FIELD_SSID +} field_id; + +typedef struct field { + field_id num; + const char *header; + unsigned int default_width; + int (*compare)(xenstat_domain *domain1, xenstat_domain *domain2); + void (*print)(xenstat_domain *domain); +} field; + +field fields[] = { + { FIELD_DOMID, "DOMID", 5, compare_domid, print_domid }, + { FIELD_STATE, "STATE", 6, compare_state, print_state }, + { FIELD_CPU, "CPU(sec)", 10, compare_cpu, print_cpu }, + { FIELD_CPU_PCT, "CPU(%)", 6, compare_cpu_pct, print_cpu_pct }, + { FIELD_MEM, "MEM(k)", 10, compare_mem, print_mem }, + { FIELD_MEM_PCT, "MEM(%)", 6, compare_mem, print_mem_pct }, + { FIELD_MAXMEM, "MAXMEM(k)", 10, compare_maxmem, print_maxmem }, + { FIELD_MAX_PCT, "MAXMEM(%)", 9, compare_maxmem, print_max_pct }, + { FIELD_VCPUS, "VCPUS", 5, compare_vcpus, print_vcpus }, + { FIELD_NETS, "NETS", 4, compare_nets, print_nets }, + { FIELD_NET_TX, "NETTX(k)", 8, compare_net_tx, print_net_tx }, + { FIELD_NET_RX, "NETRX(k)", 8, compare_net_rx, print_net_rx }, + { FIELD_SSID, "SSID", 4, compare_ssid, print_ssid } +}; + +const unsigned int NUM_FIELDS = sizeof(fields)/sizeof(field); + +/* Globals */ +struct timeval curtime, oldtime; +xenstat_handle *xhandle = NULL; +xenstat_node *prev_node = NULL; +xenstat_node *cur_node = NULL; +field_id sort_field = FIELD_DOMID; +unsigned int first_domain_index = 0; +unsigned int delay = 1; +int show_vcpus = 0; +int show_networks = 0; +int repeat_header = 0; +#define PROMPT_VAL_LEN 80 +char *prompt = NULL; +char prompt_val[PROMPT_VAL_LEN]; +int prompt_val_len = 0; +void (*prompt_complete_func)(char *); + +/* + * Function definitions + */ + +/* Utility functions */ + +/* Print usage message, using given program name */ +static void usage(const char *program) +{ + printf("Usage: %s [OPTION]\n" + "Displays ongoing information about xen vm resources \n\n" + "-h, --help display this help and exit\n" + "-V, --version output version information and exit\n" + "-d, --delay=SECONDS seconds between updates (default 1)\n" + "-n, --networks output vif network data\n" + "-r, --repeat-header repeat table header before each domain\n" + "-v, --vcpus output vcpu data\n" + "\n" XENTOP_BUGSTO, + program); + return; +} + +/* Print program version information */ +static void version(void) +{ + printf("xentop " XENTOP_VERSION "\n" + "Written by Judy Fischbach, David Hendricks, Josh Triplett\n" + "\n" XENTOP_DISCLAIMER); +} + +/* Clean up any open resources */ +static void cleanup(void) +{ + if(!isendwin()) + endwin(); + if(prev_node != NULL) + xenstat_free_node(prev_node); + if(cur_node != NULL) + xenstat_free_node(cur_node); + if(xhandle != NULL) + xenstat_uninit(xhandle); +} + +/* Display the given message and gracefully exit */ +static void fail(const char *str) +{ + if(!isendwin()) + endwin(); + fprintf(stderr, str); + exit(1); +} + +/* Return the row containing the cursor. */ +static int current_row(void) +{ + int y, x; + getyx(stdscr, y, x); + return y; +} + +/* Return the number of lines on the screen. */ +static int lines(void) +{ + int y, x; + getmaxyx(stdscr, y, x); + return y; +} + +/* printf-style print function which calls printw, but only if the cursor is + * not on the last line. */ +static void print(const char *fmt, ...) +{ + va_list args; + + if(current_row() < lines()-1) { + va_start(args, fmt); + vw_printw(stdscr, fmt, args); + va_end(args); + } +} + +/* Print a string with the given attributes set. */ +static void attr_addstr(int attr, const char *str) +{ + attron(attr); + addstr(str); + attroff(attr); +} + +/* Handle setting the delay from the user-supplied value in prompt_val */ +static void set_delay(char *value) +{ + int new_delay; + new_delay = atoi(prompt_val); + if(new_delay > 0) + delay = new_delay; +} + +/* Enable prompting mode with the given prompt string; call the given function + * when a value is available. */ +static void set_prompt(char *new_prompt, void (*func)(char *)) +{ + prompt = new_prompt; + prompt_val[0] = '\0'; + prompt_val_len = 0; + prompt_complete_func = func; +} + +/* Handle user input, return 0 if the program should quit, or 1 if not */ +static int handle_key(int ch) +{ + if(prompt == NULL) { + /* Not prompting for input; handle interactive commands */ + switch(ch) { + case 'n': case 'N': + show_networks ^= 1; + break; + case 'r': case 'R': + repeat_header ^= 1; + break; + case 's': case 'S': + sort_field = (sort_field + 1) % NUM_FIELDS; + break; + case 'v': case 'V': + show_vcpus ^= 1; + break; + case KEY_DOWN: + first_domain_index++; + break; + case KEY_UP: + if(first_domain_index > 0) + first_domain_index--; + break; + case 'd': case 'D': + set_prompt("Delay(sec)", set_delay); + break; + case 'q': case 'Q': case KEY_ESCAPE: + return 0; + } + } else { + /* Prompting for input; handle line editing */ + switch(ch) { + case '\r': + prompt_complete_func(prompt_val); + set_prompt(NULL, NULL); + break; + case KEY_ESCAPE: + set_prompt(NULL, NULL); + break; + case KEY_BACKSPACE: + if(prompt_val_len > 0) + prompt_val[--prompt_val_len] = '\0'; + default: + if((prompt_val_len+1) < PROMPT_VAL_LEN + && isprint(ch)) { + prompt_val[prompt_val_len++] = (char)ch; + prompt_val[prompt_val_len] = '\0'; + } + } + } + + return 1; +} + +/* Compares two integers, returning -1,0,1 for <,=,> */ +static int compare(unsigned long long i1, unsigned long long i2) +{ + if(i1 < i2) + return -1; + if(i1 > i2) + return 1; + return 0; +} + +/* Comparison function for use with qsort. Compares two domains using the + * current sort field. */ +static int compare_domains(xenstat_domain **domain1, xenstat_domain **domain2) +{ + return fields[sort_field].compare(*domain1, *domain2); +} + +/* Field functions */ + +/* Compares domain ids of two domains, returning -1,0,1 for <,=,> */ +int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return compare(xenstat_domain_id(domain1), xenstat_domain_id(domain2)); +} + +/* Prints domain identification number */ +void print_domid(xenstat_domain *domain) +{ + print("%5u", xenstat_domain_id(domain)); +} + +struct { + unsigned int (*get)(xenstat_domain *); + char ch; +} state_funcs[] = { + { xenstat_domain_dying, 'd' }, + { xenstat_domain_shutdown, 's' }, + { xenstat_domain_blocked, 'b' }, + { xenstat_domain_crashed, 'c' }, + { xenstat_domain_paused, 'p' }, + { xenstat_domain_running, 'r' } +}; +const unsigned int NUM_STATES = sizeof(state_funcs)/sizeof(*state_funcs); + +/* Compare states of two domains, returning -1,0,1 for <,=,> */ +static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2) +{ + unsigned int i, d1s, d2s; + for(i = 0; i < NUM_STATES; i++) { + d1s = state_funcs[i].get(domain1); + d2s = state_funcs[i].get(domain2); + if(d1s && !d2s) + return -1; + if(d2s && !d1s) + return 1; + } + return 0; +} + +/* Prints domain state in abbreviated letter format */ +static void print_state(xenstat_domain *domain) +{ + unsigned int i; + for(i = 0; i < NUM_STATES; i++) + print("%c", state_funcs[i].get(domain) ? state_funcs[i].ch + : '-'); +} + +/* Compares cpu usage of two domains, returning -1,0,1 for <,=,> */ +static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_cpu_ns(domain1), + xenstat_domain_cpu_ns(domain2)); +} + +/* Prints domain cpu usage in seconds */ +static void print_cpu(xenstat_domain *domain) +{ + print("%10llu", xenstat_domain_cpu_ns(domain)/1000000000); +} + +/* Computes the CPU percentage used for a specified domain */ +static double get_cpu_pct(xenstat_domain *domain) +{ + xenstat_domain *old_domain; + double us_elapsed; + + /* Can't calculate CPU percentage without a previous sample. */ + if(prev_node == NULL) + return 0.0; + + old_domain = xenstat_node_domain(prev_node, xenstat_domain_id(domain)); + if(old_domain == NULL) + return 0.0; + + /* Calculate the time elapsed in microseconds */ + us_elapsed = ((curtime.tv_sec-oldtime.tv_sec)*1000000.0 + +(curtime.tv_usec - oldtime.tv_usec)); + + /* In the following, nanoseconds must be multiplied by 1000.0 to + * convert to microseconds, then divided by 100.0 to get a percentage, + * resulting in a multiplication by 10.0 */ + return ((xenstat_domain_cpu_ns(domain) + -xenstat_domain_cpu_ns(old_domain))/10.0)/us_elapsed; +} + +static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(get_cpu_pct(domain1), get_cpu_pct(domain2)); +} + +/* Prints cpu percentage statistic */ +static void print_cpu_pct(xenstat_domain *domain) +{ + print("%6.1f", get_cpu_pct(domain)); +} + +/* Compares current memory of two domains, returning -1,0,1 for <,=,> */ +static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_cur_mem(domain1), + xenstat_domain_cur_mem(domain2)); +} + +/* Prints current memory statistic */ +static void print_mem(xenstat_domain *domain) +{ + print("%10llu", xenstat_domain_cur_mem(domain)/1024); +} + +/* Prints memory percentage statistic, ratio of current domain memory to total + * node memory */ +static void print_mem_pct(xenstat_domain *domain) +{ + print("%6.1f", (double)xenstat_domain_cur_mem(domain) / + (double)xenstat_node_tot_mem(cur_node) * 100); +} + +/* Compares maximum memory of two domains, returning -1,0,1 for <,=,> */ +static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_max_mem(domain1), + xenstat_domain_max_mem(domain2)); +} + +/* Prints maximum domain memory statistic in KB */ +static void print_maxmem(xenstat_domain *domain) +{ + unsigned long long max_mem = xenstat_domain_max_mem(domain); + if(max_mem == ((unsigned long long)-1)) + print("%10s", "no limit"); + else + print("%10llu", max_mem/1024); +} + +/* Prints memory percentage statistic, ratio of current domain memory to total + * node memory */ +static void print_max_pct(xenstat_domain *domain) +{ + if (xenstat_domain_max_mem(domain) == (unsigned long long)-1) + print("%9s", "n/a"); + else + print("%9.1f", (double)xenstat_domain_max_mem(domain) / + (double)xenstat_node_tot_mem(cur_node) * 100); +} + +/* Compares number of virtual CPUs of two domains, returning -1,0,1 for + * <,=,> */ +static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_num_vcpus(domain1), + xenstat_domain_num_vcpus(domain2)); +} + +/* Prints number of virtual CPUs statistic */ +static void print_vcpus(xenstat_domain *domain) +{ + print("%5u", xenstat_domain_num_vcpus(domain)); +} + +/* Compares number of virtual networks of two domains, returning -1,0,1 for + * <,=,> */ +static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_num_networks(domain1), + xenstat_domain_num_networks(domain2)); +} + +/* Prints number of virtual networks statistic */ +static void print_nets(xenstat_domain *domain) +{ + print("%4u", xenstat_domain_num_networks(domain)); +} + +/* Compares number of total network tx bytes of two domains, returning -1,0,1 for + * <,=,> */ +static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(tot_net_bytes(domain1, FALSE), + tot_net_bytes(domain2, FALSE)); +} + +/* Prints number of total network tx bytes statistic */ +static void print_net_tx(xenstat_domain *domain) +{ + print("%8llu", tot_net_bytes(domain, FALSE)/1024); +} + +/* Compares number of total network rx bytes of two domains, returning -1,0,1 for + * <,=,> */ +static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(tot_net_bytes(domain1, TRUE), + tot_net_bytes(domain2, TRUE)); +} + +/* Prints number of total network rx bytes statistic */ +static void print_net_rx(xenstat_domain *domain) +{ + print("%8llu", tot_net_bytes(domain, TRUE)/1024); +} + +/* Gets number of total network bytes statistic, if rx true, then rx bytes + * otherwise tx bytes + */ +static unsigned long long tot_net_bytes(xenstat_domain *domain, int rx_flag) +{ + int i = 0; + xenstat_network *network; + unsigned num_networks = 0; + unsigned long long total = 0; + + /* How many networks? */ + num_networks = xenstat_domain_num_networks(domain); + + /* Dump information for each network */ + for (i=0; i < num_networks; i++) { + /* Next get the network information */ + network = xenstat_domain_network(domain,i); + if (rx_flag) + total += xenstat_network_rbytes(network); + else + total += xenstat_network_tbytes(network); + } + return (total); +} + +/* Compares security id (ssid) of two domains, returning -1,0,1 for <,=,> */ +static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return compare(xenstat_domain_ssid(domain1), + xenstat_domain_ssid(domain2)); +} + +/* Prints ssid statistic */ +static void print_ssid(xenstat_domain *domain) +{ + print("%4u", xenstat_domain_ssid(domain)); +} + +/* Section printing functions */ +/* Prints the top summary, above the domain table */ +void do_summary(void) +{ +#define TIME_STR_LEN 9 + const char *TIME_STR_FORMAT = "%H:%M:%S"; + char time_str[TIME_STR_LEN]; + unsigned run = 0, block = 0, pause = 0, + crash = 0, dying = 0, shutdown = 0; + unsigned i, num_domains = 0; + unsigned long long used = 0; + xenstat_domain *domain; + + /* Print program name, current time, and number of domains */ + strftime(time_str, TIME_STR_LEN, TIME_STR_FORMAT, + localtime(&curtime.tv_sec)); + num_domains = xenstat_node_num_domains(cur_node); + print("xentop - %s\n", time_str); + + /* Tabulate what states domains are in for summary */ + for (i=0; i < num_domains; i++) { + domain = xenstat_node_domain_by_index(cur_node,i); + if (xenstat_domain_running(domain)) run++; + else if (xenstat_domain_blocked(domain)) block++; + else if (xenstat_domain_paused(domain)) pause++; + else if (xenstat_domain_shutdown(domain)) shutdown++; + else if (xenstat_domain_crashed(domain)) crash++; + else if (xenstat_domain_dying(domain)) dying++; + } + + print("%u domains: %u running, %u blocked, %u paused, " + "%u crashed, %u dying, %u shutdown \n", + num_domains, run, block, pause, crash, dying, shutdown); + + used = xenstat_node_tot_mem(cur_node)-xenstat_node_free_mem(cur_node); + + /* Dump node memory and cpu information */ + print("Mem: %lluk total, %lluk used, %lluk free " + "CPUs: %u @ %lluMHz\n", + xenstat_node_tot_mem(cur_node)/1024, used/1024, + xenstat_node_free_mem(cur_node)/1024, + xenstat_node_num_cpus(cur_node), + xenstat_node_cpu_hz(cur_node)/1000000); +} + +/* Display the top header for the domain table */ +void do_header(void) +{ + field_id i; + + /* Turn on REVERSE highlight attribute for headings */ + attron(A_REVERSE); + for(i = 0; i < NUM_FIELDS; i++) { + if(i != 0) + print(" "); + /* The BOLD attribute is turned on for the sort column */ + if(i == sort_field) + attron(A_BOLD); + print("%*s", fields[i].default_width, fields[i].header); + if(i == sort_field) + attroff(A_BOLD); + } + attroff(A_REVERSE); + print("\n"); +} + +/* Displays bottom status line or current prompt */ +void do_bottom_line(void) +{ + move(lines()-1, 2); + + if (prompt != NULL) { + printw("%s: %s", prompt, prompt_val); + } else { + addch(A_REVERSE | 'D'); addstr("elay "); + + /* network */ + addch(A_REVERSE | 'N'); + attr_addstr(show_networks ? COLOR_PAIR(1) : 0, "etworks"); + addstr(" "); + + /* vcpus */ + addch(A_REVERSE | 'V'); + attr_addstr(show_vcpus ? COLOR_PAIR(1) : 0, "CPUs"); + addstr(" "); + + /* repeat */ + addch(A_REVERSE | 'R'); + attr_addstr(repeat_header ? COLOR_PAIR(1) : 0, "epeat header"); + addstr(" "); + + /* sort order */ + addch(A_REVERSE | 'S'); addstr("ort order "); + + addch(A_REVERSE | 'Q'); addstr("uit "); + } +} + +/* Prints Domain information */ +void do_domain(xenstat_domain *domain) +{ + unsigned int i; + for(i = 0; i < NUM_FIELDS; i++) { + if(i != 0) + print(" "); + if(i == sort_field) + attron(A_BOLD); + fields[i].print(domain); + if(i == sort_field) + attroff(A_BOLD); + } + print("\n"); +} + +/* Output all vcpu information */ +void do_vcpu(xenstat_domain *domain) +{ + int i = 0; + unsigned num_vcpus = 0; + xenstat_vcpu *vcpu; + + print("VCPUs(sec): "); + + num_vcpus = xenstat_domain_num_vcpus(domain); + + /* for all vcpus dump out values */ + for (i=0; i< num_vcpus; i++) { + vcpu = xenstat_domain_vcpu(domain,i); + + if (i != 0 && (i%5)==0) + print("\n "); + print(" %2u: %10llus", i, xenstat_vcpu_ns(vcpu)/1000000000); + } + print("\n"); +} + +/* Output all network information */ +void do_network(xenstat_domain *domain) +{ + int i = 0; + xenstat_network *network; + unsigned num_networks = 0; + + /* How many networks? */ + num_networks = xenstat_domain_num_networks(domain); + + /* Dump information for each network */ + for (i=0; i < num_networks; i++) { + /* Next get the network information */ + network = xenstat_domain_network(domain,i); + + print("Net%d RX: %8llubytes %8llupkts %8lluerr %8lludrop ", + i, + xenstat_network_rbytes(network), + xenstat_network_rpackets(network), + xenstat_network_rerrs(network), + xenstat_network_rdrop(network)); + + print("TX: %8llubytes %8llupkts %8lluerr %8lludrop\n", + xenstat_network_tbytes(network), + xenstat_network_tpackets(network), + xenstat_network_terrs(network), + xenstat_network_tdrop(network)); + } +} + +static void top(void) +{ + xenstat_domain **domains; + unsigned int i, num_domains = 0; + + /* Now get the node information */ + if (prev_node != NULL) + xenstat_free_node(prev_node); + prev_node = cur_node; + cur_node = xenstat_get_node(xhandle, XENSTAT_ALL); + if (cur_node == NULL) + fail("Failed to retrieve statistics from libxenstat\n"); + + /* dump summary top information */ + do_summary(); + + /* Count the number of domains for which to report data */ + num_domains = xenstat_node_num_domains(cur_node); + + domains = malloc(num_domains*sizeof(xenstat_domain *)); + if(domains == NULL) + fail("Failed to allocate memory\n"); + + for (i=0; i < num_domains; i++) + domains[i] = xenstat_node_domain_by_index(cur_node, i); + + /* Sort */ + qsort(domains, num_domains, sizeof(xenstat_domain *), + (int(*)(const void *, const void *))compare_domains); + + if(first_domain_index >= num_domains) + first_domain_index = num_domains-1; + + for (i = first_domain_index; i < num_domains; i++) { + if(current_row() == lines()-1) + break; + if (i == first_domain_index || repeat_header) + do_header(); + do_domain(domains[i]); + if (show_vcpus) + do_vcpu(domains[i]); + if (show_networks) + do_network(domains[i]); + } + + do_bottom_line(); +} + +int main(int argc, char **argv) +{ + int opt, optind = 0; + int ch = ERR; + + struct option lopts[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { "networks", no_argument, NULL, 'n' }, + { "repeat-header", no_argument, NULL, 'r' }, + { "vcpus", no_argument, NULL, 'v' }, + { "delay", required_argument, NULL, 'd' }, + { 0, 0, 0, 0 }, + }; + const char *sopts = "hVbnvd:"; + + if (atexit(cleanup) != 0) + fail("Failed to install cleanup handler.\n"); + + while ((opt = getopt_long(argc, argv, sopts, lopts, &optind)) != -1) { + switch (opt) { + case 'h': + case '?': + default: + usage(argv[0]); + exit(0); + case 'V': + version(); + exit(0); + case 'n': + show_networks = 1; + break; + case 'r': + repeat_header = 1; + break; + case 'v': + show_vcpus = 1; + break; + case 'd': + delay = atoi(optarg); + break; + } + } + + /* Get xenstat handle */ + xhandle = xenstat_init(); + if (xhandle == NULL) + fail("Failed to initialize xenstat library\n"); + + /* Begin curses stuff */ + initscr(); + start_color(); + cbreak(); + noecho(); + nonl(); + keypad(stdscr, TRUE); + halfdelay(5); + use_default_colors(); + init_pair(1, -1, COLOR_YELLOW); + + do { + gettimeofday(&curtime, NULL); + if(ch != ERR || (curtime.tv_sec - oldtime.tv_sec) >= delay) { + clear(); + top(); + oldtime = curtime; + refresh(); + } + ch = getch(); + } while (handle_key(ch)); + + /* Cleanup occurs in cleanup(), so no work to do here. */ + + return 0; +} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |