multi size, giant hugetlb support, 1GB for x86, 16GB for powerpc
Subsystems (13)
cover multi size, giant hugetlb support, 1GB for x86, 16GB for powerpc
Hi all,
Given the amount of feedback this has had, and the powerpc patches from Jon, I'll send out one more request for review and testing before asking Andrew to merge in -mm.
Patches are against Linus's current git (eb90d81d). I will have to rebase to -mm next.
The patches pass the libhugetlbfs regression test suite here on x86 and powerpc (although my G5 can only run 16MB hugepages, so it is less interesting...).
So, review and testing welcome.
Thanks!
Nick
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 1/23 hugetlb: fix lockdep error
--- mm/hugetlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/hugetlb.c +1 -1
@@ -785,7 +785,7 @@ int copy_hugetlb_page_range(struct mm_stcontinue ;spin_lock (&dst->page_table_lock); -spin_lock (&src->page_table_lock); +spin_lock_nested (&src->page_table_lock,SINGLE_DEPTH_NESTING );if (!huge_pte_none (huge_ptep_get (src_pte))) {if (cow)huge_ptep_set_wrprotect (src, addr, src_pte);
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 01/23] hugetlb: fix lockdep error
Quoted 1 line · On 26.05.2008 [00:23:18 +1000], [email protected] wrote:
Signed-off-by Nick Piggin <[email protected]>
And can probably go upstream independent of the rest?
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 01/23] hugetlb: fix lockdep error
In reply to [email protected]Quoted 2 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlb-copy-lockdep.patch)
Signed-off-by Nick Piggin <[email protected]>
Quoted 18 lines
--- mm/hugetlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)Index:
linux-2.6/mm/hugetlb.c
===================================================================mm/hugetlb.c +1
-1@@ -785,7 +785,7 @@ int copy_hugetlb_page_range(struct mm_stcontinue ;spin_lock (&dst->page_table_lock); -spin_lock (&src->page_table_lock); +spin_lock_nested (&src->page_table_lock,SINGLE_DEPTH_NESTING );if (!huge_pte_none (huge_ptep_get (src_pte))) {if (cow)huge_ptep_set_wrprotect (src, addr, src_pte);
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 2/23 hugetlb: factor out huge_new_page
In reply to [email protected]Needed to avoid code duplication in follow up patches.
--- mm/hugetlb.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
mm/hugetlb.c +11 -6
@@ -194,6 +194,16 @@ static int adjust_pool_surplus(int deltareturn ret; } +static void prep_new_huge_page (struct page *page,int nid) +{ +set_compound_page_dtor (page, free_huge_page); +spin_lock (&hugetlb_lock); + nr_huge_pages++; + nr_huge_pages_node[nid]++; +spin_unlock (&hugetlb_lock); +put_page (page);/* free it into the hugepage allocator */ +} +static struct page *alloc_fresh_huge_page_node (int nid) {struct page *page;
@@ -207,12 +217,7 @@ static struct page *alloc_fresh_huge_pag__free_pages (page,HUGETLB_PAGE_ORDER );return NULL ; } -set_compound_page_dtor (page, free_huge_page); -spin_lock (&hugetlb_lock); - nr_huge_pages++; - nr_huge_pages_node[nid]++; -spin_unlock (&hugetlb_lock); -put_page (page);/* free it into the hugepage allocator */ +prep_new_huge_page (page, nid); }return page;
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] hugetlb: factor out huge_new_page
Quoted 4 lines · On 26.05.2008 [00:23:19 +1000], [email protected] wrote:
Needed to avoid code duplication in follow up patches.
Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Although the e-mail subject does not match the name of the function :)
And can probably be sent upstream without the other patches as well.
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] hugetlb: factor out huge_new_page
In reply to [email protected]Quoted 5 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlb-factor-page-prep.patch) Needed to avoid code duplication in follow up patches.
Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 3/23 hugetlb: modular state
In reply to [email protected]Large, but rather mechanical patch that converts most of the hugetlb.c globals into structure members and passes them around.
Right now there is only a single global hstate structure, but most of the infrastructure to extend it is there.
--- arch/ia64/mm/hugetlbpage.c | 6 arch/powerpc/mm/hugetlbpage.c | 2 arch/sh/mm/hugetlbpage.c | 2 arch/sparc64/mm/hugetlbpage.c | 4 arch/x86/mm/hugetlbpage.c | 4 fs/hugetlbfs/inode.c | 49 +++--- include/asm-ia64/hugetlb.h | 2 include/asm-powerpc/hugetlb.h | 2 include/asm-s390/hugetlb.h | 2 include/asm-sh/hugetlb.h | 2 include/asm-sparc64/hugetlb.h | 2 include/asm-x86/hugetlb.h | 7 include/linux/hugetlb.h | 81 +++++++++- ipc/shm.c | 3 mm/hugetlb.c | 321 ++++++++++++++++++++++-------------------- mm/memory.c | 2 mm/mempolicy.c | 9 - mm/mmap.c | 3 18 files changed, 308 insertions(+), 195 deletions(-)
mm/hugetlb.c +175 -146
@@ -22,30 +22,24 @@#include "internal.h" const unsigned long hugetlb_zero =0 , hugetlb_infinity = ~0UL ; -static unsigned long nr_huge_pages, free_huge_pages, resv_huge_pages; -static unsigned long surplus_huge_pages; -static unsigned long nr_overcommit_huge_pages;unsigned long max_huge_pages;unsigned long sysctl_overcommit_huge_pages; -static struct list_head hugepage_freelists[MAX_NUMNODES ]; -static unsigned int nr_huge_pages_node[MAX_NUMNODES ]; -static unsigned int free_huge_pages_node[MAX_NUMNODES ]; -static unsigned int surplus_huge_pages_node[MAX_NUMNODES ];static gfp_t htlb_alloc_mask =GFP_HIGHUSER ;unsigned long hugepages_treat_as_movable; -static int hugetlb_next_nid; + +struct hstate global_hstate;/* * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages */ static DEFINE_SPINLOCK (hugetlb_lock); -static void clear_huge_page (struct page *page,unsigned long addr) +static void clear_huge_page (struct page *page,unsigned long addr,unsigned long sz) {int i;might_sleep (); -for (i =0 ; i < (HPAGE_SIZE /PAGE_SIZE ); i++) { +for (i =0 ; i < sz/PAGE_SIZE ; i++) {cond_resched ();clear_user_highpage (page + i, addr + i *PAGE_SIZE ); }
@@ -55,42 +49,43 @@ static void copy_huge_page(struct page * unsigned long addr, struct vm_area_struct *vma) { int i; +struct hstate *h =hstate_vma (vma);might_sleep (); -for (i =0 ; i <HPAGE_SIZE /PAGE_SIZE ; i++) { +for (i =0 ; i <1 <<huge_page_order (h); i++) {cond_resched ();copy_user_highpage (dst + i, src + i, addr + i*PAGE_SIZE , vma); } } -static void enqueue_huge_page (struct page *page) +static void enqueue_huge_page (struct hstate *h,struct page *page) {int nid =page_to_nid (page); -list_add (&page->lru, &hugepage_freelists[nid]); - free_huge_pages++; - free_huge_pages_node[nid]++; +list_add (&page->lru, &h->hugepage_freelists[nid]); + h->free_huge_pages++; + h->free_huge_pages_node[nid]++; } -static struct page *dequeue_huge_page (void ) +static struct page *dequeue_huge_page (struct hstate *h) {int nid;struct page *page =NULL ;for (nid =0 ; nid <MAX_NUMNODES ; ++nid) { -if (!list_empty (&hugepage_freelists[nid])) { - page =list_entry (hugepage_freelists[nid].next, +if (!list_empty (&h->hugepage_freelists[nid])) { + page =list_entry (h->hugepage_freelists[nid].next, struct page, lru);list_del (&page->lru); - free_huge_pages--; - free_huge_pages_node[nid]--; + h->free_huge_pages--; + h->free_huge_pages_node[nid]--;break ; } }return page; } -static struct page *dequeue_huge_page_vma (struct vm_area_struct *vma, -unsigned long address) +static struct page *dequeue_huge_page_vma (struct hstate *h, +struct vm_area_struct *vma,unsigned long address) {int nid;struct page *page =NULL ;
@@ -105,14 +100,14 @@ static struct page *dequeue_huge_page_vm MAX_NR_ZONES - 1, nodemask) { nid =zone_to_nid (zone);if (cpuset_zone_allowed_softwall (zone, htlb_alloc_mask) && - !list_empty (&hugepage_freelists[nid])) { - page =list_entry (hugepage_freelists[nid].next, + !list_empty (&h->hugepage_freelists[nid])) { + page =list_entry (h->hugepage_freelists[nid].next, struct page, lru);list_del (&page->lru); - free_huge_pages--; - free_huge_pages_node[nid]--; + h->free_huge_pages--; + h->free_huge_pages_node[nid]--;if (vma && vma->vm_flags &VM_MAYSHARE ) - resv_huge_pages--; + h->resv_huge_pages--;break ; } }
@@ -120,12 +115,13 @@ static struct page *dequeue_huge_page_vmreturn page; } -static void update_and_free_page (struct page *page) +static void update_and_free_page (struct hstate *h,struct page *page) {int i; - nr_huge_pages--; - nr_huge_pages_node[page_to_nid (page)]--; -for (i =0 ; i < (HPAGE_SIZE /PAGE_SIZE ); i++) { + + h->nr_huge_pages--; + h->nr_huge_pages_node[page_to_nid (page)]--; +for (i =0 ; i < (1 <<huge_page_order (h)); i++) { page[i].flags &= ~(1 << PG_locked |1 << PG_error |1 << PG_referenced |1 << PG_dirty |1 << PG_active |1 << PG_reserved |1 << PG_private |1 << PG_writeback);
@@ -133,11 +129,16 @@ static void update_and_free_page(structset_compound_page_dtor (page,NULL );set_page_refcounted (page);arch_release_hugepage (page); -__free_pages (page,HUGETLB_PAGE_ORDER ); +__free_pages (page,huge_page_order (h)); }static void free_huge_page (struct page *page) { +/* +* Can't pass hstate in here because it is called from the +* compound page destructor. +*/ +struct hstate *h = &global_hstate;int nid =page_to_nid (page);struct address_space *mapping;
@@ -147,12 +148,12 @@ static void free_huge_page(struct page *INIT_LIST_HEAD (&page->lru);spin_lock (&hugetlb_lock); -if (surplus_huge_pages_node[nid]) { -update_and_free_page (page); - surplus_huge_pages--; - surplus_huge_pages_node[nid]--; +if (h->surplus_huge_pages_node[nid]) { +update_and_free_page (h, page); + h->surplus_huge_pages--; + h->surplus_huge_pages_node[nid]--; }else { -enqueue_huge_page (page); +enqueue_huge_page (h, page); }spin_unlock (&hugetlb_lock);if (mapping)
@@ -164,7 +165,7 @@ static void free_huge_page(struct page ** balanced by operating on them in a round-robin fashion. * Returns 1 if an adjustment was made. */ -static int adjust_pool_surplus (int delta) +static int adjust_pool_surplus (struct hstate *h,int delta) {static int prev_nid;int nid = prev_nid;
@@ -177,15 +178,15 @@ static int adjust_pool_surplus(int delta nid =first_node (node_online_map);/* To shrink on this node, there must be a surplus page */ -if (delta <0 && !surplus_huge_pages_node[nid]) +if (delta <0 && !h->surplus_huge_pages_node[nid])continue ;/* Surplus cannot exceed the total number of pages */ -if (delta >0 && surplus_huge_pages_node[nid] >= - nr_huge_pages_node[nid]) +if (delta >0 && h->surplus_huge_pages_node[nid] >= + h->nr_huge_pages_node[nid])continue ; - surplus_huge_pages += delta; - surplus_huge_pages_node[nid] += delta; + h->surplus_huge_pages += delta; + h->surplus_huge_pages_node[nid] += delta; ret =1 ;break ; }while (nid != prev_nid);
@@ -194,46 +195,46 @@ static int adjust_pool_surplus(int deltareturn ret; } -static void prep_new_huge_page (struct page *page,int nid) +static void prep_new_huge_page (struct hstate *h,struct page *page,int nid) {set_compound_page_dtor (page, free_huge_page);spin_lock (&hugetlb_lock); - nr_huge_pages++; - nr_huge_pages_node[nid]++; + h->nr_huge_pages++; + h->nr_huge_pages_node[nid]++;spin_unlock (&hugetlb_lock);put_page (page);/* free it into the hugepage allocator */ } -static struct page *alloc_fresh_huge_page_node (int nid) +static struct page *alloc_fresh_huge_page_node (struct hstate *h,int nid) {struct page *page; page =alloc_pages_node (nid, htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE| __GFP_REPEAT|__GFP_NOWARN, -HUGETLB_PAGE_ORDER ); +huge_page_order (h));if (page) {if (arch_prepare_hugepage (page)) {__free_pages (page,HUGETLB_PAGE_ORDER );return NULL ; } -prep_new_huge_page (page, nid); +prep_new_huge_page (h, page, nid); }return page; } -static int alloc_fresh_huge_page (void ) +static int alloc_fresh_huge_page (struct hstate *h) {struct page *page;int start_nid;int next_nid;int ret =0 ; - start_nid = hugetlb_next_nid; + start_nid = h->hugetlb_next_nid; do { - page = alloc_fresh_huge_page_node(hugetlb_next_nid); + page = alloc_fresh_huge_page_node(h, h->hugetlb_next_nid); if (page) ret = 1; /*
@@ -247,11 +248,11 @@ static int alloc_fresh_huge_page(void)* if we just successfully allocated a hugepage so that * the next caller gets hugepages on the next node. */ - next_nid =next_node (hugetlb_next_nid, node_online_map); + next_nid =next_node (h->hugetlb_next_nid, node_online_map);if (next_nid ==MAX_NUMNODES ) next_nid =first_node (node_online_map); - hugetlb_next_nid = next_nid; - }while (!page && hugetlb_next_nid != start_nid); + h->hugetlb_next_nid = next_nid; + }while (!page && h->hugetlb_next_nid != start_nid);if (ret)count_vm_event (HTLB_BUDDY_PGALLOC );
@@ -261,8 +262,8 @@ static int alloc_fresh_huge_page(void)return ret; } -static struct page *alloc_buddy_huge_page (struct vm_area_struct *vma, -unsigned long address) +static struct page *alloc_buddy_huge_page (struct hstate *h, +struct vm_area_struct *vma,unsigned long address) {struct page *page;unsigned int nid;
@@ -291,18 +292,18 @@ static struct page *alloc_buddy_huge_pag* per-node value is checked there. */ spin_lock (&hugetlb_lock); -if (surplus_huge_pages >= nr_overcommit_huge_pages) { +if (h->surplus_huge_pages >= h->nr_overcommit_huge_pages) {spin_unlock (&hugetlb_lock);return NULL ; }else { - nr_huge_pages++; - surplus_huge_pages++; + h->nr_huge_pages++; + h->surplus_huge_pages++; }spin_unlock (&hugetlb_lock); page =alloc_pages (htlb_alloc_mask|__GFP_COMP| __GFP_REPEAT|__GFP_NOWARN, -HUGETLB_PAGE_ORDER ); +huge_page_order (h));spin_lock (&hugetlb_lock);if (page) {
@@ -317,12 +318,12 @@ static struct page *alloc_buddy_huge_pag/* * We incremented the global counters already */ - nr_huge_pages_node[nid]++; - surplus_huge_pages_node[nid]++; + h->nr_huge_pages_node[nid]++; + h->surplus_huge_pages_node[nid]++;__count_vm_event (HTLB_BUDDY_PGALLOC ); }else { - nr_huge_pages--; - surplus_huge_pages--; + h->nr_huge_pages--; + h->surplus_huge_pages--;__count_vm_event (HTLB_BUDDY_PGALLOC_FAIL ); }spin_unlock (&hugetlb_lock);
@@ -334,16 +335,16 @@ static struct page *alloc_buddy_huge_pag* Increase the hugetlb pool such that it can accomodate a reservation * of size 'delta'. */ -static int gather_surplus_pages (int delta) +static int gather_surplus_pages (struct hstate *h,int delta) {struct list_head surplus_list;struct page *page, *tmp;int ret, i;int needed, allocated; - needed = (resv_huge_pages + delta) - free_huge_pages; + needed = (h->resv_huge_pages + delta) - h->free_huge_pages;if (needed <=0 ) { - resv_huge_pages += delta; + h->resv_huge_pages += delta;return 0 ; }
@@ -354,7 +355,7 @@ static int gather_surplus_pages(int delt retry:spin_unlock (&hugetlb_lock);for (i =0 ; i < needed; i++) { - page =alloc_buddy_huge_page (NULL ,0 ); + page =alloc_buddy_huge_page (h,NULL ,0 );if (!page) {/* * We were not able to allocate enough pages to
@@ -375,7 +376,8 @@ retry:* because either resv_huge_pages or free_huge_pages may have changed. */ spin_lock (&hugetlb_lock); - needed = (resv_huge_pages + delta) - (free_huge_pages + allocated); + needed = (h->resv_huge_pages + delta) - + (h->free_huge_pages + allocated);if (needed >0 ) goto retry;
@@ -388,7 +390,7 @@ retry:* before they are reserved. */ needed += allocated; - resv_huge_pages += delta; + h->resv_huge_pages += delta; ret =0 ; free:/* Free the needed pages to the hugetlb pool */
@@ -396,7 +398,7 @@ free:if ((--needed) <0 )break ;list_del (&page->lru); -enqueue_huge_page (page); +enqueue_huge_page (h, page); }/* Free unnecessary surplus pages to the buddy allocator */
@@ -424,7 +426,8 @@ free:* allocated to satisfy the reservation must be explicitly freed if they were * never used. */ -static void return_unused_surplus_pages (unsigned long unused_resv_pages) +static void return_unused_surplus_pages (struct hstate *h, +unsigned long unused_resv_pages) {static int nid =-1 ;struct page *page;
@@ -439,27 +442,27 @@ static void return_unused_surplus_pages(unsigned long remaining_iterations =num_online_nodes ();/* Uncommit the reservation */ - resv_huge_pages -= unused_resv_pages; + h->resv_huge_pages -= unused_resv_pages; - nr_pages =min (unused_resv_pages, surplus_huge_pages); + nr_pages =min (unused_resv_pages, h->surplus_huge_pages);while (remaining_iterations-- && nr_pages) { nid =next_node (nid, node_online_map);if (nid ==MAX_NUMNODES ) nid =first_node (node_online_map); -if (!surplus_huge_pages_node[nid]) +if (!h->surplus_huge_pages_node[nid])continue ; -if (!list_empty (&hugepage_freelists[nid])) { - page =list_entry (hugepage_freelists[nid].next, +if (!list_empty (&h->hugepage_freelists[nid])) { + page =list_entry (h->hugepage_freelists[nid].next, struct page, lru);list_del (&page->lru); -update_and_free_page (page); - free_huge_pages--; - free_huge_pages_node[nid]--; - surplus_huge_pages--; - surplus_huge_pages_node[nid]--; +update_and_free_page (h, page); + h->free_huge_pages--; + h->free_huge_pages_node[nid]--; + h->surplus_huge_pages--; + h->surplus_huge_pages_node[nid]--; nr_pages--; remaining_iterations =num_online_nodes (); }
@@ -471,9 +474,10 @@ static struct page *alloc_huge_page_shar unsigned long addr) {struct page *page; +struct hstate *h =hstate_vma (vma);spin_lock (&hugetlb_lock); - page =dequeue_huge_page_vma (vma, addr); + page =dequeue_huge_page_vma (h, vma, addr);spin_unlock (&hugetlb_lock);return page ? page :ERR_PTR (-VM_FAULT_OOM ); }
@@ -482,16 +486,17 @@ static struct page *alloc_huge_page_priv unsigned long addr) {struct page *page =NULL ; +struct hstate *h =hstate_vma (vma);if (hugetlb_get_quota (vma->vm_file->f_mapping,1 ))return ERR_PTR (-VM_FAULT_SIGBUS );spin_lock (&hugetlb_lock); -if (free_huge_pages > resv_huge_pages) - page =dequeue_huge_page_vma (vma, addr); +if (h->free_huge_pages > h->resv_huge_pages) + page =dequeue_huge_page_vma (h, vma, addr);spin_unlock (&hugetlb_lock);if (!page) { - page =alloc_buddy_huge_page (vma, addr); + page =alloc_buddy_huge_page (h, vma, addr);if (!page) {hugetlb_put_quota (vma->vm_file->f_mapping,1 );return ERR_PTR (-VM_FAULT_OOM );
@@ -521,21 +526,27 @@ static struct page *alloc_huge_page(strustatic int __init hugetlb_init (void ) {unsigned long i; +struct hstate *h = &global_hstate;if (HPAGE_SHIFT ==0 )return 0 ; +if (!h->order) { + h->order =HPAGE_SHIFT -PAGE_SHIFT ; + h->mask =HPAGE_MASK ; + } +for (i =0 ; i <MAX_NUMNODES ; ++i) -INIT_LIST_HEAD (&hugepage_freelists[i]); +INIT_LIST_HEAD (&h->hugepage_freelists[i]); - hugetlb_next_nid =first_node (node_online_map); + h->hugetlb_next_nid =first_node (node_online_map);for (i =0 ; i < max_huge_pages; ++i) { -if (!alloc_fresh_huge_page ()) +if (!alloc_fresh_huge_page (h))break ; } - max_huge_pages = free_huge_pages = nr_huge_pages = i; -printk ("Total HugeTLB memory allocated, %ld\n" , free_huge_pages); + max_huge_pages = h->free_huge_pages = h->nr_huge_pages = i; +printk ("Total HugeTLB memory allocated, %ld\n" , h->free_huge_pages);return 0 ; }module_init (hugetlb_init);
@@ -561,34 +572,36 @@ static unsigned int cpuset_mems_nr(unsig#ifdef CONFIG_SYSCTL #ifdef CONFIG_HIGHMEM -static void try_to_free_low (unsigned long count) +static void try_to_free_low (struct hstate *h,unsigned long count) {int i;for (i =0 ; i <MAX_NUMNODES ; ++i) {struct page *page, *next; -list_for_each_entry_safe (page, next, &hugepage_freelists[i], lru) { -if (count >= nr_huge_pages) +struct list_head *freel = &h->hugepage_freelists[i]; +list_for_each_entry_safe (page, next, freel, lru) { +if (count >= h->nr_huge_pages)return ;if (PageHighMem (page))continue ;list_del (&page->lru);update_and_free_page (page); - free_huge_pages--; - free_huge_pages_node[page_to_nid (page)]--; + h->free_huge_pages--; + h->free_huge_pages_node[page_to_nid (page)]--; } } }#else -static inline void try_to_free_low (unsigned long count) +static inline void try_to_free_low (struct hstate *h,unsigned long count) { }#endif -#define persistent_huge_pages (nr_huge_pages - surplus_huge_pages) +#define persistent_huge_pages (h) (h->nr_huge_pages - h->surplus_huge_pages)static unsigned long set_max_huge_pages (unsigned long count) {unsigned long min_count, ret; +struct hstate *h = &global_hstate;/* * Increase the pool size
@@ -602,12 +615,12 @@ static unsigned long set_max_huge_pages(* within all the constraints specified by the sysctls. */ spin_lock (&hugetlb_lock); -while (surplus_huge_pages && count > persistent_huge_pages) { -if (!adjust_pool_surplus (-1 )) +while (h->surplus_huge_pages && count >persistent_huge_pages (h)) { +if (!adjust_pool_surplus (h,-1 ))break ; } -while (count > persistent_huge_pages) { +while (count >persistent_huge_pages (h)) {int ret;/* * If this allocation races such that we no longer need the
@@ -615,7 +628,7 @@ static unsigned long set_max_huge_pages(* and reducing the surplus. */ spin_unlock (&hugetlb_lock); - ret =alloc_fresh_huge_page (); + ret =alloc_fresh_huge_page (h);spin_lock (&hugetlb_lock);if (!ret) goto out;
@@ -637,21 +650,21 @@ static unsigned long set_max_huge_pages(* and won't grow the pool anywhere else. Not until one of the * sysctls are changed, or the surplus pages go out of use. */ - min_count = resv_huge_pages + nr_huge_pages - free_huge_pages; + min_count = h->resv_huge_pages + h->nr_huge_pages - h->free_huge_pages; min_count =max (count, min_count); -try_to_free_low (min_count); -while (min_count < persistent_huge_pages) { -struct page *page =dequeue_huge_page (); +try_to_free_low (h, min_count); +while (min_count <persistent_huge_pages (h)) { +struct page *page =dequeue_huge_page (h);if (!page)break ; -update_and_free_page (page); +update_and_free_page (h, page); } -while (count < persistent_huge_pages) { -if (!adjust_pool_surplus (1 )) +while (count <persistent_huge_pages (h)) { +if (!adjust_pool_surplus (h,1 ))break ; } out: - ret = persistent_huge_pages; + ret =persistent_huge_pages (h);spin_unlock (&hugetlb_lock);return ret; }
@@ -681,9 +694,10 @@ int hugetlb_overcommit_handler(struct ct struct file *file, void __user *buffer, size_t *length, loff_t *ppos) { + struct hstate *h = &global_hstate;proc_doulongvec_minmax (table, write, file, buffer, length, ppos);spin_lock (&hugetlb_lock); - nr_overcommit_huge_pages = sysctl_overcommit_huge_pages; + h->nr_overcommit_huge_pages = sysctl_overcommit_huge_pages;spin_unlock (&hugetlb_lock);return 0 ; }
@@ -692,34 +706,37 @@ int hugetlb_overcommit_handler(struct ctint hugetlb_report_meminfo (char *buf) { +struct hstate *h = &global_hstate;return sprintf (buf,"HugePages_Total: %5lu\n" "HugePages_Free: %5lu\n" "HugePages_Rsvd: %5lu\n" "HugePages_Surp: %5lu\n" "Hugepagesize: %5lu kB\n" , - nr_huge_pages, - free_huge_pages, - resv_huge_pages, - surplus_huge_pages, -HPAGE_SIZE /1024 ); + h->nr_huge_pages, + h->free_huge_pages, + h->resv_huge_pages, + h->surplus_huge_pages, +1UL << (huge_page_order (h) +PAGE_SHIFT -10 )); }int hugetlb_report_node_meminfo (int nid,char *buf) { +struct hstate *h = &global_hstate;return sprintf (buf,"Node %d HugePages_Total: %5u\n" "Node %d HugePages_Free: %5u\n" "Node %d HugePages_Surp: %5u\n" , - nid, nr_huge_pages_node[nid], - nid, free_huge_pages_node[nid], - nid, surplus_huge_pages_node[nid]); + nid, h->nr_huge_pages_node[nid], + nid, h->free_huge_pages_node[nid], + nid, h->surplus_huge_pages_node[nid]); }/* Return the number pages of memory we physically have, in PAGE_SIZE units. */ unsigned long hugetlb_total_pages (void ) { -return nr_huge_pages * (HPAGE_SIZE /PAGE_SIZE ); +struct hstate *h = &global_hstate; +return h->nr_huge_pages * (1 <<huge_page_order (h)); }/*
@@ -774,14 +791,16 @@ int copy_hugetlb_page_range(struct mm_ststruct page *ptepage;unsigned long addr;int cow; +struct hstate *h =hstate_vma (vma); +unsigned long sz =huge_page_size (h); cow = (vma->vm_flags & (VM_SHARED |VM_MAYWRITE )) ==VM_MAYWRITE ; -for (addr = vma->vm_start; addr < vma->vm_end; addr +=HPAGE_SIZE ) { +for (addr = vma->vm_start; addr < vma->vm_end; addr += sz) { src_pte =huge_pte_offset (src, addr);if (!src_pte)continue ; - dst_pte =huge_pte_alloc (dst, addr); + dst_pte =huge_pte_alloc (dst, addr, sz);if (!dst_pte) goto nomem;
@@ -817,6 +836,9 @@ void __unmap_hugepage_range(struct vm_arpte_t pte;struct page *page;struct page *tmp; +struct hstate *h =hstate_vma (vma); +unsigned long sz =huge_page_size (h); +/* * A page gathering list, protected by per file i_mmap_lock. The * lock is used to avoid list corruption from multiple unmapping
@@ -825,11 +847,11 @@ void __unmap_hugepage_range(struct vm_arLIST_HEAD (page_list);WARN_ON (!is_vm_hugetlb_page (vma)); -BUG_ON (start & ~HPAGE_MASK ); -BUG_ON (end & ~HPAGE_MASK ); +BUG_ON (start & ~huge_page_mask (h)); +BUG_ON (end & ~huge_page_mask (h));spin_lock (&mm->page_table_lock); -for (address = start; address < end; address +=HPAGE_SIZE ) { +for (address = start; address < end; address += sz) { ptep =huge_pte_offset (mm, address);if (!ptep)continue ;
@@ -877,6 +899,7 @@ static int hugetlb_cow(struct mm_struct {struct page *old_page, *new_page;int avoidcopy; +struct hstate *h =hstate_vma (vma); old_page =pte_page (pte);
@@ -901,7 +924,7 @@ static int hugetlb_cow(struct mm_struct__SetPageUptodate (new_page);spin_lock (&mm->page_table_lock); - ptep =huge_pte_offset (mm, address &HPAGE_MASK ); + ptep =huge_pte_offset (mm, address &huge_page_mask (h));if (likely (pte_same (huge_ptep_get (ptep), pte))) {/* Break COW */ huge_ptep_clear_flush (vma, address, ptep);
@@ -924,10 +947,11 @@ static int hugetlb_no_page(struct mm_strstruct page *page;struct address_space *mapping;pte_t new_pte; +struct hstate *h =hstate_vma (vma); mapping = vma->vm_file->f_mapping; - idx = ((address - vma->vm_start) >>HPAGE_SHIFT ) - + (vma->vm_pgoff >> (HPAGE_SHIFT -PAGE_SHIFT )); + idx = ((address - vma->vm_start) >>huge_page_shift (h)) + + (vma->vm_pgoff >>huge_page_order (h));/* * Use page lock to guard against racing truncation
@@ -936,7 +960,7 @@ static int hugetlb_no_page(struct mm_str retry: page =find_lock_page (mapping, idx);if (!page) { - size =i_size_read (mapping->host) >>HPAGE_SHIFT ; + size =i_size_read (mapping->host) >>huge_page_shift (h);if (idx >= size) goto out; page =alloc_huge_page (vma, address);
@@ -944,7 +968,7 @@ retry: ret = -PTR_ERR (page); goto out; } -clear_huge_page (page, address); +clear_huge_page (page, address,huge_page_size (h));__SetPageUptodate (page);if (vma->vm_flags &VM_SHARED ) {
@@ -960,14 +984,14 @@ retry: }spin_lock (&inode->i_lock); - inode->i_blocks +=BLOCKS_PER_HUGEPAGE ; + inode->i_blocks +=blocks_per_hugepage (h);spin_unlock (&inode->i_lock); }else lock_page (page); }spin_lock (&mm->page_table_lock); - size =i_size_read (mapping->host) >>HPAGE_SHIFT ; + size =i_size_read (mapping->host) >>huge_page_shift (h);if (idx >= size) goto backout;
@@ -1003,8 +1027,9 @@ int hugetlb_fault(struct mm_struct *mm,pte_t entry;int ret;static DEFINE_MUTEX (hugetlb_instantiation_mutex); +struct hstate *h =hstate_vma (vma); - ptep =huge_pte_alloc (mm, address); + ptep =huge_pte_alloc (mm, address,huge_page_size (h));if (!ptep)return VM_FAULT_OOM ;
@@ -1042,6 +1067,7 @@ int follow_hugetlb_page(struct mm_structunsigned long pfn_offset;unsigned long vaddr = *position;int remainder = *length; +struct hstate *h =hstate_vma (vma);spin_lock (&mm->page_table_lock);while (vaddr < vma->vm_end && remainder) {
@@ -1053,7 +1079,7 @@ int follow_hugetlb_page(struct mm_struct* each hugepage. We have to make * sure we get the * first, for the page indexing below to work. */ - pte =huge_pte_offset (mm, vaddr &HPAGE_MASK ); + pte =huge_pte_offset (mm, vaddr &huge_page_mask (h));if (!pte ||huge_pte_none (huge_ptep_get (pte)) || (write && !pte_write (huge_ptep_get (pte)))) {
@@ -1071,7 +1097,7 @@ int follow_hugetlb_page(struct mm_structbreak ; } - pfn_offset = (vaddr & ~HPAGE_MASK ) >>PAGE_SHIFT ; + pfn_offset = (vaddr & ~huge_page_mask (h)) >>PAGE_SHIFT ; page =pte_page (huge_ptep_get (pte)); same_page:if (pages) {
@@ -1087,7 +1113,7 @@ same_page: --remainder; ++i;if (vaddr < vma->vm_end && remainder && - pfn_offset <HPAGE_SIZE /PAGE_SIZE ) { + pfn_offset < (1 <<huge_page_order (h))) {/* * We use pfn_offset to avoid touching the pageframes * of this compound page.
@@ -1109,13 +1135,14 @@ void hugetlb_change_protection(struct vmunsigned long start = address;pte_t *ptep;pte_t pte; +struct hstate *h =hstate_vma (vma);BUG_ON (address >= end);flush_cache_range (vma, address, end);spin_lock (&vma->vm_file->f_mapping->i_mmap_lock);spin_lock (&mm->page_table_lock); -for (; address < end; address +=HPAGE_SIZE ) { +for (; address < end; address +=huge_page_size (h)) { ptep =huge_pte_offset (mm, address);if (!ptep)continue ;
@@ -1254,7 +1281,7 @@ static long region_truncate(struct list_return chg; } -static int hugetlb_acct_memory (long delta) +static int hugetlb_acct_memory (struct hstate *h,long delta) {int ret = -ENOMEM ;
@@ -1277,18 +1304,18 @@ static int hugetlb_acct_memory(long delt* semantics that cpuset has. */ if (delta >0 ) { -if (gather_surplus_pages (delta) <0 ) +if (gather_surplus_pages (h, delta) <0 ) goto out; -if (delta >cpuset_mems_nr (free_huge_pages_node)) { -return_unused_surplus_pages (delta); +if (delta >cpuset_mems_nr (h->free_huge_pages_node)) { +return_unused_surplus_pages (h, delta); goto out; } } ret =0 ;if (delta <0 ) -return_unused_surplus_pages ((unsigned long ) -delta); +return_unused_surplus_pages (h, (unsigned long ) -delta); out:spin_unlock (&hugetlb_lock);
@@ -1298,6 +1325,7 @@ out:int hugetlb_reserve_pages (struct inode *inode,long from,long to) {long ret, chg; +struct hstate *h =hstate_inode (inode); chg =region_chg (&inode->i_mapping->private_list, from, to);if (chg <0 )
@@ -1305,7 +1333,7 @@ int hugetlb_reserve_pages(struct inode *if (hugetlb_get_quota (inode->i_mapping, chg))return -ENOSPC ; - ret =hugetlb_acct_memory (chg); + ret =hugetlb_acct_memory (h, chg);if (ret <0 ) {hugetlb_put_quota (inode->i_mapping, chg);return ret;
@@ -1316,12 +1344,13 @@ int hugetlb_reserve_pages(struct inode *void hugetlb_unreserve_pages (struct inode *inode,long offset,long freed) { +struct hstate *h =hstate_inode (inode);long chg =region_truncate (&inode->i_mapping->private_list, offset);spin_lock (&inode->i_lock); - inode->i_blocks -=BLOCKS_PER_HUGEPAGE * freed; + inode->i_blocks -=blocks_per_hugepage (h);spin_unlock (&inode->i_lock);hugetlb_put_quota (inode->i_mapping, (chg - freed)); -hugetlb_acct_memory (-(chg - freed)); +hugetlb_acct_memory (h, -(chg - freed)); }
arch/powerpc/mm/hugetlbpage.c +1 -1
@@ -128,7 +128,7 @@ pte_t *huge_pte_offset(struct mm_structreturn NULL ; } -pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr) +pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz) {pgd_t *pg;pud_t *pu;
arch/sparc64/mm/hugetlbpage.c +2 -2
@@ -175,7 +175,7 @@ hugetlb_get_unmapped_area(struct file *freturn -ENOMEM ;if (flags &MAP_FIXED ) { -if (prepare_hugepage_range (addr, len)) +if (prepare_hugepage_range (file, addr, len))return -EINVAL ;return addr; }
@@ -195,7 +195,7 @@ hugetlb_get_unmapped_area(struct file *f pgoff, flags); } -pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr) +pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz) {pgd_t *pgd;pud_t *pud;
arch/sh/mm/hugetlbpage.c +1 -1
@@ -22,7 +22,7 @@#include <asm/tlbflush.h> #include <asm/cacheflush.h> -pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr) +pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz) {pgd_t *pgd;pud_t *pud;
arch/ia64/mm/hugetlbpage.c +3 -3
@@ -24,7 +24,7 @@unsigned int hpage_shift=HPAGE_SHIFT_DEFAULT ;pte_t * -huge_pte_alloc (struct mm_struct *mm,unsigned long addr) +huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz) {unsigned long taddr =htlbpage_to_page (addr);pgd_t *pgd;
@@ -75,7 +75,7 @@ int huge_pmd_unshare(struct mm_struct *m* Don't actually need to do any preparation, but need to make sure * the address is in the right region. */ -int prepare_hugepage_range (unsigned long addr,unsigned long len) +int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) {if (len & ~HPAGE_MASK )return -EINVAL ;
@@ -149,7 +149,7 @@ unsigned long hugetlb_get_unmapped_area(/* Handle MAP_FIXED */ if (flags &MAP_FIXED ) { -if (prepare_hugepage_range (addr, len)) +if (prepare_hugepage_range (file, addr, len))return -EINVAL ;return addr; }
arch/x86/mm/hugetlbpage.c +2 -2
@@ -124,7 +124,7 @@ int huge_pmd_unshare(struct mm_struct *mreturn 1 ; } -pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr) +pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz) {pgd_t *pgd;pud_t *pud;
@@ -368,7 +368,7 @@ hugetlb_get_unmapped_area(struct file *freturn -ENOMEM ;if (flags &MAP_FIXED ) { -if (prepare_hugepage_range (addr, len)) +if (prepare_hugepage_range (file, addr, len))return -EINVAL ;return addr; }
include/linux/hugetlb.h +76 -5
109 lines not on this page · raw message
fs/hugetlbfs/inode.c +28 -21
163 lines not on this page · raw message
ipc/shm.c +2 -1
@@ -577,7 +577,8 @@ static void shm_get_stat(struct ipc_nameif (is_file_hugepages (shp->shm_file)) {struct address_space *mapping = inode->i_mapping; - *rss += (HPAGE_SIZE /PAGE_SIZE )*mapping->nrpages; +struct hstate *h =hstate_file (shp->shm_file); + *rss += (1 <<huge_page_order (h)) * mapping->nrpages; }else {struct shmem_inode_info *info =SHMEM_I (inode);spin_lock (&info->lock);
mm/memory.c +1 -1
@@ -901,7 +901,7 @@ unsigned long unmap_vmas(struct mmu_gathif (unlikely (is_vm_hugetlb_page (vma))) {unmap_hugepage_range (vma, start, end); zap_work -= (end - start) / - (HPAGE_SIZE /PAGE_SIZE ); + (1 <<huge_page_order (hstate_vma (vma))); start = end; }else start = unmap_page_range(*tlbp, vma,
mm/mempolicy.c +6 -3
@@ -1477,7 +1477,7 @@ struct zonelist *huge_zonelist(struct vmif (unlikely ((*mpol)->mode ==MPOL_INTERLEAVE )) { zl =node_zonelist (interleave_nid (*mpol, vma, addr, -HPAGE_SHIFT ), gfp_flags); +huge_page_shift (hstate_vma (vma))), gfp_flags); }else { zl =policy_zonelist (gfp_flags, *mpol);if ((*mpol)->mode ==MPOL_BIND )
@@ -2216,9 +2216,12 @@ static void check_huge_range(struct vm_a {unsigned long addr;struct page *page; +struct hstate *h =hstate_vma (vma); +unsigned long sz =huge_page_size (h); -for (addr = start; addr < end; addr +=HPAGE_SIZE ) { -pte_t *ptep =huge_pte_offset (vma->vm_mm, addr &HPAGE_MASK ); +for (addr = start; addr < end; addr += sz) { +pte_t *ptep =huge_pte_offset (vma->vm_mm, + addr &huge_page_mask (h));pte_t pte;if (!ptep)
mm/mmap.c +2 -1
@@ -1800,7 +1800,8 @@ int split_vma(struct mm_struct * mm, strstruct mempolicy *pol;struct vm_area_struct *new; -if (is_vm_hugetlb_page (vma) && (addr & ~HPAGE_MASK )) +if (is_vm_hugetlb_page (vma) && (addr & + ~(huge_page_mask (hstate_vma (vma)))))return -EINVAL ;if (mm->map_count >= sysctl_max_map_count)
include/asm-ia64/hugetlb.h +1 -1
@@ -8,7 +8,7 @@ void hugetlb_free_pgd_range(struct mmu_g unsigned long end, unsigned long floor, unsigned long ceiling); -int prepare_hugepage_range (unsigned long addr,unsigned long len); +int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len); static inline int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
include/asm-powerpc/hugetlb.h +1 -1
@@ -21,7 +21,7 @@ pte_t huge_ptep_get_and_clear(struct mm_* If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range (unsigned long addr,unsigned long len) +static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) {if (len & ~HPAGE_MASK )return -EINVAL ;
include/asm-s390/hugetlb.h +1 -1
@@ -22,7 +22,7 @@ void set_huge_pte_at(struct mm_struct *m* If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range (unsigned long addr,unsigned long len) +static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) {if (len & ~HPAGE_MASK )return -EINVAL ;
include/asm-sh/hugetlb.h +1 -1
@@ -14,7 +14,7 @@ static inline int is_hugepage_only_range* If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range (unsigned long addr,unsigned long len) +static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) {if (len & ~HPAGE_MASK )return -EINVAL ;
include/asm-sparc64/hugetlb.h +1 -1
@@ -22,7 +22,7 @@ static inline int is_hugepage_only_range* If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range (unsigned long addr,unsigned long len) +static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) {if (len & ~HPAGE_MASK )return -EINVAL ;
include/asm-x86/hugetlb.h +4 -3
@@ -14,11 +14,12 @@ static inline int is_hugepage_only_range* If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range (unsigned long addr,unsigned long len) +static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) { -if (len & ~HPAGE_MASK ) +struct hstate *h =hstate_file (file); +if (len & ~huge_page_mask (h))return -EINVAL ; -if (addr & ~HPAGE_MASK ) +if (addr & ~huge_page_mask (h))return -EINVAL ;return 0 ; }
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 03/23] hugetlb: modular state
Quoted 69 lines · On 26.05.2008 [00:23:20 +1000], [email protected] wrote:
Large, but rather mechanical patch that converts most of the
hugetlb.cglobals into structure members and passes them around.Right now there is only a single global hstate structure, but most of the infrastructure to extend it is there.
Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>--- arch/ia64/mm/hugetlbpage.c | 6 arch/powerpc/mm/hugetlbpage.c | 2 arch/sh/mm/hugetlbpage.c | 2 arch/sparc64/mm/hugetlbpage.c | 4 arch/x86/mm/hugetlbpage.c | 4 fs/hugetlbfs/inode.c | 49 +++--- include/asm-ia64/hugetlb.h | 2 include/asm-powerpc/hugetlb.h | 2 include/asm-s390/hugetlb.h | 2 include/asm-sh/hugetlb.h | 2 include/asm-sparc64/hugetlb.h | 2 include/asm-x86/hugetlb.h | 7 include/linux/hugetlb.h | 81 +++++++++- ipc/shm.c | 3 mm/hugetlb.c | 321 ++++++++++++++++++++++-------------------- mm/memory.c | 2 mm/mempolicy.c | 9 - mm/mmap.c | 3 18 files changed, 308 insertions(+), 195 deletions(-)Index:
linux-2.6/mm/hugetlb.c
===================================================================mm/hugetlb.c +4
-10@@ -22,30 +22,24 @@#include "internal.h" const unsigned long hugetlb_zero =0 , hugetlb_infinity = ~0UL ; -static unsigned long nr_huge_pages, free_huge_pages, resv_huge_pages; -static unsigned long surplus_huge_pages; -static unsigned long nr_overcommit_huge_pages;unsigned long max_huge_pages;unsigned long sysctl_overcommit_huge_pages; -static struct list_head hugepage_freelists[MAX_NUMNODES ]; -static unsigned int nr_huge_pages_node[MAX_NUMNODES ]; -static unsigned int free_huge_pages_node[MAX_NUMNODES ]; -static unsigned int surplus_huge_pages_node[MAX_NUMNODES ];static gfp_t htlb_alloc_mask =GFP_HIGHUSER ;unsigned long hugepages_treat_as_movable; -static int hugetlb_next_nid; + +struct hstate global_hstate;/* * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages */ static DEFINE_SPINLOCK (hugetlb_lock); -static void clear_huge_page (struct page *page,unsigned long addr) +static void clear_huge_page (struct page *page,unsigned long addr,unsigned long sz) {int i;might_sleep (); -for (i =0 ; i < (HPAGE_SIZE /PAGE_SIZE ); i++) { +for (i =0 ; i < sz/PAGE_SIZE ; i++) {cond_resched ();clear_user_highpage (page + i, addr + i *PAGE_SIZE ); }
mm/hugetlb.c static void copy_huge_page(struct page * · line 55
Quoted 8 lines
mm/hugetlb.c +2
-1@@ -55,42 +49,43 @@ static void copy_huge_page(struct page * unsigned long addr, struct vm_area_struct *vma) { int i; +struct hstate *h =hstate_vma (vma);might_sleep (); -for (i =0 ; i <HPAGE_SIZE /PAGE_SIZE ; i++) { +for (i =0 ; i <1 <<huge_page_order (h); i++) {
So it seems like most (not quite all) users of huge_page_order(h) don't actually care about the order, per se, but want some sense of the underlying pagesize. Either pages_per_huge_page() or huge_page_size().
So perhaps it would be sensible to have the helpers defined as such?
huge_page_size(h) -> size in bytes of huge page (corresponds to what was HPAGE_SIZE), which is what I think you currently have
and
pages_per_huge_page(h) -> number of base pages per huge page (corresponds to HPAGE_SIZE / PAGE_SIZE)
?
Also, I noticed that this caller has no parentheses, but the other one does, for (1 << huge_page_order(h))
Neither are huge issues and the first can be a clean-up patch from me, so
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 03/23] hugetlb: modular state
Quoted 15 lines · Nishanth Aravamudan
mm/hugetlb.c static void copy_huge_page(struct page * · line 55
Quoted 4 lines · On 26.05.2008 [00:23:20 +1000], [email protected] wrote:
mm/hugetlb.c +1
-1might_sleep (); -for (i =0 ; i <HPAGE_SIZE /PAGE_SIZE ; i++) { +for (i =0 ; i <1 <<huge_page_order (h); i++) {So it seems like most (not quite all) users of
huge_page_order(h)don't actually care about the order, per se, but want some sense of the underlying pagesize. Eitherpages_per_huge_page()orhuge_page_size().So perhaps it would be sensible to have the helpers defined as such?
huge_page_size(h)-> size in bytes of huge page (corresponds to what wasHPAGE_SIZE), which is what I think you currently have
Quoted 6 lines
and
pages_per_huge_page(h)-> number of base pages per huge page (corresponds toHPAGE_SIZE/PAGE_SIZE)?
I think pages_per_huge_page would be reasonable, yes.
Quoted 7 lines
Also, I noticed that this caller has no parentheses, but the other one does, for (1 <<
huge_page_order(h))Neither are huge issues and the first can be a clean-up patch from me, so
Thanks... I'll do pages_per_huge_page(), it won't be much work.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 03/23] hugetlb: modular state
In reply to [email protected]Phew. At last I made it to the end of this one :) It seems okay to me though. Have you done any performance testing on this patch series yet? I don't expect the hstate structure to introduce any measurable performance degradation, but it would be nice to have some numbers to back up that educated guess.
Quoted 1,473 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlb-modular-state.patch) Large, but rather mechanical patch that converts most of the
hugetlb.cglobals into structure members and passes them around.Right now there is only a single global hstate structure, but most of the infrastructure to extend it is there.
Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>--- arch/ia64/mm/hugetlbpage.c | 6 arch/powerpc/mm/hugetlbpage.c | 2 arch/sh/mm/hugetlbpage.c | 2 arch/sparc64/mm/hugetlbpage.c | 4 arch/x86/mm/hugetlbpage.c | 4 fs/hugetlbfs/inode.c | 49 +++--- include/asm-ia64/hugetlb.h | 2 include/asm-powerpc/hugetlb.h | 2 include/asm-s390/hugetlb.h | 2 include/asm-sh/hugetlb.h | 2 include/asm-sparc64/hugetlb.h | 2 include/asm-x86/hugetlb.h | 7 include/linux/hugetlb.h | 81 +++++++++- ipc/shm.c | 3 mm/hugetlb.c | 321 ++++++++++++++++++++++-------------------- mm/memory.c | 2 mm/mempolicy.c | 9 - mm/mmap.c | 3 18 files changed, 308 insertions(+), 195 deletions(-)Index:
linux-2.6/mm/hugetlb.c
===================================================================mm/hugetlb.c +175
-146@@ -22,30 +22,24 @@#include "internal.h" const unsigned long hugetlb_zero =0 , hugetlb_infinity = ~0UL ; -static unsigned long nr_huge_pages, free_huge_pages, resv_huge_pages; -static unsigned long surplus_huge_pages; -static unsigned long nr_overcommit_huge_pages;unsigned long max_huge_pages;unsigned long sysctl_overcommit_huge_pages; -static struct list_head hugepage_freelists[MAX_NUMNODES ]; -static unsigned int nr_huge_pages_node[MAX_NUMNODES ]; -static unsigned int free_huge_pages_node[MAX_NUMNODES ]; -static unsigned int surplus_huge_pages_node[MAX_NUMNODES ];static gfp_t htlb_alloc_mask =GFP_HIGHUSER ;unsigned long hugepages_treat_as_movable; -static int hugetlb_next_nid; + +struct hstate global_hstate;/* * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages */ static DEFINE_SPINLOCK (hugetlb_lock); -static void clear_huge_page (struct page *page,unsigned long addr) +static void clear_huge_page (struct page *page,unsigned long addr,unsigned long sz) {int i;might_sleep (); -for (i =0 ; i < (HPAGE_SIZE /PAGE_SIZE ); i++) { +for (i =0 ; i < sz/PAGE_SIZE ; i++) {cond_resched ();clear_user_highpage (page + i, addr + i *PAGE_SIZE ); }@@ -55,42 +49,43 @@ static void copy_huge_page(struct page * unsigned long addr, struct vm_area_struct *vma) { int i; +struct hstate *h =hstate_vma (vma);might_sleep (); -for (i =0 ; i <HPAGE_SIZE /PAGE_SIZE ; i++) { +for (i =0 ; i <1 <<huge_page_order (h); i++) {cond_resched ();copy_user_highpage (dst + i, src + i, addr + i*PAGE_SIZE , vma); } } -static void enqueue_huge_page (struct page *page) +static void enqueue_huge_page (struct hstate *h,struct page *page) {int nid =page_to_nid (page); -list_add (&page->lru, &hugepage_freelists[nid]); - free_huge_pages++; - free_huge_pages_node[nid]++; +list_add (&page->lru, &h->hugepage_freelists[nid]); + h->free_huge_pages++; + h->free_huge_pages_node[nid]++; } -static struct page *dequeue_huge_page (void ) +static struct page *dequeue_huge_page (struct hstate *h) {int nid;struct page *page =NULL ;for (nid =0 ; nid <MAX_NUMNODES ; ++nid) { -if (!list_empty (&hugepage_freelists[nid])) { - page =list_entry (hugepage_freelists[nid].next, +if (!list_empty (&h->hugepage_freelists[nid])) { + page =list_entry (h->hugepage_freelists[nid].next, struct page, lru);list_del (&page->lru); - free_huge_pages--; - free_huge_pages_node[nid]--; + h->free_huge_pages--; + h->free_huge_pages_node[nid]--;break ; } }return page; } -static struct page *dequeue_huge_page_vma (struct vm_area_struct *vma, -unsigned long address) +static struct page *dequeue_huge_page_vma (struct hstate *h, +struct vm_area_struct *vma,unsigned long address) {int nid;struct page *page =NULL ;@@ -105,14 +100,14 @@ static struct page *dequeue_huge_page_vm MAX_NR_ZONES - 1, nodemask) { nid =zone_to_nid (zone);if (cpuset_zone_allowed_softwall (zone, htlb_alloc_mask) && - !list_empty (&hugepage_freelists[nid])) { - page =list_entry (hugepage_freelists[nid].next, + !list_empty (&h->hugepage_freelists[nid])) { + page =list_entry (h->hugepage_freelists[nid].next, struct page, lru);list_del (&page->lru); - free_huge_pages--; - free_huge_pages_node[nid]--; + h->free_huge_pages--; + h->free_huge_pages_node[nid]--;if (vma && vma->vm_flags &VM_MAYSHARE ) - resv_huge_pages--; + h->resv_huge_pages--;break ; } }@@ -120,12 +115,13 @@ static struct page *dequeue_huge_page_vmreturn page; } -static void update_and_free_page (struct page *page) +static void update_and_free_page (struct hstate *h,struct page *page) {int i; - nr_huge_pages--; - nr_huge_pages_node[page_to_nid (page)]--; -for (i =0 ; i < (HPAGE_SIZE /PAGE_SIZE ); i++) { + + h->nr_huge_pages--; + h->nr_huge_pages_node[page_to_nid (page)]--; +for (i =0 ; i < (1 <<huge_page_order (h)); i++) { page[i].flags &= ~(1 << PG_locked |1 << PG_error |1 << PG_referenced |1 << PG_dirty |1 << PG_active |1 << PG_reserved |1 << PG_private |1 << PG_writeback);@@ -133,11 +129,16 @@ static void update_and_free_page(structset_compound_page_dtor (page,NULL );set_page_refcounted (page);arch_release_hugepage (page); -__free_pages (page,HUGETLB_PAGE_ORDER ); +__free_pages (page,huge_page_order (h)); }static void free_huge_page (struct page *page) { +/* +* Can't pass hstate in here because it is called from the +* compound page destructor. +*/ +struct hstate *h = &global_hstate;int nid =page_to_nid (page);struct address_space *mapping;@@ -147,12 +148,12 @@ static void free_huge_page(struct page *INIT_LIST_HEAD (&page->lru);spin_lock (&hugetlb_lock); -if (surplus_huge_pages_node[nid]) { -update_and_free_page (page); - surplus_huge_pages--; - surplus_huge_pages_node[nid]--; +if (h->surplus_huge_pages_node[nid]) { +update_and_free_page (h, page); + h->surplus_huge_pages--; + h->surplus_huge_pages_node[nid]--; }else { -enqueue_huge_page (page); +enqueue_huge_page (h, page); }spin_unlock (&hugetlb_lock);if (mapping)@@ -164,7 +165,7 @@ static void free_huge_page(struct page ** balanced by operating on them in a round-robin fashion. * Returns 1 if an adjustment was made. */ -static int adjust_pool_surplus (int delta) +static int adjust_pool_surplus (struct hstate *h,int delta) {static int prev_nid;int nid = prev_nid;@@ -177,15 +178,15 @@ static int adjust_pool_surplus(int delta nid =first_node (node_online_map);/* To shrink on this node, there must be a surplus page */ -if (delta <0 && !surplus_huge_pages_node[nid]) +if (delta <0 && !h->surplus_huge_pages_node[nid])continue ;/* Surplus cannot exceed the total number of pages */ -if (delta >0 && surplus_huge_pages_node[nid] >= - nr_huge_pages_node[nid]) +if (delta >0 && h->surplus_huge_pages_node[nid] >= + h->nr_huge_pages_node[nid])continue ; - surplus_huge_pages += delta; - surplus_huge_pages_node[nid] += delta; + h->surplus_huge_pages += delta; + h->surplus_huge_pages_node[nid] += delta; ret =1 ;break ; }while (nid != prev_nid);@@ -194,46 +195,46 @@ static int adjust_pool_surplus(int deltareturn ret; } -static void prep_new_huge_page (struct page *page,int nid) +static void prep_new_huge_page (struct hstate *h,struct page *page,int nid) {set_compound_page_dtor (page, free_huge_page);spin_lock (&hugetlb_lock); - nr_huge_pages++; - nr_huge_pages_node[nid]++; + h->nr_huge_pages++; + h->nr_huge_pages_node[nid]++;spin_unlock (&hugetlb_lock);put_page (page);/* free it into the hugepage allocator */ } -static struct page *alloc_fresh_huge_page_node (int nid) +static struct page *alloc_fresh_huge_page_node (struct hstate *h,int nid) {struct page *page; page =alloc_pages_node (nid, htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE| __GFP_REPEAT|__GFP_NOWARN, -HUGETLB_PAGE_ORDER ); +huge_page_order (h));if (page) {if (arch_prepare_hugepage (page)) {__free_pages (page,HUGETLB_PAGE_ORDER );return NULL ; } -prep_new_huge_page (page, nid); +prep_new_huge_page (h, page, nid); }return page; } -static int alloc_fresh_huge_page (void ) +static int alloc_fresh_huge_page (struct hstate *h) {struct page *page;int start_nid;int next_nid;int ret =0 ; - start_nid = hugetlb_next_nid; + start_nid = h->hugetlb_next_nid; do { - page = alloc_fresh_huge_page_node(hugetlb_next_nid); + page = alloc_fresh_huge_page_node(h, h->hugetlb_next_nid); if (page) ret = 1; /*@@ -247,11 +248,11 @@ static int alloc_fresh_huge_page(void)* if we just successfully allocated a hugepage so that * the next caller gets hugepages on the next node. */ - next_nid =next_node (hugetlb_next_nid, node_online_map); + next_nid =next_node (h->hugetlb_next_nid, node_online_map);if (next_nid ==MAX_NUMNODES ) next_nid =first_node (node_online_map); - hugetlb_next_nid = next_nid; - }while (!page && hugetlb_next_nid != start_nid); + h->hugetlb_next_nid = next_nid; + }while (!page && h->hugetlb_next_nid != start_nid);if (ret)count_vm_event (HTLB_BUDDY_PGALLOC );@@ -261,8 +262,8 @@ static int alloc_fresh_huge_page(void)return ret; } -static struct page *alloc_buddy_huge_page (struct vm_area_struct *vma, -unsigned long address) +static struct page *alloc_buddy_huge_page (struct hstate *h, +struct vm_area_struct *vma,unsigned long address) {struct page *page;unsigned int nid;@@ -291,18 +292,18 @@ static struct page *alloc_buddy_huge_pag* per-node value is checked there. */ spin_lock (&hugetlb_lock); -if (surplus_huge_pages >= nr_overcommit_huge_pages) { +if (h->surplus_huge_pages >= h->nr_overcommit_huge_pages) {spin_unlock (&hugetlb_lock);return NULL ; }else { - nr_huge_pages++; - surplus_huge_pages++; + h->nr_huge_pages++; + h->surplus_huge_pages++; }spin_unlock (&hugetlb_lock); page =alloc_pages (htlb_alloc_mask|__GFP_COMP| __GFP_REPEAT|__GFP_NOWARN, -HUGETLB_PAGE_ORDER ); +huge_page_order (h));spin_lock (&hugetlb_lock);if (page) {@@ -317,12 +318,12 @@ static struct page *alloc_buddy_huge_pag/* * We incremented the global counters already */ - nr_huge_pages_node[nid]++; - surplus_huge_pages_node[nid]++; + h->nr_huge_pages_node[nid]++; + h->surplus_huge_pages_node[nid]++;__count_vm_event (HTLB_BUDDY_PGALLOC ); }else { - nr_huge_pages--; - surplus_huge_pages--; + h->nr_huge_pages--; + h->surplus_huge_pages--;__count_vm_event (HTLB_BUDDY_PGALLOC_FAIL ); }spin_unlock (&hugetlb_lock);@@ -334,16 +335,16 @@ static struct page *alloc_buddy_huge_pag* Increase the hugetlb pool such that it can accomodate a reservation * of size 'delta'. */ -static int gather_surplus_pages (int delta) +static int gather_surplus_pages (struct hstate *h,int delta) {struct list_head surplus_list;struct page *page, *tmp;int ret, i;int needed, allocated; - needed = (resv_huge_pages + delta) - free_huge_pages; + needed = (h->resv_huge_pages + delta) - h->free_huge_pages;if (needed <=0 ) { - resv_huge_pages += delta; + h->resv_huge_pages += delta;return 0 ; }@@ -354,7 +355,7 @@ static int gather_surplus_pages(int delt retry:spin_unlock (&hugetlb_lock);for (i =0 ; i < needed; i++) { - page =alloc_buddy_huge_page (NULL ,0 ); + page =alloc_buddy_huge_page (h,NULL ,0 );if (!page) {/* * We were not able to allocate enough pages to @@ -375,7 +376,8 @@ retry:* because either resv_huge_pages or free_huge_pages may have changed. */ spin_lock (&hugetlb_lock); - needed = (resv_huge_pages + delta) - (free_huge_pages + allocated); + needed = (h->resv_huge_pages + delta) - + (h->free_huge_pages + allocated);if (needed >0 ) goto retry;@@ -388,7 +390,7 @@ retry:* before they are reserved. */ needed += allocated; - resv_huge_pages += delta; + h->resv_huge_pages += delta; ret =0 ; free:/* Free the needed pages to the hugetlb pool */ @@ -396,7 +398,7 @@ free:if ((--needed) <0 )break ;list_del (&page->lru); -enqueue_huge_page (page); +enqueue_huge_page (h, page); }/* Free unnecessary surplus pages to the buddy allocator */ @@ -424,7 +426,8 @@ free:* allocated to satisfy the reservation must be explicitly freed if they were * never used. */ -static void return_unused_surplus_pages (unsigned long unused_resv_pages) +static void return_unused_surplus_pages (struct hstate *h, +unsigned long unused_resv_pages) {static int nid =-1 ;struct page *page;@@ -439,27 +442,27 @@ static void return_unused_surplus_pages(unsigned long remaining_iterations =num_online_nodes ();/* Uncommit the reservation */ - resv_huge_pages -= unused_resv_pages; + h->resv_huge_pages -= unused_resv_pages; - nr_pages =min (unused_resv_pages, surplus_huge_pages); + nr_pages =min (unused_resv_pages, h->surplus_huge_pages);while (remaining_iterations-- && nr_pages) { nid =next_node (nid, node_online_map);if (nid ==MAX_NUMNODES ) nid =first_node (node_online_map); -if (!surplus_huge_pages_node[nid]) +if (!h->surplus_huge_pages_node[nid])continue ; -if (!list_empty (&hugepage_freelists[nid])) { - page =list_entry (hugepage_freelists[nid].next, +if (!list_empty (&h->hugepage_freelists[nid])) { + page =list_entry (h->hugepage_freelists[nid].next, struct page, lru);list_del (&page->lru); -update_and_free_page (page); - free_huge_pages--; - free_huge_pages_node[nid]--; - surplus_huge_pages--; - surplus_huge_pages_node[nid]--; +update_and_free_page (h, page); + h->free_huge_pages--; + h->free_huge_pages_node[nid]--; + h->surplus_huge_pages--; + h->surplus_huge_pages_node[nid]--; nr_pages--; remaining_iterations =num_online_nodes (); }@@ -471,9 +474,10 @@ static struct page *alloc_huge_page_shar unsigned long addr) {struct page *page; +struct hstate *h =hstate_vma (vma);spin_lock (&hugetlb_lock); - page =dequeue_huge_page_vma (vma, addr); + page =dequeue_huge_page_vma (h, vma, addr);spin_unlock (&hugetlb_lock);return page ? page :ERR_PTR (-VM_FAULT_OOM ); }@@ -482,16 +486,17 @@ static struct page *alloc_huge_page_priv unsigned long addr) {struct page *page =NULL ; +struct hstate *h =hstate_vma (vma);if (hugetlb_get_quota (vma->vm_file->f_mapping,1 ))return ERR_PTR (-VM_FAULT_SIGBUS );spin_lock (&hugetlb_lock); -if (free_huge_pages > resv_huge_pages) - page =dequeue_huge_page_vma (vma, addr); +if (h->free_huge_pages > h->resv_huge_pages) + page =dequeue_huge_page_vma (h, vma, addr);spin_unlock (&hugetlb_lock);if (!page) { - page =alloc_buddy_huge_page (vma, addr); + page =alloc_buddy_huge_page (h, vma, addr);if (!page) {hugetlb_put_quota (vma->vm_file->f_mapping,1 );return ERR_PTR (-VM_FAULT_OOM );@@ -521,21 +526,27 @@ static struct page *alloc_huge_page(strustatic int __init hugetlb_init (void ) {unsigned long i; +struct hstate *h = &global_hstate;if (HPAGE_SHIFT ==0 )return 0 ; +if (!h->order) { + h->order =HPAGE_SHIFT -PAGE_SHIFT ; + h->mask =HPAGE_MASK ; + } +for (i =0 ; i <MAX_NUMNODES ; ++i) -INIT_LIST_HEAD (&hugepage_freelists[i]); +INIT_LIST_HEAD (&h->hugepage_freelists[i]); - hugetlb_next_nid =first_node (node_online_map); + h->hugetlb_next_nid =first_node (node_online_map);for (i =0 ; i < max_huge_pages; ++i) { -if (!alloc_fresh_huge_page ()) +if (!alloc_fresh_huge_page (h))break ; } - max_huge_pages = free_huge_pages = nr_huge_pages = i; -printk ("Total HugeTLB memory allocated, %ld\n" , free_huge_pages); + max_huge_pages = h->free_huge_pages = h->nr_huge_pages = i; +printk ("Total HugeTLB memory allocated, %ld\n" , h->free_huge_pages);return 0 ; }module_init (hugetlb_init);@@ -561,34 +572,36 @@ static unsigned int cpuset_mems_nr(unsig#ifdef CONFIG_SYSCTL #ifdef CONFIG_HIGHMEM -static void try_to_free_low (unsigned long count) +static void try_to_free_low (struct hstate *h,unsigned long count) {int i;for (i =0 ; i <MAX_NUMNODES ; ++i) {struct page *page, *next; -list_for_each_entry_safe (page, next, &hugepage_freelists[i], lru) { -if (count >= nr_huge_pages) +struct list_head *freel = &h->hugepage_freelists[i]; +list_for_each_entry_safe (page, next, freel, lru) { +if (count >= h->nr_huge_pages)return ;if (PageHighMem (page))continue ;list_del (&page->lru);update_and_free_page (page); - free_huge_pages--; - free_huge_pages_node[page_to_nid (page)]--; + h->free_huge_pages--; + h->free_huge_pages_node[page_to_nid (page)]--; } } }#else -static inline void try_to_free_low (unsigned long count) +static inline void try_to_free_low (struct hstate *h,unsigned long count) { }#endif -#define persistent_huge_pages (nr_huge_pages - surplus_huge_pages) +#define persistent_huge_pages (h) (h->nr_huge_pages - h->surplus_huge_pages)static unsigned long set_max_huge_pages (unsigned long count) {unsigned long min_count, ret; +struct hstate *h = &global_hstate;/* * Increase the pool size @@ -602,12 +615,12 @@ static unsigned long set_max_huge_pages(* within all the constraints specified by the sysctls. */ spin_lock (&hugetlb_lock); -while (surplus_huge_pages && count > persistent_huge_pages) { -if (!adjust_pool_surplus (-1 )) +while (h->surplus_huge_pages && count >persistent_huge_pages (h)) { +if (!adjust_pool_surplus (h,-1 ))break ; } -while (count > persistent_huge_pages) { +while (count >persistent_huge_pages (h)) {int ret;/* * If this allocation races such that we no longer need the @@ -615,7 +628,7 @@ static unsigned long set_max_huge_pages(* and reducing the surplus. */ spin_unlock (&hugetlb_lock); - ret =alloc_fresh_huge_page (); + ret =alloc_fresh_huge_page (h);spin_lock (&hugetlb_lock);if (!ret) goto out;@@ -637,21 +650,21 @@ static unsigned long set_max_huge_pages(* and won't grow the pool anywhere else. Not until one of the * sysctls are changed, or the surplus pages go out of use. */ - min_count = resv_huge_pages + nr_huge_pages - free_huge_pages; + min_count = h->resv_huge_pages + h->nr_huge_pages - h->free_huge_pages; min_count =max (count, min_count); -try_to_free_low (min_count); -while (min_count < persistent_huge_pages) { -struct page *page =dequeue_huge_page (); +try_to_free_low (h, min_count); +while (min_count <persistent_huge_pages (h)) { +struct page *page =dequeue_huge_page (h);if (!page)break ; -update_and_free_page (page); +update_and_free_page (h, page); } -while (count < persistent_huge_pages) { -if (!adjust_pool_surplus (1 )) +while (count <persistent_huge_pages (h)) { +if (!adjust_pool_surplus (h,1 ))break ; } out: - ret = persistent_huge_pages; + ret =persistent_huge_pages (h);spin_unlock (&hugetlb_lock);return ret; }@@ -681,9 +694,10 @@ int hugetlb_overcommit_handler(struct ct struct file *file, void __user *buffer, size_t *length, loff_t *ppos) { + struct hstate *h = &global_hstate;proc_doulongvec_minmax (table, write, file, buffer, length, ppos);spin_lock (&hugetlb_lock); - nr_overcommit_huge_pages = sysctl_overcommit_huge_pages; + h->nr_overcommit_huge_pages = sysctl_overcommit_huge_pages;spin_unlock (&hugetlb_lock);return 0 ; }@@ -692,34 +706,37 @@ int hugetlb_overcommit_handler(struct ctint hugetlb_report_meminfo (char *buf) { +struct hstate *h = &global_hstate;return sprintf (buf,"HugePages_Total: %5lu\n" "HugePages_Free: %5lu\n" "HugePages_Rsvd: %5lu\n" "HugePages_Surp: %5lu\n" "Hugepagesize: %5lu kB\n" , - nr_huge_pages, - free_huge_pages, - resv_huge_pages, - surplus_huge_pages, -HPAGE_SIZE /1024 ); + h->nr_huge_pages, + h->free_huge_pages, + h->resv_huge_pages, + h->surplus_huge_pages, +1UL << (huge_page_order (h) +PAGE_SHIFT -10 )); }int hugetlb_report_node_meminfo (int nid,char *buf) { +struct hstate *h = &global_hstate;return sprintf (buf,"Node %d HugePages_Total: %5u\n" "Node %d HugePages_Free: %5u\n" "Node %d HugePages_Surp: %5u\n" , - nid, nr_huge_pages_node[nid], - nid, free_huge_pages_node[nid], - nid, surplus_huge_pages_node[nid]); + nid, h->nr_huge_pages_node[nid], + nid, h->free_huge_pages_node[nid], + nid, h->surplus_huge_pages_node[nid]); }/* Return the number pages of memory we physically have, in PAGE_SIZE units. */ unsigned long hugetlb_total_pages (void ) { -return nr_huge_pages * (HPAGE_SIZE /PAGE_SIZE ); +struct hstate *h = &global_hstate; +return h->nr_huge_pages * (1 <<huge_page_order (h)); }/* @@ -774,14 +791,16 @@ int copy_hugetlb_page_range(struct mm_ststruct page *ptepage;unsigned long addr;int cow; +struct hstate *h =hstate_vma (vma); +unsigned long sz =huge_page_size (h); cow = (vma->vm_flags & (VM_SHARED |VM_MAYWRITE )) ==VM_MAYWRITE ; -for (addr = vma->vm_start; addr < vma->vm_end; addr +=HPAGE_SIZE ) { +for (addr = vma->vm_start; addr < vma->vm_end; addr += sz) { src_pte =huge_pte_offset (src, addr);if (!src_pte)continue ; - dst_pte =huge_pte_alloc (dst, addr); + dst_pte =huge_pte_alloc (dst, addr, sz);if (!dst_pte) goto nomem;@@ -817,6 +836,9 @@ void __unmap_hugepage_range(struct vm_arpte_t pte;struct page *page;struct page *tmp; +struct hstate *h =hstate_vma (vma); +unsigned long sz =huge_page_size (h); +/* * A page gathering list, protected by per file i_mmap_lock. The * lock is used to avoid list corruption from multiple unmapping @@ -825,11 +847,11 @@ void __unmap_hugepage_range(struct vm_arLIST_HEAD (page_list);WARN_ON (!is_vm_hugetlb_page (vma)); -BUG_ON (start & ~HPAGE_MASK ); -BUG_ON (end & ~HPAGE_MASK ); +BUG_ON (start & ~huge_page_mask (h)); +BUG_ON (end & ~huge_page_mask (h));spin_lock (&mm->page_table_lock); -for (address = start; address < end; address +=HPAGE_SIZE ) { +for (address = start; address < end; address += sz) { ptep =huge_pte_offset (mm, address);if (!ptep)continue ;@@ -877,6 +899,7 @@ static int hugetlb_cow(struct mm_struct {struct page *old_page, *new_page;int avoidcopy; +struct hstate *h =hstate_vma (vma); old_page =pte_page (pte);@@ -901,7 +924,7 @@ static int hugetlb_cow(struct mm_struct__SetPageUptodate (new_page);spin_lock (&mm->page_table_lock); - ptep =huge_pte_offset (mm, address &HPAGE_MASK ); + ptep =huge_pte_offset (mm, address &huge_page_mask (h));if (likely (pte_same (huge_ptep_get (ptep), pte))) {/* Break COW */ huge_ptep_clear_flush (vma, address, ptep);@@ -924,10 +947,11 @@ static int hugetlb_no_page(struct mm_strstruct page *page;struct address_space *mapping;pte_t new_pte; +struct hstate *h =hstate_vma (vma); mapping = vma->vm_file->f_mapping; - idx = ((address - vma->vm_start) >>HPAGE_SHIFT ) - + (vma->vm_pgoff >> (HPAGE_SHIFT -PAGE_SHIFT )); + idx = ((address - vma->vm_start) >>huge_page_shift (h)) + + (vma->vm_pgoff >>huge_page_order (h));/* * Use page lock to guard against racing truncation @@ -936,7 +960,7 @@ static int hugetlb_no_page(struct mm_str retry: page =find_lock_page (mapping, idx);if (!page) { - size =i_size_read (mapping->host) >>HPAGE_SHIFT ; + size =i_size_read (mapping->host) >>huge_page_shift (h);if (idx >= size) goto out; page =alloc_huge_page (vma, address);@@ -944,7 +968,7 @@ retry: ret = -PTR_ERR (page); goto out; } -clear_huge_page (page, address); +clear_huge_page (page, address,huge_page_size (h));__SetPageUptodate (page);if (vma->vm_flags &VM_SHARED ) {@@ -960,14 +984,14 @@ retry: }spin_lock (&inode->i_lock); - inode->i_blocks +=BLOCKS_PER_HUGEPAGE ; + inode->i_blocks +=blocks_per_hugepage (h);spin_unlock (&inode->i_lock); }else lock_page (page); }spin_lock (&mm->page_table_lock); - size =i_size_read (mapping->host) >>HPAGE_SHIFT ; + size =i_size_read (mapping->host) >>huge_page_shift (h);if (idx >= size) goto backout;@@ -1003,8 +1027,9 @@ int hugetlb_fault(struct mm_struct *mm,pte_t entry;int ret;static DEFINE_MUTEX (hugetlb_instantiation_mutex); +struct hstate *h =hstate_vma (vma); - ptep =huge_pte_alloc (mm, address); + ptep =huge_pte_alloc (mm, address,huge_page_size (h));if (!ptep)return VM_FAULT_OOM ;@@ -1042,6 +1067,7 @@ int follow_hugetlb_page(struct mm_structunsigned long pfn_offset;unsigned long vaddr = *position;int remainder = *length; +struct hstate *h =hstate_vma (vma);spin_lock (&mm->page_table_lock);while (vaddr < vma->vm_end && remainder) {@@ -1053,7 +1079,7 @@ int follow_hugetlb_page(struct mm_struct* each hugepage. We have to make * sure we get the * first, for the page indexing below to work. */ - pte =huge_pte_offset (mm, vaddr &HPAGE_MASK ); + pte =huge_pte_offset (mm, vaddr &huge_page_mask (h));if (!pte ||huge_pte_none (huge_ptep_get (pte)) || (write && !pte_write (huge_ptep_get (pte)))) {@@ -1071,7 +1097,7 @@ int follow_hugetlb_page(struct mm_structbreak ; } - pfn_offset = (vaddr & ~HPAGE_MASK ) >>PAGE_SHIFT ; + pfn_offset = (vaddr & ~huge_page_mask (h)) >>PAGE_SHIFT ; page =pte_page (huge_ptep_get (pte)); same_page:if (pages) {@@ -1087,7 +1113,7 @@ same_page: --remainder; ++i;if (vaddr < vma->vm_end && remainder && - pfn_offset <HPAGE_SIZE /PAGE_SIZE ) { + pfn_offset < (1 <<huge_page_order (h))) {/* * We use pfn_offset to avoid touching the pageframes * of this compound page. @@ -1109,13 +1135,14 @@ void hugetlb_change_protection(struct vmunsigned long start = address;pte_t *ptep;pte_t pte; +struct hstate *h =hstate_vma (vma);BUG_ON (address >= end);flush_cache_range (vma, address, end);spin_lock (&vma->vm_file->f_mapping->i_mmap_lock);spin_lock (&mm->page_table_lock); -for (; address < end; address +=HPAGE_SIZE ) { +for (; address < end; address +=huge_page_size (h)) { ptep =huge_pte_offset (mm, address);if (!ptep)continue ;@@ -1254,7 +1281,7 @@ static long region_truncate(struct list_return chg; } -static int hugetlb_acct_memory (long delta) +static int hugetlb_acct_memory (struct hstate *h,long delta) {int ret = -ENOMEM ;@@ -1277,18 +1304,18 @@ static int hugetlb_acct_memory(long delt* semantics that cpuset has. */ if (delta >0 ) { -if (gather_surplus_pages (delta) <0 ) +if (gather_surplus_pages (h, delta) <0 ) goto out; -if (delta >cpuset_mems_nr (free_huge_pages_node)) { -return_unused_surplus_pages (delta); +if (delta >cpuset_mems_nr (h->free_huge_pages_node)) { +return_unused_surplus_pages (h, delta); goto out; } } ret =0 ;if (delta <0 ) -return_unused_surplus_pages ((unsigned long ) -delta); +return_unused_surplus_pages (h, (unsigned long ) -delta); out:spin_unlock (&hugetlb_lock);@@ -1298,6 +1325,7 @@ out:int hugetlb_reserve_pages (struct inode *inode,long from,long to) {long ret, chg; +struct hstate *h =hstate_inode (inode); chg =region_chg (&inode->i_mapping->private_list, from, to);if (chg <0 )@@ -1305,7 +1333,7 @@ int hugetlb_reserve_pages(struct inode *if (hugetlb_get_quota (inode->i_mapping, chg))return -ENOSPC ; - ret =hugetlb_acct_memory (chg); + ret =hugetlb_acct_memory (h, chg);if (ret <0 ) {hugetlb_put_quota (inode->i_mapping, chg);return ret;@@ -1316,12 +1344,13 @@ int hugetlb_reserve_pages(struct inode *void hugetlb_unreserve_pages (struct inode *inode,long offset,long freed) { +struct hstate *h =hstate_inode (inode);long chg =region_truncate (&inode->i_mapping->private_list, offset);spin_lock (&inode->i_lock); - inode->i_blocks -=BLOCKS_PER_HUGEPAGE * freed; + inode->i_blocks -=blocks_per_hugepage (h);spin_unlock (&inode->i_lock);hugetlb_put_quota (inode->i_mapping, (chg - freed)); -hugetlb_acct_memory (-(chg - freed)); +hugetlb_acct_memory (h, -(chg - freed)); }Index:
linux-2.6/arch/powerpc/mm/hugetlbpage.c
===================================================================arch/powerpc/mm/hugetlbpage.c +1
-1@@ -128,7 +128,7 @@ pte_t *huge_pte_offset(struct mm_structreturn NULL ; } -pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr) +pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz) {pgd_t *pg;pud_t *pu;Index:
linux-2.6/arch/sparc64/mm/hugetlbpage.c
===================================================================arch/sparc64/mm/hugetlbpage.c +2
-2@@ -175,7 +175,7 @@ hugetlb_get_unmapped_area(struct file *freturn -ENOMEM ;if (flags &MAP_FIXED ) { -if (prepare_hugepage_range (addr, len)) +if (prepare_hugepage_range (file, addr, len))return -EINVAL ;return addr; }@@ -195,7 +195,7 @@ hugetlb_get_unmapped_area(struct file *f pgoff, flags); } -pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr) +pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz) {pgd_t *pgd;pud_t *pud;Index:
linux-2.6/arch/sh/mm/hugetlbpage.c
===================================================================arch/sh/mm/hugetlbpage.c +1
-1@@ -22,7 +22,7 @@#include <asm/tlbflush.h> #include <asm/cacheflush.h> -pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr) +pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz) {pgd_t *pgd;pud_t *pud;Index:
linux-2.6/arch/ia64/mm/hugetlbpage.c
===================================================================arch/ia64/mm/hugetlbpage.c +3
-3@@ -24,7 +24,7 @@unsigned int hpage_shift=HPAGE_SHIFT_DEFAULT ;pte_t * -huge_pte_alloc (struct mm_struct *mm,unsigned long addr) +huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz) {unsigned long taddr =htlbpage_to_page (addr);pgd_t *pgd;@@ -75,7 +75,7 @@ int huge_pmd_unshare(struct mm_struct *m* Don't actually need to do any preparation, but need to make sure * the address is in the right region. */ -int prepare_hugepage_range (unsigned long addr,unsigned long len) +int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) {if (len & ~HPAGE_MASK )return -EINVAL ;@@ -149,7 +149,7 @@ unsigned long hugetlb_get_unmapped_area(/* Handle MAP_FIXED */ if (flags &MAP_FIXED ) { -if (prepare_hugepage_range (addr, len)) +if (prepare_hugepage_range (file, addr, len))return -EINVAL ;return addr; }Index:
linux-2.6/arch/x86/mm/hugetlbpage.c
===================================================================arch/x86/mm/hugetlbpage.c +2
-2@@ -124,7 +124,7 @@ int huge_pmd_unshare(struct mm_struct *mreturn 1 ; } -pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr) +pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz) {pgd_t *pgd;pud_t *pud;@@ -368,7 +368,7 @@ hugetlb_get_unmapped_area(struct file *freturn -ENOMEM ;if (flags &MAP_FIXED ) { -if (prepare_hugepage_range (addr, len)) +if (prepare_hugepage_range (file, addr, len))return -EINVAL ;return addr; }Index:
linux-2.6/include/linux/hugetlb.h
===================================================================include/linux/hugetlb.h +76
-5@@ -8,7 +8,6 @@#include <linux/mempolicy.h> #include <linux/shm.h> #include <asm/tlbflush.h> -#include <asm/hugetlb.h> struct ctl_table ;@@ -41,7 +40,7 @@ extern int sysctl_hugetlb_shm_group;/* arch callbacks */ -pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr); +pte_t *huge_pte_alloc (struct mm_struct *mm,unsigned long addr,unsigned long sz);pte_t *huge_pte_offset (struct mm_struct *mm,unsigned long addr);int huge_pmd_unshare (struct mm_struct *mm,unsigned long *addr,pte_t *ptep); struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,@@ -71,7 +70,7 @@ static inline unsigned long hugetlb_tota#define hugetlb_report_meminfo (buf) 0#define hugetlb_report_node_meminfo (n, buf) 0#define follow_huge_pmd (mm, addr, pmd, write) NULL -#define prepare_hugepage_range (addr,len) (-EINVAL) +#define prepare_hugepage_range (file, addr, len) (-EINVAL)#define pmd_huge (x) 0#define is_hugepage_only_range (mm, addr, len) 0#define hugetlb_free_pgd_range (tlb, addr, end, floor, ceiling) ({BUG(); 0; })@@ -125,8 +124,6 @@ struct file *hugetlb_file_setup(const chint hugetlb_get_quota (struct address_space *mapping,long delta);void hugetlb_put_quota (struct address_space *mapping,long delta); -#define BLOCKS_PER_HUGEPAGE (HPAGE_SIZE / 512) -static inline int is_file_hugepages (struct file *file) {if (file->f_op == &hugetlbfs_file_operations)@@ -155,4 +152,78 @@ unsigned long hugetlb_get_unmapped_area( unsigned long flags);#endif /* HAVE_ARCH_HUGETLB_UNMAPPED_AREA */ +#ifdef CONFIG_HUGETLB_PAGE + +/* Defines one hugetlb page size */ +struct hstate { +int hugetlb_next_nid; +unsigned int order; +unsigned long mask; +unsigned long max_huge_pages; +unsigned long nr_huge_pages; +unsigned long free_huge_pages; +unsigned long resv_huge_pages; +unsigned long surplus_huge_pages; +unsigned long nr_overcommit_huge_pages; +struct list_head hugepage_freelists[MAX_NUMNODES ]; +unsigned int nr_huge_pages_node[MAX_NUMNODES ]; +unsigned int free_huge_pages_node[MAX_NUMNODES ]; +unsigned int surplus_huge_pages_node[MAX_NUMNODES ]; +}; + +extern struct hstate global_hstate; + +static inline struct hstate *hstate_vma (struct vm_area_struct *vma) +{ +return &global_hstate; +} + +static inline struct hstate *hstate_file (struct file *f) +{ +return &global_hstate; +} + +static inline struct hstate *hstate_inode (struct inode *i) +{ +return &global_hstate; +} + +static inline unsigned long huge_page_size (struct hstate *h) +{ +return (unsigned long )PAGE_SIZE << h->order; +} + +static inline unsigned long huge_page_mask (struct hstate *h) +{ +return h->mask; +} + +static inline unsigned long huge_page_order (struct hstate *h) +{ +return h->order; +} + +static inline unsigned huge_page_shift (struct hstate *h) +{ +return h->order +PAGE_SHIFT ; +} + +static inline unsigned int blocks_per_hugepage (struct hstate *h) +{ +return huge_page_size (h) /512 ; +} + +#else +struct hstate {}; +#define hstate_file (f) NULL +#define hstate_vma (v) NULL +#define hstate_inode (i) NULL +#define huge_page_size (h) PAGE_SIZE +#define huge_page_mask (h) PAGE_MASK +#define huge_page_order (h) 0 +#define huge_page_shift (h) PAGE_SHIFT +#endif + +#include <asm/hugetlb.h> +#endif /* _LINUX_HUGETLB_H */ Index:
linux-2.6/fs/hugetlbfs/inode.c
===================================================================fs/hugetlbfs/inode.c +28
-21@@ -80,6 +80,7 @@ static int hugetlbfs_file_mmap(struct fistruct inode *inode = file->f_path.dentry->d_inode;loff_t len, vma_len;int ret; +struct hstate *h =hstate_file (file);/* * vma address alignment (but not the pgoff alignment) has @@ -92,7 +93,7 @@ static int hugetlbfs_file_mmap(struct fi vma->vm_flags |=VM_HUGETLB |VM_RESERVED ; vma->vm_ops = &hugetlb_vm_ops; -if (vma->vm_pgoff & ~(HPAGE_MASK >>PAGE_SHIFT )) +if (vma->vm_pgoff & ~(huge_page_mask (h) >>PAGE_SHIFT ))return -EINVAL ; vma_len = (loff_t)(vma->vm_end - vma->vm_start);@@ -104,8 +105,8 @@ static int hugetlbfs_file_mmap(struct fi len = vma_len + ((loff_t )vma->vm_pgoff <<PAGE_SHIFT );if (vma->vm_flags &VM_MAYSHARE && -hugetlb_reserve_pages (inode, vma->vm_pgoff >> (HPAGE_SHIFT -PAGE_SHIFT ), - len >>HPAGE_SHIFT )) +hugetlb_reserve_pages (inode, vma->vm_pgoff >>huge_page_order (h), + len >>huge_page_shift (h))) goto out; ret =0 ;@@ -130,20 +131,21 @@ hugetlb_get_unmapped_area(struct file *fstruct mm_struct *mm = current->mm;struct vm_area_struct *vma;unsigned long start_addr; +struct hstate *h =hstate_file (file); -if (len & ~HPAGE_MASK ) +if (len & ~huge_page_mask (h))return -EINVAL ;if (len >TASK_SIZE )return -ENOMEM ;if (flags &MAP_FIXED ) { -if (prepare_hugepage_range (addr, len)) +if (prepare_hugepage_range (file, addr, len))return -EINVAL ;return addr; }if (addr) { - addr =ALIGN (addr,HPAGE_SIZE ); + addr =ALIGN (addr,huge_page_size (h)); vma =find_vma (mm, addr);if (TASK_SIZE - len >= addr && (!vma || addr + len <= vma->vm_start))@@ -156,7 +158,7 @@ hugetlb_get_unmapped_area(struct file *f start_addr =TASK_UNMAPPED_BASE ; full_search: - addr =ALIGN (start_addr,HPAGE_SIZE ); + addr =ALIGN (start_addr,huge_page_size (h));for (vma =find_vma (mm, addr); ; vma = vma->vm_next) {/* At this point: (!vma || addr < vma->vm_end). */ @@ -174,7 +176,7 @@ full_search:if (!vma || addr + len <= vma->vm_start)return addr; - addr = ALIGN(vma->vm_end, HPAGE_SIZE); + addr = ALIGN(vma->vm_end, huge_page_size(h)); } }#endif @@ -225,10 +227,11 @@ hugetlbfs_read_actor(struct page *page,static ssize_t hugetlbfs_read (struct file *filp,char __user *buf,size_t len,loff_t *ppos) { +struct hstate *h =hstate_file (filp);struct address_space *mapping = filp->f_mapping;struct inode *inode = mapping->host; -unsigned long index = *ppos >>HPAGE_SHIFT ; -unsigned long offset = *ppos & ~HPAGE_MASK ; +unsigned long index = *ppos >>huge_page_shift (h); +unsigned long offset = *ppos & ~huge_page_mask (h);unsigned long end_index;loff_t isize;ssize_t retval =0 ;@@ -243,17 +246,17 @@ static ssize_t hugetlbfs_read(struct filif (!isize) goto out; - end_index = (isize -1 ) >>HPAGE_SHIFT ; + end_index = (isize -1 ) >>huge_page_shift (h);for (;;) {struct page *page; -int nr, ret; +unsigned long nr, ret;/* nr is the maximum number of bytes to copy from this page */ - nr =HPAGE_SIZE ; + nr =huge_page_size (h);if (index >= end_index) {if (index > end_index) goto out; - nr = ((isize -1 ) & ~HPAGE_MASK ) +1 ; + nr = ((isize -1 ) & ~huge_page_mask (h)) +1 ;if (nr <= offset) { goto out; }@@ -287,8 +290,8 @@ static ssize_t hugetlbfs_read(struct fil offset += ret; retval += ret; len -= ret; - index += offset >>HPAGE_SHIFT ; - offset &= ~HPAGE_MASK ; + index += offset >>huge_page_shift (h); + offset &= ~huge_page_mask (h);if (page)page_cache_release (page);@@ -298,7 +301,7 @@ static ssize_t hugetlbfs_read(struct filbreak ; } out: - *ppos = ((loff_t )index <<HPAGE_SHIFT ) + offset; + *ppos = ((loff_t )index <<huge_page_shift (h)) + offset;mutex_unlock (&inode->i_mutex);return retval; }@@ -339,8 +342,9 @@ static void truncate_huge_page(struct pastatic void truncate_hugepages (struct inode *inode,loff_t lstart) { +struct hstate *h =hstate_inode (inode);struct address_space *mapping = &inode->i_data; -const pgoff_t start = lstart >>HPAGE_SHIFT ; +const pgoff_t start = lstart >>huge_page_shift (h);struct pagevec pvec;pgoff_t next;int i, freed =0 ;@@ -449,8 +453,9 @@ static int hugetlb_vmtruncate(struct ino {pgoff_t pgoff;struct address_space *mapping = inode->i_mapping; +struct hstate *h =hstate_inode (inode); -BUG_ON (offset & ~HPAGE_MASK ); +BUG_ON (offset & ~huge_page_mask (h)); pgoff = offset >>PAGE_SHIFT ;i_size_write (inode, offset);@@ -465,6 +470,7 @@ static int hugetlb_vmtruncate(struct inostatic int hugetlbfs_setattr (struct dentry *dentry,struct iattr *attr) {struct inode *inode = dentry->d_inode; +struct hstate *h =hstate_inode (inode);int error;unsigned int ia_valid = attr->ia_valid;@@ -476,7 +482,7 @@ static int hugetlbfs_setattr(struct dentif (ia_valid &ATTR_SIZE ) { error = -EINVAL ; -if (!(attr->ia_size & ~HPAGE_MASK )) +if (!(attr->ia_size & ~huge_page_mask (h))) error =hugetlb_vmtruncate (inode, attr->ia_size);if (error) goto out;@@ -610,9 +616,10 @@ static int hugetlbfs_set_page_dirty(strustatic int hugetlbfs_statfs (struct dentry *dentry,struct kstatfs *buf) {struct hugetlbfs_sb_info *sbinfo =HUGETLBFS_SB (dentry->d_sb); +struct hstate *h =hstate_inode (dentry->d_inode); buf->f_type =HUGETLBFS_MAGIC ; - buf->f_bsize =HPAGE_SIZE ; + buf->f_bsize =huge_page_size (h);if (sbinfo) {spin_lock (&sbinfo->stat_lock);/* If no limits set, just report 0 for max/free/used Index:
linux-2.6/ipc/shm.c
===================================================================ipc/shm.c +2
-1@@ -577,7 +577,8 @@ static void shm_get_stat(struct ipc_nameif (is_file_hugepages (shp->shm_file)) {struct address_space *mapping = inode->i_mapping; - *rss += (HPAGE_SIZE /PAGE_SIZE )*mapping->nrpages; +struct hstate *h =hstate_file (shp->shm_file); + *rss += (1 <<huge_page_order (h)) * mapping->nrpages; }else {struct shmem_inode_info *info =SHMEM_I (inode);spin_lock (&info->lock);Index:
linux-2.6/mm/memory.c
===================================================================mm/memory.c +1
-1@@ -901,7 +901,7 @@ unsigned long unmap_vmas(struct mmu_gathif (unlikely (is_vm_hugetlb_page (vma))) {unmap_hugepage_range (vma, start, end); zap_work -= (end - start) / - (HPAGE_SIZE /PAGE_SIZE ); + (1 <<huge_page_order (hstate_vma (vma))); start = end; }else start = unmap_page_range(*tlbp, vma,Index:
linux-2.6/mm/mempolicy.c
===================================================================mm/mempolicy.c +6
-3@@ -1477,7 +1477,7 @@ struct zonelist *huge_zonelist(struct vmif (unlikely ((*mpol)->mode ==MPOL_INTERLEAVE )) { zl =node_zonelist (interleave_nid (*mpol, vma, addr, -HPAGE_SHIFT ), gfp_flags); +huge_page_shift (hstate_vma (vma))), gfp_flags); }else { zl =policy_zonelist (gfp_flags, *mpol);if ((*mpol)->mode ==MPOL_BIND )@@ -2216,9 +2216,12 @@ static void check_huge_range(struct vm_a {unsigned long addr;struct page *page; +struct hstate *h =hstate_vma (vma); +unsigned long sz =huge_page_size (h); -for (addr = start; addr < end; addr +=HPAGE_SIZE ) { -pte_t *ptep =huge_pte_offset (vma->vm_mm, addr &HPAGE_MASK ); +for (addr = start; addr < end; addr += sz) { +pte_t *ptep =huge_pte_offset (vma->vm_mm, + addr &huge_page_mask (h));pte_t pte;if (!ptep)Index:
linux-2.6/mm/mmap.c
===================================================================mm/mmap.c +2
-1@@ -1800,7 +1800,8 @@ int split_vma(struct mm_struct * mm, strstruct mempolicy *pol;struct vm_area_struct *new; -if (is_vm_hugetlb_page (vma) && (addr & ~HPAGE_MASK )) +if (is_vm_hugetlb_page (vma) && (addr & + ~(huge_page_mask (hstate_vma (vma)))))return -EINVAL ;if (mm->map_count >= sysctl_max_map_count)Index:
linux-2.6/include/asm-ia64/hugetlb.h
===================================================================include/asm-ia64/hugetlb.h +1
-1@@ -8,7 +8,7 @@ void hugetlb_free_pgd_range(struct mmu_g unsigned long end, unsigned long floor, unsigned long ceiling); -int prepare_hugepage_range (unsigned long addr,unsigned long len); +int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len); static inline int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,Index:
linux-2.6/include/asm-powerpc/hugetlb.h
===================================================================include/asm-powerpc/hugetlb.h +1
-1@@ -21,7 +21,7 @@ pte_t huge_ptep_get_and_clear(struct mm_* If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range (unsigned long addr,unsigned long len) +static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) {if (len & ~HPAGE_MASK )return -EINVAL ;Index:
linux-2.6/include/asm-s390/hugetlb.h
===================================================================include/asm-s390/hugetlb.h +1
-1@@ -22,7 +22,7 @@ void set_huge_pte_at(struct mm_struct *m* If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range (unsigned long addr,unsigned long len) +static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) {if (len & ~HPAGE_MASK )return -EINVAL ;Index:
linux-2.6/include/asm-sh/hugetlb.h
===================================================================include/asm-sh/hugetlb.h +1
-1@@ -14,7 +14,7 @@ static inline int is_hugepage_only_range* If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range (unsigned long addr,unsigned long len) +static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) {if (len & ~HPAGE_MASK )return -EINVAL ;Index:
linux-2.6/include/asm-sparc64/hugetlb.h
===================================================================include/asm-sparc64/hugetlb.h +1
-1@@ -22,7 +22,7 @@ static inline int is_hugepage_only_range* If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range (unsigned long addr,unsigned long len) +static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) {if (len & ~HPAGE_MASK )return -EINVAL ;Index:
linux-2.6/include/asm-x86/hugetlb.h
===================================================================include/asm-x86/hugetlb.h +4
-3@@ -14,11 +14,12 @@ static inline int is_hugepage_only_range* If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range (unsigned long addr,unsigned long len) +static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) { -if (len & ~HPAGE_MASK ) +struct hstate *h =hstate_file (file); +if (len & ~huge_page_mask (h))return -EINVAL ; -if (addr & ~HPAGE_MASK ) +if (addr & ~huge_page_mask (h))return -EINVAL ;return 0 ; }
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 03/23] hugetlb: modular state
Quoted 5 lines · Adam Litke
Phew. At last I made it to the end of this one :) It seems okay to me though. Have you done any performance testing on this patch series yet? I don't expect the hstate structure to introduce any measurable performance degradation, but it would be nice to have some numbers to back up that educated guess.
Haven't seen any noticable performance differences, but I don't know that I'm doing particularly interesting testing. Would be nice to get some results with HPC or databases or something that actually test the code.
I'd say with HUGE_MAX_HSTATE == 1, the compiler _should_ be able to constant fold much of it away. There would be a few more pointer dereferences (eg to get hstate from inode or vma)... if that _really_ matters, we could special case HUGE_MAX_HSTATE == 1 in some places to bring performance back up.
Quoted 7 lines
Acked-by Adam Litke <[email protected]>Quoted 3 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlb-modular-state.patch) Large, but rather mechanical patch that converts most of the
hugetlb.cglobals into structure members and passes them around.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 4/23 hugetlb: multiple hstates
In reply to [email protected]Add basic support for more than one hstate in hugetlbfs
- Convert hstates to an array
- Add a first default entry covering the standard huge page size
- Add functions for architectures to register new hstates
- Add basic iterators over hstates
--- include/linux/hugetlb.h | 16 +++++++ mm/hugetlb.c | 98 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 95 insertions(+), 19 deletions(-)
mm/hugetlb.c +80 -18
@@ -27,7 +27,15 @@ unsigned long sysctl_overcommit_huge_pagstatic gfp_t htlb_alloc_mask =GFP_HIGHUSER ;unsigned long hugepages_treat_as_movable; -struct hstate global_hstate; +static int max_hstate =0 ; +struct hstate hstates[HUGE_MAX_HSTATE ]; + +/* for command line parsing */ +static struct hstate *__initdata parsed_hstate =NULL ; +static unsigned long __initdata default_hstate_max_huge_pages =0 ; + +#define for_each_hstate (h) \ + for ((h) = hstates; (h) < &hstates[max_hstate]; (h)++)/* * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
@@ -132,13 +140,24 @@ static void update_and_free_page(struct__free_pages (page,huge_page_order (h)); } +struct hstate *size_to_hstate (unsigned long size) +{ +struct hstate *h; + +for_each_hstate (h) { +if (huge_page_size (h) == size) +return h; + } +return NULL ; +} +static void free_huge_page (struct page *page) {/* * Can't pass hstate in here because it is called from the * compound page destructor. */ -struct hstate *h = &global_hstate; +struct hstate *h =page_hstate (page);int nid =page_to_nid (page);struct address_space *mapping;
@@ -523,38 +542,80 @@ static struct page *alloc_huge_page(strureturn page; } -static int __init hugetlb_init (void ) +static void __init hugetlb_init_one_hstate (struct hstate *h) {unsigned long i; -struct hstate *h = &global_hstate; - -if (HPAGE_SHIFT ==0 ) -return 0 ; - -if (!h->order) { - h->order =HPAGE_SHIFT -PAGE_SHIFT ; - h->mask =HPAGE_MASK ; - }for (i =0 ; i <MAX_NUMNODES ; ++i)INIT_LIST_HEAD (&h->hugepage_freelists[i]); h->hugetlb_next_nid =first_node (node_online_map); -for (i =0 ; i < max_huge_pages; ++i) { +for (i =0 ; i < h->max_huge_pages; ++i) {if (!alloc_fresh_huge_page (h))break ; } - max_huge_pages = h->free_huge_pages = h->nr_huge_pages = i; -printk ("Total HugeTLB memory allocated, %ld\n" , h->free_huge_pages); + h->max_huge_pages = h->free_huge_pages = h->nr_huge_pages = i; +} + +static void __init hugetlb_init_hstates (void ) +{ +struct hstate *h; + +for_each_hstate (h) { +hugetlb_init_one_hstate (h); + } +} + +static void __init report_hugepages (void ) +{ +struct hstate *h; + +for_each_hstate (h) { +printk (KERN_INFO "Total HugeTLB memory allocated, %ld %dMB pages\n" , + h->free_huge_pages, +1 << (h->order +PAGE_SHIFT -20 )); + } +} + +static int __init hugetlb_init (void ) +{ +BUILD_BUG_ON (HPAGE_SHIFT ==0 ); + +if (!size_to_hstate (HPAGE_SIZE )) { +hugetlb_add_hstate (HUGETLB_PAGE_ORDER ); + parsed_hstate->max_huge_pages = default_hstate_max_huge_pages; + } + +hugetlb_init_hstates (); + +report_hugepages (); +return 0 ; }module_init (hugetlb_init); +/* Should be called on processing a hugepagesz=... option */ +void __init hugetlb_add_hstate (unsigned order) +{ +struct hstate *h; +if (size_to_hstate (PAGE_SIZE << order)) { +printk (KERN_WARNING "hugepagesz= specified twice, ignoring\n" ); +return ; + } +BUG_ON (max_hstate >=HUGE_MAX_HSTATE ); +BUG_ON (order ==0 ); + h = &hstates[max_hstate++]; + h->order = order; + h->mask = ~((1ULL << (order +PAGE_SHIFT )) -1 ); +hugetlb_init_one_hstate (h); + parsed_hstate = h; +} +static int __init hugetlb_setup (char *s) { -if (sscanf (s,"%lu" , &max_huge_pages) <=0 ) - max_huge_pages =0 ; +if (sscanf (s,"%lu" , &default_hstate_max_huge_pages) <=0 ) + default_hstate_max_huge_pages =0 ;return 1 ; }__setup ("hugepages=" , hugetlb_setup);
@@ -585,7 +646,7 @@ static void try_to_free_low(struct hstatif (PageHighMem (page))continue ;list_del (&page->lru); -update_and_free_page (page); +update_and_free_page (h, page); h->free_huge_pages--; h->free_huge_pages_node[page_to_nid (page)]--; }
@@ -675,6 +736,7 @@ int hugetlb_sysctl_handler(struct ctl_ta {proc_doulongvec_minmax (table, write, file, buffer, length, ppos); max_huge_pages =set_max_huge_pages (max_huge_pages); + global_hstate.max_huge_pages = max_huge_pages;return 0 ; }
include/linux/hugetlb.h +15 -1
@@ -171,7 +171,16 @@ struct hstate {unsigned int surplus_huge_pages_node[MAX_NUMNODES ]; }; -extern struct hstate global_hstate; +void __init hugetlb_add_hstate (unsigned order); +struct hstate *size_to_hstate (unsigned long size); + +#ifndef HUGE_MAX_HSTATE +#define HUGE_MAX_HSTATE 1 +#endif + +extern struct hstate hstates[HUGE_MAX_HSTATE ]; + +#define global_hstate (hstates[0])static inline struct hstate *hstate_vma (struct vm_area_struct *vma) {
@@ -213,6 +222,11 @@ static inline unsigned int blocks_per_hu return huge_page_size(h) / 512; } +static inline struct hstate *page_hstate (struct page *page) +{ +return size_to_hstate (PAGE_SIZE <<compound_order (page)); +} +#else struct hstate {};#define hstate_file (f) NULL
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 04/23] hugetlb: multiple hstates
Quoted 9 lines · On 26.05.2008 [00:23:21 +1000], [email protected] wrote:
Add basic support for more than one hstate in hugetlbfs
- Convert hstates to an array
- Add a first default entry covering the standard huge page size
- Add functions for architectures to register new hstates
- Add basic iterators over hstatesSigned-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 04/23] hugetlb: multiple hstates
In reply to [email protected]Quoted 10 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlb-multiple-hstates.patch) Add basic support for more than one hstate in hugetlbfs
- Convert hstates to an array
- Add a first default entry covering the standard huge page size
- Add functions for architectures to register new hstates
- Add basic iterators over hstatesSigned-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 5/23 hugetlb: multi hstate proc files
In reply to [email protected]Convert /proc output code over to report multiple hstates
I chose to just report the numbers in a row, in the hope to minimze breakage of existing software. The "compat" page size is always the first number.
--- mm/hugetlb.c | 64 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 22 deletions(-)
mm/hugetlb.c +42 -22
@@ -766,39 +766,59 @@ int hugetlb_overcommit_handler(struct ct#endif /* CONFIG_SYSCTL */ +static int dump_field (char *buf,unsigned field) +{ +int n =0 ; +struct hstate *h; + for_each_hstate (h) + n += sprintf(buf + n, " %5lu", *(unsigned long *)((char *)h + field)); + buf[n++] ='\n' ; +return n; +} +int hugetlb_report_meminfo (char *buf) { -struct hstate *h = &global_hstate; -return sprintf (buf, -"HugePages_Total: %5lu\n" -"HugePages_Free: %5lu\n" -"HugePages_Rsvd: %5lu\n" -"HugePages_Surp: %5lu\n" -"Hugepagesize: %5lu kB\n" , - h->nr_huge_pages, - h->free_huge_pages, - h->resv_huge_pages, - h->surplus_huge_pages, -1UL << (huge_page_order (h) +PAGE_SHIFT -10 )); +struct hstate *h; +int n =0 ; + n +=sprintf (buf +0 ,"HugePages_Total:" ); + n +=dump_field (buf + n, offsetof(struct hstate , nr_huge_pages)); + n +=sprintf (buf + n,"HugePages_Free: " ); + n +=dump_field (buf + n, offsetof(struct hstate , free_huge_pages)); + n +=sprintf (buf + n,"HugePages_Rsvd: " ); + n +=dump_field (buf + n, offsetof(struct hstate , resv_huge_pages)); + n +=sprintf (buf + n,"HugePages_Surp: " ); + n +=dump_field (buf + n, offsetof(struct hstate , surplus_huge_pages)); + n +=sprintf (buf + n,"Hugepagesize: " ); +for_each_hstate (h) + n += sprintf(buf + n, " %5lu", huge_page_size(h) / 1024); + n +=sprintf (buf + n," kB\n" ); +return n; }int hugetlb_report_node_meminfo (int nid,char *buf) { -struct hstate *h = &global_hstate; -return sprintf (buf, -"Node %d HugePages_Total: %5u\n" -"Node %d HugePages_Free: %5u\n" -"Node %d HugePages_Surp: %5u\n" , - nid, h->nr_huge_pages_node[nid], - nid, h->free_huge_pages_node[nid], - nid, h->surplus_huge_pages_node[nid]); +int n =0 ; + n +=sprintf (buf,"Node %d HugePages_Total: " , nid); + n +=dump_field (buf + n, offsetof(struct hstate , + nr_huge_pages_node[nid])); + n +=sprintf (buf + n,"Node %d HugePages_Free: " , nid); + n +=dump_field (buf + n, offsetof(struct hstate , + free_huge_pages_node[nid])); + n +=sprintf (buf + n,"Node %d HugePages_Surp: " , nid); + n +=dump_field (buf + n, offsetof(struct hstate , + surplus_huge_pages_node[nid])); +return n; }/* Return the number pages of memory we physically have, in PAGE_SIZE units. */ unsigned long hugetlb_total_pages (void ) { -struct hstate *h = &global_hstate; -return h->nr_huge_pages * (1 <<huge_page_order (h)); +long x =0 ; +struct hstate *h; +for_each_hstate (h) { + x += h->nr_huge_pages * (1 <<huge_page_order (h)); + } +return x; }/*
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 05/23] hugetlb: multi hstate proc files
Quoted 5 lines · On 26.05.2008 [00:23:22 +1000], [email protected] wrote:
Convert /proc output code over to report multiple hstates
I chose to just report the numbers in a row, in the hope to minimze breakage of existing software. The "compat" page size is always the first number.
I'm assuming this is just copied from the old changelog, because as far as I can tell, and from my quick testing just now with my sysfs patch, hstates[0] is just whichever hugepage size is registered first. So that either means by "compat" you meant the default on the current system (which is only compatible with boots having the same order of boot-line parameters) or we need to fix this patch to put HPAGE_SIZE (which we haven't changed, per se) to be in hstates[0]. It might help to have a helper macro called default_hstate (or a comment) [which I thought we had in the beginnning of the patchset, but I see one of the intervening patches removed it] indicating which state is the default when none is specified.
The reason I bring this up is that I have my sysfs patchset in two parts. First, I add the sysfs interface and then I remove the multi-valued proc files. But for the latter, I rely on hstates[0] to be the one we want to be presenting in proc. If that's not the case, how should I be determining which hstate is the default? If that is the case, shall I make the reverting patch also put the "right" value in hstates[0]?
At the same time, my testing of the sysfs code appears successful still and I will hopefully be able to post them in the morning.
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 05/23] hugetlb: multi hstate proc files
Quoted 19 lines · Nishanth Aravamudan
Quoted 5 lines · On 26.05.2008 [00:23:22 +1000], [email protected] wrote:
Convert /proc output code over to report multiple hstates
I chose to just report the numbers in a row, in the hope to minimze breakage of existing software. The "compat" page size is always the first number.
I'm assuming this is just copied from the old changelog, because as far as I can tell, and from my quick testing just now with my sysfs patch, hstates[0] is just whichever hugepage size is registered first. So that either means by "compat" you meant the default on the current system (which is only compatible with boots having the same order of boot-line parameters) or we need to fix this patch to put
HPAGE_SIZE(which we haven't changed, per se) to be in hstates[0]. It might help to have a helper macro calleddefault_hstate(or a comment) [which I thought we had in the beginnning of the patchset, but I see one of the intervening patches removed it] indicating which state is the default when none is specified.
Quoted 7 lines
The reason I bring this up is that I have my sysfs patchset in two parts. First, I add the sysfs interface and then I remove the multi-valued proc files. But for the latter, I rely on hstates[0] to be the one we want to be presenting in proc. If that's not the case, how should I be determining which hstate is the default? If that is the case, shall I make the reverting patch also put the "right" value in hstates[0]?
Oh, I think I know what is going on now. It's because I hadn't changed my test script between the old version of the stack and this one so it was still putting "hugepagesz=64k hugepagesz=16m hugepagesz=16g" on the kernel command-line, thus making 64k (the first hugepagesz specified) be the default for the system. So, actually, using hstates[0] in this way does work. Running one more test set without specifying any hugepagesz options on the kernel command-line to see the default layout in proc and sys is sane.
However, this nuance definitely should be documented in vm/hugetlbpage.txt / kernel-parameters.txt. Administrators who wish to preallocate hugepages should be aware that the order in which they specify the preallocation affects which hugepage size is the default (presuming my interpretation of my results is correct).
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 05/23] hugetlb: multi hstate proc files
Quoted 28 lines · Nishanth Aravamudan
Quoted 19 lines · Nishanth Aravamudan
Quoted 5 lines · On 26.05.2008 [00:23:22 +1000], [email protected] wrote:
Convert /proc output code over to report multiple hstates
I chose to just report the numbers in a row, in the hope to minimze breakage of existing software. The "compat" page size is always the first number.
I'm assuming this is just copied from the old changelog, because as far as I can tell, and from my quick testing just now with my sysfs patch, hstates[0] is just whichever hugepage size is registered first. So that either means by "compat" you meant the default on the current system (which is only compatible with boots having the same order of boot-line parameters) or we need to fix this patch to put
HPAGE_SIZE(which we haven't changed, per se) to be in hstates[0]. It might help to have a helper macro calleddefault_hstate(or a comment) [which I thought we had in the beginnning of the patchset, but I see one of the intervening patches removed it] indicating which state is the default when none is specified.Quoted 7 lines
The reason I bring this up is that I have my sysfs patchset in two parts. First, I add the sysfs interface and then I remove the multi-valued proc files. But for the latter, I rely on hstates[0] to be the one we want to be presenting in proc. If that's not the case, how should I be determining which hstate is the default? If that is the case, shall I make the reverting patch also put the "right" value in hstates[0]?
Quoted 8 lines
Oh, I think I know what is going on now. It's because I hadn't changed my test script between the old version of the stack and this one so it was still putting "hugepagesz=64k hugepagesz=16m hugepagesz=16g" on the kernel command-line, thus making 64k (the first hugepagesz specified) be the default for the system. So, actually, using hstates[0] in this way does work. Running one more test set without specifying any hugepagesz options on the kernel command-line to see the default layout in proc and sys is sane.
Confirmed that it's a result of my kernel command-line specifying 64k first.
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 05/23] hugetlb: multi hstate proc files
In reply to Nishanth AravamudanQuoted 19 lines · Nishanth Aravamudan
Quoted 5 lines · On 26.05.2008 [00:23:22 +1000], [email protected] wrote:
Convert /proc output code over to report multiple hstates
I chose to just report the numbers in a row, in the hope to minimze breakage of existing software. The "compat" page size is always the first number.
I'm assuming this is just copied from the old changelog, because as far as I can tell, and from my quick testing just now with my sysfs patch, hstates[0] is just whichever hugepage size is registered first. So that either means by "compat" you meant the default on the current system (which is only compatible with boots having the same order of boot-line parameters) or we need to fix this patch to put
HPAGE_SIZE(which we haven't changed, per se) to be in hstates[0]. It might help to have a helper macro calleddefault_hstate(or a comment) [which I thought we had in the beginnning of the patchset, but I see one of the intervening patches removed it] indicating which state is the default when none is specified.
Quoted 7 lines
The reason I bring this up is that I have my sysfs patchset in two parts. First, I add the sysfs interface and then I remove the multi-valued proc files. But for the latter, I rely on hstates[0] to be the one we want to be presenting in proc. If that's not the case, how should I be determining which hstate is the default? If that is the case, shall I make the reverting patch also put the "right" value in hstates[0]?
No it's just laziness on my part. I wanted to get the patchset out again as quickly as I could (after the delay), so I kind of ignored the user interface problems.
I can try to fix something up, or otherwise I guess you could do it in your patchset? Eg. have an index which maps the default hstate from the hstate array. This would default to the existing sizes but I guess it would make sense to be able to override it at boot.
Do you want to do that, or should I?
Quoted 2 lines
At the same time, my testing of the sysfs code appears successful still and I will hopefully be able to post them in the morning.
Oh good.
Thanks,
Nick
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 6/23 hugetlbfs: per mount hstates
In reply to [email protected]Add support to have individual hstates for each hugetlbfs mount
- Add a new pagesize= option to the hugetlbfs mount that allows setting the page size
- Set up pointers to a suitable hstate for the set page size option to the super block and the inode and the vma.
- Change the hstate accessors to use this information
- Add code to the hstate init function to set parsed_hstate for command line processing
- Handle duplicated hstate registrations to the make command line user proof
[np: take hstate out of hugetlbfs inode and vma->vm_private_data]
--- fs/hugetlbfs/inode.c | 48 ++++++++++++++++++++++++++++++++++++++---------- include/linux/hugetlb.h | 14 +++++++++----- mm/hugetlb.c | 16 +++------------- mm/memory.c | 18 ++++++++++++++++-- 4 files changed, 66 insertions(+), 30 deletions(-)
include/linux/hugetlb.h +9 -5
@@ -92,6 +92,7 @@ struct hugetlbfs_config {umode_t mode;long nr_blocks;long nr_inodes; +struct hstate *hstate; };struct hugetlbfs_sb_info {
@@ -100,6 +101,7 @@ struct hugetlbfs_sb_info {long max_inodes;/* inodes allowed */ long free_inodes;/* inodes free */ spinlock_t stat_lock; +struct hstate *hstate; };
@@ -182,19 +184,21 @@ extern struct hstate hstates[HUGE_MAX_HS#define global_hstate (hstates[0]) -static inline struct hstate *hstate_vma (struct vm_area_struct *vma) +static inline struct hstate *hstate_inode (struct inode *i) { -return &global_hstate; +struct hugetlbfs_sb_info *hsb; + hsb =HUGETLBFS_SB (i->i_sb); +return hsb->hstate; }static inline struct hstate *hstate_file (struct file *f) { -return &global_hstate; +return hstate_inode (f->f_dentry->d_inode); } -static inline struct hstate *hstate_inode (struct inode *i) +static inline struct hstate *hstate_vma (struct vm_area_struct *vma) { -return &global_hstate; +return hstate_file (vma->vm_file); }static inline unsigned long huge_page_size (struct hstate *h)
fs/hugetlbfs/inode.c +38 -10
112 lines not on this page · raw message
mm/hugetlb.c +3 -13
@@ -961,19 +961,9 @@ void __unmap_hugepage_range(struct vm_arvoid unmap_hugepage_range (struct vm_area_struct *vma,unsigned long start,unsigned long end) { -/* -* It is undesirable to test vma->vm_file as it should be non-null -* for valid hugetlb area. However, vm_file will be NULL in the error -* cleanup path of do_mmap_pgoff. When hugetlbfs ->mmap method fails, -* do_mmap_pgoff() nullifies vma->vm_file before calling this function -* to clean up. Since no pte has actually been setup, it is safe to -* do nothing in this case. -*/ -if (vma->vm_file) { -spin_lock (&vma->vm_file->f_mapping->i_mmap_lock); -__unmap_hugepage_range (vma, start, end); -spin_unlock (&vma->vm_file->f_mapping->i_mmap_lock); - } +spin_lock (&vma->vm_file->f_mapping->i_mmap_lock); +__unmap_hugepage_range (vma, start, end); +spin_unlock (&vma->vm_file->f_mapping->i_mmap_lock); } static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
mm/memory.c +16 -2
@@ -899,9 +899,23 @@ unsigned long unmap_vmas(struct mmu_gath }if (unlikely (is_vm_hugetlb_page (vma))) { -unmap_hugepage_range (vma, start, end); - zap_work -= (end - start) / +/* +* It is undesirable to test vma->vm_file as it +* should be non-null for valid hugetlb area. +* However, vm_file will be NULL in the error +* cleanup path of do_mmap_pgoff. When +* hugetlbfs ->mmap method fails, +* do_mmap_pgoff() nullifies vma->vm_file +* before calling this function to clean up. +* Since no pte has actually been setup, it is +* safe to do nothing in this case. +*/ +if (vma->vm_file) { +unmap_hugepage_range (vma, start, end); + zap_work -= (end - start) / (1 <<huge_page_order (hstate_vma (vma))); + } + start = end; }else start = unmap_page_range(*tlbp, vma,
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 06/23] hugetlbfs: per mount hstates
Quoted 11 lines · On 26.05.2008 [00:23:23 +1000], [email protected] wrote:
Add support to have individual hstates for each hugetlbfs mount
- Add a new pagesize= option to the hugetlbfs mount that allows setting the page size
- Set up pointers to a suitable hstate for the set page size option to the super block and the inode and the vma.
- Change the hstate accessors to use this information
- Add code to the hstate init function to setparsed_hstatefor command line processing
- Handle duplicated hstate registrations to the make command line user proof
Quoted 4 lines
[np: take hstate out of hugetlbfs inode and
vma->vm_private_data]Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 06/23] hugetlbfs: per mount hstates
In reply to [email protected]Quoted 12 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlbfs-per-mount-hstate.patch) Add support to have individual hstates for each hugetlbfs mount
- Add a new pagesize= option to the hugetlbfs mount that allows setting the page size
- Set up pointers to a suitable hstate for the set page size option to the super block and the inode and the vma.
- Change the hstate accessors to use this information
- Add code to the hstate init function to setparsed_hstatefor command line processing
- Handle duplicated hstate registrations to the make command line user proof
Quoted 4 lines
[np: take hstate out of hugetlbfs inode and
vma->vm_private_data]Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 7/23 hugetlb: multi hstate sysctls
In reply to [email protected]Expand the hugetlbfs sysctls to handle arrays for all hstates. This now allows the removal of global_hstate -- everything is now hstate aware.
- I didn't bother with hugetlb_shm_group and treat_as_movable, these are still single global.
- Also improve error propagation for the sysctl handlers a bit
--- include/linux/hugetlb.h | 7 ++-- kernel/sysctl.c | 4 ++ mm/hugetlb.c | 70 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 61 insertions(+), 20 deletions(-)
include/linux/hugetlb.h +3 -4
@@ -32,8 +32,6 @@ int hugetlb_fault(struct mm_struct *mm,int hugetlb_reserve_pages (struct inode *inode,long from,long to);void hugetlb_unreserve_pages (struct inode *inode,long offset,long freed); -extern unsigned long max_huge_pages; -extern unsigned long sysctl_overcommit_huge_pages;extern unsigned long hugepages_treat_as_movable;extern const unsigned long hugetlb_zero, hugetlb_infinity;extern int sysctl_hugetlb_shm_group;
@@ -182,8 +180,6 @@ struct hstate *size_to_hstate(unsigned lextern struct hstate hstates[HUGE_MAX_HSTATE ]; -#define global_hstate (hstates[0]) -static inline struct hstate *hstate_inode (struct inode *i) {struct hugetlbfs_sb_info *hsb;
@@ -231,6 +227,9 @@ static inline struct hstate *page_hstate return size_to_hstate(PAGE_SIZE << compound_order(page)); } +extern unsigned long max_huge_pages[HUGE_MAX_HSTATE ]; +extern unsigned long sysctl_overcommit_huge_pages[HUGE_MAX_HSTATE ]; +#else struct hstate {};#define hstate_file (f) NULL
kernel/sysctl.c +3 -1
@@ -928,7 +928,7 @@ static struct ctl_table vm_table[] = { { .procname = "nr_hugepages", .data = &max_huge_pages, - .maxlen = sizeof(unsigned long), + .maxlen = sizeof(max_huge_pages), .mode = 0644, .proc_handler = &hugetlb_sysctl_handler, .extra1 = (void *)&hugetlb_zero,
@@ -957,6 +957,8 @@ static struct ctl_table vm_table[] = { .maxlen = sizeof(sysctl_overcommit_huge_pages), .mode = 0644, .proc_handler = &hugetlb_overcommit_handler, + .extra1 = (void *)&hugetlb_zero, + .extra2 = (void *)&hugetlb_infinity, },#endif {
mm/hugetlb.c +55 -15
108 lines not on this page · raw message
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 07/23] hugetlb: multi hstate sysctls
mm/hugetlb.c void __init hugetlb_add_hstate(unsigned · line 618
Quoted 8 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
mm/hugetlb.c +2
-2@@ -614,8 +614,16 @@ void __init hugetlb_add_hstate(unsignedstatic int __init hugetlb_setup (char *s) { -if (sscanf (s,"%lu" , &default_hstate_max_huge_pages) <=0 ) - default_hstate_max_huge_pages =0 ; +unsigned long *mhp; +
Perhaps a one-liner comment here to remind us that !max_hstate means we currently have only one huge page size defined, and that it is considered the default (or compat) size, and that it gets special treatment by using i>>?default_hstate_max_huge_pages.
Quoted 11 lines
mm/hugetlb.c +8
-0+if (!max_hstate) + mhp = &default_hstate_max_huge_pages; +else + mhp = &parsed_hstate->max_huge_pages; + +if (sscanf (s,"%lu" , mhp) <=0 ) + *mhp =0 ; +return 1 ; }__setup ("hugepages=" , hugetlb_setup);
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 07/23] hugetlb: multi hstate sysctls
Quoted 14 lines · Adam Litke
mm/hugetlb.c void __init hugetlb_add_hstate(unsigned · line 618
Quoted 8 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
mm/hugetlb.c +2
-2@@ -614,8 +614,16 @@ void __init hugetlb_add_hstate(unsignedstatic int __init hugetlb_setup (char *s) { -if (sscanf (s,"%lu" , &default_hstate_max_huge_pages) <=0 ) - default_hstate_max_huge_pages =0 ; +unsigned long *mhp; +Perhaps a one-liner comment here to remind us that !max_hstate means we currently have only one huge page size defined, and that it is considered the default (or compat) size, and that it gets special treatment by using ???default_hstate_max_huge_pages.
Sure.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 07/23] hugetlb: multi hstate sysctls
In reply to [email protected]Quoted 10 lines · On 26.05.2008 [00:23:24 +1000], [email protected] wrote:
Expand the hugetlbfs sysctls to handle arrays for all hstates. This now allows the removal of
global_hstate-- everything is now hstate aware.- I didn't bother with
hugetlb_shm_groupandtreat_as_movable, these are still single global.
- Also improve error propagation for the sysctl handlers a bitSigned-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
<snip>
mm/hugetlb.c int hugetlb_sysctl_handler(struct ctl_ta · line 773
Quoted 5 lines
int hugetlb_treat_movable_handler(struct
ctl_table*table, int write,mm/hugetlb.c +1
-0struct file *file, void __user *buffer, size_t *length, loff_t *ppos) { + table->maxlen = max_hstate * sizeof(int);
Are you sure this is correct? I was just testing my sysfs patch (and the removal of the multi-valued proc files) and noticed that /proc/sys/vm/hugepages_treat_as_movable was multi-valued (3 values, corresponding to the three page sizes on this machine), and the last value was garbage. And, in any case, this change seems to conflict with the changelog?
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 07/23] hugetlb: multi hstate sysctls
Quoted 20 lines · Nishanth Aravamudan
Quoted 10 lines · On 26.05.2008 [00:23:24 +1000], [email protected] wrote:
Expand the hugetlbfs sysctls to handle arrays for all hstates. This now allows the removal of
global_hstate-- everything is now hstate aware.- I didn't bother with
hugetlb_shm_groupandtreat_as_movable, these are still single global.
- Also improve error propagation for the sysctl handlers a bitSigned-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]><snip>
mm/hugetlb.c int hugetlb_sysctl_handler(struct ctl_ta · line 773
Quoted 5 lines
int hugetlb_treat_movable_handler(struct
ctl_table*table, int write,mm/hugetlb.c +1
-0struct file *file, void __user *buffer, size_t *length, loff_t *ppos) { + table->maxlen = max_hstate * sizeof(int);
Quoted 6 lines
Are you sure this is correct? I was just testing my sysfs patch (and the removal of the multi-valued proc files) and noticed that
/proc/sys/vm/hugepages_treat_as_movablewas multi-valued (3 values, corresponding to the three page sizes on this machine), and the last value was garbage. And, in any case, this change seems to conflict with the changelog?
Confirmed that with just your patches, I see
# cat /proc/sys/vm/hugepages_treat_as_movable 0 0 -1073741824
which is hopefully bogus :) So I'd say this is a bad part of this particular change?
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 07/23] hugetlb: multi hstate sysctls
In reply to Nishanth AravamudanQuoted 20 lines · Nishanth Aravamudan
Quoted 10 lines · On 26.05.2008 [00:23:24 +1000], [email protected] wrote:
Expand the hugetlbfs sysctls to handle arrays for all hstates. This now allows the removal of
global_hstate-- everything is now hstate aware.- I didn't bother with
hugetlb_shm_groupandtreat_as_movable, these are still single global.
- Also improve error propagation for the sysctl handlers a bitSigned-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]><snip>
mm/hugetlb.c int hugetlb_sysctl_handler(struct ctl_ta · line 773
Quoted 5 lines
int hugetlb_treat_movable_handler(struct
ctl_table*table, int write,mm/hugetlb.c +1
-0struct file *file, void __user *buffer, size_t *length, loff_t *ppos) { + table->maxlen = max_hstate * sizeof(int);
Quoted 6 lines
Are you sure this is correct? I was just testing my sysfs patch (and the removal of the multi-valued proc files) and noticed that
/proc/sys/vm/hugepages_treat_as_movablewas multi-valued (3 values, corresponding to the three page sizes on this machine), and the last value was garbage. And, in any case, this change seems to conflict with the changelog?
Hmm, might have slipped in during a merge. I'll fix it.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
RFC PATCH 1/2 hugetlb: present information in sysfs
In reply to [email protected]While the procfs presentation of the hstate counters has tried to be as backwards compatible as possible, I do not believe trying to maintain all of the information in the same files is a good long-term plan. This particularly matters for architectures that can support many hugepage sizes (sparc64 might be one). Even with the three potential pagesizes on power (64k, 16m and 16g), I found the proc interface to be a little awkward.
Instead, migrate the information to sysfs in a new directory, /sys/kernel/hugepages. Underneath that directory there will be a directory per-supported hugepage size, e.g.:
/sys/kernel/hugepages/hugepages-64/sys/kernel/hugepages/hugepages-16384/sys/kernel/hugepages/hugepages-16777216
corresponding to 64k, 16m and 16g respectively. Within each hugepages-size directory there are a number of files, corresponding to the tracked counters in the hstate, e.g.:
/sys/kernel/hugepages/hugepages-64/nr_hugepages /sys/kernel/hugepages/hugepages-64/nr_overcommit_hugepages /sys/kernel/hugepages/hugepages-64/free_hugepages /sys/kernel/hugepages/hugepages-64/resv_hugepages /sys/kernel/hugepages/hugepages-64/surplus_hugepages
Of these files, the first two are read-write and the latter three are read-only. The size of the hugepage being manipulated is trivially deducible from the enclosing directory and is always expressed in kB (to match meminfo).
---
Nick, I tested this patch and the following one at this point the series, that is between patches 7 and 8. This does require a few compile fixes/patch modifications in the later parts of the series. If we decide that 2/2 is undesirable, there will be fewer of those and 1/2 could also apply at the end, with less work. I can send you that diff, if you'd prefer.
Greg, I didn't hear back from you on the last posting of this patch. Not intended as a complaint, just an indication of why I didn't make any changes relative to that version. Does this seem like a reasonable patch as far as using the sysfs API? I realize a follow-on patch will be needed to updated Documentation/ABI.
include/linux/hugetlb.h +1 -0
@@ -169,6 +169,7 @@ struct hstate {unsigned int nr_huge_pages_node[MAX_NUMNODES ];unsigned int free_huge_pages_node[MAX_NUMNODES ];unsigned int surplus_huge_pages_node[MAX_NUMNODES ]; +char name[32 ]; };void __init hugetlb_add_hstate (unsigned order);
mm/hugetlb.c +224 -61
303 lines not on this page · raw message
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
RFC PATCH 2/2 hugetlb: remove multi-valued proc files.
Now that we present the same information in a cleaner way in sysfs, we can remove the duplicate information and interfaces from procfs (and consider them to be the legacy interface). The proc interface only controls the default hugepage size, which is either
a) the first one specified via hugepagesz= on the kernel command-line, if any
b) the legacy huge page size, otherwise
All other hugepage size pool manipulations can occur through sysfs.
---
Note, this does end up making the manipulation and validation of multiple hstates impossible without sysfs enabled and mounted. As such, I'm not sure if this is the right approach and perhaps we should be leaving the multi-valued proc files in place (but not as the preferred interface). Or we could present the values in procfs only if SYSFS is not enabled in the kernel? I imagine (but am not 100% sure) that the only current architecture where this might be important is SUPERH?
Nick, this includes the fix to make hugepages_treat_as_movable single-valued again, which presumably will get thrown up as a merge conflict if it's fixed at the right place in the stack.
Realistically, this patch shouldn't need to exist in the upstream patchset, if we decide to not extend the proc files, as we can add the sysfs files as a new patch 5 and drop the current patches 5 and 7. I can work out how the patch should look if that is what we decide to do (or git-rebase -i can :).
include/linux/hugetlb.h +2 -2
@@ -228,8 +228,8 @@ static inline struct hstate *page_hstate(struct page *page) return size_to_hstate(PAGE_SIZE << compound_order(page)); } -extern unsigned long max_huge_pages[HUGE_MAX_HSTATE ]; -extern unsigned long sysctl_overcommit_huge_pages[HUGE_MAX_HSTATE ]; +extern unsigned long max_huge_pages; +extern unsigned long sysctl_overcommit_huge_pages;#else struct hstate {};
mm/hugetlb.c +35 -58
153 lines not on this page · raw message
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH 2/2] hugetlb: remove multi-valued proc files.
Quoted 8 lines · Nishanth Aravamudan
Now that we present the same information in a cleaner way in sysfs, we can remove the duplicate information and interfaces from procfs (and consider them to be the legacy interface). The proc interface only controls the default hugepage size, which is either
a) the first one specified via hugepagesz= on the kernel command-line, if any
b) the legacy huge page size, otherwise
Quoted 7 lines
All other hugepage size pool manipulations can occur through sysfs.
Signed-off-by Nishanth Aravamudan <[email protected]>---
Note, this does end up making the manipulation and validation of multiple hstates impossible without sysfs enabled and mounted. As such,
I don't think that's such a problem. The overlap between users with no sysfs and those that use multiple hugepages won't be large. And if any exist, they can specify at boot or come up with their own customer solution.
Quoted 5 lines
I'm not sure if this is the right approach and perhaps we should be leaving the multi-valued proc files in place (but not as the preferred interface). Or we could present the values in procfs only if SYSFS is not enabled in the kernel? I imagine (but am not 100% sure) that the only current architecture where this might be important is SUPERH?
I wouldn't worry too much. I think /proc/sys/vm/nr_hugepages etc is better as one (the compat) value after we now have the sysfs stuff. However /proc/meminfo is a little more tricky. Of course the information does exist in sysfs too, but meminfo is also for user reporting, so maybe it will be better to leave it multi column?
Quoted 3 lines
Nick, this includes the fix to make
hugepages_treat_as_movablesingle-valued again, which presumably will get thrown up as a merge conflict if it's fixed at the right place in the stack.
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH 2/2] hugetlb: remove multi-valued proc files.
Quoted 13 lines · Nick Piggin
Quoted 12 lines · Nishanth Aravamudan
Now that we present the same information in a cleaner way in sysfs, we can remove the duplicate information and interfaces from procfs (and consider them to be the legacy interface). The proc interface only controls the default hugepage size, which is either
a) the first one specified via hugepagesz= on the kernel command-line, if any
b) the legacy huge page size, otherwiseAll other hugepage size pool manipulations can occur through sysfs.
Signed-off-by Nishanth Aravamudan <[email protected]>
Quoted 8 lines
Quoted 3 lines
---
Note, this does end up making the manipulation and validation of multiple hstates impossible without sysfs enabled and mounted. As such,I don't think that's such a problem. The overlap between users with no sysfs and those that use multiple hugepages won't be large. And if any exist, they can specify at boot or come up with their own customer solution.
Yeah, like I said, I imagine the only ones that might care are sh folks and even there, I don't know their MMU well enough to know how big of a deal it is.
Quoted 6 lines
Quoted 5 lines
I'm not sure if this is the right approach and perhaps we should be leaving the multi-valued proc files in place (but not as the preferred interface). Or we could present the values in procfs only if SYSFS is not enabled in the kernel? I imagine (but am not 100% sure) that the only current architecture where this might be important is SUPERH?
Quoted 6 lines
I wouldn't worry too much. I think
/proc/sys/vm/nr_hugepagesetc is better as one (the compat) value after we now have the sysfs stuff. However/proc/meminfois a little more tricky. Of course the information does exist in sysfs too, but meminfo is also for user reporting, so maybe it will be better to leave it multi column?
Yeah, I suppose it could be either way. I definitely agree the writable interfaces are cleaner single-valued.
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH 1/2] hugetlb: present information in sysfs
In reply to Nishanth AravamudanQuoted 41 lines · Nishanth Aravamudan
While the procfs presentation of the hstate counters has tried to be as backwards compatible as possible, I do not believe trying to maintain all of the information in the same files is a good long-term plan. This particularly matters for architectures that can support many hugepage sizes (sparc64 might be one). Even with the three potential pagesizes on power (64k, 16m and 16g), I found the proc interface to be a little awkward.
Instead, migrate the information to sysfs in a new directory,
/sys/kernel/hugepages. Underneath that directory there will be a directory per-supported hugepage size, e.g.:
/sys/kernel/hugepages/hugepages-64/sys/kernel/hugepages/hugepages-16384/sys/kernel/hugepages/hugepages-16777216corresponding to 64k, 16m and 16g respectively. Within each hugepages-size directory there are a number of files, corresponding to the tracked counters in the hstate, e.g.:
/sys/kernel/hugepages/hugepages-64/nr_hugepages/sys/kernel/hugepages/hugepages-64/nr_overcommit_hugepages/sys/kernel/hugepages/hugepages-64/free_hugepages/sys/kernel/hugepages/hugepages-64/resv_hugepages/sys/kernel/hugepages/hugepages-64/surplus_hugepagesOf these files, the first two are read-write and the latter three are read-only. The size of the hugepage being manipulated is trivially deducible from the enclosing directory and is always expressed in kB (to match meminfo).
Signed-off-by Nishanth Aravamudan <[email protected]>---
Nick, I tested this patch and the following one at this point the series, that is between patches 7 and 8. This does require a few compile fixes/patch modifications in the later parts of the series. If we decide that 2/2 is undesirable, there will be fewer of those and 1/2 could also apply at the end, with less work. I can send you that diff, if you'd prefer.
Quoted 5 lines
Greg, I didn't hear back from you on the last posting of this patch. Not intended as a complaint, just an indication of why I didn't make any changes relative to that version. Does this seem like a reasonable patch as far as using the sysfs API? I realize a follow-on patch will be needed to updated
Documentation/ABI.
I'm sorry, it got lost in the bowels of my inbox, my appologies.
This looks fine to me, nice job. And yes, i do want to see the ABI addition as well :)
If you add that, feel free to add an:
to the patch.
thanks,
greg k-h
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH 1/2] hugetlb: present information in sysfs
Quoted 48 lines · Greg KH
Quoted 41 lines · Nishanth Aravamudan
While the procfs presentation of the hstate counters has tried to be as backwards compatible as possible, I do not believe trying to maintain all of the information in the same files is a good long-term plan. This particularly matters for architectures that can support many hugepage sizes (sparc64 might be one). Even with the three potential pagesizes on power (64k, 16m and 16g), I found the proc interface to be a little awkward.
Instead, migrate the information to sysfs in a new directory,
/sys/kernel/hugepages. Underneath that directory there will be a directory per-supported hugepage size, e.g.:
/sys/kernel/hugepages/hugepages-64/sys/kernel/hugepages/hugepages-16384/sys/kernel/hugepages/hugepages-16777216corresponding to 64k, 16m and 16g respectively. Within each hugepages-size directory there are a number of files, corresponding to the tracked counters in the hstate, e.g.:
/sys/kernel/hugepages/hugepages-64/nr_hugepages/sys/kernel/hugepages/hugepages-64/nr_overcommit_hugepages/sys/kernel/hugepages/hugepages-64/free_hugepages/sys/kernel/hugepages/hugepages-64/resv_hugepages/sys/kernel/hugepages/hugepages-64/surplus_hugepagesOf these files, the first two are read-write and the latter three are read-only. The size of the hugepage being manipulated is trivially deducible from the enclosing directory and is always expressed in kB (to match meminfo).
Signed-off-by Nishanth Aravamudan <[email protected]>---
Nick, I tested this patch and the following one at this point the series, that is between patches 7 and 8. This does require a few compile fixes/patch modifications in the later parts of the series. If we decide that 2/2 is undesirable, there will be fewer of those and 1/2 could also apply at the end, with less work. I can send you that diff, if you'd prefer.Quoted 5 lines
Greg, I didn't hear back from you on the last posting of this patch. Not intended as a complaint, just an indication of why I didn't make any changes relative to that version. Does this seem like a reasonable patch as far as using the sysfs API? I realize a follow-on patch will be needed to updated
Documentation/ABI.
Quoted 8 lines
I'm sorry, it got lost in the bowels of my inbox, my appologies.
This looks fine to me, nice job. And yes, i do want to see the ABI addition as well :)
If you add that, feel free to add an:
to the patch.
Thanks Greg. Nish will be away for a few weeks but I'm picking up his patch and so I can add the Documentation/ABI change.
I agree the interface looks nice, so thanks to everyone for the input and discussion. A minor nit: is there any point specifying units in the hugepages directory names? hugepages-64K hugepages-16M hugepages-16G?
Or perhaps for easier parsing, they could be the same unit but still specificied? hugepages-64K hugepages-16384K etc?
But it's just a very minor point, I'll not make the change myself...
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH 1/2] hugetlb: present information in sysfs
Quoted 61 lines · Nick Piggin
Quoted 48 lines · Greg KH
Quoted 41 lines · Nishanth Aravamudan
While the procfs presentation of the hstate counters has tried to be as backwards compatible as possible, I do not believe trying to maintain all of the information in the same files is a good long-term plan. This particularly matters for architectures that can support many hugepage sizes (sparc64 might be one). Even with the three potential pagesizes on power (64k, 16m and 16g), I found the proc interface to be a little awkward.
Instead, migrate the information to sysfs in a new directory,
/sys/kernel/hugepages. Underneath that directory there will be a directory per-supported hugepage size, e.g.:
/sys/kernel/hugepages/hugepages-64/sys/kernel/hugepages/hugepages-16384/sys/kernel/hugepages/hugepages-16777216corresponding to 64k, 16m and 16g respectively. Within each hugepages-size directory there are a number of files, corresponding to the tracked counters in the hstate, e.g.:
/sys/kernel/hugepages/hugepages-64/nr_hugepages/sys/kernel/hugepages/hugepages-64/nr_overcommit_hugepages/sys/kernel/hugepages/hugepages-64/free_hugepages/sys/kernel/hugepages/hugepages-64/resv_hugepages/sys/kernel/hugepages/hugepages-64/surplus_hugepagesOf these files, the first two are read-write and the latter three are read-only. The size of the hugepage being manipulated is trivially deducible from the enclosing directory and is always expressed in kB (to match meminfo).
Signed-off-by Nishanth Aravamudan <[email protected]>---
Nick, I tested this patch and the following one at this point the series, that is between patches 7 and 8. This does require a few compile fixes/patch modifications in the later parts of the series. If we decide that 2/2 is undesirable, there will be fewer of those and 1/2 could also apply at the end, with less work. I can send you that diff, if you'd prefer.Quoted 5 lines
Greg, I didn't hear back from you on the last posting of this patch. Not intended as a complaint, just an indication of why I didn't make any changes relative to that version. Does this seem like a reasonable patch as far as using the sysfs API? I realize a follow-on patch will be needed to updated
Documentation/ABI.Quoted 8 lines
I'm sorry, it got lost in the bowels of my inbox, my appologies.
This looks fine to me, nice job. And yes, i do want to see the ABI addition as well :)
If you add that, feel free to add an:
to the patch.
Thanks Greg. Nish will be away for a few weeks but I'm picking up his patch and so I can add the
Documentation/ABIchange.
Quoted 6 lines
I agree the interface looks nice, so thanks to everyone for the input and discussion. A minor nit: is there any point specifying units in the hugepages directory names? hugepages-64K hugepages-16M hugepages-16G?
Or perhaps for easier parsing, they could be the same unit but still specificied? hugepages-64K hugepages-16384K etc?
I don't care, nothing is going to parse the directory names, they are pretty much fixed, right? Just pick a unit and stick with it :)
thanks,
greg k-h
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH 1/2] hugetlb: present information in sysfs
Quoted 9 lines · Greg KH
Quoted 8 lines · Nick Piggin
Thanks Greg. Nish will be away for a few weeks but I'm picking up his patch and so I can add the
Documentation/ABIchange.I agree the interface looks nice, so thanks to everyone for the input and discussion. A minor nit: is there any point specifying units in the hugepages directory names? hugepages-64K hugepages-16M hugepages-16G?
Quoted 5 lines
Quoted 2 lines
Or perhaps for easier parsing, they could be the same unit but still specificied? hugepages-64K hugepages-16384K etc?
I don't care, nothing is going to parse the directory names, they are pretty much fixed, right? Just pick a unit and stick with it :)
I can imagine a cross platform app or library parsing them to find eg. the largest one available that fits the required size and alignment. Even within the same platform, there could be many different sizes (eg. ia64).
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH 1/2] hugetlb: present information in sysfs
In reply to Greg KHQuoted 66 lines · Greg KH
Quoted 65 lines · Nick Piggin
Quoted 48 lines · Greg KH
Quoted 41 lines · Nishanth Aravamudan
While the procfs presentation of the hstate counters has tried to be as backwards compatible as possible, I do not believe trying to maintain all of the information in the same files is a good long-term plan. This particularly matters for architectures that can support many hugepage sizes (sparc64 might be one). Even with the three potential pagesizes on power (64k, 16m and 16g), I found the proc interface to be a little awkward.
Instead, migrate the information to sysfs in a new directory,
/sys/kernel/hugepages. Underneath that directory there will be a directory per-supported hugepage size, e.g.:
/sys/kernel/hugepages/hugepages-64/sys/kernel/hugepages/hugepages-16384/sys/kernel/hugepages/hugepages-16777216corresponding to 64k, 16m and 16g respectively. Within each hugepages-size directory there are a number of files, corresponding to the tracked counters in the hstate, e.g.:
/sys/kernel/hugepages/hugepages-64/nr_hugepages/sys/kernel/hugepages/hugepages-64/nr_overcommit_hugepages/sys/kernel/hugepages/hugepages-64/free_hugepages/sys/kernel/hugepages/hugepages-64/resv_hugepages/sys/kernel/hugepages/hugepages-64/surplus_hugepagesOf these files, the first two are read-write and the latter three are read-only. The size of the hugepage being manipulated is trivially deducible from the enclosing directory and is always expressed in kB (to match meminfo).
Signed-off-by Nishanth Aravamudan <[email protected]>---
Nick, I tested this patch and the following one at this point the series, that is between patches 7 and 8. This does require a few compile fixes/patch modifications in the later parts of the series. If we decide that 2/2 is undesirable, there will be fewer of those and 1/2 could also apply at the end, with less work. I can send you that diff, if you'd prefer.Quoted 5 lines
Greg, I didn't hear back from you on the last posting of this patch. Not intended as a complaint, just an indication of why I didn't make any changes relative to that version. Does this seem like a reasonable patch as far as using the sysfs API? I realize a follow-on patch will be needed to updated
Documentation/ABI.Quoted 8 lines
I'm sorry, it got lost in the bowels of my inbox, my appologies.
This looks fine to me, nice job. And yes, i do want to see the ABI addition as well :)
If you add that, feel free to add an:
to the patch.
Thanks Greg. Nish will be away for a few weeks but I'm picking up his patch and so I can add the
Documentation/ABIchange.I agree the interface looks nice, so thanks to everyone for the input and discussion. A minor nit: is there any point specifying units in the hugepages directory names? hugepages-64K hugepages-16M hugepages-16G?
Quoted 5 lines
Quoted 2 lines
Or perhaps for easier parsing, they could be the same unit but still specificied? hugepages-64K hugepages-16384K etc?
I don't care, nothing is going to parse the directory names, they are pretty much fixed, right? Just pick a unit and stick with it :)
Well, sort of. libhuge will either parse sysfs or meminfo to see what the supported hugepage sizes are. Really, it doesn't matter too much, though, if meminfo contains the same information.
And they are only fixed per-arch, and only until someone needs the next ginormous huge page size :)
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH 1/2] hugetlb: present information in sysfs
In reply to Nick PigginQuoted 61 lines · Nick Piggin
Quoted 48 lines · Greg KH
Quoted 41 lines · Nishanth Aravamudan
While the procfs presentation of the hstate counters has tried to be as backwards compatible as possible, I do not believe trying to maintain all of the information in the same files is a good long-term plan. This particularly matters for architectures that can support many hugepage sizes (sparc64 might be one). Even with the three potential pagesizes on power (64k, 16m and 16g), I found the proc interface to be a little awkward.
Instead, migrate the information to sysfs in a new directory,
/sys/kernel/hugepages. Underneath that directory there will be a directory per-supported hugepage size, e.g.:
/sys/kernel/hugepages/hugepages-64/sys/kernel/hugepages/hugepages-16384/sys/kernel/hugepages/hugepages-16777216corresponding to 64k, 16m and 16g respectively. Within each hugepages-size directory there are a number of files, corresponding to the tracked counters in the hstate, e.g.:
/sys/kernel/hugepages/hugepages-64/nr_hugepages/sys/kernel/hugepages/hugepages-64/nr_overcommit_hugepages/sys/kernel/hugepages/hugepages-64/free_hugepages/sys/kernel/hugepages/hugepages-64/resv_hugepages/sys/kernel/hugepages/hugepages-64/surplus_hugepagesOf these files, the first two are read-write and the latter three are read-only. The size of the hugepage being manipulated is trivially deducible from the enclosing directory and is always expressed in kB (to match meminfo).
Signed-off-by Nishanth Aravamudan <[email protected]>---
Nick, I tested this patch and the following one at this point the series, that is between patches 7 and 8. This does require a few compile fixes/patch modifications in the later parts of the series. If we decide that 2/2 is undesirable, there will be fewer of those and 1/2 could also apply at the end, with less work. I can send you that diff, if you'd prefer.Quoted 5 lines
Greg, I didn't hear back from you on the last posting of this patch. Not intended as a complaint, just an indication of why I didn't make any changes relative to that version. Does this seem like a reasonable patch as far as using the sysfs API? I realize a follow-on patch will be needed to updated
Documentation/ABI.Quoted 8 lines
I'm sorry, it got lost in the bowels of my inbox, my appologies.
This looks fine to me, nice job. And yes, i do want to see the ABI addition as well :)
If you add that, feel free to add an:
to the patch.
Thanks Greg. Nish will be away for a few weeks but I'm picking up his patch and so I can add the
Documentation/ABIchange.
Quoted 7 lines
I agree the interface looks nice, so thanks to everyone for the input and discussion. A minor nit: is there any point specifying units in the hugepages directory names? hugepages-64K hugepages-16M hugepages-16G?
Or perhaps for easier parsing, they could be the same unit but still specificied? hugepages-64K hugepages-16384K etc?
Basically, I left it in kilobytes just to avoid any extra work on the kernel name side (e.g., using memfmt to dynamically create the string with the appropriate suffix) and because that's the size we report in meminfo. Userspace can presumably do the parsing to figure out what the underlying size might look prettier as, but I wanted to avoid it (and feel like that may have come up in one of Greg's reviews of a previous version of the patch).
Quoted 1 line
But it's just a very minor point, I'll not make the change myself...
Well, if it's at all a concern, we should make sure we're all happy, sysfs being an ABI and all :)
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH 1/2] hugetlb: present information in sysfs
In reply to Nick PigginQuoted 61 lines · Nick Piggin
Quoted 48 lines · Greg KH
Quoted 41 lines · Nishanth Aravamudan
While the procfs presentation of the hstate counters has tried to be as backwards compatible as possible, I do not believe trying to maintain all of the information in the same files is a good long-term plan. This particularly matters for architectures that can support many hugepage sizes (sparc64 might be one). Even with the three potential pagesizes on power (64k, 16m and 16g), I found the proc interface to be a little awkward.
Instead, migrate the information to sysfs in a new directory,
/sys/kernel/hugepages. Underneath that directory there will be a directory per-supported hugepage size, e.g.:
/sys/kernel/hugepages/hugepages-64/sys/kernel/hugepages/hugepages-16384/sys/kernel/hugepages/hugepages-16777216corresponding to 64k, 16m and 16g respectively. Within each hugepages-size directory there are a number of files, corresponding to the tracked counters in the hstate, e.g.:
/sys/kernel/hugepages/hugepages-64/nr_hugepages/sys/kernel/hugepages/hugepages-64/nr_overcommit_hugepages/sys/kernel/hugepages/hugepages-64/free_hugepages/sys/kernel/hugepages/hugepages-64/resv_hugepages/sys/kernel/hugepages/hugepages-64/surplus_hugepagesOf these files, the first two are read-write and the latter three are read-only. The size of the hugepage being manipulated is trivially deducible from the enclosing directory and is always expressed in kB (to match meminfo).
Signed-off-by Nishanth Aravamudan <[email protected]>---
Nick, I tested this patch and the following one at this point the series, that is between patches 7 and 8. This does require a few compile fixes/patch modifications in the later parts of the series. If we decide that 2/2 is undesirable, there will be fewer of those and 1/2 could also apply at the end, with less work. I can send you that diff, if you'd prefer.Quoted 5 lines
Greg, I didn't hear back from you on the last posting of this patch. Not intended as a complaint, just an indication of why I didn't make any changes relative to that version. Does this seem like a reasonable patch as far as using the sysfs API? I realize a follow-on patch will be needed to updated
Documentation/ABI.Quoted 8 lines
I'm sorry, it got lost in the bowels of my inbox, my appologies.
This looks fine to me, nice job. And yes, i do want to see the ABI addition as well :)
If you add that, feel free to add an:
to the patch.
Thanks Greg. Nish will be away for a few weeks but I'm picking up his patch and so I can add the
Documentation/ABIchange.
Quoted 6 lines
I agree the interface looks nice, so thanks to everyone for the input and discussion. A minor nit: is there any point specifying units in the hugepages directory names? hugepages-64K hugepages-16M hugepages-16G?
Or perhaps for easier parsing, they could be the same unit but still specificied? hugepages-64K hugepages-16384K etc?
Just my two cents, but I would prefer to either leave them as-is, or to append the K suffix to all values. I don't think mixing the K/M/G units buys enough user-friendliness to justify the extra complexity on the kernel side and in programs that will work with these directories.
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH 1/2] hugetlb: present information in sysfs
In reply to Greg KHQuoted 42 lines · Greg KH
Quoted 41 lines · Nishanth Aravamudan
While the procfs presentation of the hstate counters has tried to be as backwards compatible as possible, I do not believe trying to maintain all of the information in the same files is a good long-term plan. This particularly matters for architectures that can support many hugepage sizes (sparc64 might be one). Even with the three potential pagesizes on power (64k, 16m and 16g), I found the proc interface to be a little awkward.
Instead, migrate the information to sysfs in a new directory,
/sys/kernel/hugepages. Underneath that directory there will be a directory per-supported hugepage size, e.g.:
/sys/kernel/hugepages/hugepages-64/sys/kernel/hugepages/hugepages-16384/sys/kernel/hugepages/hugepages-16777216corresponding to 64k, 16m and 16g respectively. Within each hugepages-size directory there are a number of files, corresponding to the tracked counters in the hstate, e.g.:
/sys/kernel/hugepages/hugepages-64/nr_hugepages/sys/kernel/hugepages/hugepages-64/nr_overcommit_hugepages/sys/kernel/hugepages/hugepages-64/free_hugepages/sys/kernel/hugepages/hugepages-64/resv_hugepages/sys/kernel/hugepages/hugepages-64/surplus_hugepagesOf these files, the first two are read-write and the latter three are read-only. The size of the hugepage being manipulated is trivially deducible from the enclosing directory and is always expressed in kB (to match meminfo).
Signed-off-by Nishanth Aravamudan <[email protected]>---
Nick, I tested this patch and the following one at this point the series, that is between patches 7 and 8. This does require a few compile fixes/patch modifications in the later parts of the series. If we decide that 2/2 is undesirable, there will be fewer of those and 1/2 could also apply at the end, with less work. I can send you that diff, if you'd prefer.
Quoted 7 lines
Quoted 5 lines
Greg, I didn't hear back from you on the last posting of this patch. Not intended as a complaint, just an indication of why I didn't make any changes relative to that version. Does this seem like a reasonable patch as far as using the sysfs API? I realize a follow-on patch will be needed to updated
Documentation/ABI.I'm sorry, it got lost in the bowels of my inbox, my appologies.
No need to apologize, you get a lot more e-mail than I ever will :) I appreciate all your help with this stuff as well as the excellent examples in samples and the Documentation.
Quoted 6 lines
This looks fine to me, nice job. And yes, i do want to see the ABI addition as well :)
If you add that, feel free to add an:
to the patch.
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 8/23 hugetlb: abstract numa round robin selection
In reply to [email protected]Need this as a separate function for a future patch.
No behaviour change.
--- mm/hugetlb.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-)
mm/hugetlb.c +22 -15
@@ -243,6 +243,27 @@ static struct page *alloc_fresh_huge_pagreturn page; } +/* +* Use a helper variable to find the next node and then +* copy it back to hugetlb_next_nid afterwards: +* otherwise there's a window in which a racer might +* pass invalid nid MAX_NUMNODES to alloc_pages_node. +* But we don't need to use a spin_lock here: it really +* doesn't matter if occasionally a racer chooses the +* same nid as we do. Move nid forward in the mask even +* if we just successfully allocated a hugepage so that +* the next caller gets hugepages on the next node. +*/ +static int hstate_next_node (struct hstate *h) +{ +int next_nid; + next_nid =next_node (h->hugetlb_next_nid, node_online_map); +if (next_nid ==MAX_NUMNODES ) + next_nid =first_node (node_online_map); + h->hugetlb_next_nid = next_nid; +return next_nid; +} +static int alloc_fresh_huge_page (struct hstate *h) {struct page *page;
@@ -256,21 +277,7 @@ static int alloc_fresh_huge_page(struct page =alloc_fresh_huge_page_node (h, h->hugetlb_next_nid);if (page) ret =1 ; -/* -* Use a helper variable to find the next node and then -* copy it back to hugetlb_next_nid afterwards: -* otherwise there's a window in which a racer might -* pass invalid nid MAX_NUMNODES to alloc_pages_node. -* But we don't need to use a spin_lock here: it really -* doesn't matter if occasionally a racer chooses the -* same nid as we do. Move nid forward in the mask even -* if we just successfully allocated a hugepage so that -* the next caller gets hugepages on the next node. -*/ - next_nid =next_node (h->hugetlb_next_nid, node_online_map); -if (next_nid ==MAX_NUMNODES ) - next_nid =first_node (node_online_map); - h->hugetlb_next_nid = next_nid; + next_nid =hstate_next_node (h); }while (!page && h->hugetlb_next_nid != start_nid);if (ret)
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 08/23] hugetlb: abstract numa round robin selection
Quoted 6 lines · On 26.05.2008 [00:23:25 +1000], [email protected] wrote:
Need this as a separate function for a future patch.
No behaviour change.
Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 08/23] hugetlb: abstract numa round robin selection
In reply to [email protected]Quoted 7 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlb-abstract-numa-rr.patch) Need this as a separate function for a future patch.
No behaviour change.
Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 9/23 mm: introduce non panic alloc_bootmem
In reply to [email protected]Straight forward variant of the existing __alloc_bootmem_node, only difference is that it doesn't panic on failure.
--- include/linux/bootmem.h | 4 ++++ mm/bootmem.c | 12 ++++++++++++ 2 files changed, 16 insertions(+)
mm/bootmem.c +12 -0
@@ -576,6 +576,18 @@ void * __init alloc_bootmem_section(unsi }#endif +void *__init __alloc_bootmem_node_nopanic (pg_data_t *pgdat,unsigned long size, +unsigned long align,unsigned long goal) +{ +void *ptr; + + ptr =__alloc_bootmem_core (pgdat->bdata, size, align, goal,0 ); +if (ptr) +return ptr; + +return __alloc_bootmem_nopanic (size, align, goal); +} +#ifndef ARCH_LOW_ADDRESS_LIMIT #define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL#endif
include/linux/bootmem.h +4 -0
@@ -90,6 +90,10 @@ extern void *__alloc_bootmem_node(pg_datunsigned long size, unsigned long align, unsigned long goal); +extern void *__alloc_bootmem_node_nopanic (pg_data_t *pgdat, +unsigned long size, +unsigned long align, +unsigned long goal); extern unsigned long init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn, unsigned long startpfn,
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 10/23 mm: export prep_compound_page to mm
In reply to [email protected]hugetlb will need to get compound pages from bootmem to handle the case of them being greater than or equal to MAX_ORDER. Export the constructor function needed for this.
--- mm/internal.h | 2 ++ mm/page_alloc.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-)
mm/internal.h +2 -0
@@ -13,6 +13,8 @@#include <linux/mm.h> +extern void prep_compound_page (struct page *page,unsigned long order); +static inline void set_page_count (struct page *page,int v) {atomic_set (&page->_count, v);
mm/page_alloc.c +1 -1
@@ -273,7 +273,7 @@ static void free_compound_page(struct pa__free_pages_ok (page,compound_order (page)); } -static void prep_compound_page (struct page *page,unsigned long order) +void prep_compound_page (struct page *page,unsigned long order) {int i;int nr_pages =1 << order;
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 10/23] mm: export prep_compound_page to mm
Quoted 7 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (mm-export-prep_compound_page.patch) hugetlb will need to get compound pages from bootmem to handle the case of them being greater than or equal to
MAX_ORDER. Export the constructor function needed for this.Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 11/23 hugetlb: support larger than MAX_ORDER
In reply to [email protected]This is needed on x86-64 to handle GB pages in hugetlbfs, because it is not practical to enlarge MAX_ORDER to 1GB.
Instead the 1GB pages are only allocated at boot using the bootmem allocator using the hugepages=... option.
These 1G bootmem pages are never freed. In theory it would be possible to implement that with some complications, but since it would be a one-way street (>= MAX_ORDER pages cannot be allocated later) I decided not to currently.
The >= MAX_ORDER code is not ifdef'ed per architecture. It is not very big and the ifdef uglyness seemed not be worth it.
Known problems: /proc/meminfo and "free" do not display the memory allocated for gb pages in "Total". This is a little confusing for the user.
--- mm/hugetlb.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-)
mm/hugetlb.c +72 -2
@@ -14,6 +14,7 @@#include <linux/mempolicy.h> #include <linux/cpuset.h> #include <linux/mutex.h> +#include <linux/bootmem.h> #include <asm/page.h> #include <asm/pgtable.h>
@@ -167,7 +168,7 @@ static void free_huge_page(struct page *INIT_LIST_HEAD (&page->lru);spin_lock (&hugetlb_lock); -if (h->surplus_huge_pages_node[nid]) { +if (h->surplus_huge_pages_node[nid] &&huge_page_order (h) <MAX_ORDER ) {update_and_free_page (h, page); h->surplus_huge_pages--; h->surplus_huge_pages_node[nid]--;
@@ -228,6 +229,9 @@ static struct page *alloc_fresh_huge_pag {struct page *page; +if (h->order >=MAX_ORDER ) +return NULL ; + page = alloc_pages_node(nid, htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE| __GFP_REPEAT|__GFP_NOWARN,
@@ -294,6 +298,9 @@ static struct page *alloc_buddy_huge_pagstruct page *page;unsigned int nid; +if (h->order >=MAX_ORDER ) +return NULL ; +/* * Assume we will successfully allocate the surplus page to * prevent racing processes from causing the surplus to exceed
@@ -470,6 +477,10 @@ static void return_unused_surplus_pages(/* Uncommit the reservation */ h->resv_huge_pages -= unused_resv_pages; +/* Cannot return gigantic pages currently */ +if (h->order >=MAX_ORDER ) +return ; + nr_pages =min (unused_resv_pages, h->surplus_huge_pages);while (remaining_iterations-- && nr_pages) {
@@ -549,6 +560,51 @@ static struct page *alloc_huge_page(strureturn page; } +static __initdata LIST_HEAD (huge_boot_pages); + +struct huge_bootmem_page { +struct list_head list; +struct hstate *hstate; +}; + +static int __init alloc_bootmem_huge_page (struct hstate *h) +{ +struct huge_bootmem_page *m; +int nr_nodes =nodes_weight (node_online_map); + +while (nr_nodes) { + m =__alloc_bootmem_node_nopanic (NODE_DATA (h->hugetlb_next_nid), +huge_page_size (h),huge_page_size (h), +0 ); +if (m) + goto found; +hstate_next_node (h); + nr_nodes--; + } +return 0 ; + +found: +BUG_ON ((unsigned long )virt_to_phys (m) & (huge_page_size (h) -1 )); +/* Put them into a private list first because mem_map is not up yet */ +list_add (&m->list, &huge_boot_pages); + m->hstate = h; +return 1 ; +} + +/* Put bootmem huge pages into the standard lists after mem_map is up */ +static void __init gather_bootmem_prealloc (void ) +{ +struct huge_bootmem_page *m; + list_for_each_entry (m, &huge_boot_pages, list) { +struct page *page =virt_to_page (m); +struct hstate *h = m->hstate; +__ClearPageReserved (page); +WARN_ON (page_count (page) !=1 ); +prep_compound_page (page, h->order); +prep_new_huge_page (h, page,page_to_nid (page)); + } +} +static void __init hugetlb_init_one_hstate (struct hstate *h) {unsigned long i;
@@ -559,7 +615,10 @@ static void __init hugetlb_init_one_hsta h->hugetlb_next_nid =first_node (node_online_map);for (i =0 ; i < h->max_huge_pages; ++i) { -if (!alloc_fresh_huge_page (h)) +if (h->order >=MAX_ORDER ) { +if (!alloc_bootmem_huge_page (h)) +break ; + }else if (!alloc_fresh_huge_page (h))break ; } h->max_huge_pages = h->free_huge_pages = h->nr_huge_pages = i;
@@ -596,6 +655,8 @@ static int __init hugetlb_init(void)hugetlb_init_hstates (); +gather_bootmem_prealloc (); +report_hugepages ();return 0 ;
@@ -652,6 +713,9 @@ static void try_to_free_low(struct hstat {int i; +if (h->order >=MAX_ORDER ) +return ; +for (i =0 ; i <MAX_NUMNODES ; ++i) {struct page *page, *next;struct list_head *freel = &h->hugepage_freelists[i];
@@ -681,6 +745,12 @@ set_max_huge_pages(struct hstate *h, uns *err =0 ; +if (h->order >=MAX_ORDER ) { +if (count != h->max_huge_pages) + *err = -EINVAL ; +return h->max_huge_pages; + } +/* * Increase the pool size * First take pages out of surplus state. Then make up the
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 11/23] hugetlb: support larger than MAX_ORDER
Quoted 24 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
mm/hugetlb.c +20
-0@@ -549,6 +560,51 @@ static struct page *alloc_huge_page(strureturn page; } +static __initdata LIST_HEAD (huge_boot_pages); + +struct huge_bootmem_page { +struct list_head list; +struct hstate *hstate; +}; + +static int __init alloc_bootmem_huge_page (struct hstate *h) +{ +struct huge_bootmem_page *m; +int nr_nodes =nodes_weight (node_online_map); + +while (nr_nodes) { + m =__alloc_bootmem_node_nopanic (NODE_DATA (h->hugetlb_next_nid), +huge_page_size (h),huge_page_size (h), +0 ); +if (m) + goto found; +hstate_next_node (h); + nr_nodes--;
mm/hugetlb.c static struct page *alloc_huge_page(stru · line 592
Quoted 10 lines
mm/hugetlb.c +10
-0+ } +return 0 ; + +found: +BUG_ON ((unsigned long )virt_to_phys (m) & (huge_page_size (h) -1 )); +/* Put them into a private list first because mem_map is not up yet */ +list_add (&m->list, &huge_boot_pages); + m->hstate = h; +return 1 ; +}
At first I was pretty confused by how you are directly using the newly-allocated bootmem page to create a temporary list until the mem map comes up. Clever. I bet I would have understood right away if it were written like the following:
void *vaddr;
struct huge_bootmem_page *m;
vaddr = __alloc_bootmem_node_nopanic(...);
if (vaddr) {
/*
* Use the beginning of this block to store some temporary
* meta-data until the mem_map comes up.
*/
m = (huge_bootmem_page *) vaddr;
goto found;
}If you don't like that level of verbosity, could we add a comment just to make it immediately clear to the reader?
Quoted 17 lines
mm/hugetlb.c +14
-0+/* Put bootmem huge pages into the standard lists after mem_map is up */ +static void __init gather_bootmem_prealloc (void ) +{ +struct huge_bootmem_page *m; + list_for_each_entry (m, &huge_boot_pages, list) { +struct page *page =virt_to_page (m); +struct hstate *h = m->hstate; +__ClearPageReserved (page); +WARN_ON (page_count (page) !=1 ); +prep_compound_page (page, h->order); +prep_new_huge_page (h, page,page_to_nid (page)); + } +} +static void __init hugetlb_init_one_hstate (struct hstate *h) {unsigned long i;
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 11/23] hugetlb: support larger than MAX_ORDER
Quoted 31 lines · Adam Litke
Quoted 30 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
mm/hugetlb.c +26
-0@@ -549,6 +560,51 @@ static struct page *alloc_huge_page(strureturn page; } +static __initdata LIST_HEAD (huge_boot_pages); + +struct huge_bootmem_page { +struct list_head list; +struct hstate *hstate; +}; + +static int __init alloc_bootmem_huge_page (struct hstate *h) +{ +struct huge_bootmem_page *m; +int nr_nodes =nodes_weight (node_online_map); + +while (nr_nodes) { + m =__alloc_bootmem_node_nopanic (NODE_DATA (h->hugetlb_next_nid), +huge_page_size (h),huge_page_size (h), +0 ); +if (m) + goto found; +hstate_next_node (h); + nr_nodes--; + } +return 0 ; + +found: +BUG_ON ((unsigned long )virt_to_phys (m) & (huge_page_size (h) -1 )); +/* Put them into a private list first because mem_map is not up yet */
Quoted 8 lines
mm/hugetlb.c static struct page *alloc_huge_page(stru · line 592
Quoted 4 lines
mm/hugetlb.c +4
-0+list_add (&m->list, &huge_boot_pages); + m->hstate = h; +return 1 ; +}At first I was pretty confused by how you are directly using the newly-allocated bootmem page to create a temporary list until the mem map comes up. Clever. I bet I would have understood right away if it
Just a note that Andi wrote it.
Quoted 15 lines
were written like the following:
void *vaddr;
structhuge_bootmem_page*m;vaddr =
__alloc_bootmem_node_nopanic(...);if (vaddr) { /* * Use the beginning of this block to store some temporary * meta-data until the mem_map comes up. */ m = (huge_bootmem_page *) vaddr; goto found; }
Quoted 2 lines
If you don't like that level of verbosity, could we add a comment just to make it immediately clear to the reader?
Yeah OK.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 12/23 hugetlb: support boot allocate different sizes
In reply to [email protected]--- mm/hugetlb.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
mm/hugetlb.c +19 -5
@@ -609,10 +609,13 @@ static void __init hugetlb_init_one_hsta {unsigned long i; -for (i =0 ; i <MAX_NUMNODES ; ++i) -INIT_LIST_HEAD (&h->hugepage_freelists[i]); +/* Don't reinitialize lists if they have been already init'ed */ +if (!h->hugepage_freelists[0 ].next) { +for (i =0 ; i <MAX_NUMNODES ; ++i) +INIT_LIST_HEAD (&h->hugepage_freelists[i]); - h->hugetlb_next_nid =first_node (node_online_map); + h->hugetlb_next_nid =first_node (node_online_map); + }for (i =0 ; i < h->max_huge_pages; ++i) {if (h->order >=MAX_ORDER ) {
@@ -621,7 +624,7 @@ static void __init hugetlb_init_one_hsta }else if (!alloc_fresh_huge_page (h))break ; } - h->max_huge_pages = h->free_huge_pages = h->nr_huge_pages = i; + h->max_huge_pages = i; }static void __init hugetlb_init_hstates (void )
@@ -629,7 +632,10 @@ static void __init hugetlb_init_hstates(struct hstate *h;for_each_hstate (h) { -hugetlb_init_one_hstate (h); +/* oversize hugepages were init'ed in early boot */ +if (h->order <MAX_ORDER ) +hugetlb_init_one_hstate (h); + max_huge_pages[h - hstates] = h->max_huge_pages; } }
@@ -692,6 +698,14 @@ static int __init hugetlb_setup(char *s)if (sscanf (s,"%lu" , mhp) <=0 ) *mhp =0 ; +/* +* Global state is always initialized later in hugetlb_init. +* But we need to allocate >= MAX_ORDER hstates here early to still +* use the bootmem allocator. +*/ +if (max_hstate >0 && parsed_hstate->order >=MAX_ORDER ) +hugetlb_init_one_hstate (parsed_hstate); +return 1 ; }__setup ("hugepages=" , hugetlb_setup);
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 12/23] hugetlb: support boot allocate different sizes
Quoted 3 lines · On 26.05.2008 [00:23:29 +1000], [email protected] wrote:
Acked-by Andrew Hastings <[email protected]>Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 12/23] hugetlb: support boot allocate different sizes
In reply to [email protected]Seems nice, but what exactly is this patch for? From reading the code it would seem that this allows more than one >MAX_ORDER hstates to exist and removes assumptions about their positioning withing the hstates array? A small patch leader would definitely clear up my confusion.
Quoted 66 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlb-different-page-sizes.patch)
Acked-by Andrew Hastings <[email protected]>Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>--- mm/hugetlb.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)Index:
linux-2.6/mm/hugetlb.c
===================================================================mm/hugetlb.c +19
-5@@ -609,10 +609,13 @@ static void __init hugetlb_init_one_hsta {unsigned long i; -for (i =0 ; i <MAX_NUMNODES ; ++i) -INIT_LIST_HEAD (&h->hugepage_freelists[i]); +/* Don't reinitialize lists if they have been already init'ed */ +if (!h->hugepage_freelists[0 ].next) { +for (i =0 ; i <MAX_NUMNODES ; ++i) +INIT_LIST_HEAD (&h->hugepage_freelists[i]); - h->hugetlb_next_nid =first_node (node_online_map); + h->hugetlb_next_nid =first_node (node_online_map); + }for (i =0 ; i < h->max_huge_pages; ++i) {if (h->order >=MAX_ORDER ) {@@ -621,7 +624,7 @@ static void __init hugetlb_init_one_hsta }else if (!alloc_fresh_huge_page (h))break ; } - h->max_huge_pages = h->free_huge_pages = h->nr_huge_pages = i; + h->max_huge_pages = i; }static void __init hugetlb_init_hstates (void )@@ -629,7 +632,10 @@ static void __init hugetlb_init_hstates(struct hstate *h;for_each_hstate (h) { -hugetlb_init_one_hstate (h); +/* oversize hugepages were init'ed in early boot */ +if (h->order <MAX_ORDER ) +hugetlb_init_one_hstate (h); + max_huge_pages[h - hstates] = h->max_huge_pages; } }@@ -692,6 +698,14 @@ static int __init hugetlb_setup(char *s)if (sscanf (s,"%lu" , mhp) <=0 ) *mhp =0 ; +/* +* Global state is always initialized later in hugetlb_init. +* But we need to allocate >= MAX_ORDER hstates here early to still +* use the bootmem allocator. +*/ +if (max_hstate >0 && parsed_hstate->order >=MAX_ORDER ) +hugetlb_init_one_hstate (parsed_hstate); +return 1 ; }__setup ("hugepages=" , hugetlb_setup);
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 12/23] hugetlb: support boot allocate different sizes
Quoted 4 lines · Adam Litke
Seems nice, but what exactly is this patch for? From reading the code it would seem that this allows more than one >MAX_ORDER hstates to exist and removes assumptions about their positioning withing the hstates array? A small patch leader would definitely clear up my confusion.
Yes it allows I guess hugetlb_init_one_hstate to be called multiple times on an hstate, and also some logic dealing with giant page setup.
Though hmm, possibly it can be made a little cleaner by separating hstate init from the actual page allocation a little more. I'll have a look but it is kind of tricky... otherwise I can try a changelog.
Quoted 56 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
Quoted 54 lines
plain text document attachment (hugetlb-different-page-sizes.patch)
Acked-by Andrew Hastings <[email protected]>Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>--- mm/hugetlb.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)Index:
linux-2.6/mm/hugetlb.c
===================================================================mm/hugetlb.c +11
-5@@ -609,10 +609,13 @@ static void __init hugetlb_init_one_hsta {unsigned long i; -for (i =0 ; i <MAX_NUMNODES ; ++i) -INIT_LIST_HEAD (&h->hugepage_freelists[i]); +/* Don't reinitialize lists if they have been already init'ed */ +if (!h->hugepage_freelists[0 ].next) { +for (i =0 ; i <MAX_NUMNODES ; ++i) +INIT_LIST_HEAD (&h->hugepage_freelists[i]); - h->hugetlb_next_nid =first_node (node_online_map); + h->hugetlb_next_nid =first_node (node_online_map); + }for (i =0 ; i < h->max_huge_pages; ++i) {if (h->order >=MAX_ORDER ) {@@ -621,7 +624,7 @@ static void __init hugetlb_init_one_hsta }else if (!alloc_fresh_huge_page (h))break ; } - h->max_huge_pages = h->free_huge_pages = h->nr_huge_pages = i; + h->max_huge_pages = i; }static void __init hugetlb_init_hstates (void )@@ -629,7 +632,10 @@ static void __init hugetlb_init_hstates(struct hstate *h;for_each_hstate (h) { -hugetlb_init_one_hstate (h); +/* oversize hugepages were init'ed in early boot */ +if (h->order <MAX_ORDER ) +hugetlb_init_one_hstate (h); + max_huge_pages[h - hstates] = h->max_huge_pages; } }@@ -692,6 +698,14 @@ static int __init hugetlb_setup(char *s)if (sscanf (s,"%lu" , mhp) <=0 ) *mhp =0 ;
Quoted 15 lines
Quoted 12 lines
mm/hugetlb.c +8
-0+/* +* Global state is always initialized later in hugetlb_init. +* But we need to allocate >= MAX_ORDER hstates here early to still +* use the bootmem allocator. +*/ +if (max_hstate >0 && parsed_hstate->order >=MAX_ORDER ) +hugetlb_init_one_hstate (parsed_hstate); +return 1 ; }__setup ("hugepages=" , hugetlb_setup);Signature · 2 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 12/23] hugetlb: support boot allocate different sizes
Quoted 6 lines · Nick Piggin
Quoted 4 lines · Adam Litke
Seems nice, but what exactly is this patch for? From reading the code it would seem that this allows more than one >MAX_ORDER hstates to exist and removes assumptions about their positioning withing the hstates array? A small patch leader would definitely clear up my confusion.
Quoted 6 lines
Yes it allows I guess
hugetlb_init_one_hstateto be called multiple times on an hstate, and also some logic dealing with giant page setup.Though hmm, possibly it can be made a little cleaner by separating hstate init from the actual page allocation a little more. I'll have a look but it is kind of tricky... otherwise I can try a changelog.
This is how I've made the patch:
---
hugetlb: support boot allocate different sizes
Make some infrastructure changes to allow boot allocation of different hugepage page sizes.
- move all basic hstate initialisation into hugetlb_add_hstate
- create a new function hugetlb_hstate_alloc_pages() to do the actual initial page allocations. Call this function early in order to allocate giant pages from bootmem.
- Check for multiple hugepages= parameters
--- mm/hugetlb.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
mm/hugetlb.c +30 -9
@@ -617,15 +617,10 @@ static void __init gather_bootmem_preall } } -static void __init hugetlb_init_one_hstate (struct hstate *h) +static void __init hugetlb_hstate_alloc_pages (struct hstate *h) {unsigned long i; -for (i =0 ; i <MAX_NUMNODES ; ++i) -INIT_LIST_HEAD (&h->hugepage_freelists[i]); - - h->hugetlb_next_nid =first_node (node_online_map); -for (i =0 ; i < h->max_huge_pages; ++i) {if (h->order >=MAX_ORDER ) {if (!alloc_bootmem_huge_page (h))
@@ -633,7 +628,7 @@ static void __init hugetlb_init_one_hsta }else if (!alloc_fresh_huge_page (h))break ; } - h->max_huge_pages = h->free_huge_pages = h->nr_huge_pages = i; + h->max_huge_pages = i; }static void __init hugetlb_init_hstates (void )
@@ -641,7 +636,10 @@ static void __init hugetlb_init_hstates(struct hstate *h;for_each_hstate (h) { -hugetlb_init_one_hstate (h); +/* oversize hugepages were init'ed in early boot */ +if (h->order <MAX_ORDER ) +hugetlb_hstate_alloc_pages (h); + max_huge_pages[h - hstates] = h->max_huge_pages; } }
@@ -679,6 +677,8 @@ module_init(hugetlb_init);void __init hugetlb_add_hstate (unsigned order) {struct hstate *h; +unsigned long i; +if (size_to_hstate (PAGE_SIZE << order)) {printk (KERN_WARNING "hugepagesz= specified twice, ignoring\n" );return ;
@@ -688,13 +688,19 @@ void __init hugetlb_add_hstate(unsigned h = &hstates[max_hstate++]; h->order = order; h->mask = ~((1ULL << (order +PAGE_SHIFT )) -1 ); -hugetlb_init_one_hstate (h); + h->nr_huge_pages =0 ; + h->free_huge_pages =0 ; +for (i =0 ; i <MAX_NUMNODES ; ++i) +INIT_LIST_HEAD (&h->hugepage_freelists[i]); + h->hugetlb_next_nid =first_node (node_online_map); + parsed_hstate = h; }static int __init hugetlb_setup (char *s) {unsigned long *mhp; +static unsigned long *last_mhp;/* * !max_hstate means we haven't parsed a hugepagesz= parameter yet,
@@ -705,9 +711,24 @@ static int __init hugetlb_setup(char *s)else mhp = &parsed_hstate->max_huge_pages; +if (mhp == last_mhp) { +printk (KERN_WARNING "hugepages= specified twice without interleaving hugepagesz=, ignoring\n" ); +return 1 ; + } +if (sscanf (s,"%lu" , mhp) <=0 ) *mhp =0 ; +/* +* Global state is always initialized later in hugetlb_init. +* But we need to allocate >= MAX_ORDER hstates here early to still +* use the bootmem allocator. +*/ +if (max_hstate && parsed_hstate->order >=MAX_ORDER ) +hugetlb_hstate_alloc_pages (parsed_hstate); + + last_mhp = mhp; +return 1 ; }__setup ("hugepages=" , hugetlb_setup);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Adam Litke
Acked-byRe: [patch 12/23] hugetlb: support boot allocate different sizes
Quoted 7 lines · Nick Piggin
Quoted 6 lines · Nick Piggin
Quoted 4 lines · Adam Litke
Seems nice, but what exactly is this patch for? From reading the code it would seem that this allows more than one >MAX_ORDER hstates to exist and removes assumptions about their positioning withing the hstates array? A small patch leader would definitely clear up my confusion.
Quoted 8 lines
Quoted 6 lines
Yes it allows I guess
hugetlb_init_one_hstateto be called multiple times on an hstate, and also some logic dealing with giant page setup.Though hmm, possibly it can be made a little cleaner by separating hstate init from the actual page allocation a little more. I'll have a look but it is kind of tricky... otherwise I can try a changelog.
This is how I've made the patch:
Thanks. That's a lot clearer to me.
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 13/23 hugetlb: printk cleanup
In reply to [email protected]- Reword sentence to clarify meaning with multiple options
- Add support for using GB prefixes for the page size
- Add extra printk to delayed > MAX_ORDER allocation code
--- mm/hugetlb.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)
mm/hugetlb.c +17 -4
@@ -639,15 +639,28 @@ static void __init hugetlb_init_hstates( } } +static char *__init memfmt (char *buf,unsigned long n) +{ +if (n >= (1UL <<30 )) +sprintf (buf,"%lu GB" , n >>30 ); +else if (n >= (1UL <<20 )) +sprintf (buf,"%lu MB" , n >>20 ); +else +sprintf (buf,"%lu KB" , n >>10 ); +return buf; +} +static void __init report_hugepages (void ) {struct hstate *h;for_each_hstate (h) { -printk (KERN_INFO "Total HugeTLB memory allocated, %ld %dMB pages\n" , - h->free_huge_pages, -1 << (h->order +PAGE_SHIFT -20 )); - } +char buf[32 ]; +printk (KERN_INFO "HugeTLB registered %s page size, " +"pre-allocated %ld pages\n" , +memfmt (buf,huge_page_size (h)), + h->free_huge_pages); + } }static int __init hugetlb_init (void )
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 13/23] hugetlb: printk cleanup
Quoted 6 lines · On 26.05.2008 [00:23:30 +1000], [email protected] wrote:
- Reword sentence to clarify meaning with multiple options
- Add support for using GB prefixes for the page size
- Add extra printk to delayed >MAX_ORDERallocation codeSigned-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 13/23] hugetlb: printk cleanup
In reply to [email protected]Quoted 7 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlb-printk-cleanup.patch)
- Reword sentence to clarify meaning with multiple options
- Add support for using GB prefixes for the page size
- Add extra printk to delayed >MAX_ORDERallocation codeSigned-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 14/23 hugetlb: introduce huge_pud
In reply to [email protected]Straight forward extensions for huge pages located in the PUD instead of PMDs.
--- arch/ia64/mm/hugetlbpage.c | 6 ++++++ arch/powerpc/mm/hugetlbpage.c | 5 +++++ arch/sh/mm/hugetlbpage.c | 5 +++++ arch/sparc64/mm/hugetlbpage.c | 5 +++++ arch/x86/mm/hugetlbpage.c | 25 ++++++++++++++++++++++++- include/linux/hugetlb.h | 5 +++++ mm/hugetlb.c | 9 +++++++++ mm/memory.c | 10 +++++++++- 8 files changed, 68 insertions(+), 2 deletions(-)
include/linux/hugetlb.h +5 -0
@@ -45,7 +45,10 @@ struct page *follow_huge_addr(struct mm_ int write);struct page *follow_huge_pmd (struct mm_struct *mm,unsigned long address,pmd_t *pmd,int write); +struct page *follow_huge_pud (struct mm_struct *mm,unsigned long address, +pud_t *pud,int write);int pmd_huge (pmd_t pmd); +int pud_huge (pud_t pmd);void hugetlb_change_protection (struct vm_area_struct *vma,unsigned long address,unsigned long end,pgprot_t newprot);
@@ -68,8 +71,10 @@ static inline unsigned long hugetlb_tota#define hugetlb_report_meminfo (buf) 0#define hugetlb_report_node_meminfo (n, buf) 0#define follow_huge_pmd (mm, addr, pmd, write) NULL +#define follow_huge_pud (mm, addr, pud, write) NULL#define prepare_hugepage_range (file, addr, len) (-EINVAL)#define pmd_huge (x) 0 +#define pud_huge (x) 0#define is_hugepage_only_range (mm, addr, len) 0#define hugetlb_free_pgd_range (tlb, addr, end, floor, ceiling) ({BUG(); 0; })#define hugetlb_fault (mm, vma, addr, write) ({ BUG(); 0; })
arch/ia64/mm/hugetlbpage.c +6 -0
@@ -106,6 +106,12 @@ int pmd_huge(pmd_t pmd) {return 0 ; } + +int pud_huge (pud_t pud) +{ +return 0 ; +} +struct page *follow_huge_pmd (struct mm_struct *mm,unsigned long address,pmd_t *pmd,int write) {
arch/powerpc/mm/hugetlbpage.c +5 -0
@@ -368,6 +368,11 @@ int pmd_huge(pmd_t pmd)return 0 ; } +int pud_huge (pud_t pud) +{ +return 0 ; +} +struct page *follow_huge_pmd (struct mm_struct *mm,unsigned long address,pmd_t *pmd,int write)
arch/sh/mm/hugetlbpage.c +5 -0
@@ -78,6 +78,11 @@ int pmd_huge(pmd_t pmd)return 0 ; } +int pud_huge (pud_t pud) +{ +return 0 ; +} +struct page *follow_huge_pmd (struct mm_struct *mm,unsigned long address,pmd_t *pmd,int write) {
arch/sparc64/mm/hugetlbpage.c +5 -0
@@ -294,6 +294,11 @@ int pmd_huge(pmd_t pmd)return 0 ; } +int pud_huge (pud_t pud) +{ +return 0 ; +} +struct page *follow_huge_pmd (struct mm_struct *mm,unsigned long address,pmd_t *pmd,int write) {
arch/x86/mm/hugetlbpage.c +24 -1
@@ -188,6 +188,11 @@ int pmd_huge(pmd_t pmd)return 0 ; } +int pud_huge (pud_t pud) +{ +return 0 ; +} +struct page *follow_huge_pmd (struct mm_struct *mm,unsigned long address,pmd_t *pmd,int write)
@@ -208,6 +213,11 @@ int pmd_huge(pmd_t pmd)return !!(pmd_val (pmd) & _PAGE_PSE); } +int pud_huge (pud_t pud) +{ +return 0 ; +} +struct page *follow_huge_pmd (struct mm_struct *mm,unsigned long address,pmd_t *pmd,int write)
@@ -216,9 +226,22 @@ follow_huge_pmd(struct mm_struct *mm, un page =pte_page (*(pte_t *)pmd);if (page) - page += ((address & ~HPAGE_MASK ) >>PAGE_SHIFT ); + page += ((address & ~PMD_MASK ) >>PAGE_SHIFT ); return page; } + +struct page * +follow_huge_pud (struct mm_struct *mm,unsigned long address, +pud_t *pud,int write) +{ +struct page *page; + + page =pte_page (*(pte_t *)pud); +if (page) + page += ((address & ~PUD_MASK ) >>PAGE_SHIFT ); +return page; +} +#endif /* x86_64 also uses this file */
mm/hugetlb.c +9 -0
@@ -1275,6 +1275,15 @@ int hugetlb_fault(struct mm_struct *mm,return ret; } +/* Can be overriden by architectures */ +__attribute__((weak))struct page * +follow_huge_pud (struct mm_struct *mm,unsigned long address, +pud_t *pud,int write) +{ +BUG (); +return NULL ; +} + int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, struct page **pages, struct vm_area_struct **vmas, unsigned long *position, int *length, int i,
mm/memory.c +9 -1
@@ -998,7 +998,13 @@ struct page *follow_page(struct vm_area_ pud =pud_offset (pgd, address);if (pud_none (*pud) ||unlikely (pud_bad (*pud))) goto no_page_table; - + +if (pud_huge (*pud)) { +BUG_ON (flags &FOLL_GET ); + page =follow_huge_pud (mm, address, pud, flags &FOLL_WRITE ); + goto out; + } + pmd =pmd_offset (pud, address);if (pmd_none (*pmd)) goto no_page_table;
@@ -1534,6 +1540,8 @@ static int apply_to_pmd_range(struct mm_unsigned long next;int err; +BUG_ON (pud_huge (*pud)); + pmd =pmd_alloc (mm, pud, addr);if (!pmd)return -ENOMEM ;
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 14/23] hugetlb: introduce huge_pud
Quoted 5 lines · On Mon, 26 May 2008, [email protected] wrote:
Straight forward extensions for huge pages located in the PUD instead of PMDs.
Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Sorry, I've not looked through all these, but the subject of this one (which should say "pud_huge" rather than "huge_pud") led me to check:
please take a look at commit aeed5fce37196e09b4dac3a1c00d8b7122e040ce, I believe your follow_page will need to try pud_huge before pud_bad.
Though note in the comment to that commit, I'm dubious whether we can ever actually hit that case, or need follow_huge_pmd (or your follow_huge_pud) at all: please cross check, you might prefer to delete the huge pmd code there rather than add huge pud code, if you agree that there's actually no way we need it.
Hugh
Quoted 7 lines
mm/memory.c +0
-1@@ -998,7 +998,13 @@ struct page *follow_page(struct vm_area_ pud =pud_offset (pgd, address);if (pud_none (*pud) ||unlikely (pud_bad (*pud))) goto no_page_table; -
mm/memory.c struct page *follow_page(struct vm_area_ · line 1010
Quoted 10 lines
mm/memory.c +7
-0+ +if (pud_huge (*pud)) { +BUG_ON (flags &FOLL_GET ); + page =follow_huge_pud (mm, address, pud, flags &FOLL_WRITE ); + goto out; + } + pmd =pmd_offset (pud, address);if (pmd_none (*pmd)) goto no_page_table;
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 14/23] hugetlb: introduce huge_pud
Quoted 11 lines · Hugh Dickins
Quoted 5 lines · On Mon, 26 May 2008, [email protected] wrote:
Straight forward extensions for huge pages located in the PUD instead of PMDs.
Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>Sorry, I've not looked through all these, but the subject of this one (which should say "
pud_huge" rather than "huge_pud") led me to check:
please take a look at commitaeed5fce37196e09b4dac3a1c00d8b7122e040ce, I believe yourfollow_pagewill need to trypud_hugebeforepud_bad.
Ah, you're right there, yes thanks.
Quoted 5 lines
Though note in the comment to that commit, I'm dubious whether we can ever actually hit that case, or need
follow_huge_pmd(or yourfollow_huge_pud) at all: please cross check, you might prefer to delete the huge pmd code there rather than add huge pud code, if you agree that there's actually no way we need it.
Haven't had a look yet, but I'll probably leave that for another person or time to do.
Thanks,
Nick
Quoted 12 lines
Hugh
Quoted 9 lines
mm/memory.c +2
-1@@ -998,7 +998,13 @@ struct page *follow_page(struct vm_area_ pud =pud_offset (pgd, address);if (pud_none (*pud) ||unlikely (pud_bad (*pud))) goto no_page_table; - + +if (pud_huge (*pud)) {
Quoted 8 lines
mm/memory.c struct page *follow_page(struct vm_area_ · line 1010
Quoted 8 lines
mm/memory.c +5
-0+BUG_ON (flags &FOLL_GET ); + page =follow_huge_pud (mm, address, pud, flags &FOLL_WRITE ); + goto out; + } + pmd =pmd_offset (pud, address);if (pmd_none (*pmd)) goto no_page_table;
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 15/23 x86: support GB hugepages on 64-bit
In reply to [email protected]--- arch/x86/mm/hugetlbpage.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-)
arch/x86/mm/hugetlbpage.c +22 -11
@@ -133,9 +133,14 @@ pte_t *huge_pte_alloc(struct mm_struct * pgd =pgd_offset (mm, addr); pud =pud_alloc (mm, pgd, addr);if (pud) { -if (pud_none (*pud)) -huge_pmd_share (mm, addr, pud); - pte = (pte_t *)pmd_alloc (mm, pud, addr); +if (sz ==PUD_SIZE ) { + pte = (pte_t *)pud; + }else { +BUG_ON (sz !=PMD_SIZE ); +if (pud_none (*pud)) +huge_pmd_share (mm, addr, pud); + pte = (pte_t *)pmd_alloc (mm, pud, addr); + } }BUG_ON (pte && !pte_none (*pte) && !pte_huge (*pte));
@@ -151,8 +156,11 @@ pte_t *huge_pte_offset(struct mm_struct pgd =pgd_offset (mm, addr);if (pgd_present (*pgd)) { pud =pud_offset (pgd, addr); -if (pud_present (*pud)) +if (pud_present (*pud)) { +if (pud_large (*pud)) +return (pte_t *)pud; pmd =pmd_offset (pud, addr); + } }return (pte_t *) pmd; }
@@ -215,7 +223,7 @@ int pmd_huge(pmd_t pmd)int pud_huge (pud_t pud) { -return 0 ; +return !!(pud_val (pud) & _PAGE_PSE); } struct page *
@@ -251,6 +259,7 @@ static unsigned long hugetlb_get_unmappe unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { + struct hstate *h = hstate_file(file);struct mm_struct *mm = current->mm;struct vm_area_struct *vma;unsigned long start_addr;
@@ -263,7 +272,7 @@ static unsigned long hugetlb_get_unmappe } full_search: - addr =ALIGN (start_addr,HPAGE_SIZE ); + addr =ALIGN (start_addr,huge_page_size (h));for (vma =find_vma (mm, addr); ; vma = vma->vm_next) {/* At this point: (!vma || addr < vma->vm_end). */
@@ -285,7 +294,7 @@ full_search: }if (addr + mm->cached_hole_size < vma->vm_start) mm->cached_hole_size = vma->vm_start - addr; - addr =ALIGN (vma->vm_end,HPAGE_SIZE ); + addr =ALIGN (vma->vm_end,huge_page_size (h)); } }
@@ -293,6 +302,7 @@ static unsigned long hugetlb_get_unmappe unsigned long addr0, unsigned long len, unsigned long pgoff, unsigned long flags) { + struct hstate *h = hstate_file(file);struct mm_struct *mm = current->mm;struct vm_area_struct *vma, *prev_vma;unsigned long base = mm->mmap_base, addr = addr0;
@@ -313,7 +323,7 @@ try_again: goto fail;/* either no address requested or cant fit in requested address hole */ - addr = (mm->free_area_cache - len) &HPAGE_MASK ; + addr = (mm->free_area_cache - len) &huge_page_mask (h); do { /* * Lookup failure means no vma is above this address,
@@ -344,7 +354,7 @@ try_again: largest_hole = vma->vm_start - addr;/* try just below the current vma->vm_start */ - addr = (vma->vm_start - len) &HPAGE_MASK ; + addr = (vma->vm_start - len) &huge_page_mask (h); }while (len <= vma->vm_start); fail:
@@ -382,10 +392,11 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { + struct hstate *h = hstate_file(file);struct mm_struct *mm = current->mm;struct vm_area_struct *vma; -if (len & ~HPAGE_MASK ) +if (len & ~huge_page_mask (h))return -EINVAL ;if (len >TASK_SIZE )return -ENOMEM ;
@@ -397,7 +408,7 @@ hugetlb_get_unmapped_area(struct file *f }if (addr) { - addr =ALIGN (addr,HPAGE_SIZE ); + addr =ALIGN (addr,huge_page_size (h)); vma =find_vma (mm, addr);if (TASK_SIZE - len >= addr && (!vma || addr + len <= vma->vm_start))
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 15/23] x86: support GB hugepages on 64-bit
Quoted 3 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (x86-support-GB-hugetlb-pages.patch)
Signed-off-by Andi Kleen <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 16/23 x86: add hugepagesz option on 64-bit
In reply to [email protected]Add an hugepagesz=... option similar to IA64, PPC etc. to x86-64.
This finally allows to select GB pages for hugetlbfs in x86 now that all the infrastructure is in place.
--- Documentation/kernel-parameters.txt | 11 +++++++++-- arch/x86/mm/hugetlbpage.c | 17 +++++++++++++++++ include/asm-x86/page.h | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-)
arch/x86/mm/hugetlbpage.c +17 -0
@@ -424,3 +424,20 @@ hugetlb_get_unmapped_area(struct file *f#endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/ +#ifdef CONFIG_X86_64 +static __init int setup_hugepagesz (char *opt) +{ +unsigned long ps =memparse (opt, &opt); +if (ps ==PMD_SIZE ) { +hugetlb_add_hstate (PMD_SHIFT -PAGE_SHIFT ); + }else if (ps ==PUD_SIZE && cpu_has_gbpages) { +hugetlb_add_hstate (PUD_SHIFT -PAGE_SHIFT ); + }else { +printk (KERN_ERR "hugepagesz: Unsupported page size %lu M\n" , + ps >>20 ); +return 0 ; + } +return 1 ; +} +__setup ("hugepagesz=" , setup_hugepagesz); +#endif
include/asm-x86/page.h +2 -0
@@ -29,6 +29,8 @@#define HPAGE_MASK (~(HPAGE_SIZE - 1))#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) +#define HUGE_MAX_HSTATE 2 +/* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN (addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
Documentation/kernel-parameters.txt +9 -2
@@ -737,8 +737,15 @@ and is between 256 and 4096 characters. hisax= [HW,ISDN] See Documentation/isdn/README.HiSax. - hugepages= [HW,X86-32,IA-64] Maximal number of HugeTLB pages. - hugepagesz= [HW,IA-64,PPC] The size of the HugeTLB pages. + hugepages= [HW,X86-32,IA-64] HugeTLB pages to allocate at boot. + hugepagesz= [HW,IA-64,PPC,X86-64] The size of the HugeTLB pages. + On x86 this option can be specified multiple times + interleaved with hugepages= to reserve huge pages + of different sizes. Valid pages sizes on x86-64 + are 2M (when the CPU supports "pse") and 1G (when the + CPU supports the "pdpe1gb" cpuinfo flag) + Note that 1GB pages can only be allocated at boot time + using hugepages= and not freed afterwards. i8042.direct [HW] Put keyboard port into non-translated mode i8042.dumbkbd [HW] Pretend that controller can only read data from
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 17/23 hugetlb: do not always register default HPAGE_SIZE huge page size
In reply to [email protected]Allow configurations without the default HPAGE_SIZE size (mainly useful for testing -- the final form of the userspace API / cmdline is not quite nailed down).
--- fs/hugetlbfs/inode.c | 2 ++ mm/hugetlb.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-)
mm/hugetlb.c +1 -1
@@ -667,7 +667,7 @@ static int __init hugetlb_init(void) {BUILD_BUG_ON (HPAGE_SHIFT ==0 ); -if (!size_to_hstate (HPAGE_SIZE )) { +if (!max_hstate) {hugetlb_add_hstate (HUGETLB_PAGE_ORDER ); parsed_hstate->max_huge_pages = default_hstate_max_huge_pages; }
fs/hugetlbfs/inode.c +2 -0
@@ -858,6 +858,8 @@ hugetlbfs_fill_super(struct super_block config.gid = current->fsgid; config.mode =0755 ; config.hstate =size_to_hstate (HPAGE_SIZE ); +if (!config.hstate) + config.hstate = &hstates[0 ]; ret =hugetlbfs_parse_options (data, &config);if (ret)return ret;
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 17/23] hugetlb: do not always register default HPAGE_SIZE huge page size
Quoted 6 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlb-non-default-hstate.patch) Allow configurations without the default
HPAGE_SIZEsize (mainly useful for testing -- the final form of the userspace API / cmdline is not quite nailed down).Signed-off-by Nick Piggin <[email protected]>
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 18/23 hugetlb: allow arch overried hugepage allocation
In reply to [email protected]Allow alloc_bootmem_huge_page() to be overridden by architectures that can't always use bootmem. This requires huge_boot_pages to be available for use by this function. The 16G pages on ppc64 have to be reserved prior to boot-time. The location of these pages are indicated in the device tree.
---
include/linux/hugetlb.h | 10 ++++++++++ mm/hugetlb.c | 12 ++++-------- 2 files changed, 14 insertions(+), 8 deletions(-)
include/linux/hugetlb.h +10 -0
@@ -35,6 +35,7 @@ void hugetlb_unreserve_pages(struct inodextern unsigned long hugepages_treat_as_movable;extern const unsigned long hugetlb_zero, hugetlb_infinity;extern int sysctl_hugetlb_shm_group; +extern struct list_head huge_boot_pages;/* arch callbacks */
@@ -176,6 +177,14 @@ struct hstate {unsigned int surplus_huge_pages_node[MAX_NUMNODES ]; }; +struct huge_bootmem_page { +struct list_head list; +struct hstate *hstate; +}; + +/* arch callback */ +int __init alloc_bootmem_huge_page (struct hstate *h); +void __init hugetlb_add_hstate (unsigned order);struct hstate *size_to_hstate (unsigned long size);
@@ -237,6 +246,7 @@ extern unsigned long sysctl_overcommit_h#else struct hstate {}; +#define alloc_bootmem_huge_page (h) NULL#define hstate_file (f) NULL#define hstate_vma (v) NULL#define hstate_inode (i) NULL
mm/hugetlb.c +4 -8
@@ -27,6 +27,7 @@ unsigned long max_huge_pages[HUGE_MAX_HSunsigned long sysctl_overcommit_huge_pages[HUGE_MAX_HSTATE ];static gfp_t htlb_alloc_mask =GFP_HIGHUSER ;unsigned long hugepages_treat_as_movable; +struct list_head huge_boot_pages;static int max_hstate =0 ;struct hstate hstates[HUGE_MAX_HSTATE ];
@@ -560,14 +561,7 @@ static struct page *alloc_huge_page(strureturn page; } -static __initdata LIST_HEAD (huge_boot_pages); - -struct huge_bootmem_page { -struct list_head list; -struct hstate *hstate; -}; - -static int __init alloc_bootmem_huge_page (struct hstate *h) +__attribute__((weak))int alloc_bootmem_huge_page (struct hstate *h) {struct huge_bootmem_page *m;int nr_nodes =nodes_weight (node_online_map);
@@ -610,6 +604,8 @@ static void __init hugetlb_init_one_hstaunsigned long i;/* Don't reinitialize lists if they have been already init'ed */ +if (!huge_boot_pages.next) +INIT_LIST_HEAD (&huge_boot_pages);if (!h->hugepage_freelists[0 ].next) {for (i =0 ; i <MAX_NUMNODES ; ++i)INIT_LIST_HEAD (&h->hugepage_freelists[i]);
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 18/23] hugetlb: allow arch overried hugepage allocation
Quoted 10 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (hugetlb-allow-arch-override-hugepage-allocation.patch)
Allowalloc_bootmem_huge_page()to be overridden by architectures that can't always use bootmem. This requireshuge_boot_pagesto be available for use by this function. The 16G pages on ppc64 have to be reserved prior to boot-time. The location of these pages are indicated in the device tree.Signed-off-by Jon Tollefson <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 19/23 powerpc: function to allocate gigantic hugepages
In reply to [email protected]The 16G page locations have been saved during early boot in an array. The alloc_bootmem_huge_page() function adds a page from here to the huge_boot_pages list.
---
arch/powerpc/mm/hugetlbpage.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
arch/powerpc/mm/hugetlbpage.c +22 -0
@@ -29,6 +29,12 @@#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT) +#define MAX_NUMBER_GPAGES 1024 + +/* Tracks the 16G pages after the device tree is scanned and before the +* huge_boot_pages list is ready. */ +static unsigned long gpage_freearray[MAX_NUMBER_GPAGES ]; +static unsigned nr_gpages;unsigned int hugepte_shift;#define PTRS_PER_HUGEPTE (1 << hugepte_shift)
@@ -104,6 +110,22 @@ pmd_t *hpmd_alloc(struct mm_struct *mm, }#endif +/* Moves the gigantic page addresses from the temporary list to the +* huge_boot_pages list. +*/ +int alloc_bootmem_huge_page (struct hstate *h) +{ +struct huge_bootmem_page *m; +if (nr_gpages ==0 ) +return 0 ; + m =phys_to_virt (gpage_freearray[--nr_gpages]); + gpage_freearray[nr_gpages] =0 ; +list_add (&m->list, &huge_boot_pages); + m->hstate = h; +return 1 ; +} + +/* Modelled after find_linux_pte() */ pte_t *huge_pte_offset (struct mm_struct *mm,unsigned long addr) {
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 19/23] powerpc: function to allocate gigantic hugepages
Quoted 8 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (powerpc-function-for-gigantic-hugepage-allocation.patch) The 16G page locations have been saved during early boot in an array. The
alloc_bootmem_huge_page()function adds a page from here to thehuge_boot_pageslist.Signed-off-by Jon Tollefson <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Quoted 10 lines
---
arch/powerpc/mm/hugetlbpage.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)Index:
linux-2.6/arch/powerpc/mm/hugetlbpage.c
===================================================================
arch/powerpc/mm/hugetlbpage.c line 35
Quoted 7 lines
arch/powerpc/mm/hugetlbpage.c +4
-0@@ -29,6 +29,12 @@#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT) +#define MAX_NUMBER_GPAGES 1024 + +/* Tracks the 16G pages after the device tree is scanned and before the +* huge_boot_pages list is ready. */
Minor nit: This comment format looks a bit wacky.
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 20/23 powerpc: scan device tree for gigantic pages
In reply to [email protected]The 16G huge pages have to be reserved in the HMC prior to boot. The
location of the pages are placed in the device tree. This patch adds
code to scan the device tree during very early boot and save these page locations until hugetlbfs is ready for them.
---
arch/powerpc/mm/hash_utils_64.c | 44 ++++++++++++++++++++++++++++++++++++++- arch/powerpc/mm/hugetlbpage.c | 16 ++++++++++++++ include/asm-powerpc/mmu-hash64.h | 2 + 3 files changed, 61 insertions(+), 1 deletion(-)
arch/powerpc/mm/hash_utils_64.c +43 -1
@@ -68,6 +68,7 @@#define KB (1024)#define MB (1024*KB) +#define GB (1024L*MB)/* * Note: pte --> Linux PTE
@@ -329,6 +330,44 @@ static int __init htab_dt_scan_page_sizereturn 0 ; } +/* Scan for 16G memory blocks that have been set aside for huge pages +* and reserve those blocks for 16G huge pages. +*/ +static int __init htab_dt_scan_hugepage_blocks (unsigned long node, +const char *uname,int depth, +void *data) { +char *type =of_get_flat_dt_prop (node,"device_type" ,NULL ); +unsigned long *addr_prop; +u32 *page_count_prop; +unsigned int expected_pages; +long unsigned int phys_addr; +long unsigned int block_size; + +/* We are scanning "memory" nodes only */ +if (type ==NULL ||strcmp (type,"memory" ) !=0 ) +return 0 ; + +/* This property is the log base 2 of the number of virtual pages that +* will represent this memory block. */ + page_count_prop =of_get_flat_dt_prop (node,"ibm,expected#pages" ,NULL ); +if (page_count_prop ==NULL ) +return 0 ; + expected_pages = (1 << page_count_prop[0 ]); + addr_prop =of_get_flat_dt_prop (node,"reg" ,NULL ); +if (addr_prop ==NULL ) +return 0 ; + phys_addr = addr_prop[0 ]; + block_size = addr_prop[1 ]; +if (block_size != (16 *GB )) +return 0 ; +printk (KERN_INFO "Huge page(16GB) memory: " +"addr = 0x%lX size = 0x%lX pages = %d\n" , + phys_addr, block_size, expected_pages); +lmb_reserve (phys_addr, block_size * expected_pages); +add_gpage (phys_addr, block_size, expected_pages); +return 0 ; +} +static void __init htab_init_page_sizes (void ) {int rc;
@@ -418,7 +457,10 @@ static void __init htab_init_page_sizes( );#ifdef CONFIG_HUGETLB_PAGE -/* Init large page size. Currently, we pick 16M or 1M depending +/* Reserve 16G huge page memory sections for huge pages */ +of_scan_flat_dt (htab_dt_scan_hugepage_blocks,NULL ); + +/* Init large page size. Currently, we pick 16M or 1M depending * on what is available */ if (mmu_psize_defs[MMU_PAGE_16M ].shift)
arch/powerpc/mm/hugetlbpage.c +16 -0
@@ -110,6 +110,22 @@ pmd_t *hpmd_alloc(struct mm_struct *mm, }#endif +/* Build list of addresses of gigantic pages. This function is used in early +* boot before the buddy or bootmem allocator is setup. +*/ +void add_gpage (unsigned long addr,unsigned long page_size, +unsigned long number_of_pages) +{ +if (!addr) +return ; +while (number_of_pages >0 ) { + gpage_freearray[nr_gpages] = addr; + nr_gpages++; + number_of_pages--; + addr += page_size; + } +} +/* Moves the gigantic page addresses from the temporary list to the * huge_boot_pages list. */
include/asm-powerpc/mmu-hash64.h +2 -0
@@ -280,6 +280,8 @@ extern int htab_bolt_mapping(unsigned lo unsigned long pstart, unsigned long mode, int psize, int ssize);extern void set_huge_psize (int psize); +extern void add_gpage (unsigned long addr,unsigned long page_size, +unsigned long number_of_pages);extern void demote_segment_4k (struct mm_struct *mm,unsigned long addr);extern void htab_initialize (void );
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 20/23] powerpc: scan device tree for gigantic pages
Quoted 9 lines · On Mon, 2008-05-26 at 00:23 +1000, [email protected] wrote:
plain text document attachment (powerpc-scan-device-tree-and-save-gigantic-page-locations.patch) The 16G huge pages have to be reserved in the HMC prior to boot. The
location of the pages are placed in the device tree. This patch adds
code to scan the device tree during very early boot and save these page locations until hugetlbfs is ready for them.Signed-off-by Jon Tollefson <[email protected]>Signed-off-by Nick Piggin <[email protected]>
I am not really qualified to pass judgment on the device tree-specific parts of this patch, but as for the rest:
Signature · 8 lines
Adam Litke - (agl at us.ibm.com) IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 21/23 powerpc: define support for 16G hugepages
In reply to [email protected]The huge page size is defined for 16G pages. If a hugepagesz of 16G is specified at boot-time then it becomes the huge page size instead of the default 16M.
The change in pgtable-64K.h is to the macro pte_iterate_hashed_subpages to make the increment to va (the 1 being shifted) be a long so that it is not shifted to 0. Otherwise it would create an infinite loop when the shift value is for a 16G page (when base page size is 64K).
---
arch/powerpc/mm/hugetlbpage.c | 62 ++++++++++++++++++++++++++------------ include/asm-powerpc/pgtable-64k.h | 2 - 2 files changed, 45 insertions(+), 19 deletions(-)
arch/powerpc/mm/hugetlbpage.c +44 -18
@@ -24,8 +24,9 @@#include <asm/cputable.h> #include <asm/spu.h> -#define HPAGE_SHIFT_64K 16 -#define HPAGE_SHIFT_16M 24 +#define PAGE_SHIFT_64K 16 +#define PAGE_SHIFT_16M 24 +#define PAGE_SHIFT_16G 34#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
@@ -95,7 +96,7 @@ static int __hugepte_alloc(struct mm_strstatic inline pmd_t *hpmd_offset (pud_t *pud,unsigned long addr) { -if (HPAGE_SHIFT ==HPAGE_SHIFT_64K ) +if (HPAGE_SHIFT ==PAGE_SHIFT_64K )return pmd_offset (pud, addr);else return (pmd_t *) pud;
@@ -103,7 +104,7 @@ pmd_t *hpmd_offset(pud_t *pud, unsignedstatic inline pmd_t *hpmd_alloc (struct mm_struct *mm,pud_t *pud,unsigned long addr) { -if (HPAGE_SHIFT ==HPAGE_SHIFT_64K ) +if (HPAGE_SHIFT ==PAGE_SHIFT_64K )return pmd_alloc (mm, pud, addr);else return (pmd_t *) pud;
@@ -260,7 +261,7 @@ static void hugetlb_free_pud_range(struccontinue ;hugetlb_free_pmd_range (tlb, pud, addr, next, floor, ceiling);#else -if (HPAGE_SHIFT ==HPAGE_SHIFT_64K ) { +if (HPAGE_SHIFT ==PAGE_SHIFT_64K ) {if (pud_none_or_clear_bad (pud))continue ;hugetlb_free_pmd_range (tlb, pud, addr, next, floor, ceiling);
@@ -591,20 +592,40 @@ void set_huge_psize(int psize) {/* Check that it is a page size supported by the hardware and * that it fits within pagetable limits. */ -if (mmu_psize_defs[psize].shift && mmu_psize_defs[psize].shift <SID_SHIFT && +if (mmu_psize_defs[psize].shift && + mmu_psize_defs[psize].shift <SID_SHIFT_1T && (mmu_psize_defs[psize].shift >MIN_HUGEPTE_SHIFT || - mmu_psize_defs[psize].shift ==HPAGE_SHIFT_64K )) { + mmu_psize_defs[psize].shift ==PAGE_SHIFT_64K || + mmu_psize_defs[psize].shift ==PAGE_SHIFT_16G )) { +/* Return if huge page size is the same as the +* base page size. */ +if (mmu_psize_defs[psize].shift ==PAGE_SHIFT ) +return ; +HPAGE_SHIFT = mmu_psize_defs[psize].shift; mmu_huge_psize = psize; -#ifdef CONFIG_PPC_64K_PAGES - hugepte_shift = (PMD_SHIFT -HPAGE_SHIFT ); -#else -if (HPAGE_SHIFT ==HPAGE_SHIFT_64K ) - hugepte_shift = (PMD_SHIFT -HPAGE_SHIFT ); -else - hugepte_shift = (PUD_SHIFT -HPAGE_SHIFT ); -#endif +switch (HPAGE_SHIFT ) { +case PAGE_SHIFT_64K : +/* We only allow 64k hpages with 4k base page, +* which was checked above, and always put them +* at the PMD */ + hugepte_shift =PMD_SHIFT ; +break ; +case PAGE_SHIFT_16M : +/* 16M pages can be at two different levels +* of pagestables based on base page size */ +if (PAGE_SHIFT ==PAGE_SHIFT_64K ) + hugepte_shift =PMD_SHIFT ; +else /* 4k base page */ + hugepte_shift =PUD_SHIFT ; +break ; +case PAGE_SHIFT_16G : +/* 16G pages are always at PGD level */ + hugepte_shift =PGDIR_SHIFT ; +break ; + } + hugepte_shift -=HPAGE_SHIFT ; }else HPAGE_SHIFT =0 ; }
@@ -620,17 +641,22 @@ static int __init hugepage_setup_sz(char shift =__ffs (size);switch (shift) {#ifndef CONFIG_PPC_64K_PAGES -case HPAGE_SHIFT_64K : +case PAGE_SHIFT_64K : mmu_psize =MMU_PAGE_64K ;break ;#endif -case HPAGE_SHIFT_16M : +case PAGE_SHIFT_16M : mmu_psize =MMU_PAGE_16M ;break ; +case PAGE_SHIFT_16G : + mmu_psize =MMU_PAGE_16G ; +break ; } -if (mmu_psize >=0 && mmu_psize_defs[mmu_psize].shift) +if (mmu_psize >=0 && mmu_psize_defs[mmu_psize].shift) {set_huge_psize (mmu_psize); +hugetlb_add_hstate (shift -PAGE_SHIFT ); + }else printk (KERN_WARNING "Invalid huge page size specified(%llu)\n" , size);
include/asm-powerpc/pgtable-64k.h +1 -1
@@ -125,7 +125,7 @@ static inline struct subpage_prot_tableunsigned __split = (psize ==MMU_PAGE_4K || \ psize ==MMU_PAGE_64K_AP ); \ shift = mmu_psize_defs[psize].shift; \ - for (index = 0; va < __end; index++, va += (1 << shift)) { \ + for (index = 0; va < __end; index++, va += (1L << shift)) { \ if (!__split || __rpte_sub_valid(rpte, index)) do { \ #define pte_iterate_hashed_end() } while(0); } } while(0)
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 22/23 fs: check for statfs overflow
In reply to [email protected]Adds a check for an overflow in the filesystem size so if someone is checking with statfs() on a 16G hugetlbfs in a 32bit binary that it will report back EOVERFLOW instead of a size of 0.
Are other places that need a similar check? I had tried a similar check in put_compat_statfs64 too but it didn't seem to generate an EOVERFLOW in my test case.
---
fs/compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/compat.c +2 -2
@@ -197,8 +197,8 @@ static int put_compat_statfs(struct comp {if (sizeof ubuf->f_blocks ==4 ) { -if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) & -0xffffffff00000000ULL ) +if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | + kbuf->f_bsize | kbuf->f_frsize) &0xffffffff00000000ULL )return -EOVERFLOW ;/* f_files and f_ffree may be -1; it's okay * to stuff that into 32 bits */
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 22/23] fs: check for statfs overflow
Quoted 7 lines · On 26.05.2008 [00:23:39 +1000], [email protected] wrote:
Adds a check for an overflow in the filesystem size so if someone is checking with
statfs()on a 16G hugetlbfs in a 32bit binary that it will report back EOVERFLOW instead of a size of 0.Are other places that need a similar check? I had tried a similar check in
put_compat_statfs64too but it didn't seem to generate an EOVERFLOW in my test case.
I think this part of the changelog was meant to be a post-"---" question, which I don't have an answer for, but probably shouldn't go in the final changelog?
Quoted 2 lines
Signed-off-by Jon Tollefson <[email protected]>Signed-off-by Nick Piggin <[email protected]>
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 22/23] fs: check for statfs overflow
Quoted 6 lines · Nishanth Aravamudan
Quoted 4 lines · On 26.05.2008 [00:23:39 +1000], [email protected] wrote:
Adds a check for an overflow in the filesystem size so if someone is checking with
statfs()on a 16G hugetlbfs in a 32bit binary that it will report back EOVERFLOW instead of a size of 0.
Quoted 9 lines
Quoted 4 lines
Are other places that need a similar check? I had tried a similar check in
put_compat_statfs64too but it didn't seem to generate an EOVERFLOW in my test case.I think this part of the changelog was meant to be a post-"---" question, which I don't have an answer for, but probably shouldn't go in the final changelog?
You are correct.
Quoted 11 lines
Quoted 4 lines
Signed-off-by Jon Tollefson <[email protected]>Signed-off-by Nick Piggin <[email protected]>Thanks,
Nish
Jon
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 22/23] fs: check for statfs overflow
Quoted 12 lines · Jon Tollefson
Quoted 11 lines · Nishanth Aravamudan
Quoted 8 lines · On 26.05.2008 [00:23:39 +1000], [email protected] wrote:
Adds a check for an overflow in the filesystem size so if someone is checking with
statfs()on a 16G hugetlbfs in a 32bit binary that it will report back EOVERFLOW instead of a size of 0.Are other places that need a similar check? I had tried a similar check in
put_compat_statfs64too but it didn't seem to generate an EOVERFLOW in my test case.
Quoted 5 lines
Quoted 4 lines
I think this part of the changelog was meant to be a post-"---" question, which I don't have an answer for, but probably shouldn't go in the final changelog?
You are correct.
I think the question is OK for the changelog. Unless we can get somebody answering it yes or no, I'll leave it (but I'd rather get an answer first).
I'm pretty unfamiliar with how the APIs work, but I'd think statfs64 is less likely to overflow because f_blocks is likely to be 8 bytes. But I still think the check might be good to have.
The non-compat stat() (and stat64 even) might also need the eoverflow check. cc'ing fsdevel with the patch attached again.
---
fs: check for statfs overflow
Adds a check for an overflow in the filesystem size so if someone is checking with statfs() on a 16G hugetlbfs in a 32bit binary that it will report back EOVERFLOW instead of a size of 0.
Are other places that need a similar check? I had tried a similar check in put_compat_statfs64 too but it didn't seem to generate an EOVERFLOW in my test case.
---
fs/compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/compat.c +2 -2
@@ -197,8 +197,8 @@ static int put_compat_statfs(struct comp {if (sizeof ubuf->f_blocks ==4 ) { -if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) & -0xffffffff00000000ULL ) +if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | + kbuf->f_bsize | kbuf->f_frsize) &0xffffffff00000000ULL )return -EOVERFLOW ;/* f_files and f_ffree may be -1; it's okay * to stuff that into 32 bits */
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 22/23] fs: check for statfs overflow
Quoted 23 lines · Nick Piggin
fs: check for statfs overflow
Adds a check for an overflow in the filesystem size so if someone is checking with
statfs()on a 16G hugetlbfs in a 32bit binary that it will report back EOVERFLOW instead of a size of 0.Are other places that need a similar check? I had tried a similar check in
put_compat_statfs64too but it didn't seem to generate an EOVERFLOW in my test case.Signed-off-by Jon Tollefson <[email protected]>Signed-off-by Nick Piggin <[email protected]>---
fs/compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)Index:
linux-2.6/fs/compat.c
===================================================================
fs/compat.c static int put_compat_statfs(struct comp · line 202
Quoted 8 lines
fs/compat.c +2
-2@@ -197,8 +197,8 @@ static int put_compat_statfs(struct comp {if (sizeof ubuf->f_blocks ==4 ) { -if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) & -0xffffffff00000000ULL ) +if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | + kbuf->f_bsize | kbuf->f_frsize) &0xffffffff00000000ULL )return -EOVERFLOW ;
Hmm, doesn't this check break every filesystem > 16TB on 4kB PAGE_SIZE nodes? It would be better, IMHO, to scale down f_blocks, f_bfree, and f_bavail and correspondingly scale up f_bsize to fit into the 32-bit statfs structure.
We did this for several years with Lustre, as the first installation was already larger than 16TB on 32-bit clients at the time. There was never a problem with statfs returning a larger f_bsize, since applications generally use the fstat() st_blocksize to determine IO size and not the statfs() data.
Returning statfs data accurate to within a few kB is better than failing the request outright, IMHO.
Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 22/23] fs: check for statfs overflow
Quoted 26 lines · Andreas Dilger
Quoted 25 lines · Nick Piggin
fs: check for statfs overflow
Adds a check for an overflow in the filesystem size so if someone is checking with
statfs()on a 16G hugetlbfs in a 32bit binary that it will report back EOVERFLOW instead of a size of 0.Are other places that need a similar check? I had tried a similar check in
put_compat_statfs64too but it didn't seem to generate an EOVERFLOW in my test case.Signed-off-by Jon Tollefson <[email protected]>Signed-off-by Nick Piggin <[email protected]>---
fs/compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)Index:
linux-2.6/fs/compat.c
===================================================================fs/compat.c +0
-0@@ -197,8 +197,8 @@ static int put_compat_statfs(struct comp {
Quoted 11 lines
fs/compat.c static int put_compat_statfs(struct comp · line 202
Quoted 6 lines
fs/compat.c +2
-2if (sizeof ubuf->f_blocks ==4 ) { -if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) & -0xffffffff00000000ULL ) +if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | + kbuf->f_bsize | kbuf->f_frsize) &0xffffffff00000000ULL )return -EOVERFLOW ;Hmm, doesn't this check break every filesystem > 16TB on 4kB
PAGE_SIZEnodes? It would be better, IMHO, to scale downf_blocks,f_bfree, andf_bavailand correspondingly scale upf_bsizeto fit into the 32-bit statfs structure.
Being a FS newbie, I'm not entirely sure I follow, could you say that again in patch-form? :) Seriously, it might make it clear to me.
Quoted 5 lines
We did this for several years with Lustre, as the first installation was already larger than 16TB on 32-bit clients at the time. There was never a problem with statfs returning a larger
f_bsize, since applications generally use thefstat()st_blocksizeto determine IO size and not thestatfs()data.
I'm not sure that's a good reason to give bad data back to userspace... We have both interfaces and both should work?
Quoted 2 lines
Returning statfs data accurate to within a few kB is better than failing the request outright, IMHO.
Well, currently (iirc), we see statfs() give bad values for 16gb hugetlbfs mountpoints. That's not good, and is inconsistent with the other hugetlbfs mountpoints. We actually do want to indicate EOVERFLOW there, as the 32-bit binary, or some kind of error, although the binary will notice it can't use the pages from that mountpoint when mmap() fails :)
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 22/23] fs: check for statfs overflow
In reply to Andreas DilgerQuoted 26 lines · Andreas Dilger
Quoted 25 lines · Nick Piggin
fs: check for statfs overflow
Adds a check for an overflow in the filesystem size so if someone is checking with
statfs()on a 16G hugetlbfs in a 32bit binary that it will report back EOVERFLOW instead of a size of 0.Are other places that need a similar check? I had tried a similar check in
put_compat_statfs64too but it didn't seem to generate an EOVERFLOW in my test case.Signed-off-by Jon Tollefson <[email protected]>Signed-off-by Nick Piggin <[email protected]>---
fs/compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)Index:
linux-2.6/fs/compat.c
===================================================================fs/compat.c +0
-0@@ -197,8 +197,8 @@ static int put_compat_statfs(struct comp {
Quoted 11 lines
fs/compat.c static int put_compat_statfs(struct comp · line 202
Quoted 6 lines
fs/compat.c +2
-2if (sizeof ubuf->f_blocks ==4 ) { -if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) & -0xffffffff00000000ULL ) +if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | + kbuf->f_bsize | kbuf->f_frsize) &0xffffffff00000000ULL )return -EOVERFLOW ;Hmm, doesn't this check break every filesystem > 16TB on 4kB
PAGE_SIZEnodes? It would be better, IMHO, to scale downf_blocks,f_bfree, andf_bavailand correspondingly scale upf_bsizeto fit into the 32-bit statfs structure.
Oh? Hmm, from my reading, such filesystems will already overflow f_blocks check which is already there. Jon's patch only adds checks for f_bsize and f_frsize.
One thing I'm a little worried about is the _exact_ semantics required of the syscall wrt overflow, and type sizes. In the man page here for example, ubuf->f_blocks is a differnt type to f_bsize and f_frsize...
Thanks,
Nick
Quoted 10 lines
We did this for several years with Lustre, as the first installation was already larger than 16TB on 32-bit clients at the time. There was never a problem with statfs returning a larger
f_bsize, since applications generally use thefstat()st_blocksizeto determine IO size and not thestatfs()data.Returning statfs data accurate to within a few kB is better than failing the request outright, IMHO.
Cheers, Andreas
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 22/23] fs: check for statfs overflow
Quoted 13 lines · Nick Piggin
Quoted 11 lines · Andreas Dilger
fs/compat.c static int put_compat_statfs(struct comp · line 200
Quoted 5 lines · Nick Piggin
fs/compat.c +2
-0@@ -197,8 +197,8 @@ static int put_compat_statfs(struct compif (sizeof ubuf->f_blocks ==4 ) { +if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | + kbuf->f_bsize | kbuf->f_frsize) &0xffffffff00000000ULL )return -EOVERFLOW ;Hmm, doesn't this check break every filesystem > 16TB on 4kB
PAGE_SIZEnodes? It would be better, IMHO, to scale downf_blocks,f_bfree, andf_bavailand correspondingly scale upf_bsizeto fit into the 32-bit statfs structure.
Quoted 3 lines
Oh? Hmm, from my reading, such filesystems will already overflow
f_blockscheck which is already there. Jon's patch only adds checks forf_bsizeandf_frsize.
Sorry, you are right - I meant that the whole f_blocks check is broken for filesystems > 16TB. Scaling f_bsize is easy, and prevents gratuitous breakage of old applications for a few kB of accuracy.
Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 22/23] fs: check for statfs overflow
Quoted 14 lines · Andreas Dilger
Quoted 13 lines · Nick Piggin
Quoted 11 lines · Andreas Dilger
fs/compat.c static int put_compat_statfs(struct comp · line 200
Quoted 5 lines · Nick Piggin
fs/compat.c +2
-0@@ -197,8 +197,8 @@ static int put_compat_statfs(struct compif (sizeof ubuf->f_blocks ==4 ) { +if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | + kbuf->f_bsize | kbuf->f_frsize) &0xffffffff00000000ULL )return -EOVERFLOW ;Hmm, doesn't this check break every filesystem > 16TB on 4kB
PAGE_SIZEnodes? It would be better, IMHO, to scale downf_blocks,f_bfree, andf_bavailand correspondingly scale upf_bsizeto fit into the 32-bit statfs structure.
Quoted 7 lines
Quoted 3 lines
Oh? Hmm, from my reading, such filesystems will already overflow
f_blockscheck which is already there. Jon's patch only adds checks forf_bsizeandf_frsize.Sorry, you are right - I meant that the whole
f_blockscheck is broken for filesystems > 16TB. Scalingf_bsizeis easy, and prevents gratuitous breakage of old applications for a few kB of accuracy.
Oh... hmm OK but they do have stat64 I guess, although maybe they aren't coded for it.
Anyway, point is noted, but I'm not the person (nor is this the patchset) to make such changes.
Do you agree that if we have these checks in coimpat_statfs, then we should put the same ones in the non-compat as well as the 64 bit versions?
Thanks,
Nick
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 22/23] fs: check for statfs overflow
Quoted 6 lines · Nick Piggin
Quoted 5 lines · Andreas Dilger
Quoted 3 lines · Nick Piggin
Oh? Hmm, from my reading, such filesystems will already overflow
f_blockscheck which is already there. Jon's patch only adds checks forf_bsizeandf_frsize.
Quoted 6 lines
Quoted 3 lines
Sorry, you are right - I meant that the whole
f_blockscheck is broken for filesystems > 16TB. Scalingf_bsizeis easy, and prevents gratuitous breakage of old applications for a few kB of accuracy.Oh... hmm OK but they do have stat64 I guess, although maybe they aren't coded for it.
Right - we had this problem with all of the tools with some older distros being compiled against the old statfs syscall and we had to put the statfs scaling inside Lustre to avoid the 16TB overflow.
The problem with the current kernel VFS interface is that the filesystem doesn't know whether the 32-bit or 64-bit statfs interface is being called, and rather than returning an error to an application we'd prefer to return scaled statfs results (with some small amount of rounding error). Even for 20PB filesystems (the largest planned for this year) the free/used/avail space would only be rounded to 4MB sizes, which isn't so bad.
Quoted 2 lines
Anyway, point is noted, but I'm not the person (nor is this the patchset) to make such changes.
Right...
Quoted 3 lines
Do you agree that if we have these checks in
coimpat_statfs, then we should put the same ones in the non-compat as well as the 64 bit versions?
If it only affects hugetlbfs then I'm not too concerned.
Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 23/23 powerpc: support multiple hugepage sizes
In reply to [email protected]Instead of using the variable mmu_huge_psize to keep track of the huge page size we use an array of MMU_PAGE_* values. For each supported huge page size we need to know the hugepte_shift value and have a pgtable_cache. The hstate or an mmu_huge_psizes index is passed to functions so that they know which huge page size they should use.
The hugepage sizes 16M and 64K are setup(if available on the hardware) so that they don't have to be set on the boot cmd line in order to use them. The number of 16G pages have to be specified at boot-time though (e.g. hugepagesz=16G hugepages=5).
---
arch/powerpc/mm/hash_utils_64.c | 9 - arch/powerpc/mm/hugetlbpage.c | 272 +++++++++++++++++++++++++-------------- arch/powerpc/mm/init_64.c | 8 - arch/powerpc/mm/tlb_64.c | 2 include/asm-powerpc/hugetlb.h | 5 include/asm-powerpc/mmu-hash64.h | 4 include/asm-powerpc/page_64.h | 1 include/asm-powerpc/pgalloc-64.h | 4 8 files changed, 192 insertions(+), 113 deletions(-)
arch/powerpc/mm/hash_utils_64.c +4 -5
@@ -103,7 +103,6 @@ int mmu_kernel_ssize = MMU_SEGSIZE_256M;int mmu_highuser_ssize =MMU_SEGSIZE_256M ;u16 mmu_slb_size =64 ;#ifdef CONFIG_HUGETLB_PAGE -int mmu_huge_psize =MMU_PAGE_16M ;unsigned int HPAGE_SHIFT ;#endif #ifdef CONFIG_PPC_64K_PAGES
@@ -460,15 +459,15 @@ static void __init htab_init_page_sizes(/* Reserve 16G huge page memory sections for huge pages */ of_scan_flat_dt (htab_dt_scan_hugepage_blocks,NULL ); -/* Init large page size. Currently, we pick 16M or 1M depending +/* Set default large page size. Currently, we pick 16M or 1M depending * on what is available */ if (mmu_psize_defs[MMU_PAGE_16M ].shift) -set_huge_psize (MMU_PAGE_16M ); +HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_16M ].shift;/* With 4k/4level pagetables, we can't (for now) cope with a * huge page size < PMD_SIZE */ else if (mmu_psize_defs[MMU_PAGE_1M ].shift) -set_huge_psize (MMU_PAGE_1M ); +HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_1M ].shift;#endif /* CONFIG_HUGETLB_PAGE */ }
@@ -873,7 +872,7 @@ int hash_page(unsigned long ea, unsigned#ifdef CONFIG_HUGETLB_PAGE /* Handle hugepage regions */ -if (HPAGE_SHIFT && psize == mmu_huge_psize) { +if (HPAGE_SHIFT && mmu_huge_psizes[psize]) {DBG_LOW (" -> huge page !\n" );return hash_huge_page (mm, access, ea, vsid, local, trap); }
arch/powerpc/mm/hugetlbpage.c +175 -97
554 lines not on this page · raw message
arch/powerpc/mm/init_64.c +4 -4
@@ -153,10 +153,10 @@ static const char *pgtable_cache_name[AR };#ifdef CONFIG_HUGETLB_PAGE -/* Hugepages need one extra cache, initialized in hugetlbpage.c. We -* can't put into the tables above, because HPAGE_SHIFT is not compile -* time constant. */ -struct kmem_cache *pgtable_cache[ARRAY_SIZE (pgtable_cache_size)+1 ]; +/* Hugepages need an extra cache per hugepagesize, initialized in +* hugetlbpage.c. We can't put into the tables above, because HPAGE_SHIFT +* is not compile time constant. */ +struct kmem_cache *pgtable_cache[ARRAY_SIZE (pgtable_cache_size)+MMU_PAGE_COUNT ];#else struct kmem_cache *pgtable_cache[ARRAY_SIZE (pgtable_cache_size)];#endif
arch/powerpc/mm/tlb_64.c +1 -1
@@ -150,7 +150,7 @@ void hpte_need_flush(struct mm_struct *m*/ if (huge) {#ifdef CONFIG_HUGETLB_PAGE - psize = mmu_huge_psize; + psize =get_slice_psize (mm, addr);;#else BUG (); psize =pte_pagesize_index (mm, addr, pte);/* shutup gcc */
include/asm-powerpc/mmu-hash64.h +2 -2
@@ -193,9 +193,9 @@ extern int mmu_ci_restrictions;#ifdef CONFIG_HUGETLB_PAGE /* -* The page size index of the huge pages for use by hugetlbfs +* The page size indexes of the huge pages for use by hugetlbfs */ -extern int mmu_huge_psize; +extern unsigned int mmu_huge_psizes[MMU_PAGE_COUNT ];#endif /* CONFIG_HUGETLB_PAGE */
include/asm-powerpc/page_64.h +1 -0
@@ -90,6 +90,7 @@ extern unsigned int HPAGE_SHIFT;#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)#define HPAGE_MASK (~(HPAGE_SIZE - 1))#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) +#define HUGE_MAX_HSTATE 3#endif /* __ASSEMBLY__ */
include/asm-powerpc/pgalloc-64.h +2 -2
@@ -22,7 +22,7 @@ extern struct kmem_cache *pgtable_cache[#define PUD_CACHE_NUM 1#define PMD_CACHE_NUM 1#define HUGEPTE_CACHE_NUM 2 -#define PTE_NONCACHE_NUM 3/* from GFP rather than kmem_cache */ +#define PTE_NONCACHE_NUM 7/* from GFP rather than kmem_cache */ static inline pgd_t *pgd_alloc (struct mm_struct *mm) {
@@ -119,7 +119,7 @@ static inline void pte_free(struct mm_st__free_page (ptepage); } -#define PGF_CACHENUM_MASK 0x3 +#define PGF_CACHENUM_MASK 0x7 typedef struct pgtable_free { unsigned long val;
include/asm-powerpc/hugetlb.h +3 -2
@@ -23,9 +23,10 @@ pte_t huge_ptep_get_and_clear(struct mm_*/ static inline int prepare_hugepage_range (struct file *file,unsigned long addr,unsigned long len) { -if (len & ~HPAGE_MASK ) +struct hstate *h =hstate_file (file); +if (len & ~huge_page_mask (h))return -EINVAL ; -if (addr & ~HPAGE_MASK ) +if (addr & ~huge_page_mask (h))return -EINVAL ;return 0 ; }
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 23/23] powerpc: support multiple hugepage sizes
Quoted 10 lines · On 26.05.2008 [00:23:40 +1000], [email protected] wrote:
Instead of using the variable
mmu_huge_psizeto keep track of the huge page size we use an array of MMU_PAGE_* values. For each supported huge page size we need to know thehugepte_shiftvalue and have apgtable_cache. The hstate or anmmu_huge_psizesindex is passed to functions so that they know which huge page size they should use.The hugepage sizes 16M and 64K are setup(if available on the hardware) so that they don't have to be set on the boot cmd line in order to use them. The number of 16G pages have to be specified at boot-time though (e.g. hugepagesz=16G hugepages=5).
This patch probably should updated Documentation as well, to indicate power can also specify hugepagesz multiple times?
Thanks,
Nish
Signature · 8 lines
Nishanth Aravamudan <[email protected]> IBM Linux Technology Center -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 23/23] powerpc: support multiple hugepage sizes
Quoted 7 lines · Nishanth Aravamudan
Quoted 6 lines · On 26.05.2008 [00:23:40 +1000], [email protected] wrote:
Instead of using the variable
mmu_huge_psizeto keep track of the huge page size we use an array of MMU_PAGE_* values. For each supported huge page size we need to know thehugepte_shiftvalue and have apgtable_cache. The hstate or anmmu_huge_psizesindex is passed to functions so that they know which huge page size they should use.
Quoted 7 lines
Quoted 4 lines
The hugepage sizes 16M and 64K are setup(if available on the hardware) so that they don't have to be set on the boot cmd line in order to use them. The number of 16G pages have to be specified at boot-time though (e.g. hugepagesz=16G hugepages=5).
This patch probably should updated Documentation as well, to indicate power can also specify hugepagesz multiple times?
OK, added a small bit to it.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 9 lines · On Mon, May 26, 2008 at 12:23:17AM +1000, [email protected] wrote:
Hi all,
Given the amount of feedback this has had, and the powerpc patches from Jon, I'll send out one more request for review and testing before asking Andrew to merge in -mm.
Patches are against Linus's current git (
eb90d81d). I will have to rebase to -mm next.
Quoted 8 lines
The patches pass the libhugetlbfs regression test suite here on x86 and powerpc (although my G5 can only run 16MB hugepages, so it is less interesting...).
So, review and testing welcome.
Thanks!
Nick
Arg, sorry I've got Andi's old suse address on some of these:
quilt mail extracts SOBs and adds them to the cc list which always gets me :(
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>