Merge tag 'v3.10.106' into update
This is the 3.10.106 stable release
This commit is contained in:
+16
-3
@@ -1235,6 +1235,18 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* foll_force can write to even unwritable pmd's, but only
|
||||
* after we've gone through a cow cycle and they are dirty.
|
||||
*/
|
||||
static inline bool can_follow_write_pmd(pmd_t pmd, struct page *page,
|
||||
unsigned int flags)
|
||||
{
|
||||
return pmd_write(pmd) ||
|
||||
((flags & FOLL_FORCE) && (flags & FOLL_COW) &&
|
||||
page && PageAnon(page));
|
||||
}
|
||||
|
||||
struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
|
||||
unsigned long addr,
|
||||
pmd_t *pmd,
|
||||
@@ -1245,15 +1257,16 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
|
||||
|
||||
assert_spin_locked(&mm->page_table_lock);
|
||||
|
||||
if (flags & FOLL_WRITE && !pmd_write(*pmd))
|
||||
goto out;
|
||||
|
||||
/* Avoid dumping huge zero page */
|
||||
if ((flags & FOLL_DUMP) && is_huge_zero_pmd(*pmd))
|
||||
return ERR_PTR(-EFAULT);
|
||||
|
||||
page = pmd_page(*pmd);
|
||||
VM_BUG_ON(!PageHead(page));
|
||||
|
||||
if (flags & FOLL_WRITE && !can_follow_write_pmd(*pmd, page, flags))
|
||||
return NULL;
|
||||
|
||||
if (flags & FOLL_TOUCH) {
|
||||
pmd_t _pmd;
|
||||
/*
|
||||
|
||||
+28
-9
@@ -1070,23 +1070,32 @@ free:
|
||||
}
|
||||
|
||||
/*
|
||||
* When releasing a hugetlb pool reservation, any surplus pages that were
|
||||
* allocated to satisfy the reservation must be explicitly freed if they were
|
||||
* never used.
|
||||
* Called with hugetlb_lock held.
|
||||
* This routine has two main purposes:
|
||||
* 1) Decrement the reservation count (resv_huge_pages) by the value passed
|
||||
* in unused_resv_pages. This corresponds to the prior adjustments made
|
||||
* to the associated reservation map.
|
||||
* 2) Free any unused surplus pages that may have been allocated to satisfy
|
||||
* the reservation. As many as unused_resv_pages may be freed.
|
||||
*
|
||||
* Called with hugetlb_lock held. However, the lock could be dropped (and
|
||||
* reacquired) during calls to cond_resched_lock. Whenever dropping the lock,
|
||||
* we must make sure nobody else can claim pages we are in the process of
|
||||
* freeing. Do this by ensuring resv_huge_page always is greater than the
|
||||
* number of huge pages we plan to free when dropping the lock.
|
||||
*/
|
||||
static void return_unused_surplus_pages(struct hstate *h,
|
||||
unsigned long unused_resv_pages)
|
||||
{
|
||||
unsigned long nr_pages;
|
||||
|
||||
/* Uncommit the reservation */
|
||||
h->resv_huge_pages -= unused_resv_pages;
|
||||
|
||||
/* Cannot return gigantic pages currently */
|
||||
if (h->order >= MAX_ORDER)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Part (or even all) of the reservation could have been backed
|
||||
* by pre-allocated pages. Only free surplus pages.
|
||||
*/
|
||||
nr_pages = min(unused_resv_pages, h->surplus_huge_pages);
|
||||
|
||||
/*
|
||||
@@ -1096,12 +1105,22 @@ static void return_unused_surplus_pages(struct hstate *h,
|
||||
* when the nodes with surplus pages have no free pages.
|
||||
* free_pool_huge_page() will balance the the freed pages across the
|
||||
* on-line nodes with memory and will handle the hstate accounting.
|
||||
*
|
||||
* Note that we decrement resv_huge_pages as we free the pages. If
|
||||
* we drop the lock, resv_huge_pages will still be sufficiently large
|
||||
* to cover subsequent pages we may free.
|
||||
*/
|
||||
while (nr_pages--) {
|
||||
h->resv_huge_pages--;
|
||||
unused_resv_pages--;
|
||||
if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1))
|
||||
break;
|
||||
goto out;
|
||||
cond_resched_lock(&hugetlb_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
/* Fully uncommit the reservation */
|
||||
h->resv_huge_pages -= unused_resv_pages;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+10
-7
@@ -5452,15 +5452,18 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
|
||||
sizeof(arch_zone_lowest_possible_pfn));
|
||||
memset(arch_zone_highest_possible_pfn, 0,
|
||||
sizeof(arch_zone_highest_possible_pfn));
|
||||
arch_zone_lowest_possible_pfn[0] = find_min_pfn_with_active_regions();
|
||||
arch_zone_highest_possible_pfn[0] = max_zone_pfn[0];
|
||||
for (i = 1; i < MAX_NR_ZONES; i++) {
|
||||
|
||||
start_pfn = find_min_pfn_with_active_regions();
|
||||
|
||||
for (i = 0; i < MAX_NR_ZONES; i++) {
|
||||
if (i == ZONE_MOVABLE)
|
||||
continue;
|
||||
arch_zone_lowest_possible_pfn[i] =
|
||||
arch_zone_highest_possible_pfn[i-1];
|
||||
arch_zone_highest_possible_pfn[i] =
|
||||
max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]);
|
||||
|
||||
end_pfn = max(max_zone_pfn[i], start_pfn);
|
||||
arch_zone_lowest_possible_pfn[i] = start_pfn;
|
||||
arch_zone_highest_possible_pfn[i] = end_pfn;
|
||||
|
||||
start_pfn = end_pfn;
|
||||
}
|
||||
arch_zone_lowest_possible_pfn[ZONE_MOVABLE] = 0;
|
||||
arch_zone_highest_possible_pfn[ZONE_MOVABLE] = 0;
|
||||
|
||||
Reference in New Issue
Block a user