Skip to content

Commit

Permalink
hugetlb: pull gigantic page initialisation out of the default path
Browse files Browse the repository at this point in the history
As we can determine exactly when a gigantic page is in use we can optimise
the common regular page cases by pulling out gigantic page initialisation
into its own function.  As gigantic pages are never released to buddy we
do not need a destructor.  This effectivly reverts the previous change to
the main buddy allocator.  It also adds a paranoid check to ensure we
never release gigantic pages from hugetlbfs to the main buddy.

Signed-off-by: Andy Whitcroft <[email protected]>
Cc: Jon Tollefson <[email protected]>
Cc: Mel Gorman <[email protected]>
Cc: Nick Piggin <[email protected]>
Cc: Christoph Lameter <[email protected]>
Cc: <[email protected]>		[2.6.27.x]
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
awhitcroft authored and torvalds committed Nov 6, 2008
1 parent 69d177c commit 18229df
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 8 deletions.
12 changes: 11 additions & 1 deletion mm/hugetlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,8 @@ static void update_and_free_page(struct hstate *h, struct page *page)
{
int i;

VM_BUG_ON(h->order >= MAX_ORDER);

h->nr_huge_pages--;
h->nr_huge_pages_node[page_to_nid(page)]--;
for (i = 0; i < pages_per_huge_page(h); i++) {
Expand Down Expand Up @@ -1005,6 +1007,14 @@ __attribute__((weak)) int alloc_bootmem_huge_page(struct hstate *h)
return 1;
}

static void prep_compound_huge_page(struct page *page, int order)
{
if (unlikely(order > (MAX_ORDER - 1)))
prep_compound_gigantic_page(page, order);
else
prep_compound_page(page, order);
}

/* Put bootmem huge pages into the standard lists after mem_map is up */
static void __init gather_bootmem_prealloc(void)
{
Expand All @@ -1015,7 +1025,7 @@ static void __init gather_bootmem_prealloc(void)
struct hstate *h = m->hstate;
__ClearPageReserved(page);
WARN_ON(page_count(page) != 1);
prep_compound_page(page, h->order);
prep_compound_huge_page(page, h->order);
prep_new_huge_page(h, page, page_to_nid(page));
}
}
Expand Down
1 change: 1 addition & 0 deletions mm/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
unsigned long floor, unsigned long ceiling);

extern void prep_compound_page(struct page *page, unsigned long order);
extern void prep_compound_gigantic_page(struct page *page, unsigned long order);

static inline void set_page_count(struct page *page, int v)
{
Expand Down
28 changes: 21 additions & 7 deletions mm/page_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,23 @@ static void free_compound_page(struct page *page)
}

void prep_compound_page(struct page *page, unsigned long order)
{
int i;
int nr_pages = 1 << order;

set_compound_page_dtor(page, free_compound_page);
set_compound_order(page, order);
__SetPageHead(page);
for (i = 1; i < nr_pages; i++) {
struct page *p = page + i;

__SetPageTail(p);
p->first_page = page;
}
}

#ifdef CONFIG_HUGETLBFS
void prep_compound_gigantic_page(struct page *page, unsigned long order)
{
int i;
int nr_pages = 1 << order;
Expand All @@ -268,29 +285,26 @@ void prep_compound_page(struct page *page, unsigned long order)
set_compound_page_dtor(page, free_compound_page);
set_compound_order(page, order);
__SetPageHead(page);
for (i = 1; i < nr_pages; i++, p++) {
if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0))
p = pfn_to_page(page_to_pfn(page) + i);
for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) {
__SetPageTail(p);
p->first_page = page;
}
}
#endif

static void destroy_compound_page(struct page *page, unsigned long order)
{
int i;
int nr_pages = 1 << order;
struct page *p = page + 1;

if (unlikely(compound_order(page) != order))
bad_page(page);

if (unlikely(!PageHead(page)))
bad_page(page);
__ClearPageHead(page);
for (i = 1; i < nr_pages; i++, p++) {
if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0))
p = pfn_to_page(page_to_pfn(page) + i);
for (i = 1; i < nr_pages; i++) {
struct page *p = page + i;

if (unlikely(!PageTail(p) |
(p->first_page != page)))
Expand Down

0 comments on commit 18229df

Please sign in to comment.