diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-11 10:28:19 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-11 10:28:19 -0500 |
commit | 734d1ece37fbf3d2ddfc71bc6c69e0fe35f02542 (patch) | |
tree | c4805dd7e746b1feb9e09e9849f3245d0b2c0c6b /mm/hugetlb.c | |
parent | 216c82c6aba63eeb49d7654b448e0d47bea255bb (diff) | |
parent | 9931faca02c604c22335f5a935a501bb2ace6e20 (diff) |
Merge tag 'v3.8-rc3' into v4l_for_linus
Linux 3.8-rc3
* tag 'v3.8-rc3': (11110 commits)
Linux 3.8-rc3
mm: reinstante dropped pmd_trans_splitting() check
cred: Remove tgcred pointer from struct cred
drm/ttm: fix fence locking in ttm_buffer_object_transfer
ARM: clps711x: Fix bad merge of clockevents setup
ARM: highbank: save and restore L2 cache and GIC on suspend
ARM: highbank: add a power request clear
ARM: highbank: fix secondary boot and hotplug
ARM: highbank: fix typos with hignbank in power request functions
ARM: dts: fix highbank cpu mpidr values
ARM: dts: add device_type prop to cpu nodes on Calxeda platforms
drm/prime: drop reference on imported dma-buf come from gem
xen/netfront: improve truesize tracking
ARM: mx5: Fix MX53 flexcan2 clock
ARM: OMAP2+: am33xx-hwmod: Fix wrongly terminated am33xx_usbss_mpu_irqs array
sctp: fix Kconfig bug in default cookie hmac selection
EDAC: Cleanup device deregistering path
EDAC: Fix EDAC Kconfig menu
EDAC: Fix kernel panic on module unloading
ALSA: hda - add mute LED for HP Pavilion 17 (Realtek codec)
...
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r-- | mm/hugetlb.c | 63 |
1 files changed, 34 insertions, 29 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 59a0059b39e2..4f3ea0b1e57c 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Generic hugetlb support. | 2 | * Generic hugetlb support. |
3 | * (C) William Irwin, April 2004 | 3 | * (C) Nadia Yvette Chambers, April 2004 |
4 | */ | 4 | */ |
5 | #include <linux/list.h> | 5 | #include <linux/list.h> |
6 | #include <linux/init.h> | 6 | #include <linux/init.h> |
@@ -1057,7 +1057,7 @@ static void return_unused_surplus_pages(struct hstate *h, | |||
1057 | * on-line nodes with memory and will handle the hstate accounting. | 1057 | * on-line nodes with memory and will handle the hstate accounting. |
1058 | */ | 1058 | */ |
1059 | while (nr_pages--) { | 1059 | while (nr_pages--) { |
1060 | if (!free_pool_huge_page(h, &node_states[N_HIGH_MEMORY], 1)) | 1060 | if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1)) |
1061 | break; | 1061 | break; |
1062 | } | 1062 | } |
1063 | } | 1063 | } |
@@ -1180,14 +1180,14 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, | |||
1180 | int __weak alloc_bootmem_huge_page(struct hstate *h) | 1180 | int __weak alloc_bootmem_huge_page(struct hstate *h) |
1181 | { | 1181 | { |
1182 | struct huge_bootmem_page *m; | 1182 | struct huge_bootmem_page *m; |
1183 | int nr_nodes = nodes_weight(node_states[N_HIGH_MEMORY]); | 1183 | int nr_nodes = nodes_weight(node_states[N_MEMORY]); |
1184 | 1184 | ||
1185 | while (nr_nodes) { | 1185 | while (nr_nodes) { |
1186 | void *addr; | 1186 | void *addr; |
1187 | 1187 | ||
1188 | addr = __alloc_bootmem_node_nopanic( | 1188 | addr = __alloc_bootmem_node_nopanic( |
1189 | NODE_DATA(hstate_next_node_to_alloc(h, | 1189 | NODE_DATA(hstate_next_node_to_alloc(h, |
1190 | &node_states[N_HIGH_MEMORY])), | 1190 | &node_states[N_MEMORY])), |
1191 | huge_page_size(h), huge_page_size(h), 0); | 1191 | huge_page_size(h), huge_page_size(h), 0); |
1192 | 1192 | ||
1193 | if (addr) { | 1193 | if (addr) { |
@@ -1259,7 +1259,7 @@ static void __init hugetlb_hstate_alloc_pages(struct hstate *h) | |||
1259 | if (!alloc_bootmem_huge_page(h)) | 1259 | if (!alloc_bootmem_huge_page(h)) |
1260 | break; | 1260 | break; |
1261 | } else if (!alloc_fresh_huge_page(h, | 1261 | } else if (!alloc_fresh_huge_page(h, |
1262 | &node_states[N_HIGH_MEMORY])) | 1262 | &node_states[N_MEMORY])) |
1263 | break; | 1263 | break; |
1264 | } | 1264 | } |
1265 | h->max_huge_pages = i; | 1265 | h->max_huge_pages = i; |
@@ -1527,7 +1527,7 @@ static ssize_t nr_hugepages_store_common(bool obey_mempolicy, | |||
1527 | if (!(obey_mempolicy && | 1527 | if (!(obey_mempolicy && |
1528 | init_nodemask_of_mempolicy(nodes_allowed))) { | 1528 | init_nodemask_of_mempolicy(nodes_allowed))) { |
1529 | NODEMASK_FREE(nodes_allowed); | 1529 | NODEMASK_FREE(nodes_allowed); |
1530 | nodes_allowed = &node_states[N_HIGH_MEMORY]; | 1530 | nodes_allowed = &node_states[N_MEMORY]; |
1531 | } | 1531 | } |
1532 | } else if (nodes_allowed) { | 1532 | } else if (nodes_allowed) { |
1533 | /* | 1533 | /* |
@@ -1537,11 +1537,11 @@ static ssize_t nr_hugepages_store_common(bool obey_mempolicy, | |||
1537 | count += h->nr_huge_pages - h->nr_huge_pages_node[nid]; | 1537 | count += h->nr_huge_pages - h->nr_huge_pages_node[nid]; |
1538 | init_nodemask_of_node(nodes_allowed, nid); | 1538 | init_nodemask_of_node(nodes_allowed, nid); |
1539 | } else | 1539 | } else |
1540 | nodes_allowed = &node_states[N_HIGH_MEMORY]; | 1540 | nodes_allowed = &node_states[N_MEMORY]; |
1541 | 1541 | ||
1542 | h->max_huge_pages = set_max_huge_pages(h, count, nodes_allowed); | 1542 | h->max_huge_pages = set_max_huge_pages(h, count, nodes_allowed); |
1543 | 1543 | ||
1544 | if (nodes_allowed != &node_states[N_HIGH_MEMORY]) | 1544 | if (nodes_allowed != &node_states[N_MEMORY]) |
1545 | NODEMASK_FREE(nodes_allowed); | 1545 | NODEMASK_FREE(nodes_allowed); |
1546 | 1546 | ||
1547 | return len; | 1547 | return len; |
@@ -1800,7 +1800,7 @@ static void hugetlb_unregister_all_nodes(void) | |||
1800 | * remove hstate attributes from any nodes that have them. | 1800 | * remove hstate attributes from any nodes that have them. |
1801 | */ | 1801 | */ |
1802 | for (nid = 0; nid < nr_node_ids; nid++) | 1802 | for (nid = 0; nid < nr_node_ids; nid++) |
1803 | hugetlb_unregister_node(&node_devices[nid]); | 1803 | hugetlb_unregister_node(node_devices[nid]); |
1804 | } | 1804 | } |
1805 | 1805 | ||
1806 | /* | 1806 | /* |
@@ -1844,8 +1844,8 @@ static void hugetlb_register_all_nodes(void) | |||
1844 | { | 1844 | { |
1845 | int nid; | 1845 | int nid; |
1846 | 1846 | ||
1847 | for_each_node_state(nid, N_HIGH_MEMORY) { | 1847 | for_each_node_state(nid, N_MEMORY) { |
1848 | struct node *node = &node_devices[nid]; | 1848 | struct node *node = node_devices[nid]; |
1849 | if (node->dev.id == nid) | 1849 | if (node->dev.id == nid) |
1850 | hugetlb_register_node(node); | 1850 | hugetlb_register_node(node); |
1851 | } | 1851 | } |
@@ -1906,14 +1906,12 @@ static int __init hugetlb_init(void) | |||
1906 | default_hstate.max_huge_pages = default_hstate_max_huge_pages; | 1906 | default_hstate.max_huge_pages = default_hstate_max_huge_pages; |
1907 | 1907 | ||
1908 | hugetlb_init_hstates(); | 1908 | hugetlb_init_hstates(); |
1909 | |||
1910 | gather_bootmem_prealloc(); | 1909 | gather_bootmem_prealloc(); |
1911 | |||
1912 | report_hugepages(); | 1910 | report_hugepages(); |
1913 | 1911 | ||
1914 | hugetlb_sysfs_init(); | 1912 | hugetlb_sysfs_init(); |
1915 | |||
1916 | hugetlb_register_all_nodes(); | 1913 | hugetlb_register_all_nodes(); |
1914 | hugetlb_cgroup_file_init(); | ||
1917 | 1915 | ||
1918 | return 0; | 1916 | return 0; |
1919 | } | 1917 | } |
@@ -1939,17 +1937,10 @@ void __init hugetlb_add_hstate(unsigned order) | |||
1939 | for (i = 0; i < MAX_NUMNODES; ++i) | 1937 | for (i = 0; i < MAX_NUMNODES; ++i) |
1940 | INIT_LIST_HEAD(&h->hugepage_freelists[i]); | 1938 | INIT_LIST_HEAD(&h->hugepage_freelists[i]); |
1941 | INIT_LIST_HEAD(&h->hugepage_activelist); | 1939 | INIT_LIST_HEAD(&h->hugepage_activelist); |
1942 | h->next_nid_to_alloc = first_node(node_states[N_HIGH_MEMORY]); | 1940 | h->next_nid_to_alloc = first_node(node_states[N_MEMORY]); |
1943 | h->next_nid_to_free = first_node(node_states[N_HIGH_MEMORY]); | 1941 | h->next_nid_to_free = first_node(node_states[N_MEMORY]); |
1944 | snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB", | 1942 | snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB", |
1945 | huge_page_size(h)/1024); | 1943 | huge_page_size(h)/1024); |
1946 | /* | ||
1947 | * Add cgroup control files only if the huge page consists | ||
1948 | * of more than two normal pages. This is because we use | ||
1949 | * page[2].lru.next for storing cgoup details. | ||
1950 | */ | ||
1951 | if (order >= HUGETLB_CGROUP_MIN_ORDER) | ||
1952 | hugetlb_cgroup_file_init(hugetlb_max_hstate - 1); | ||
1953 | 1944 | ||
1954 | parsed_hstate = h; | 1945 | parsed_hstate = h; |
1955 | } | 1946 | } |
@@ -2035,11 +2026,11 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy, | |||
2035 | if (!(obey_mempolicy && | 2026 | if (!(obey_mempolicy && |
2036 | init_nodemask_of_mempolicy(nodes_allowed))) { | 2027 | init_nodemask_of_mempolicy(nodes_allowed))) { |
2037 | NODEMASK_FREE(nodes_allowed); | 2028 | NODEMASK_FREE(nodes_allowed); |
2038 | nodes_allowed = &node_states[N_HIGH_MEMORY]; | 2029 | nodes_allowed = &node_states[N_MEMORY]; |
2039 | } | 2030 | } |
2040 | h->max_huge_pages = set_max_huge_pages(h, tmp, nodes_allowed); | 2031 | h->max_huge_pages = set_max_huge_pages(h, tmp, nodes_allowed); |
2041 | 2032 | ||
2042 | if (nodes_allowed != &node_states[N_HIGH_MEMORY]) | 2033 | if (nodes_allowed != &node_states[N_MEMORY]) |
2043 | NODEMASK_FREE(nodes_allowed); | 2034 | NODEMASK_FREE(nodes_allowed); |
2044 | } | 2035 | } |
2045 | out: | 2036 | out: |
@@ -2386,8 +2377,10 @@ again: | |||
2386 | /* | 2377 | /* |
2387 | * HWPoisoned hugepage is already unmapped and dropped reference | 2378 | * HWPoisoned hugepage is already unmapped and dropped reference |
2388 | */ | 2379 | */ |
2389 | if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) | 2380 | if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) { |
2381 | pte_clear(mm, address, ptep); | ||
2390 | continue; | 2382 | continue; |
2383 | } | ||
2391 | 2384 | ||
2392 | page = pte_page(pte); | 2385 | page = pte_page(pte); |
2393 | /* | 2386 | /* |
@@ -3014,7 +3007,7 @@ same_page: | |||
3014 | return i ? i : -EFAULT; | 3007 | return i ? i : -EFAULT; |
3015 | } | 3008 | } |
3016 | 3009 | ||
3017 | void hugetlb_change_protection(struct vm_area_struct *vma, | 3010 | unsigned long hugetlb_change_protection(struct vm_area_struct *vma, |
3018 | unsigned long address, unsigned long end, pgprot_t newprot) | 3011 | unsigned long address, unsigned long end, pgprot_t newprot) |
3019 | { | 3012 | { |
3020 | struct mm_struct *mm = vma->vm_mm; | 3013 | struct mm_struct *mm = vma->vm_mm; |
@@ -3022,6 +3015,7 @@ void hugetlb_change_protection(struct vm_area_struct *vma, | |||
3022 | pte_t *ptep; | 3015 | pte_t *ptep; |
3023 | pte_t pte; | 3016 | pte_t pte; |
3024 | struct hstate *h = hstate_vma(vma); | 3017 | struct hstate *h = hstate_vma(vma); |
3018 | unsigned long pages = 0; | ||
3025 | 3019 | ||
3026 | BUG_ON(address >= end); | 3020 | BUG_ON(address >= end); |
3027 | flush_cache_range(vma, address, end); | 3021 | flush_cache_range(vma, address, end); |
@@ -3032,12 +3026,15 @@ void hugetlb_change_protection(struct vm_area_struct *vma, | |||
3032 | ptep = huge_pte_offset(mm, address); | 3026 | ptep = huge_pte_offset(mm, address); |
3033 | if (!ptep) | 3027 | if (!ptep) |
3034 | continue; | 3028 | continue; |
3035 | if (huge_pmd_unshare(mm, &address, ptep)) | 3029 | if (huge_pmd_unshare(mm, &address, ptep)) { |
3030 | pages++; | ||
3036 | continue; | 3031 | continue; |
3032 | } | ||
3037 | if (!huge_pte_none(huge_ptep_get(ptep))) { | 3033 | if (!huge_pte_none(huge_ptep_get(ptep))) { |
3038 | pte = huge_ptep_get_and_clear(mm, address, ptep); | 3034 | pte = huge_ptep_get_and_clear(mm, address, ptep); |
3039 | pte = pte_mkhuge(pte_modify(pte, newprot)); | 3035 | pte = pte_mkhuge(pte_modify(pte, newprot)); |
3040 | set_huge_pte_at(mm, address, ptep, pte); | 3036 | set_huge_pte_at(mm, address, ptep, pte); |
3037 | pages++; | ||
3041 | } | 3038 | } |
3042 | } | 3039 | } |
3043 | spin_unlock(&mm->page_table_lock); | 3040 | spin_unlock(&mm->page_table_lock); |
@@ -3049,6 +3046,8 @@ void hugetlb_change_protection(struct vm_area_struct *vma, | |||
3049 | */ | 3046 | */ |
3050 | flush_tlb_range(vma, start, end); | 3047 | flush_tlb_range(vma, start, end); |
3051 | mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); | 3048 | mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); |
3049 | |||
3050 | return pages << h->order; | ||
3052 | } | 3051 | } |
3053 | 3052 | ||
3054 | int hugetlb_reserve_pages(struct inode *inode, | 3053 | int hugetlb_reserve_pages(struct inode *inode, |
@@ -3170,7 +3169,13 @@ int dequeue_hwpoisoned_huge_page(struct page *hpage) | |||
3170 | 3169 | ||
3171 | spin_lock(&hugetlb_lock); | 3170 | spin_lock(&hugetlb_lock); |
3172 | if (is_hugepage_on_freelist(hpage)) { | 3171 | if (is_hugepage_on_freelist(hpage)) { |
3173 | list_del(&hpage->lru); | 3172 | /* |
3173 | * Hwpoisoned hugepage isn't linked to activelist or freelist, | ||
3174 | * but dangling hpage->lru can trigger list-debug warnings | ||
3175 | * (this happens when we call unpoison_memory() on it), | ||
3176 | * so let it point to itself with list_del_init(). | ||
3177 | */ | ||
3178 | list_del_init(&hpage->lru); | ||
3174 | set_page_refcounted(hpage); | 3179 | set_page_refcounted(hpage); |
3175 | h->free_huge_pages--; | 3180 | h->free_huge_pages--; |
3176 | h->free_huge_pages_node[nid]--; | 3181 | h->free_huge_pages_node[nid]--; |