首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

缺页异常详解(9)

缺页异常详解(9)

     page_cache_get(old_page);                            pte_unmap_unlock(page_table, ptl);
                            tmp = vma->vm_ops->page_mkwrite(vma, &vmf);
                            if (unlikely(tmp &
                                               (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) {
                                     ret = tmp;
                                     goto unwritable_page;
                            }
                            if (unlikely(!(tmp & VM_FAULT_LOCKED))) {
                                     lock_page(old_page);
                                     if (!old_page->mapping) {
                                               ret = 0; /* retry the fault */
                                               unlock_page(old_page);
                                               goto unwritable_page;
                                     }
                            } else
                                     VM_BUG_ON(!PageLocked(old_page));
                            /*
                             * Since we dropped the lock we need to revalidate
                             * the PTE as someone else may have changed it.  If
                             * they did, we just return, as we can count on the
                             * MMU to tell us if they didn't also make it writable.
                             */
                            page_table = pte_offset_map_lock(mm, pmd, address,
                                                                  &ptl);
                            if (!pte_same(*page_table, orig_pte)) {
                                     unlock_page(old_page);
                                     page_cache_release(old_page);
                                     goto unlock;
                            }
                            page_mkwrite = 1;
                   }
                   dirty_page = old_page;
                   get_page(dirty_page);
                   reuse = 1;
         }
    /*reuse: 不进行COW,直接操作该页old_page*/
         if (reuse) {
reuse:
                   flush_cache_page(vma, address, pte_pfn(orig_pte));
                   entry = pte_mkyoung(orig_pte);
        /*写该页的二级页表属性,加入可写且脏*/
                   entry = maybe_mkwrite(pte_mkdirty(entry), vma);
                   if (ptep_set_access_flags(vma, address, page_table, entry,1))
                            update_mmu_cache(vma, address, entry);
                   ret |= VM_FAULT_WRITE;
                   goto unlock;
         }
         /*
          * Ok, we need to copy. Oh, well..
          */
/*真正的COW即将开始*/
    /*首先增加之前的页的被映射次数(get_page(), page->_count)*/
         page_cache_get(old_page);
gotten:
         pte_unmap_unlock(page_table, ptl);
         if (unlikely(anon_vma_prepare(vma)))
                   goto oom;
    /*COW的第一种情况(zero_pfn),将分配新页并清零该页*/
         if (is_zero_pfn(pte_pfn(orig_pte))) {
                   new_page = alloc_zeroed_user_highpage_movable(vma, address);
                   if (!new_page)
                            goto oom;
         }
    /*COW的第二种情况(fork),申请一个页,并把old_page页的内容拷贝到新页new_page(4K字节的内容)*/
    else {
                   new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
                   if (!new_page)
                            goto oom;
                   cow_user_page(new_page, old_page, address, vma);
         }
         __SetPageUptodate(new_page);
         /*
          * Don't let another task, with possibly unlocked vma,
          * keep the mlocked page.
          */
         /*COW第二种情况下,如果vma还是锁定的,那还需要解锁*/
         if ((vma->vm_flags & VM_LOCKED) && old_page) {
                   lock_page(old_page);      /* for LRU manipulation */
                   clear_page_mlock(old_page);
                   unlock_page(old_page);
         }
    /*空函数*/
         if (mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))
                   goto oom_free_new;
         /*
          * Re-check the pte - we dropped the lock
          */
继承事业,薪火相传
返回列表