diff options
Diffstat (limited to 'mm/ksm.c')
-rw-r--r-- | mm/ksm.c | 65 |
1 files changed, 65 insertions, 0 deletions
@@ -1656,6 +1656,71 @@ out: | |||
1656 | return ret; | 1656 | return ret; |
1657 | } | 1657 | } |
1658 | 1658 | ||
1659 | #ifdef CONFIG_MIGRATION | ||
1660 | int rmap_walk_ksm(struct page *page, int (*rmap_one)(struct page *, | ||
1661 | struct vm_area_struct *, unsigned long, void *), void *arg) | ||
1662 | { | ||
1663 | struct stable_node *stable_node; | ||
1664 | struct hlist_node *hlist; | ||
1665 | struct rmap_item *rmap_item; | ||
1666 | int ret = SWAP_AGAIN; | ||
1667 | int search_new_forks = 0; | ||
1668 | |||
1669 | VM_BUG_ON(!PageKsm(page)); | ||
1670 | VM_BUG_ON(!PageLocked(page)); | ||
1671 | |||
1672 | stable_node = page_stable_node(page); | ||
1673 | if (!stable_node) | ||
1674 | return ret; | ||
1675 | again: | ||
1676 | hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) { | ||
1677 | struct anon_vma *anon_vma = rmap_item->anon_vma; | ||
1678 | struct vm_area_struct *vma; | ||
1679 | |||
1680 | spin_lock(&anon_vma->lock); | ||
1681 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { | ||
1682 | if (rmap_item->address < vma->vm_start || | ||
1683 | rmap_item->address >= vma->vm_end) | ||
1684 | continue; | ||
1685 | /* | ||
1686 | * Initially we examine only the vma which covers this | ||
1687 | * rmap_item; but later, if there is still work to do, | ||
1688 | * we examine covering vmas in other mms: in case they | ||
1689 | * were forked from the original since ksmd passed. | ||
1690 | */ | ||
1691 | if ((rmap_item->mm == vma->vm_mm) == search_new_forks) | ||
1692 | continue; | ||
1693 | |||
1694 | ret = rmap_one(page, vma, rmap_item->address, arg); | ||
1695 | if (ret != SWAP_AGAIN) { | ||
1696 | spin_unlock(&anon_vma->lock); | ||
1697 | goto out; | ||
1698 | } | ||
1699 | } | ||
1700 | spin_unlock(&anon_vma->lock); | ||
1701 | } | ||
1702 | if (!search_new_forks++) | ||
1703 | goto again; | ||
1704 | out: | ||
1705 | return ret; | ||
1706 | } | ||
1707 | |||
1708 | void ksm_migrate_page(struct page *newpage, struct page *oldpage) | ||
1709 | { | ||
1710 | struct stable_node *stable_node; | ||
1711 | |||
1712 | VM_BUG_ON(!PageLocked(oldpage)); | ||
1713 | VM_BUG_ON(!PageLocked(newpage)); | ||
1714 | VM_BUG_ON(newpage->mapping != oldpage->mapping); | ||
1715 | |||
1716 | stable_node = page_stable_node(newpage); | ||
1717 | if (stable_node) { | ||
1718 | VM_BUG_ON(stable_node->page != oldpage); | ||
1719 | stable_node->page = newpage; | ||
1720 | } | ||
1721 | } | ||
1722 | #endif /* CONFIG_MIGRATION */ | ||
1723 | |||
1659 | #ifdef CONFIG_SYSFS | 1724 | #ifdef CONFIG_SYSFS |
1660 | /* | 1725 | /* |
1661 | * This all compiles without CONFIG_SYSFS, but is a waste of space. | 1726 | * This all compiles without CONFIG_SYSFS, but is a waste of space. |