[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] Re: [PATCH 1/3] xen-balloon: Move core balloon functionality out of module



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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.