summaryrefslogtreecommitdiffstats
path: root/mm/gup.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/gup.c')
-rw-r--r--mm/gup.c48
1 files changed, 36 insertions, 12 deletions
diff --git a/mm/gup.c b/mm/gup.c
index f84e22685aaa..91819b8ad9cc 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -160,8 +160,12 @@ retry:
160 goto retry; 160 goto retry;
161 } 161 }
162 162
163 if (flags & FOLL_GET) 163 if (flags & FOLL_GET) {
164 get_page(page); 164 if (unlikely(!try_get_page(page))) {
165 page = ERR_PTR(-ENOMEM);
166 goto out;
167 }
168 }
165 if (flags & FOLL_TOUCH) { 169 if (flags & FOLL_TOUCH) {
166 if ((flags & FOLL_WRITE) && 170 if ((flags & FOLL_WRITE) &&
167 !pte_dirty(pte) && !PageDirty(page)) 171 !pte_dirty(pte) && !PageDirty(page))
@@ -298,7 +302,10 @@ retry_locked:
298 if (pmd_trans_unstable(pmd)) 302 if (pmd_trans_unstable(pmd))
299 ret = -EBUSY; 303 ret = -EBUSY;
300 } else { 304 } else {
301 get_page(page); 305 if (unlikely(!try_get_page(page))) {
306 spin_unlock(ptl);
307 return ERR_PTR(-ENOMEM);
308 }
302 spin_unlock(ptl); 309 spin_unlock(ptl);
303 lock_page(page); 310 lock_page(page);
304 ret = split_huge_page(page); 311 ret = split_huge_page(page);
@@ -500,7 +507,10 @@ static int get_gate_page(struct mm_struct *mm, unsigned long address,
500 if (is_device_public_page(*page)) 507 if (is_device_public_page(*page))
501 goto unmap; 508 goto unmap;
502 } 509 }
503 get_page(*page); 510 if (unlikely(!try_get_page(*page))) {
511 ret = -ENOMEM;
512 goto unmap;
513 }
504out: 514out:
505 ret = 0; 515 ret = 0;
506unmap: 516unmap:
@@ -1545,6 +1555,20 @@ static void undo_dev_pagemap(int *nr, int nr_start, struct page **pages)
1545 } 1555 }
1546} 1556}
1547 1557
1558/*
1559 * Return the compund head page with ref appropriately incremented,
1560 * or NULL if that failed.
1561 */
1562static inline struct page *try_get_compound_head(struct page *page, int refs)
1563{
1564 struct page *head = compound_head(page);
1565 if (WARN_ON_ONCE(page_ref_count(head) < 0))
1566 return NULL;
1567 if (unlikely(!page_cache_add_speculative(head, refs)))
1568 return NULL;
1569 return head;
1570}
1571
1548#ifdef CONFIG_ARCH_HAS_PTE_SPECIAL 1572#ifdef CONFIG_ARCH_HAS_PTE_SPECIAL
1549static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, 1573static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
1550 int write, struct page **pages, int *nr) 1574 int write, struct page **pages, int *nr)
@@ -1579,9 +1603,9 @@ static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
1579 1603
1580 VM_BUG_ON(!pfn_valid(pte_pfn(pte))); 1604 VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
1581 page = pte_page(pte); 1605 page = pte_page(pte);
1582 head = compound_head(page);
1583 1606
1584 if (!page_cache_get_speculative(head)) 1607 head = try_get_compound_head(page, 1);
1608 if (!head)
1585 goto pte_unmap; 1609 goto pte_unmap;
1586 1610
1587 if (unlikely(pte_val(pte) != pte_val(*ptep))) { 1611 if (unlikely(pte_val(pte) != pte_val(*ptep))) {
@@ -1720,8 +1744,8 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr,
1720 refs++; 1744 refs++;
1721 } while (addr += PAGE_SIZE, addr != end); 1745 } while (addr += PAGE_SIZE, addr != end);
1722 1746
1723 head = compound_head(pmd_page(orig)); 1747 head = try_get_compound_head(pmd_page(orig), refs);
1724 if (!page_cache_add_speculative(head, refs)) { 1748 if (!head) {
1725 *nr -= refs; 1749 *nr -= refs;
1726 return 0; 1750 return 0;
1727 } 1751 }
@@ -1758,8 +1782,8 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr,
1758 refs++; 1782 refs++;
1759 } while (addr += PAGE_SIZE, addr != end); 1783 } while (addr += PAGE_SIZE, addr != end);
1760 1784
1761 head = compound_head(pud_page(orig)); 1785 head = try_get_compound_head(pud_page(orig), refs);
1762 if (!page_cache_add_speculative(head, refs)) { 1786 if (!head) {
1763 *nr -= refs; 1787 *nr -= refs;
1764 return 0; 1788 return 0;
1765 } 1789 }
@@ -1795,8 +1819,8 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr,
1795 refs++; 1819 refs++;
1796 } while (addr += PAGE_SIZE, addr != end); 1820 } while (addr += PAGE_SIZE, addr != end);
1797 1821
1798 head = compound_head(pgd_page(orig)); 1822 head = try_get_compound_head(pgd_page(orig), refs);
1799 if (!page_cache_add_speculative(head, refs)) { 1823 if (!head) {
1800 *nr -= refs; 1824 *nr -= refs;
1801 return 0; 1825 return 0;
1802 } 1826 }