免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2035 | 回复: 0
打印 上一主题 下一主题

[内存管理] page_count(page) != page_mapcount(page) + 2 的解释 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-01-25 08:19 |只看该作者 |倒序浏览
static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
{
    struct mm_struct *mm = vma->vm_mm;
    unsigned long address;
    pgd_t *pgd;
    pud_t *pud;
    pmd_t *pmd;
    pte_t *pte;
    pte_t pteval;
    int ret = SWAP_AGAIN;

    if (!mm->rss)
        goto out;
    address = vma_address(page, vma);
    if (address == -EFAULT)
        goto out;

    /*
     * We need the page_table_lock to protect us from page faults,
     * munmap, fork, etc...
     */
    spin_lock(&mm->page_table_lock);

    pgd = pgd_offset(mm, address);
    if (!pgd_present(*pgd))
        goto out_unlock;

    pud = pud_offset(pgd, address);
    if (!pud_present(*pud))
        goto out_unlock;

    pmd = pmd_offset(pud, address);
    if (!pmd_present(*pmd))
        goto out_unlock;

    pte = pte_offset_map(pmd, address);
    if (!pte_present(*pte))
        goto out_unmap;

    if (page_to_pfn(page) != pte_pfn(*pte))
        goto out_unmap;

    /*
     * If the page is mlock()d, we cannot swap it out.
     * If it's recently referenced (perhaps page_referenced
     * skipped over this mm) then we should reactivate it.
     */
    if ((vma->vm_flags & (VM_LOCKED|VM_RESERVED)) ||
            ptep_clear_flush_young(vma, address, pte)) {
        ret = SWAP_FAIL;
        goto out_unmap;
    }

    /*
     * Don't pull an anonymous page out from under get_user_pages.
     * GUP carefully breaks COW and raises page count (while holding
     * page_table_lock, as we have here) to make sure that the page
     * cannot be freed.  If we unmap that page here, a user write
     * access to the virtual address will bring back the page, but
     * its raised count will (ironically) be taken to mean it's not
     * an exclusive swap page, do_wp_page will replace it by a copy
     * page, and the user never get to see the data GUP was holding
     * the original page for.
     *
     * This test is also useful for when swapoff (unuse_process) has
     * to drop page lock: its reference to the page stops existing
     * ptes from being unmapped, so swapoff can make progress.
     *
     * 我不理解
     */
    if (PageSwapCache(page) &&
            page_count(page) != page_mapcount(page) + 2) {
        ret = SWAP_FAIL;
        goto out_unmap;
    }


    /* Nuke the page table entry. */
    flush_cache_page(vma, address);
    pteval = ptep_clear_flush(vma, address, pte);

    /* Move the dirty bit to the physical page now the pte is gone. */
    if (pte_dirty(pteval))
        set_page_dirty(page);

    if (PageAnon(page)) {
        swp_entry_t entry = { .val = page->private };
        /*
         * Store the swap location in the pte.
         * See handle_pte_fault() ...
         */
        BUG_ON(!PageSwapCache(page));
        swap_duplicate(entry);
        if (list_empty(&mm->mmlist)) {
            spin_lock(&mmlist_lock);
            list_add(&mm->mmlist, &init_mm.mmlist);
            spin_unlock(&mmlist_lock);
        }
        set_pte(pte, swp_entry_to_pte(entry));
        BUG_ON(pte_file(*pte));
        mm->anon_rss--;
    }

    mm->rss--;
    acct_update_integrals();
    page_remove_rmap(page);
    page_cache_release(page);

out_unmap:
    pte_unmap(pte);
out_unlock:
    spin_unlock(&mm->page_table_lock);
out:
    return ret;
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP