aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2006-10-06 11:52:41 +0100
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2006-10-06 11:52:41 +0100
commit431414939662f36e8f09346ceeddfca7102fcc65 (patch)
treea1df4141d4a81bc020e9104deff0f535ddd2f7ff
parentdb002ee4a03f1d5a0df42d3f25bcc21257ae20f6 (diff)
downloadxen-431414939662f36e8f09346ceeddfca7102fcc65.tar.gz
xen-431414939662f36e8f09346ceeddfca7102fcc65.tar.bz2
xen-431414939662f36e8f09346ceeddfca7102fcc65.zip
[BALLOON] Replace alloc_empty_page_range with new helper alloc_empty_pages_and_pagevec.
This is a better fit with all the callers, who now allocate discontiguous empty pages. Signed-off-by: Keir Fraser <keir@xensource.com>
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c125
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c15
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c29
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/netback/netback.c22
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c28
-rw-r--r--linux-2.6-xen-sparse/include/xen/balloon.h12
6 files changed, 86 insertions, 145 deletions
diff --git a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
index ad39655661..f4a7d4b398 100644
--- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
+++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
@@ -534,87 +534,88 @@ static int dealloc_pte_fn(
return 0;
}
-struct page *balloon_alloc_empty_page_range(unsigned long nr_pages)
+struct page **alloc_empty_pages_and_pagevec(int nr_pages)
{
- unsigned long vstart, flags;
- unsigned int order = get_order(nr_pages * PAGE_SIZE);
- int ret;
- unsigned long i;
- struct page *page;
+ unsigned long vaddr, flags;
+ struct page *page, **pagevec;
+ int i, ret;
- vstart = __get_free_pages(GFP_KERNEL, order);
- if (vstart == 0)
+ pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL);
+ if (pagevec == NULL)
return NULL;
- scrub_pages(vstart, 1 << order);
-
- balloon_lock(flags);
- if (xen_feature(XENFEAT_auto_translated_physmap)) {
- unsigned long gmfn = __pa(vstart) >> PAGE_SHIFT;
- struct xen_memory_reservation reservation = {
- .nr_extents = 1,
- .extent_order = order,
- .domid = DOMID_SELF
- };
- set_xen_guest_handle(reservation.extent_start, &gmfn);
- ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
- &reservation);
- if (ret == -ENOSYS)
- goto err;
- BUG_ON(ret != 1);
- } else {
- ret = apply_to_page_range(&init_mm, vstart, PAGE_SIZE << order,
- dealloc_pte_fn, NULL);
- if (ret == -ENOSYS)
+ for (i = 0; i < nr_pages; i++) {
+ page = pagevec[i] = alloc_page(GFP_KERNEL);
+ if (page == NULL)
goto err;
- BUG_ON(ret);
- }
- current_pages -= 1UL << order;
- totalram_pages = current_pages;
- balloon_unlock(flags);
- schedule_work(&balloon_worker);
+ vaddr = (unsigned long)page_address(page);
- flush_tlb_all();
+ scrub_pages(vaddr, 1);
- page = virt_to_page(vstart);
+ balloon_lock(flags);
- for (i = 0; i < (1UL << order); i++)
- set_page_count(page + i, 1);
+ if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ unsigned long gmfn = page_to_pfn(page);
+ struct xen_memory_reservation reservation = {
+ .nr_extents = 1,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ };
+ set_xen_guest_handle(reservation.extent_start, &gmfn);
+ ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+ &reservation);
+ if (ret == 1)
+ ret = 0; /* success */
+ } else {
+ ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE,
+ dealloc_pte_fn, NULL);
+ }
- return page;
+ if (ret != 0) {
+ balloon_unlock(flags);
+ __free_page(page);
+ goto err;
+ }
+
+ totalram_pages = --current_pages;
+
+ balloon_unlock(flags);
+ }
+
+ out:
+ schedule_work(&balloon_worker);
+ flush_tlb_all();
+ return pagevec;
err:
- free_pages(vstart, order);
+ balloon_lock(flags);
+ while (--i >= 0)
+ balloon_append(pagevec[i]);
balloon_unlock(flags);
- return NULL;
+ kfree(pagevec);
+ pagevec = NULL;
+ goto out;
}
-void balloon_dealloc_empty_page_range(
- struct page *page, unsigned long nr_pages)
+void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
{
- unsigned long i, flags;
- unsigned int order = get_order(nr_pages * PAGE_SIZE);
+ unsigned long flags;
+ int i;
+
+ if (pagevec == NULL)
+ return;
balloon_lock(flags);
- for (i = 0; i < (1UL << order); i++) {
- BUG_ON(page_count(page + i) != 1);
- balloon_append(page + i);
+ for (i = 0; i < nr_pages; i++) {
+ BUG_ON(page_count(pagevec[i]) != 1);
+ balloon_append(pagevec[i]);
}
balloon_unlock(flags);
- schedule_work(&balloon_worker);
-}
+ kfree(pagevec);
-struct page *balloon_alloc_empty_page(void)
-{
- return balloon_alloc_empty_page_range(1);
-}
-
-void balloon_free_empty_page(
- struct page *page)
-{
- balloon_dealloc_empty_page_range(page, 1);
+ schedule_work(&balloon_worker);
}
void balloon_release_driver_page(struct page *page)
@@ -630,10 +631,8 @@ void balloon_release_driver_page(struct page *page)
}
EXPORT_SYMBOL_GPL(balloon_update_driver_allowance);
-EXPORT_SYMBOL_GPL(balloon_alloc_empty_page_range);
-EXPORT_SYMBOL_GPL(balloon_dealloc_empty_page_range);
-EXPORT_SYMBOL_GPL(balloon_alloc_empty_page);
-EXPORT_SYMBOL_GPL(balloon_free_empty_page);
+EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec);
+EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec);
EXPORT_SYMBOL_GPL(balloon_release_driver_page);
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
index 5d5856d8f9..1941d61b0d 100644
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
@@ -515,20 +515,13 @@ static int __init blkif_init(void)
blkif_reqs, GFP_KERNEL);
pending_grant_handles = kmalloc(sizeof(pending_grant_handles[0]) *
mmap_pages, GFP_KERNEL);
- pending_pages = kmalloc(sizeof(pending_pages[0]) *
- mmap_pages, GFP_KERNEL);
+ pending_pages = alloc_empty_pages_and_pagevec(mmap_pages);
+
if (!pending_reqs || !pending_grant_handles || !pending_pages)
goto out_of_memory;
- for (i = 0; i < mmap_pages; i++) {
- pending_pages[i] = balloon_alloc_empty_page();
- if (pending_pages[i] == NULL) {
- while (--i >= 0)
- balloon_free_empty_page(pending_pages[i]);
- goto out_of_memory;
- }
+ for (i = 0; i < mmap_pages; i++)
pending_grant_handles[i] = BLKBACK_INVALID_HANDLE;
- }
blkif_interface_init();
@@ -545,7 +538,7 @@ static int __init blkif_init(void)
out_of_memory:
kfree(pending_reqs);
kfree(pending_grant_handles);
- kfree(pending_pages);
+ free_empty_pages_and_pagevec(pending_pages, mmap_pages);
printk("%s: out of memory\n", __FUNCTION__);
return -ENOMEM;
}
diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
index 7f26492902..0a0d31fe27 100644
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
@@ -728,29 +728,17 @@ static void make_response(blkif_t *blkif, unsigned long id,
static int req_increase(void)
{
int i, j;
- struct page **pages = NULL;
if (mmap_alloc >= MAX_PENDING_REQS || mmap_lock)
return -EINVAL;
- pending_reqs[mmap_alloc] = kzalloc(sizeof(pending_req_t) *
- blkif_reqs, GFP_KERNEL);
- pages = kmalloc(sizeof(pages[0]) * mmap_pages, GFP_KERNEL);
+ pending_reqs[mmap_alloc] = kzalloc(sizeof(pending_req_t)
+ * blkif_reqs, GFP_KERNEL);
+ foreign_pages[mmap_alloc] = alloc_empty_pages_and_pagevec(mmap_pages);
- if (!pending_reqs[mmap_alloc] || !pages)
+ if (!pending_reqs[mmap_alloc] || !foreign_pages[mmap_alloc])
goto out_of_memory;
- for (i = 0; i < mmap_pages; i++) {
- pages[i] = balloon_alloc_empty_page();
- if (!pages[i]) {
- while (--i >= 0)
- balloon_free_empty_page(pages[i]);
- goto out_of_memory;
- }
- }
-
- foreign_pages[mmap_alloc] = pages;
-
DPRINTK("%s: reqs=%d, pages=%d\n",
__FUNCTION__, blkif_reqs, mmap_pages);
@@ -768,7 +756,7 @@ static int req_increase(void)
return 0;
out_of_memory:
- kfree(pages);
+ free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages);
kfree(pending_reqs[mmap_alloc]);
WPRINTK("%s: out of memory\n", __FUNCTION__);
return -ENOMEM;
@@ -776,15 +764,12 @@ static int req_increase(void)
static void mmap_req_del(int mmap)
{
- int i;
-
BUG_ON(!spin_is_locked(&pending_free_lock));
kfree(pending_reqs[mmap]);
+ pending_reqs[mmap] = NULL;
- for (i = 0; i < mmap_pages; i++)
- balloon_free_empty_page(foreign_pages[mmap][i]);
- kfree(foreign_pages[mmap]);
+ free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages);
foreign_pages[mmap] = NULL;
mmap_lock = 0;
diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c
index 3cee68ffb4..a75a4c9bc2 100644
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c
@@ -1440,19 +1440,14 @@ static int __init netback_init(void)
net_timer.data = 0;
net_timer.function = net_alarm;
- mmap_pages = kmalloc(sizeof(mmap_pages[0]) * MAX_PENDING_REQS,
- GFP_KERNEL);
- if (mmap_pages == NULL)
- goto out_of_memory;
+ mmap_pages = alloc_empty_pages_and_pagevec(MAX_PENDING_REQS);
+ if (mmap_pages == NULL) {
+ printk("%s: out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
for (i = 0; i < MAX_PENDING_REQS; i++) {
- page = mmap_pages[i] = balloon_alloc_empty_page();
- if (page == NULL) {
- while (--i >= 0)
- balloon_free_empty_page(mmap_pages[i]);
- goto out_of_memory;
- }
- set_page_count(page, 1);
+ page = mmap_pages[i];
SetPageForeign(page, netif_page_release);
page->index = i;
}
@@ -1478,11 +1473,6 @@ static int __init netback_init(void)
#endif
return 0;
-
- out_of_memory:
- kfree(mmap_pages);
- printk("%s: out of memory\n", __FUNCTION__);
- return -ENOMEM;
}
module_init(netback_init);
diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
index ce06f7ce58..2614aa5126 100644
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
@@ -23,10 +23,9 @@ LIST_HEAD(tpmif_list);
static tpmif_t *alloc_tpmif(domid_t domid, struct backend_info *bi)
{
tpmif_t *tpmif;
- int i;
tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
- if (!tpmif)
+ if (tpmif == NULL)
goto out_of_memory;
memset(tpmif, 0, sizeof (*tpmif));
@@ -36,46 +35,27 @@ static tpmif_t *alloc_tpmif(domid_t domid, struct backend_info *bi)
snprintf(tpmif->devname, sizeof(tpmif->devname), "tpmif%d", domid);
atomic_set(&tpmif->refcnt, 1);
- tpmif->mmap_pages = kmalloc(sizeof(tpmif->mmap_pages[0])
- * TPMIF_TX_RING_SIZE, GFP_KERNEL);
+ tpmif->mmap_pages = alloc_empty_pages_and_pagevec(TPMIF_TX_RING_SIZE);
if (tpmif->mmap_pages == NULL)
goto out_of_memory;
- for (i = 0; i < TPMIF_TX_RING_SIZE; i++) {
- tpmif->mmap_pages[i] = balloon_alloc_empty_page();
- if (tpmif->mmap_pages[i] == NULL) {
- while (--i >= 0)
- balloon_free_empty_page(tpmif->mmap_pages[i]);
- goto out_of_memory;
- }
- }
-
list_add(&tpmif->tpmif_list, &tpmif_list);
num_frontends++;
return tpmif;
out_of_memory:
- if (tpmif != NULL) {
- kfree(tpmif->mmap_pages);
+ if (tpmif != NULL)
kmem_cache_free(tpmif_cachep, tpmif);
- }
printk("%s: out of memory\n", __FUNCTION__);
return ERR_PTR(-ENOMEM);
}
static void free_tpmif(tpmif_t * tpmif)
{
- int i;
-
num_frontends--;
-
list_del(&tpmif->tpmif_list);
-
- for (i = 0; i < TPMIF_TX_RING_SIZE; i++)
- balloon_free_empty_page(tpmif->mmap_pages[i]);
- kfree(tpmif->mmap_pages);
-
+ free_empty_pages_and_pagevec(tpmif->mmap_pages, TPMIF_TX_RING_SIZE);
kmem_cache_free(tpmif_cachep, tpmif);
}
diff --git a/linux-2.6-xen-sparse/include/xen/balloon.h b/linux-2.6-xen-sparse/include/xen/balloon.h
index 4e27a2e39a..d26c62bef4 100644
--- a/linux-2.6-xen-sparse/include/xen/balloon.h
+++ b/linux-2.6-xen-sparse/include/xen/balloon.h
@@ -40,15 +40,9 @@
*/
void balloon_update_driver_allowance(long delta);
-/* Allocate an empty low-memory page range. */
-struct page *balloon_alloc_empty_page_range(unsigned long nr_pages);
-
-/* Deallocate an empty page range, adding to the balloon. */
-void balloon_dealloc_empty_page_range(
- struct page *page, unsigned long nr_pages);
-
-struct page *balloon_alloc_empty_page(void);
-void balloon_free_empty_page(struct page *page);
+/* Allocate/free a set of empty pages in low memory (i.e., no RAM mapped). */
+struct page **alloc_empty_pages_and_pagevec(int nr_pages);
+void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages);
void balloon_release_driver_page(struct page *page);