From: Christoph Lameter <clameter@sgi.com>
To: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Subject: [04/14] vcompound: Core piece
Date: Thu, 20 Mar 2008 23:17:07 -0700 [thread overview]
Message-ID: <20080321061724.956843984@sgi.com> (raw)
In-Reply-To: <20080321061703.921169367@sgi.com>
[-- Attachment #1: newcore --]
[-- Type: text/plain, Size: 7317 bytes --]
Add support functions to allow the creation and destruction of virtual compound
pages. Virtual compound pages are similar to compound pages in that if
PageTail(page) is true then page->first points to the first page.
vcompound_head_page(address)
(similar to virt_to_head_page) can be used to determine the head page from an
address.
Another similarity to compound pages is that page[1].lru.next contains the
order of the virtual compound page. However, the page structs of virtual
compound pages are not in order. So page[1] means the second page belonging
to the virtual compound mapping which is not necessarily the page following
the head page.
Freeing of virtual compound pages is support both from preemptible and
non preemptible context (freeing requires a preemptible context, we simply
defer free if we are not in a preemptible context).
However, allocation of virtual compound pages must at this stage be done from
preemptible contexts only (there are patches to implement allocations from
atomic context but those are unecessary at this early stage).
Signed-off-by: Christoph Lameter <clameter@sgi.com>
---
include/linux/vmalloc.h | 14 +++
mm/vmalloc.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 211 insertions(+)
Index: linux-2.6.25-rc5-mm1/include/linux/vmalloc.h
===================================================================
--- linux-2.6.25-rc5-mm1.orig/include/linux/vmalloc.h 2008-03-20 23:03:14.600588151 -0700
+++ linux-2.6.25-rc5-mm1/include/linux/vmalloc.h 2008-03-20 23:03:14.612588010 -0700
@@ -86,6 +86,20 @@ extern struct vm_struct *alloc_vm_area(s
extern void free_vm_area(struct vm_struct *area);
/*
+ * Support for virtual compound pages.
+ *
+ * Calls to vcompound alloc will result in the allocation of normal compound
+ * pages unless memory is fragmented. If insufficient physical linear memory
+ * is available then a virtually contiguous area of memory will be created
+ * using the vmalloc functionality.
+ */
+struct page *alloc_vcompound_alloc(gfp_t flags, int order);
+void free_vcompound(struct page *);
+void *__alloc_vcompound(gfp_t flags, int order);
+void __free_vcompound(void *addr);
+struct page *vcompound_head_page(const void *x);
+
+/*
* Internals. Dont't use..
*/
extern rwlock_t vmlist_lock;
Index: linux-2.6.25-rc5-mm1/mm/vmalloc.c
===================================================================
--- linux-2.6.25-rc5-mm1.orig/mm/vmalloc.c 2008-03-20 23:03:14.600588151 -0700
+++ linux-2.6.25-rc5-mm1/mm/vmalloc.c 2008-03-20 23:06:43.703428350 -0700
@@ -989,3 +989,200 @@ const struct seq_operations vmalloc_op =
};
#endif
+/*
+ * Virtual Compound Page support.
+ *
+ * Virtual Compound Pages are used to fall back to order 0 allocations if large
+ * linear mappings are not available. They are formatted according to compound
+ * page conventions. I.e. following page->first_page if PageTail(page) is set
+ * can be used to determine the head page.
+ */
+
+/*
+ * Determine the appropriate page struct given a virtual address
+ * (including vmalloced areas).
+ *
+ * Return the head page if this is a compound page.
+ *
+ * Cannot be inlined since VMALLOC_START and VMALLOC_END may contain
+ * complex calculations that depend on multiple arch includes or
+ * even variables.
+ */
+struct page *vcompound_head_page(const void *x)
+{
+ unsigned long addr = (unsigned long)x;
+ struct page *page;
+
+ if (unlikely(is_vmalloc_addr(x)))
+ page = vmalloc_to_page(x);
+ else
+ page = virt_to_page(addr);
+
+ return compound_head(page);
+}
+
+static void __vcompound_free(void *addr)
+{
+
+ struct page **pages;
+ int i;
+ int order;
+
+ pages = vunmap(addr);
+ order = (unsigned long)pages[1]->lru.prev;
+
+ /*
+ * First page will have zero refcount since it maintains state
+ * for the compound and was decremented before we got here.
+ */
+ set_page_address(pages[0], NULL);
+ __ClearPageVcompound(pages[0]);
+ free_hot_page(pages[0]);
+
+ for (i = 1; i < (1 << order); i++) {
+ struct page *page = pages[i];
+ BUG_ON(!PageTail(page) || !PageVcompound(page));
+ set_page_address(page, NULL);
+ __ClearPageVcompound(page);
+ __free_page(page);
+ }
+ kfree(pages);
+}
+
+static void vcompound_free_work(struct work_struct *w)
+{
+ __vcompound_free((void *)w);
+}
+
+static void vcompound_free(void *addr, struct page *page)
+{
+ struct work_struct *w = addr;
+
+ BUG_ON((!PageVcompound(page) || !PageHead(page)));
+
+ if (!put_page_testzero(page))
+ return;
+
+ if (!preemptible()) {
+ /*
+ * Need to defer the free until we are in
+ * a preemptible context.
+ */
+ INIT_WORK(w, vcompound_free_work);
+ schedule_work(w);
+ } else
+ __vcompound_free(addr);
+}
+
+
+void __free_vcompound(void *addr)
+{
+ struct page *page;
+
+ if (unlikely(is_vmalloc_addr(addr)))
+ vcompound_free(addr, vmalloc_to_page(addr));
+ else {
+ page = virt_to_page(addr);
+ free_pages((unsigned long)addr, compound_order(page));
+ }
+}
+
+void free_vcompound(struct page *page)
+{
+ if (unlikely(PageVcompound(page)))
+ vcompound_free(page_address(page), page);
+ else
+ __free_pages(page, compound_order(page));
+}
+
+static struct vm_struct *____alloc_vcompound(gfp_t gfp_mask, unsigned long order,
+ void *caller)
+{
+ struct page *page;
+ int i;
+ struct vm_struct *vm;
+ int nr_pages = 1 << order;
+ struct page **pages = kmalloc(nr_pages * sizeof(struct page *),
+ gfp_mask & GFP_RECLAIM_MASK);
+ struct page **pages2;
+
+ if (!pages)
+ return NULL;
+
+ for (i = 0; i < nr_pages; i++) {
+ page = alloc_page(gfp_mask);
+ if (!page)
+ goto abort;
+
+ /* Sets PageCompound which makes PageHead(page) true */
+ __SetPageVcompound(page);
+ pages[i] = page;
+ }
+
+ vm = __get_vm_area_node(nr_pages << PAGE_SHIFT, VM_VCOMPOUND,
+ VMALLOC_START, VMALLOC_END, -1, gfp_mask, caller);
+
+ if (!vm)
+ goto abort;
+
+ vm->caller = caller;
+ pages2 = pages;
+ if (map_vm_area(vm, PAGE_KERNEL, &pages2))
+ goto abort;
+
+ pages[1]->lru.prev = (void *)order;
+
+ for (i = 0; i < nr_pages; i++) {
+ struct page *page = pages[i];
+
+ __SetPageTail(page);
+ page->first_page = pages[0];
+ set_page_address(page, vm->addr + (i << PAGE_SHIFT));
+ }
+ return vm;
+
+abort:
+ while (i-- > 0) {
+ page = pages[i];
+ if (!page)
+ continue;
+ set_page_address(page, NULL);
+ __ClearPageVcompound(page);
+ __free_page(page);
+ }
+ kfree(pages);
+ return NULL;
+}
+
+struct page *alloc_vcompound(gfp_t flags, int order)
+{
+ struct vm_struct *vm;
+ struct page *page;
+
+ page = alloc_pages(flags | __GFP_NORETRY | __GFP_NOWARN, order);
+ if (page || !order)
+ return page;
+
+ vm = ____alloc_vcompound(flags, order, __builtin_return_address(0));
+ if (vm)
+ return vm->pages[0];
+
+ return NULL;
+}
+
+void *__alloc_vcompound(gfp_t flags, int order)
+{
+ struct vm_struct *vm;
+ void *addr;
+
+ addr = (void *)__get_free_pages(flags | __GFP_NORETRY | __GFP_NOWARN,
+ order);
+ if (addr || !order)
+ return addr;
+
+ vm = ____alloc_vcompound(flags, order, __builtin_return_address(0));
+ if (vm)
+ return vm->addr;
+
+ return NULL;
+}
--
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2008-03-21 6:17 UTC|newest]
Thread overview: 87+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-03-21 6:17 [00/14] Virtual Compound Page Support V3 Christoph Lameter
2008-03-21 6:17 ` [01/14] vcompound: Return page array on vunmap Christoph Lameter
2008-03-21 6:17 ` [02/14] vcompound: pageflags: Add PageVcompound() Christoph Lameter
2008-03-21 6:17 ` [03/14] vmallocinfo: Support display of vcompound for a virtual compound page Christoph Lameter
2008-03-21 7:55 ` Eric Dumazet
2008-03-21 17:32 ` Christoph Lameter
2008-03-21 6:17 ` Christoph Lameter [this message]
2008-03-22 12:10 ` [04/14] vcompound: Core piece KOSAKI Motohiro
2008-03-24 18:28 ` Christoph Lameter
2008-03-21 6:17 ` [05/14] vcompound: Debugging aid Christoph Lameter
2008-03-21 6:17 ` [06/14] vcompound: Virtual fallback for sparsemem Christoph Lameter
2008-03-21 6:17 ` [07/14] vcompound: bit waitqueue support Christoph Lameter
2008-03-21 6:17 ` [08/14] vcompound: Fallback for zone wait table Christoph Lameter
2008-03-21 6:17 ` [09/14] vcompound: crypto: Fallback for temporary order 2 allocation Christoph Lameter
2008-03-21 6:17 ` [10/14] vcompound: slub: Use for buffer to correlate allocation addresses Christoph Lameter
2008-03-21 6:17 ` [11/14] vcompound: Fallbacks for order 1 stack allocations on IA64 and x86 Christoph Lameter
2008-03-21 7:25 ` David Miller, Christoph Lameter
2008-03-21 8:39 ` Ingo Molnar
2008-03-21 17:33 ` Christoph Lameter
2008-03-21 19:02 ` Ingo Molnar
2008-03-21 19:04 ` Christoph Lameter
2008-03-21 17:40 ` Christoph Lameter
2008-03-21 21:57 ` David Miller, Christoph Lameter
2008-03-24 18:27 ` Christoph Lameter
2008-03-24 20:37 ` larger default page sizes David Miller, Christoph Lameter
2008-03-24 21:05 ` Christoph Lameter
2008-03-24 21:43 ` David Miller, Christoph Lameter
2008-03-25 17:48 ` Christoph Lameter
2008-03-25 23:22 ` David Miller, Christoph Lameter
2008-03-25 23:41 ` Peter Chubb
2008-03-25 23:49 ` David Miller, Peter Chubb
2008-03-26 0:25 ` Peter Chubb
2008-03-26 0:31 ` David Miller, Peter Chubb
2008-03-26 0:34 ` David Mosberger-Tang
2008-03-26 0:39 ` David Miller, David Mosberger-Tang
2008-03-26 0:57 ` Peter Chubb
2008-03-26 4:16 ` John Marvin
2008-03-26 4:36 ` David Miller, John Marvin
2008-03-24 21:25 ` Luck, Tony
2008-03-24 21:46 ` David Miller, Luck, Tony
2008-03-25 3:29 ` Paul Mackerras
2008-03-25 4:15 ` David Miller, Paul Mackerras
2008-03-25 11:50 ` Paul Mackerras
2008-03-25 23:32 ` David Miller, Paul Mackerras
2008-03-25 23:49 ` Luck, Tony
2008-03-26 0:16 ` David Miller, Luck, Tony
2008-03-26 15:54 ` Nish Aravamudan
2008-03-26 17:05 ` Luck, Tony
2008-03-26 18:54 ` Mel Gorman
2008-03-25 12:05 ` Andi Kleen
2008-03-25 21:27 ` Paul Mackerras
2008-03-26 5:24 ` Paul Mackerras
2008-03-26 15:59 ` Linus Torvalds
2008-03-27 1:08 ` Paul Mackerras
2008-03-26 17:56 ` Christoph Lameter
2008-03-26 23:21 ` David Miller, Christoph Lameter
2008-03-27 3:00 ` Paul Mackerras
2008-03-25 18:27 ` Dave Hansen
2008-03-24 21:13 ` [11/14] vcompound: Fallbacks for order 1 stack allocations on IA64 and x86 Luck, Tony
2008-03-25 17:42 ` Christoph Lameter
2008-03-25 19:09 ` Luck, Tony
2008-03-25 19:25 ` Christoph Lameter
2008-03-21 22:30 ` Andi Kleen
2008-03-24 19:53 ` Christoph Lameter
2008-03-25 7:51 ` Andi Kleen
2008-03-25 17:55 ` Christoph Lameter
2008-03-25 18:07 ` Andi Kleen
2008-03-21 6:17 ` [12/14] vcompound: Avoid vmalloc in e1000 driver Christoph Lameter
2008-03-21 17:27 ` Kok, Auke
2008-03-21 6:17 ` [13/14] vcompound: Use vcompound for swap_map Christoph Lameter
2008-03-21 21:25 ` Andi Kleen
2008-03-21 21:33 ` Christoph Lameter
2008-03-24 19:54 ` Christoph Lameter
2008-03-25 7:52 ` Andi Kleen
2008-03-25 17:45 ` Christoph Lameter
2008-03-25 17:55 ` Andi Kleen
2008-03-25 17:51 ` Christoph Lameter
2008-03-21 6:17 ` [14/14] vcompound: Avoid vmalloc for ehash_locks Christoph Lameter
2008-03-21 7:02 ` Eric Dumazet
2008-03-21 7:03 ` Christoph Lameter
2008-03-21 7:31 ` David Miller, Christoph Lameter
2008-03-21 7:42 ` Eric Dumazet
2008-03-21 7:31 ` David Miller, Eric Dumazet
2008-03-21 17:31 ` Christoph Lameter
2008-03-22 18:40 ` [00/14] Virtual Compound Page Support V3 Arjan van de Ven
2008-03-24 18:31 ` Christoph Lameter
2008-03-24 19:29 ` Christoph Lameter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080321061724.956843984@sgi.com \
--to=clameter@sgi.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox