diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2006-10-06 11:52:41 +0100 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2006-10-06 11:52:41 +0100 |
commit | 431414939662f36e8f09346ceeddfca7102fcc65 (patch) | |
tree | a1df4141d4a81bc020e9104deff0f535ddd2f7ff | |
parent | db002ee4a03f1d5a0df42d3f25bcc21257ae20f6 (diff) | |
download | xen-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.c | 125 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c | 15 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c | 29 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 22 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c | 28 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/include/xen/balloon.h | 12 |
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); |