On Mon, 2011-03-07 at 18:06 +0000, Daniel De Graaf wrote:
> The basic functionality of ballooning pages is useful for Xen drivers in
> general. Rather than require a dependency on the balloon module, split
> the functionality that is reused into the core. The balloon module is
> still required to follow ballooning requests from xenstore or to view
> balloon statistics in sysfs.
>
> Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
balloon vs xen-balloon is a bit non-obvious but then events vs
xen-evtchn and grant-table vs xen-gntdev are arguably even worse. At
least you didn't go for xen-blndev ;-)
Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> ---
> drivers/xen/Makefile | 4 +-
> drivers/xen/balloon.c | 220 +--------------------------------------
> drivers/xen/xen-balloon.c | 249
> +++++++++++++++++++++++++++++++++++++++++++++
> include/xen/balloon.h | 21 ++++
> 4 files changed, 278 insertions(+), 216 deletions(-)
> create mode 100644 drivers/xen/xen-balloon.c
> create mode 100644 include/xen/balloon.h
>
> diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
> index ad8c450..aa3ef62 100644
> --- a/drivers/xen/Makefile
> +++ b/drivers/xen/Makefile
> @@ -1,4 +1,4 @@
> -obj-y += grant-table.o features.o events.o manage.o
> +obj-y += grant-table.o features.o events.o manage.o balloon.o
> obj-y += xenbus/
>
> nostackp := $(call cc-option, -fno-stack-protector)
> @@ -7,7 +7,7 @@ CFLAGS_features.o := $(nostackp)
> obj-$(CONFIG_BLOCK) += biomerge.o
> obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
> obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
> -obj-$(CONFIG_XEN_BALLOON) += balloon.o
> +obj-$(CONFIG_XEN_BALLOON) += xen-balloon.o
> obj-$(CONFIG_XEN_DEV_EVTCHN) += xen-evtchn.o
> obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback/
> obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
> diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
> index 718050a..b0a7a92 100644
> --- a/drivers/xen/balloon.c
> +++ b/drivers/xen/balloon.c
> @@ -1,6 +1,4 @@
>
> /******************************************************************************
> - * balloon.c
> - *
> * Xen balloon driver - enables returning/claiming memory to/from Xen.
> *
> * Copyright (c) 2003, B Dragovic
> @@ -33,7 +31,6 @@
> */
>
> #include <linux/kernel.h>
> -#include <linux/module.h>
> #include <linux/sched.h>
> #include <linux/errno.h>
> #include <linux/mm.h>
> @@ -42,13 +39,11 @@
> #include <linux/highmem.h>
> #include <linux/mutex.h>
> #include <linux/list.h>
> -#include <linux/sysdev.h>
> #include <linux/gfp.h>
>
> #include <asm/page.h>
> #include <asm/pgalloc.h>
> #include <asm/pgtable.h>
> -#include <asm/uaccess.h>
> #include <asm/tlb.h>
> #include <asm/e820.h>
>
> @@ -58,35 +53,16 @@
> #include <xen/xen.h>
> #include <xen/interface/xen.h>
> #include <xen/interface/memory.h>
> -#include <xen/xenbus.h>
> +#include <xen/balloon.h>
> #include <xen/features.h>
> #include <xen/page.h>
>
> #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
>
> -#define BALLOON_CLASS_NAME "xen_memory"
> -
> -struct balloon_stats {
> - /* We aim for 'current allocation' == 'target allocation'. */
> - unsigned long current_pages;
> - unsigned long target_pages;
> - /*
> - * 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;
> -};
> -
> static DEFINE_MUTEX(balloon_mutex);
>
> -static struct sys_device balloon_sysdev;
> -
> -static int register_balloon(struct sys_device *sysdev);
> -
> -static struct balloon_stats balloon_stats;
> +struct balloon_stats balloon_stats;
> +EXPORT_SYMBOL_GPL(balloon_stats);
>
> /* We increase/decrease in batches which fit in a page */
> static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
> @@ -344,51 +320,13 @@ static void balloon_process(struct work_struct *work)
> }
>
> /* Resets the Xen limit, sets new target, and kicks off processing. */
> -static void balloon_set_new_target(unsigned long target)
> +void balloon_set_new_target(unsigned long target)
> {
> /* No need for lock. Not read-modify-write updates. */
> balloon_stats.target_pages = target;
> schedule_work(&balloon_worker);
> }
> -
> -static struct xenbus_watch target_watch =
> -{
> - .node = "memory/target"
> -};
> -
> -/* React to a change in the target key */
> -static void watch_target(struct xenbus_watch *watch,
> - const char **vec, unsigned int len)
> -{
> - unsigned long long new_target;
> - int err;
> -
> - err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
> - if (err != 1) {
> - /* This is ok (for domain0 at least) - so just return */
> - return;
> - }
> -
> - /* The given memory/target value is in KiB, so it needs converting to
> - * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
> - */
> - balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
> -}
> -
> -static int balloon_init_watcher(struct notifier_block *notifier,
> - unsigned long event,
> - void *data)
> -{
> - int err;
> -
> - err = register_xenbus_watch(&target_watch);
> - if (err)
> - printk(KERN_ERR "Failed to set balloon watcher\n");
> -
> - return NOTIFY_DONE;
> -}
> -
> -static struct notifier_block xenstore_notifier;
> +EXPORT_SYMBOL_GPL(balloon_set_new_target);
>
> static int __init balloon_init(void)
> {
> @@ -398,7 +336,7 @@ static int __init balloon_init(void)
> if (!xen_domain())
> return -ENODEV;
>
> - pr_info("xen_balloon: Initialising balloon driver.\n");
> + pr_info("xen/balloon: Initialising balloon driver.\n");
>
> if (xen_pv_domain())
> nr_pages = xen_start_info->nr_pages;
> @@ -414,8 +352,6 @@ static int __init balloon_init(void)
> balloon_timer.data = 0;
> balloon_timer.function = balloon_alarm;
>
> - register_balloon(&balloon_sysdev);
> -
> /*
> * Initialise the balloon with excess memory space. We need
> * to make sure we don't add memory which doesn't exist or
> @@ -436,153 +372,9 @@ static int __init balloon_init(void)
> __balloon_append(page);
> }
>
> - target_watch.callback = watch_target;
> - xenstore_notifier.notifier_call = balloon_init_watcher;
> -
> - register_xenstore_notifier(&xenstore_notifier);
> -
> return 0;
> }
>
> subsys_initcall(balloon_init);
>
> -static void balloon_exit(void)
> -{
> - /* XXX - release balloon here */
> - return;
> -}
> -
> -module_exit(balloon_exit);
> -
> -#define BALLOON_SHOW(name, format, args...) \
> - static ssize_t show_##name(struct sys_device *dev, \
> - struct sysdev_attribute *attr, \
> - char *buf) \
> - { \
> - return sprintf(buf, format, ##args); \
> - } \
> - static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
> -
> -BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
> -BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
> -BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
> -BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
> -
> -static ssize_t show_target_kb(struct sys_device *dev, struct
> sysdev_attribute *attr,
> - char *buf)
> -{
> - return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
> -}
> -
> -static ssize_t store_target_kb(struct sys_device *dev,
> - struct sysdev_attribute *attr,
> - const char *buf,
> - size_t count)
> -{
> - char *endchar;
> - unsigned long long target_bytes;
> -
> - if (!capable(CAP_SYS_ADMIN))
> - return -EPERM;
> -
> - target_bytes = simple_strtoull(buf, &endchar, 0) * 1024;
> -
> - 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 ssize_t show_target(struct sys_device *dev, struct sysdev_attribute
> *attr,
> - char *buf)
> -{
> - return sprintf(buf, "%llu\n",
> - (unsigned long long)balloon_stats.target_pages
> - << PAGE_SHIFT);
> -}
> -
> -static ssize_t store_target(struct sys_device *dev,
> - struct sysdev_attribute *attr,
> - const char *buf,
> - size_t count)
> -{
> - char *endchar;
> - unsigned long long target_bytes;
> -
> - if (!capable(CAP_SYS_ADMIN))
> - return -EPERM;
> -
> - target_bytes = memparse(buf, &endchar);
> -
> - balloon_set_new_target(target_bytes >> PAGE_SHIFT);
> -
> - return count;
> -}
> -
> -static SYSDEV_ATTR(target, S_IRUGO | S_IWUSR,
> - show_target, store_target);
> -
> -
> -static struct sysdev_attribute *balloon_attrs[] = {
> - &attr_target_kb,
> - &attr_target,
> -};
> -
> -static struct attribute *balloon_info_attrs[] = {
> - &attr_current_kb.attr,
> - &attr_low_kb.attr,
> - &attr_high_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 = {
> - .name = BALLOON_CLASS_NAME,
> -};
> -
> -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;
> -}
> -
> MODULE_LICENSE("GPL");
> diff --git a/drivers/xen/xen-balloon.c b/drivers/xen/xen-balloon.c
> new file mode 100644
> index 0000000..59dfd79
> --- /dev/null
> +++ b/drivers/xen/xen-balloon.c
> @@ -0,0 +1,249 @@
> +/******************************************************************************
> + * Xen balloon driver - enables returning/claiming memory to/from Xen.
> + *
> + * Copyright (c) 2003, B Dragovic
> + * Copyright (c) 2003-2004, M Williamson, K Fraser
> + * Copyright (c) 2005 Dan M. Smith, IBM Corporation
> + *
> + * 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/kernel.h>
> +#include <linux/module.h>
> +#include <linux/sysdev.h>
> +#include <linux/capability.h>
> +
> +#include <xen/xen.h>
> +#include <xen/interface/xen.h>
> +#include <xen/balloon.h>
> +#include <xen/xenbus.h>
> +#include <xen/features.h>
> +#include <xen/page.h>
> +
> +#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
> +
> +#define BALLOON_CLASS_NAME "xen_memory"
> +
> +static struct sys_device balloon_sysdev;
> +
> +static int register_balloon(struct sys_device *sysdev);
> +
> +static struct xenbus_watch target_watch =
> +{
> + .node = "memory/target"
> +};
> +
> +/* React to a change in the target key */
> +static void watch_target(struct xenbus_watch *watch,
> + const char **vec, unsigned int len)
> +{
> + unsigned long long new_target;
> + int err;
> +
> + err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
> + if (err != 1) {
> + /* This is ok (for domain0 at least) - so just return */
> + return;
> + }
> +
> + /* The given memory/target value is in KiB, so it needs converting to
> + * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
> + */
> + balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
> +}
> +
> +static int balloon_init_watcher(struct notifier_block *notifier,
> + unsigned long event,
> + void *data)
> +{
> + int err;
> +
> + err = register_xenbus_watch(&target_watch);
> + if (err)
> + printk(KERN_ERR "Failed to set balloon watcher\n");
> +
> + return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block xenstore_notifier;
> +
> +static int __init balloon_init(void)
> +{
> + if (!xen_domain())
> + return -ENODEV;
> +
> + pr_info("xen-balloon: Initialising balloon driver.\n");
> +
> + register_balloon(&balloon_sysdev);
> +
> + target_watch.callback = watch_target;
> + xenstore_notifier.notifier_call = balloon_init_watcher;
> +
> + register_xenstore_notifier(&xenstore_notifier);
> +
> + return 0;
> +}
> +subsys_initcall(balloon_init);
> +
> +static void balloon_exit(void)
> +{
> + /* XXX unregister? */
> + return;
> +}
> +
> +module_exit(balloon_exit);
> +
> +#define BALLOON_SHOW(name, format, args...) \
> + static ssize_t show_##name(struct sys_device *dev, \
> + struct sysdev_attribute *attr, \
> + char *buf) \
> + { \
> + return sprintf(buf, format, ##args); \
> + } \
> + static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
> +
> +BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
> +BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
> +BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
> +BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
> +
> +static ssize_t show_target_kb(struct sys_device *dev, struct
> sysdev_attribute *attr,
> + char *buf)
> +{
> + return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
> +}
> +
> +static ssize_t store_target_kb(struct sys_device *dev,
> + struct sysdev_attribute *attr,
> + const char *buf,
> + size_t count)
> +{
> + char *endchar;
> + unsigned long long target_bytes;
> +
> + if (!capable(CAP_SYS_ADMIN))
> + return -EPERM;
> +
> + target_bytes = simple_strtoull(buf, &endchar, 0) * 1024;
> +
> + 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 ssize_t show_target(struct sys_device *dev, struct sysdev_attribute
> *attr,
> + char *buf)
> +{
> + return sprintf(buf, "%llu\n",
> + (unsigned long long)balloon_stats.target_pages
> + << PAGE_SHIFT);
> +}
> +
> +static ssize_t store_target(struct sys_device *dev,
> + struct sysdev_attribute *attr,
> + const char *buf,
> + size_t count)
> +{
> + char *endchar;
> + unsigned long long target_bytes;
> +
> + if (!capable(CAP_SYS_ADMIN))
> + return -EPERM;
> +
> + target_bytes = memparse(buf, &endchar);
> +
> + balloon_set_new_target(target_bytes >> PAGE_SHIFT);
> +
> + return count;
> +}
> +
> +static SYSDEV_ATTR(target, S_IRUGO | S_IWUSR,
> + show_target, store_target);
> +
> +
> +static struct sysdev_attribute *balloon_attrs[] = {
> + &attr_target_kb,
> + &attr_target,
> +};
> +
> +static struct attribute *balloon_info_attrs[] = {
> + &attr_current_kb.attr,
> + &attr_low_kb.attr,
> + &attr_high_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 = {
> + .name = BALLOON_CLASS_NAME,
> +};
> +
> +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;
> +}
> +
> +MODULE_LICENSE("GPL");
> diff --git a/include/xen/balloon.h b/include/xen/balloon.h
> new file mode 100644
> index 0000000..b2b7c21
> --- /dev/null
> +++ b/include/xen/balloon.h
> @@ -0,0 +1,21 @@
> +/******************************************************************************
> + * Xen balloon functionality
> + */
> +
> +struct balloon_stats {
> + /* We aim for 'current allocation' == 'target allocation'. */
> + unsigned long current_pages;
> + unsigned long target_pages;
> + /*
> + * 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;
> +
> +void balloon_set_new_target(unsigned long target);
> --
> 1.7.3.4
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|