Skip to content

Commit

Permalink
xen-balloon: Add interface to retrieve ballooned pages
Browse files Browse the repository at this point in the history
Pages that have been ballooned are useful for other Xen drivers doing
grant table actions, because these pages have valid struct page/PFNs but
have no valid MFN so are available for remapping.

Acked-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
[v2: Deal with rebasing on top of modified balloon code]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
  • Loading branch information
Konrad Rzeszutek Wilk committed Mar 16, 2011
1 parent 803eb04 commit b6f3067
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 6 deletions.
73 changes: 67 additions & 6 deletions drivers/xen/balloon.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,17 @@ static void balloon_append(struct page *page)
}

/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
static struct page *balloon_retrieve(void)
static struct page *balloon_retrieve(bool prefer_highmem)
{
struct page *page;

if (list_empty(&ballooned_pages))
return NULL;

page = list_entry(ballooned_pages.next, struct page, lru);
if (prefer_highmem)
page = list_entry(ballooned_pages.prev, struct page, lru);
else
page = list_entry(ballooned_pages.next, struct page, lru);
list_del(&page->lru);

if (PageHighMem(page)) {
Expand Down Expand Up @@ -233,7 +236,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
return BP_EAGAIN;

for (i = 0; i < rc; i++) {
page = balloon_retrieve();
page = balloon_retrieve(false);
BUG_ON(page == NULL);

pfn = page_to_pfn(page);
Expand Down Expand Up @@ -263,7 +266,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
return BP_DONE;
}

static enum bp_state decrease_reservation(unsigned long nr_pages)
static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
{
enum bp_state state = BP_DONE;
unsigned long pfn, i;
Expand All @@ -279,7 +282,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages)
nr_pages = ARRAY_SIZE(frame_list);

for (i = 0; i < nr_pages; i++) {
if ((page = alloc_page(GFP_BALLOON)) == NULL) {
if ((page = alloc_page(gfp)) == NULL) {
nr_pages = i;
state = BP_EAGAIN;
break;
Expand Down Expand Up @@ -340,7 +343,7 @@ static void balloon_process(struct work_struct *work)
state = increase_reservation(credit);

if (credit < 0)
state = decrease_reservation(-credit);
state = decrease_reservation(-credit, GFP_BALLOON);

state = update_schedule(state);

Expand All @@ -366,6 +369,64 @@ void balloon_set_new_target(unsigned long target)
}
EXPORT_SYMBOL_GPL(balloon_set_new_target);

/**
* alloc_xenballooned_pages - get pages that have been ballooned out
* @nr_pages: Number of pages to get
* @pages: pages returned
* @return 0 on success, error otherwise
*/
int alloc_xenballooned_pages(int nr_pages, struct page** pages)
{
int pgno = 0;
struct page* page;
mutex_lock(&balloon_mutex);
while (pgno < nr_pages) {
page = balloon_retrieve(true);
if (page) {
pages[pgno++] = page;
} else {
enum bp_state st;
st = decrease_reservation(nr_pages - pgno, GFP_HIGHUSER);
if (st != BP_DONE)
goto out_undo;
}
}
mutex_unlock(&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);
return -ENOMEM;
}
EXPORT_SYMBOL(alloc_xenballooned_pages);

/**
* free_xenballooned_pages - return pages retrieved with get_ballooned_pages
* @nr_pages: Number of pages
* @pages: pages to return
*/
void free_xenballooned_pages(int nr_pages, struct page** pages)
{
int i;

mutex_lock(&balloon_mutex);

for (i = 0; i < nr_pages; i++) {
if (pages[i])
balloon_append(pages[i]);
}

/* The balloon may be too large now. Shrink it if needed. */
if (current_target() != balloon_stats.current_pages)
schedule_delayed_work(&balloon_worker, 0);

mutex_unlock(&balloon_mutex);
}
EXPORT_SYMBOL(free_xenballooned_pages);

static int __init balloon_init(void)
{
unsigned long pfn, extra_pfn_end;
Expand Down
3 changes: 3 additions & 0 deletions include/xen/balloon.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ struct balloon_stats {
extern struct balloon_stats balloon_stats;

void balloon_set_new_target(unsigned long target);

int alloc_xenballooned_pages(int nr_pages, struct page** pages);
void free_xenballooned_pages(int nr_pages, struct page** pages);

0 comments on commit b6f3067

Please sign in to comment.