mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
[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>
This commit is contained in:
1 parent
db002ee4a0
commit
4314149396
6 files changed
+86
-145
No files matched your search
@@ -534,89 +534,90 @@ 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);
|
||||
for (i = 0; i < nr_pages; i++) {
|
||||
page = pagevec[i] = alloc_page(GFP_KERNEL);
|
||||
if (page == NULL)
|
||||
goto err;
|
||||
|
||||
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)
|
||||
vaddr = (unsigned long)page_address(page);
|
||||
|
||||
scrub_pages(vaddr, 1);
|
||||
|
||||
balloon_lock(flags);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
balloon_unlock(flags);
|
||||
__free_page(page);
|
||||
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)
|
||||
goto err;
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
totalram_pages = --current_pages;
|
||||
|
||||
balloon_unlock(flags);
|
||||
}
|
||||
current_pages -= 1UL << order;
|
||||
totalram_pages = current_pages;
|
||||
balloon_unlock(flags);
|
||||
|
||||
out:
|
||||
schedule_work(&balloon_worker);
|
||||
|
||||
flush_tlb_all();
|
||||
|
||||
page = virt_to_page(vstart);
|
||||
|
||||
for (i = 0; i < (1UL << order); i++)
|
||||
set_page_count(page + i, 1);
|
||||
|
||||
return page;
|
||||
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);
|
||||
|
||||
kfree(pagevec);
|
||||
|
||||
schedule_work(&balloon_worker);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void balloon_release_driver_page(struct page *page)
|
||||
{
|
||||
unsigned long flags;
|
||||
@@ -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");
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||