BP_ECANCELED
};
-
-static DEFINE_MUTEX(balloon_mutex);
-
-struct balloon_stats balloon_stats;
-EXPORT_SYMBOL_GPL(balloon_stats);
+struct xen_balloon xen_balloon;
+EXPORT_SYMBOL_GPL(xen_balloon);
/* We increase/decrease in batches which fit in a page */
static xen_pfn_t frame_list[PAGE_SIZE / sizeof(unsigned long)];
static DEFINE_PER_CPU(struct page *, balloon_scratch_page);
-
-/* List of ballooned pages, threaded through the mem_map array. */
-static LIST_HEAD(ballooned_pages);
-
/* Main work function, always executed in process context. */
static void balloon_process(struct work_struct *work);
static DECLARE_DELAYED_WORK(balloon_worker, balloon_process);
{
/* Lowmem is re-populated first, so highmem pages go at list tail. */
if (PageHighMem(page)) {
- list_add_tail(&page->lru, &ballooned_pages);
- balloon_stats.balloon_high++;
+ list_add_tail(&page->lru, &xen_balloon.ballooned_pages);
+ xen_balloon.balloon_stats.balloon_high++;
} else {
- list_add(&page->lru, &ballooned_pages);
- balloon_stats.balloon_low++;
+ list_add(&page->lru, &xen_balloon.ballooned_pages);
+ xen_balloon.balloon_stats.balloon_low++;
}
}
{
struct page *page;
- if (list_empty(&ballooned_pages))
+ if (list_empty(&xen_balloon.ballooned_pages))
return NULL;
if (prefer_highmem)
- page = list_entry(ballooned_pages.prev, struct page, lru);
+ page = list_entry(xen_balloon.ballooned_pages.prev,
+ struct page, lru);
else
- page = list_entry(ballooned_pages.next, struct page, lru);
+ page = list_entry(xen_balloon.ballooned_pages.next,
+ struct page, lru);
list_del(&page->lru);
if (PageHighMem(page))
- balloon_stats.balloon_high--;
+ xen_balloon.balloon_stats.balloon_high--;
else
- balloon_stats.balloon_low--;
+ xen_balloon.balloon_stats.balloon_low--;
adjust_managed_page_count(page, 1);
static struct page *balloon_next_page(struct page *page)
{
struct list_head *next = page->lru.next;
- if (next == &ballooned_pages)
+ if (next == &xen_balloon.ballooned_pages)
return NULL;
return list_entry(next, struct page, lru);
}
static enum bp_state update_schedule(enum bp_state state)
{
if (state == BP_DONE) {
- balloon_stats.schedule_delay = 1;
- balloon_stats.retry_count = 1;
+ xen_balloon.balloon_stats.schedule_delay = 1;
+ xen_balloon.balloon_stats.retry_count = 1;
return BP_DONE;
}
- ++balloon_stats.retry_count;
+ ++xen_balloon.balloon_stats.retry_count;
- if (balloon_stats.max_retry_count != RETRY_UNLIMITED &&
- balloon_stats.retry_count > balloon_stats.max_retry_count) {
- balloon_stats.schedule_delay = 1;
- balloon_stats.retry_count = 1;
+ if (xen_balloon.balloon_stats.max_retry_count != RETRY_UNLIMITED &&
+ xen_balloon.balloon_stats.retry_count >
+ xen_balloon.balloon_stats.max_retry_count) {
+ xen_balloon.balloon_stats.schedule_delay = 1;
+ xen_balloon.balloon_stats.retry_count = 1;
return BP_ECANCELED;
}
- balloon_stats.schedule_delay <<= 1;
+ xen_balloon.balloon_stats.schedule_delay <<= 1;
- if (balloon_stats.schedule_delay > balloon_stats.max_schedule_delay)
- balloon_stats.schedule_delay = balloon_stats.max_schedule_delay;
+ if (xen_balloon.balloon_stats.schedule_delay >
+ xen_balloon.balloon_stats.max_schedule_delay)
+ xen_balloon.balloon_stats.schedule_delay =
+ xen_balloon.balloon_stats.max_schedule_delay;
return BP_EAGAIN;
}
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
static long current_credit(void)
{
- return balloon_stats.target_pages - balloon_stats.current_pages -
- balloon_stats.hotplug_pages;
+ return xen_balloon.balloon_stats.target_pages -
+ xen_balloon.balloon_stats.current_pages -
+ xen_balloon.balloon_stats.hotplug_pages;
}
static bool balloon_is_inflated(void)
{
- if (balloon_stats.balloon_low || balloon_stats.balloon_high ||
- balloon_stats.balloon_hotplug)
+ if (xen_balloon.balloon_stats.balloon_low ||
+ xen_balloon.balloon_stats.balloon_high ||
+ xen_balloon.balloon_stats.balloon_hotplug)
return true;
else
return false;
balloon_hotplug -= credit;
- balloon_stats.hotplug_pages += credit;
- balloon_stats.balloon_hotplug = balloon_hotplug;
+ xen_balloon.balloon_stats.hotplug_pages += credit;
+ xen_balloon.balloon_stats.balloon_hotplug = balloon_hotplug;
return BP_DONE;
}
{
__online_page_set_limits(page);
- mutex_lock(&balloon_mutex);
+ mutex_lock(&xen_balloon.balloon_mutex);
__balloon_append(page);
- if (balloon_stats.hotplug_pages)
- --balloon_stats.hotplug_pages;
+ if (xen_balloon.balloon_stats.hotplug_pages)
+ --xen_balloon.balloon_stats.hotplug_pages;
else
- --balloon_stats.balloon_hotplug;
+ --xen_balloon.balloon_stats.balloon_hotplug;
- mutex_unlock(&balloon_mutex);
+ mutex_unlock(&xen_balloon.balloon_mutex);
}
static int xen_memory_notifier(struct notifier_block *nb, unsigned long val, void *v)
#else
static long current_credit(void)
{
- unsigned long target = balloon_stats.target_pages;
+ unsigned long target = xen_balloon.balloon_stats.target_pages;
target = min(target,
- balloon_stats.current_pages +
- balloon_stats.balloon_low +
- balloon_stats.balloon_high);
+ xen_balloon.balloon_stats.current_pages +
+ xen_balloon.balloon_stats.balloon_low +
+ xen_balloon.balloon_stats.balloon_high);
- return target - balloon_stats.current_pages;
+ return target - xen_balloon.balloon_stats.current_pages;
}
static bool balloon_is_inflated(void)
{
- if (balloon_stats.balloon_low || balloon_stats.balloon_high)
+ if (xen_balloon.balloon_stats.balloon_low ||
+ xen_balloon.balloon_stats.balloon_high)
return true;
else
return false;
static enum bp_state reserve_additional_memory(long credit)
{
- balloon_stats.target_pages = balloon_stats.current_pages;
+ xen_balloon.balloon_stats.target_pages =
+ xen_balloon.balloon_stats.current_pages;
return BP_DONE;
}
#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
};
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
- if (!balloon_stats.balloon_low && !balloon_stats.balloon_high) {
- nr_pages = min(nr_pages, balloon_stats.balloon_hotplug);
- balloon_stats.hotplug_pages += nr_pages;
- balloon_stats.balloon_hotplug -= nr_pages;
+ if (!xen_balloon.balloon_stats.balloon_low &&
+ !xen_balloon.balloon_stats.balloon_high) {
+ nr_pages = min(nr_pages,
+ xen_balloon.balloon_stats.balloon_hotplug);
+ xen_balloon.balloon_stats.hotplug_pages += nr_pages;
+ xen_balloon.balloon_stats.balloon_hotplug -= nr_pages;
return BP_DONE;
}
#endif
if (nr_pages > ARRAY_SIZE(frame_list))
nr_pages = ARRAY_SIZE(frame_list);
- page = list_first_entry_or_null(&ballooned_pages, struct page, lru);
+ page = list_first_entry_or_null(&xen_balloon.ballooned_pages,
+ struct page, lru);
for (i = 0; i < nr_pages; i++) {
if (!page) {
nr_pages = i;
__free_reserved_page(page);
}
- balloon_stats.current_pages += rc;
+ xen_balloon.balloon_stats.current_pages += rc;
return BP_DONE;
}
};
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
- if (balloon_stats.hotplug_pages) {
- nr_pages = min(nr_pages, balloon_stats.hotplug_pages);
- balloon_stats.hotplug_pages -= nr_pages;
- balloon_stats.balloon_hotplug += nr_pages;
+ if (xen_balloon.balloon_stats.hotplug_pages) {
+ nr_pages = min(nr_pages,
+ xen_balloon.balloon_stats.hotplug_pages);
+ xen_balloon.balloon_stats.hotplug_pages -= nr_pages;
+ xen_balloon.balloon_stats.balloon_hotplug += nr_pages;
return BP_DONE;
}
#endif
ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
BUG_ON(ret != nr_pages);
- balloon_stats.current_pages -= nr_pages;
+ xen_balloon.balloon_stats.current_pages -= nr_pages;
return state;
}
enum bp_state state = BP_DONE;
long credit;
- mutex_lock(&balloon_mutex);
+ mutex_lock(&xen_balloon.balloon_mutex);
do {
credit = current_credit();
/* Schedule more work if there is some still to be done. */
if (state == BP_EAGAIN)
- schedule_delayed_work(&balloon_worker, balloon_stats.schedule_delay * HZ);
+ schedule_delayed_work(&balloon_worker,
+ xen_balloon.balloon_stats.schedule_delay * HZ);
- mutex_unlock(&balloon_mutex);
+ mutex_unlock(&xen_balloon.balloon_mutex);
}
struct page *get_balloon_scratch_page(void)
void balloon_set_new_target(unsigned long target)
{
/* No need for lock. Not read-modify-write updates. */
- balloon_stats.target_pages = target;
+ xen_balloon.balloon_stats.target_pages = target;
schedule_delayed_work(&balloon_worker, 0);
}
EXPORT_SYMBOL_GPL(balloon_set_new_target);
{
int pgno = 0;
struct page *page;
- mutex_lock(&balloon_mutex);
+ mutex_lock(&xen_balloon.balloon_mutex);
while (pgno < nr_pages) {
page = balloon_retrieve(highmem);
if (page && (highmem || !PageHighMem(page))) {
goto out_undo;
}
}
- mutex_unlock(&balloon_mutex);
+ mutex_unlock(&xen_balloon.balloon_mutex);
return 0;
out_undo:
while (pgno)
balloon_append(pages[--pgno]);
/* Free the memory back to the kernel soon */
schedule_delayed_work(&balloon_worker, 0);
- mutex_unlock(&balloon_mutex);
+ mutex_unlock(&xen_balloon.balloon_mutex);
return -ENOMEM;
}
EXPORT_SYMBOL(alloc_xenballooned_pages);
{
int i;
- mutex_lock(&balloon_mutex);
+ mutex_lock(&xen_balloon.balloon_mutex);
for (i = 0; i < nr_pages; i++) {
if (pages[i])
if (current_credit())
schedule_delayed_work(&balloon_worker, 0);
- mutex_unlock(&balloon_mutex);
+ mutex_unlock(&xen_balloon.balloon_mutex);
}
EXPORT_SYMBOL(free_xenballooned_pages);
pr_info("Initialising balloon driver\n");
- balloon_stats.current_pages = xen_pv_domain()
+ memset(&xen_balloon, 0, sizeof(xen_balloon));
+
+ mutex_init(&xen_balloon.balloon_mutex);
+
+ INIT_LIST_HEAD(&xen_balloon.ballooned_pages);
+
+ xen_balloon.balloon_stats.current_pages = xen_pv_domain()
? min(xen_start_info->nr_pages - xen_released_pages, max_pfn)
: get_num_physpages();
- balloon_stats.target_pages = balloon_stats.current_pages;
- balloon_stats.balloon_low = 0;
- balloon_stats.balloon_high = 0;
+ xen_balloon.balloon_stats.target_pages =
+ xen_balloon.balloon_stats.current_pages;
+ xen_balloon.balloon_stats.balloon_low = 0;
+ xen_balloon.balloon_stats.balloon_high = 0;
- balloon_stats.schedule_delay = 1;
- balloon_stats.max_schedule_delay = 32;
- balloon_stats.retry_count = 1;
- balloon_stats.max_retry_count = RETRY_UNLIMITED;
+ xen_balloon.balloon_stats.schedule_delay = 1;
+ xen_balloon.balloon_stats.max_schedule_delay = 32;
+ xen_balloon.balloon_stats.retry_count = 1;
+ xen_balloon.balloon_stats.max_retry_count = RETRY_UNLIMITED;
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
- balloon_stats.hotplug_pages = 0;
- balloon_stats.balloon_hotplug = 0;
+ xen_balloon.balloon_stats.hotplug_pages = 0;
+ xen_balloon.balloon_stats.balloon_hotplug = 0;
set_online_page_callback(&xen_online_page);
register_memory_notifier(&xen_memory_nb);