diff options
-rw-r--r-- | include/linux/ksm.h | 6 | ||||
-rw-r--r-- | mm/ksm.c | 50 | ||||
-rw-r--r-- | mm/rmap.c | 154 |
3 files changed, 42 insertions, 168 deletions
diff --git a/include/linux/ksm.h b/include/linux/ksm.h index 0eef8cb0baf7..91b9719722c3 100644 --- a/include/linux/ksm.h +++ b/include/linux/ksm.h | |||
@@ -75,7 +75,6 @@ struct page *ksm_might_need_to_copy(struct page *page, | |||
75 | 75 | ||
76 | int page_referenced_ksm(struct page *page, | 76 | int page_referenced_ksm(struct page *page, |
77 | struct mem_cgroup *memcg, unsigned long *vm_flags); | 77 | struct mem_cgroup *memcg, unsigned long *vm_flags); |
78 | int try_to_unmap_ksm(struct page *page, enum ttu_flags flags); | ||
79 | int rmap_walk_ksm(struct page *page, struct rmap_walk_control *rwc); | 78 | int rmap_walk_ksm(struct page *page, struct rmap_walk_control *rwc); |
80 | void ksm_migrate_page(struct page *newpage, struct page *oldpage); | 79 | void ksm_migrate_page(struct page *newpage, struct page *oldpage); |
81 | 80 | ||
@@ -114,11 +113,6 @@ static inline int page_referenced_ksm(struct page *page, | |||
114 | return 0; | 113 | return 0; |
115 | } | 114 | } |
116 | 115 | ||
117 | static inline int try_to_unmap_ksm(struct page *page, enum ttu_flags flags) | ||
118 | { | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static inline int rmap_walk_ksm(struct page *page, | 116 | static inline int rmap_walk_ksm(struct page *page, |
123 | struct rmap_walk_control *rwc) | 117 | struct rmap_walk_control *rwc) |
124 | { | 118 | { |
@@ -1946,56 +1946,6 @@ out: | |||
1946 | return referenced; | 1946 | return referenced; |
1947 | } | 1947 | } |
1948 | 1948 | ||
1949 | int try_to_unmap_ksm(struct page *page, enum ttu_flags flags) | ||
1950 | { | ||
1951 | struct stable_node *stable_node; | ||
1952 | struct rmap_item *rmap_item; | ||
1953 | int ret = SWAP_AGAIN; | ||
1954 | int search_new_forks = 0; | ||
1955 | |||
1956 | VM_BUG_ON(!PageKsm(page)); | ||
1957 | VM_BUG_ON(!PageLocked(page)); | ||
1958 | |||
1959 | stable_node = page_stable_node(page); | ||
1960 | if (!stable_node) | ||
1961 | return SWAP_FAIL; | ||
1962 | again: | ||
1963 | hlist_for_each_entry(rmap_item, &stable_node->hlist, hlist) { | ||
1964 | struct anon_vma *anon_vma = rmap_item->anon_vma; | ||
1965 | struct anon_vma_chain *vmac; | ||
1966 | struct vm_area_struct *vma; | ||
1967 | |||
1968 | anon_vma_lock_read(anon_vma); | ||
1969 | anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root, | ||
1970 | 0, ULONG_MAX) { | ||
1971 | vma = vmac->vma; | ||
1972 | if (rmap_item->address < vma->vm_start || | ||
1973 | rmap_item->address >= vma->vm_end) | ||
1974 | continue; | ||
1975 | /* | ||
1976 | * Initially we examine only the vma which covers this | ||
1977 | * rmap_item; but later, if there is still work to do, | ||
1978 | * we examine covering vmas in other mms: in case they | ||
1979 | * were forked from the original since ksmd passed. | ||
1980 | */ | ||
1981 | if ((rmap_item->mm == vma->vm_mm) == search_new_forks) | ||
1982 | continue; | ||
1983 | |||
1984 | ret = try_to_unmap_one(page, vma, | ||
1985 | rmap_item->address, (void *)flags); | ||
1986 | if (ret != SWAP_AGAIN || !page_mapped(page)) { | ||
1987 | anon_vma_unlock_read(anon_vma); | ||
1988 | goto out; | ||
1989 | } | ||
1990 | } | ||
1991 | anon_vma_unlock_read(anon_vma); | ||
1992 | } | ||
1993 | if (!search_new_forks++) | ||
1994 | goto again; | ||
1995 | out: | ||
1996 | return ret; | ||
1997 | } | ||
1998 | |||
1999 | int rmap_walk_ksm(struct page *page, struct rmap_walk_control *rwc) | 1949 | int rmap_walk_ksm(struct page *page, struct rmap_walk_control *rwc) |
2000 | { | 1950 | { |
2001 | struct stable_node *stable_node; | 1951 | struct stable_node *stable_node; |
@@ -1177,9 +1177,6 @@ out: | |||
1177 | } | 1177 | } |
1178 | 1178 | ||
1179 | /* | 1179 | /* |
1180 | * Subfunctions of try_to_unmap: try_to_unmap_one called | ||
1181 | * repeatedly from try_to_unmap_ksm, try_to_unmap_anon or try_to_unmap_file. | ||
1182 | * | ||
1183 | * @arg: enum ttu_flags will be passed to this argument | 1180 | * @arg: enum ttu_flags will be passed to this argument |
1184 | */ | 1181 | */ |
1185 | int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | 1182 | int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, |
@@ -1521,107 +1518,6 @@ static bool invalid_migration_vma(struct vm_area_struct *vma, void *arg) | |||
1521 | return is_vma_temporary_stack(vma); | 1518 | return is_vma_temporary_stack(vma); |
1522 | } | 1519 | } |
1523 | 1520 | ||
1524 | /** | ||
1525 | * try_to_unmap_anon - unmap or unlock anonymous page using the object-based | ||
1526 | * rmap method | ||
1527 | * @page: the page to unmap/unlock | ||
1528 | * @flags: action and flags | ||
1529 | * | ||
1530 | * Find all the mappings of a page using the mapping pointer and the vma chains | ||
1531 | * contained in the anon_vma struct it points to. | ||
1532 | * | ||
1533 | * This function is only called from try_to_unmap/try_to_munlock for | ||
1534 | * anonymous pages. | ||
1535 | * When called from try_to_munlock(), the mmap_sem of the mm containing the vma | ||
1536 | * where the page was found will be held for write. So, we won't recheck | ||
1537 | * vm_flags for that VMA. That should be OK, because that vma shouldn't be | ||
1538 | * 'LOCKED. | ||
1539 | */ | ||
1540 | static int try_to_unmap_anon(struct page *page, enum ttu_flags flags) | ||
1541 | { | ||
1542 | struct anon_vma *anon_vma; | ||
1543 | pgoff_t pgoff; | ||
1544 | struct anon_vma_chain *avc; | ||
1545 | int ret = SWAP_AGAIN; | ||
1546 | |||
1547 | anon_vma = page_lock_anon_vma_read(page); | ||
1548 | if (!anon_vma) | ||
1549 | return ret; | ||
1550 | |||
1551 | pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | ||
1552 | anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, pgoff, pgoff) { | ||
1553 | struct vm_area_struct *vma = avc->vma; | ||
1554 | unsigned long address; | ||
1555 | |||
1556 | /* | ||
1557 | * During exec, a temporary VMA is setup and later moved. | ||
1558 | * The VMA is moved under the anon_vma lock but not the | ||
1559 | * page tables leading to a race where migration cannot | ||
1560 | * find the migration ptes. Rather than increasing the | ||
1561 | * locking requirements of exec(), migration skips | ||
1562 | * temporary VMAs until after exec() completes. | ||
1563 | */ | ||
1564 | if (IS_ENABLED(CONFIG_MIGRATION) && (flags & TTU_MIGRATION) && | ||
1565 | is_vma_temporary_stack(vma)) | ||
1566 | continue; | ||
1567 | |||
1568 | address = vma_address(page, vma); | ||
1569 | ret = try_to_unmap_one(page, vma, address, (void *)flags); | ||
1570 | if (ret != SWAP_AGAIN || !page_mapped(page)) | ||
1571 | break; | ||
1572 | } | ||
1573 | |||
1574 | page_unlock_anon_vma_read(anon_vma); | ||
1575 | return ret; | ||
1576 | } | ||
1577 | |||
1578 | /** | ||
1579 | * try_to_unmap_file - unmap/unlock file page using the object-based rmap method | ||
1580 | * @page: the page to unmap/unlock | ||
1581 | * @flags: action and flags | ||
1582 | * | ||
1583 | * Find all the mappings of a page using the mapping pointer and the vma chains | ||
1584 | * contained in the address_space struct it points to. | ||
1585 | * | ||
1586 | * This function is only called from try_to_unmap/try_to_munlock for | ||
1587 | * object-based pages. | ||
1588 | * When called from try_to_munlock(), the mmap_sem of the mm containing the vma | ||
1589 | * where the page was found will be held for write. So, we won't recheck | ||
1590 | * vm_flags for that VMA. That should be OK, because that vma shouldn't be | ||
1591 | * 'LOCKED. | ||
1592 | */ | ||
1593 | static int try_to_unmap_file(struct page *page, enum ttu_flags flags) | ||
1594 | { | ||
1595 | struct address_space *mapping = page->mapping; | ||
1596 | pgoff_t pgoff = page->index << compound_order(page); | ||
1597 | struct vm_area_struct *vma; | ||
1598 | int ret = SWAP_AGAIN; | ||
1599 | |||
1600 | mutex_lock(&mapping->i_mmap_mutex); | ||
1601 | vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) { | ||
1602 | unsigned long address = vma_address(page, vma); | ||
1603 | ret = try_to_unmap_one(page, vma, address, (void *)flags); | ||
1604 | if (ret != SWAP_AGAIN || !page_mapped(page)) | ||
1605 | goto out; | ||
1606 | } | ||
1607 | |||
1608 | if (list_empty(&mapping->i_mmap_nonlinear)) | ||
1609 | goto out; | ||
1610 | |||
1611 | /* | ||
1612 | * We don't bother to try to find the munlocked page in nonlinears. | ||
1613 | * It's costly. Instead, later, page reclaim logic may call | ||
1614 | * try_to_unmap(TTU_MUNLOCK) and recover PG_mlocked lazily. | ||
1615 | */ | ||
1616 | if (TTU_ACTION(flags) == TTU_MUNLOCK) | ||
1617 | goto out; | ||
1618 | |||
1619 | ret = try_to_unmap_nonlinear(page, mapping, vma); | ||
1620 | out: | ||
1621 | mutex_unlock(&mapping->i_mmap_mutex); | ||
1622 | return ret; | ||
1623 | } | ||
1624 | |||
1625 | static int page_not_mapped(struct page *page) | 1521 | static int page_not_mapped(struct page *page) |
1626 | { | 1522 | { |
1627 | return !page_mapped(page); | 1523 | return !page_mapped(page); |
@@ -1689,14 +1585,25 @@ int try_to_unmap(struct page *page, enum ttu_flags flags) | |||
1689 | */ | 1585 | */ |
1690 | int try_to_munlock(struct page *page) | 1586 | int try_to_munlock(struct page *page) |
1691 | { | 1587 | { |
1588 | int ret; | ||
1589 | struct rmap_walk_control rwc = { | ||
1590 | .rmap_one = try_to_unmap_one, | ||
1591 | .arg = (void *)TTU_MUNLOCK, | ||
1592 | .done = page_not_mapped, | ||
1593 | /* | ||
1594 | * We don't bother to try to find the munlocked page in | ||
1595 | * nonlinears. It's costly. Instead, later, page reclaim logic | ||
1596 | * may call try_to_unmap() and recover PG_mlocked lazily. | ||
1597 | */ | ||
1598 | .file_nonlinear = NULL, | ||
1599 | .anon_lock = page_lock_anon_vma_read, | ||
1600 | |||
1601 | }; | ||
1602 | |||
1692 | VM_BUG_ON(!PageLocked(page) || PageLRU(page)); | 1603 | VM_BUG_ON(!PageLocked(page) || PageLRU(page)); |
1693 | 1604 | ||
1694 | if (unlikely(PageKsm(page))) | 1605 | ret = rmap_walk(page, &rwc); |
1695 | return try_to_unmap_ksm(page, TTU_MUNLOCK); | 1606 | return ret; |
1696 | else if (PageAnon(page)) | ||
1697 | return try_to_unmap_anon(page, TTU_MUNLOCK); | ||
1698 | else | ||
1699 | return try_to_unmap_file(page, TTU_MUNLOCK); | ||
1700 | } | 1607 | } |
1701 | 1608 | ||
1702 | void __put_anon_vma(struct anon_vma *anon_vma) | 1609 | void __put_anon_vma(struct anon_vma *anon_vma) |
@@ -1732,8 +1639,18 @@ static struct anon_vma *rmap_walk_anon_lock(struct page *page, | |||
1732 | } | 1639 | } |
1733 | 1640 | ||
1734 | /* | 1641 | /* |
1735 | * rmap_walk() and its helpers rmap_walk_anon() and rmap_walk_file(): | 1642 | * rmap_walk_anon - do something to anonymous page using the object-based |
1736 | * Called by migrate.c to remove migration ptes, but might be used more later. | 1643 | * rmap method |
1644 | * @page: the page to be handled | ||
1645 | * @rwc: control variable according to each walk type | ||
1646 | * | ||
1647 | * Find all the mappings of a page using the mapping pointer and the vma chains | ||
1648 | * contained in the anon_vma struct it points to. | ||
1649 | * | ||
1650 | * When called from try_to_munlock(), the mmap_sem of the mm containing the vma | ||
1651 | * where the page was found will be held for write. So, we won't recheck | ||
1652 | * vm_flags for that VMA. That should be OK, because that vma shouldn't be | ||
1653 | * LOCKED. | ||
1737 | */ | 1654 | */ |
1738 | static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc) | 1655 | static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc) |
1739 | { | 1656 | { |
@@ -1763,6 +1680,19 @@ static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc) | |||
1763 | return ret; | 1680 | return ret; |
1764 | } | 1681 | } |
1765 | 1682 | ||
1683 | /* | ||
1684 | * rmap_walk_file - do something to file page using the object-based rmap method | ||
1685 | * @page: the page to be handled | ||
1686 | * @rwc: control variable according to each walk type | ||
1687 | * | ||
1688 | * Find all the mappings of a page using the mapping pointer and the vma chains | ||
1689 | * contained in the address_space struct it points to. | ||
1690 | * | ||
1691 | * When called from try_to_munlock(), the mmap_sem of the mm containing the vma | ||
1692 | * where the page was found will be held for write. So, we won't recheck | ||
1693 | * vm_flags for that VMA. That should be OK, because that vma shouldn't be | ||
1694 | * LOCKED. | ||
1695 | */ | ||
1766 | static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc) | 1696 | static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc) |
1767 | { | 1697 | { |
1768 | struct address_space *mapping = page->mapping; | 1698 | struct address_space *mapping = page->mapping; |