[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [BALLOON] Add a sysfs interface.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID 93f0957e02ce59777167d46adf1c37e290194c32 # Parent c6747b81d30814a8b3fcfed45a891072df38075c [BALLOON] Add a sysfs interface. Information is located under /sys/devices/system/memory. Original patch from Satoshi UCHIDA <s-uchida@xxxxxxxxxxxxx> Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- linux-2.6-xen-sparse/drivers/xen/balloon/Makefile | 2 linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c | 91 +++++------ linux-2.6-xen-sparse/drivers/xen/balloon/common.h | 58 +++++++ linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c | 165 +++++++++++++++++++++ 4 files changed, 264 insertions(+), 52 deletions(-) diff -r c6747b81d308 -r 93f0957e02ce linux-2.6-xen-sparse/drivers/xen/balloon/Makefile --- a/linux-2.6-xen-sparse/drivers/xen/balloon/Makefile Mon Oct 23 13:10:24 2006 +0100 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/Makefile Mon Oct 23 14:09:01 2006 +0100 @@ -1,2 +1,2 @@ -obj-y += balloon.o +obj-y := balloon.o sysfs.o diff -r c6747b81d308 -r 93f0957e02ce linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Mon Oct 23 13:10:24 2006 +0100 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Mon Oct 23 14:09:01 2006 +0100 @@ -53,10 +53,8 @@ #include <asm/uaccess.h> #include <asm/tlb.h> #include <linux/list.h> - #include <xen/xenbus.h> - -#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) +#include "common.h" #ifdef CONFIG_PROC_FS static struct proc_dir_entry *balloon_pde; @@ -71,9 +69,7 @@ static DECLARE_MUTEX(balloon_mutex); */ DEFINE_SPINLOCK(balloon_lock); -/* We aim for 'current allocation' == 'target allocation'. */ -static unsigned long current_pages; -static unsigned long target_pages; +struct balloon_stats balloon_stats; /* We increase/decrease in batches which fit in a page */ static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)]; @@ -81,18 +77,8 @@ static unsigned long frame_list[PAGE_SIZ /* VM /proc information for memory */ extern unsigned long totalram_pages; -/* We may hit the hard limit in Xen. If we do then we remember it. */ -static unsigned long hard_limit; - -/* - * Drivers may alter the memory reservation independently, but they must - * inform the balloon driver so that we can avoid hitting the hard limit. - */ -static unsigned long driver_pages; - /* List of ballooned pages, threaded through the mem_map array. */ static LIST_HEAD(ballooned_pages); -static unsigned long balloon_low, balloon_high; /* Main work function, always executed in process context. */ static void balloon_process(void *unused); @@ -124,10 +110,10 @@ static void balloon_append(struct page * /* 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++; + bs.balloon_high++; } else { list_add(PAGE_TO_LIST(page), &ballooned_pages); - balloon_low++; + bs.balloon_low++; } } @@ -143,9 +129,9 @@ static struct page *balloon_retrieve(voi UNLIST_PAGE(page); if (PageHighMem(page)) - balloon_high--; + bs.balloon_high--; else - balloon_low--; + bs.balloon_low--; return page; } @@ -172,9 +158,9 @@ static void balloon_alarm(unsigned long 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; + unsigned long target = min(bs.target_pages, bs.hard_limit); + if (target > (bs.current_pages + bs.balloon_low + bs.balloon_high)) + target = bs.current_pages + bs.balloon_low + bs.balloon_high; return target; } @@ -216,7 +202,8 @@ static int increase_reservation(unsigned BUG_ON(ret != rc); } if (rc >= 0) - hard_limit = current_pages + rc - driver_pages; + bs.hard_limit = (bs.current_pages + rc - + bs.driver_pages); goto out; } @@ -248,8 +235,8 @@ static int increase_reservation(unsigned __free_page(page); } - current_pages += nr_pages; - totalram_pages = current_pages; + bs.current_pages += nr_pages; + totalram_pages = bs.current_pages; out: balloon_unlock(flags); @@ -317,8 +304,8 @@ static int decrease_reservation(unsigned ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation); BUG_ON(ret != nr_pages); - current_pages -= nr_pages; - totalram_pages = current_pages; + bs.current_pages -= nr_pages; + totalram_pages = bs.current_pages; balloon_unlock(flags); @@ -339,7 +326,7 @@ static void balloon_process(void *unused down(&balloon_mutex); do { - credit = current_target() - current_pages; + credit = current_target() - bs.current_pages; if (credit > 0) need_sleep = (increase_reservation(credit) != 0); if (credit < 0) @@ -352,18 +339,18 @@ static void balloon_process(void *unused } while ((credit != 0) && !need_sleep); /* Schedule more work if there is some still to be done. */ - if (current_target() != current_pages) + if (current_target() != bs.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) +void balloon_set_new_target(unsigned long target) { /* No need for lock. Not read-modify-write updates. */ - hard_limit = ~0UL; - target_pages = target; + bs.hard_limit = ~0UL; + bs.target_pages = target; schedule_work(&balloon_worker); } @@ -388,7 +375,7 @@ static void watch_target(struct xenbus_w /* The given memory/target value is in KiB, so it needs converting to * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10. */ - set_new_target(new_target >> (PAGE_SHIFT - 10)); + balloon_set_new_target(new_target >> (PAGE_SHIFT - 10)); } static int balloon_init_watcher(struct notifier_block *notifier, @@ -424,7 +411,7 @@ static int balloon_write(struct file *fi memstring[sizeof(memstring)-1] = '\0'; target_bytes = memparse(memstring, &endchar); - set_new_target(target_bytes >> PAGE_SHIFT); + balloon_set_new_target(target_bytes >> PAGE_SHIFT); return count; } @@ -442,12 +429,13 @@ static int balloon_read(char *page, char "High-mem balloon: %8lu kB\n" "Driver pages: %8lu kB\n" "Xen hard limit: ", - PAGES2KB(current_pages), PAGES2KB(target_pages), - PAGES2KB(balloon_low), PAGES2KB(balloon_high), - PAGES2KB(driver_pages)); - - if (hard_limit != ~0UL) - len += sprintf(page + len, "%8lu kB\n", PAGES2KB(hard_limit)); + PAGES2KB(bs.current_pages), PAGES2KB(bs.target_pages), + PAGES2KB(bs.balloon_low), PAGES2KB(bs.balloon_high), + PAGES2KB(bs.driver_pages)); + + if (bs.hard_limit != ~0UL) + len += sprintf(page + len, "%8lu kB\n", + PAGES2KB(bs.hard_limit)); else len += sprintf(page + len, " ??? kB\n"); @@ -468,13 +456,13 @@ static int __init balloon_init(void) IPRINTK("Initialising balloon driver.\n"); - current_pages = min(xen_start_info->nr_pages, max_pfn); - totalram_pages = current_pages; - target_pages = current_pages; - balloon_low = 0; - balloon_high = 0; - driver_pages = 0UL; - hard_limit = ~0UL; + bs.current_pages = min(xen_start_info->nr_pages, max_pfn); + totalram_pages = bs.current_pages; + bs.target_pages = bs.current_pages; + bs.balloon_low = 0; + bs.balloon_high = 0; + bs.driver_pages = 0UL; + bs.hard_limit = ~0UL; init_timer(&balloon_timer); balloon_timer.data = 0; @@ -489,6 +477,7 @@ static int __init balloon_init(void) balloon_pde->read_proc = balloon_read; balloon_pde->write_proc = balloon_write; #endif + balloon_sysfs_init(); /* Initialise the balloon with excess memory space. */ for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) { @@ -512,7 +501,7 @@ void balloon_update_driver_allowance(lon unsigned long flags; balloon_lock(flags); - driver_pages += delta; + bs.driver_pages += delta; balloon_unlock(flags); } @@ -578,7 +567,7 @@ struct page **alloc_empty_pages_and_page goto err; } - totalram_pages = --current_pages; + totalram_pages = --bs.current_pages; balloon_unlock(flags); } @@ -624,7 +613,7 @@ void balloon_release_driver_page(struct balloon_lock(flags); balloon_append(page); - driver_pages--; + bs.driver_pages--; balloon_unlock(flags); schedule_work(&balloon_worker); diff -r c6747b81d308 -r 93f0957e02ce linux-2.6-xen-sparse/drivers/xen/balloon/common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/common.h Mon Oct 23 14:09:01 2006 +0100 @@ -0,0 +1,58 @@ +/****************************************************************************** + * balloon/common.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __XEN_BALLOON_COMMON_H__ +#define __XEN_BALLOON_COMMON_H__ + +#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) + +struct balloon_stats { + /* We aim for 'current allocation' == 'target allocation'. */ + unsigned long current_pages; + unsigned long target_pages; + /* We may hit the hard limit in Xen. If we do then we remember it. */ + unsigned long hard_limit; + /* + * Drivers may alter the memory reservation independently, but they + * must inform the balloon driver so we avoid hitting the hard limit. + */ + unsigned long driver_pages; + /* Number of pages in high- and low-memory balloons. */ + unsigned long balloon_low; + unsigned long balloon_high; +}; + +extern struct balloon_stats balloon_stats; +#define bs balloon_stats + +int balloon_sysfs_init(void); +void balloon_sysfs_exit(void); + +void balloon_set_new_target(unsigned long target); + +#endif /* __XEN_BALLOON_COMMON_H__ */ diff -r c6747b81d308 -r 93f0957e02ce linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c Mon Oct 23 14:09:01 2006 +0100 @@ -0,0 +1,165 @@ +/****************************************************************************** + * balloon/sysfs.c + * + * Xen balloon driver - sysfs interfaces. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <linux/config.h> +#include <linux/capability.h> +#include <linux/stat.h> +#include <linux/sysdev.h> +#include "common.h" + +#define BALLOON_CLASS_NAME "memory" + +#define BALLOON_SHOW(name, format, args...) \ + static ssize_t show_##name(struct sys_device *dev, \ + char *buf) \ + { \ + return sprintf(buf, format, ##args); \ + } \ + static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL) + +BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(bs.current_pages)); +BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(bs.balloon_low)); +BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(bs.balloon_high)); +BALLOON_SHOW(hard_limit_kb, + (bs.hard_limit!=~0UL) ? "%lu\n" : "???\n", + (bs.hard_limit!=~0UL) ? PAGES2KB(bs.hard_limit) : 0); +BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(bs.driver_pages)); + +static ssize_t show_target_kb(struct sys_device *dev, char *buf) +{ + return sprintf(buf, "%lu\n", PAGES2KB(bs.target_pages)); +} + +static ssize_t store_target_kb(struct sys_device *dev, + const char *buf, + size_t 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 */ + strcpy(memstring, buf); + + target_bytes = memparse(memstring, &endchar); + balloon_set_new_target(target_bytes >> PAGE_SHIFT); + + return count; +} + +static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR, + show_target_kb, store_target_kb); + +static struct sysdev_attribute *balloon_attrs[] = { + &attr_target_kb, +}; + +static struct attribute *balloon_info_attrs[] = { + &attr_current_kb.attr, + &attr_low_kb.attr, + &attr_high_kb.attr, + &attr_hard_limit_kb.attr, + &attr_driver_kb.attr, + NULL +}; + +static struct attribute_group balloon_info_group = { + .name = "info", + .attrs = balloon_info_attrs, +}; + +static struct sysdev_class balloon_sysdev_class = { + set_kset_name(BALLOON_CLASS_NAME), +}; + +static struct sys_device balloon_sysdev; + +static int register_balloon(struct sys_device *sysdev) +{ + int i, error; + + error = sysdev_class_register(&balloon_sysdev_class); + if (error) + return error; + + sysdev->id = 0; + sysdev->cls = &balloon_sysdev_class; + + error = sysdev_register(sysdev); + if (error) { + sysdev_class_unregister(&balloon_sysdev_class); + return error; + } + + for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) { + error = sysdev_create_file(sysdev, balloon_attrs[i]); + if (error) + goto fail; + } + + error = sysfs_create_group(&sysdev->kobj, &balloon_info_group); + if (error) + goto fail; + + return 0; + + fail: + while (--i >= 0) + sysdev_remove_file(sysdev, balloon_attrs[i]); + sysdev_unregister(sysdev); + sysdev_class_unregister(&balloon_sysdev_class); + return error; +} + +static void unregister_balloon(struct sys_device *sysdev) +{ + int i; + + sysfs_remove_group(&sysdev->kobj, &balloon_info_group); + for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) + sysdev_remove_file(sysdev, balloon_attrs[i]); + sysdev_unregister(sysdev); + sysdev_class_unregister(&balloon_sysdev_class); +} + +int balloon_sysfs_init(void) +{ + return register_balloon(&balloon_sysdev); +} + +void balloon_sysfs_exit(void) +{ + unregister_balloon(&balloon_sysdev); +} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |