*参照元 [#lc5dc598]
#backlinks

*説明 [#c41493ca]
-パス: [[linux-2.6.33/mm/memory.c]]

-FIXME: これは何?
--説明


**引数 [#a2276094]
-struct task_struct *tsk
--
--[[linux-2.6.33/task_struct]]
-struct mm_struct *mm
--
--[[linux-2.6.33/mm_struct]]
-unsigned long start
--
-int nr_pages
--
-int write
-unsigned int foll_flags
--
-int force
--
-struct page **pages
--
--[[linux-2.6.33/page]]
-struct vm_area_struct **vmas
-
--[[linux-2.6.33/vm_area_struct]]


**返り値 [#q6541b95]
-int
--


**参考 [#n5408a21]


*実装 [#h309d47e]
 int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 		     unsigned long start, int nr_pages, unsigned int gup_flags,
 		     struct page **pages, struct vm_area_struct **vmas)
 {
 	int i;
 	unsigned long vm_flags;
 
 	if (nr_pages <= 0)
 		return 0;
 
 	VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET));
 
-
--[[linux-2.6.33/VM_BUG_ON()]]
-
--[[linux-2.6.33/FOLL_GET]]

 	/* 
 	 * Require read or write permissions.
 	 * If FOLL_FORCE is set, we only require the "MAY" flags.
 	 */
 	vm_flags  = (gup_flags & FOLL_WRITE) ?
 			(VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
 	vm_flags &= (gup_flags & FOLL_FORCE) ?
 			(VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
 	i = 0;
 
-
--[[linux-2.6.33/FOLL_WRITE]]
-
--[[linux-2.6.33/FOLL_FORCE]]
-
--[[linux-2.6.33/VM_WRITE]]
-
--[[linux-2.6.33/VM_MAYWRITE]]
-
--[[linux-2.6.33/VM_READ]]
-
--[[linux-2.6.33/VM_MAYREAD]]

 	do {
 		struct vm_area_struct *vma;
 
 		vma = find_extend_vma(mm, start);
-
--[[linux-2.6.33/vm_area_struct]]
-
--[[linux-2.6.33/find_extended_vma()]]

 		if (!vma && in_gate_area(tsk, start)) {
 			unsigned long pg = start & PAGE_MASK;
 			struct vm_area_struct *gate_vma = get_gate_vma(tsk);
 			pgd_t *pgd;
 			pud_t *pud;
 			pmd_t *pmd;
 			pte_t *pte;
 
-
--[[linux-2.6.33/in_gate_area()]]
-
--[[linux-2.6.33/PAGE_MASK]]
-
--[[linux-2.6.33/get_gate_vma()]]
-
--[[linux-2.6.33/pgd_t]]
-
--[[linux-2.6.33/pud_t]]
-
--[[linux-2.6.33/pmd_t]]
-
--[[linux-2.6.33/pte_t]]

 			/* user gate pages are read-only */
 			if (gup_flags & FOLL_WRITE)
 				return i ? : -EFAULT;
 			if (pg > TASK_SIZE)
 				pgd = pgd_offset_k(pg);
 			else
 				pgd = pgd_offset_gate(mm, pg);
-
--[[linux-2.6.33/TASK_SIZE]]
-
--[[linux-2.6.33/pgd_offset_k()]]
-
--[[linux-2.6.33/pgd_offset_gate()]]

 			BUG_ON(pgd_none(*pgd));
 			pud = pud_offset(pgd, pg);
 			BUG_ON(pud_none(*pud));
 			pmd = pmd_offset(pud, pg);
 			if (pmd_none(*pmd))
 				return i ? : -EFAULT;
-
--[[linux-2.6.33/BUG_ON()]]
-
--[[linux-2.6.33/pgd_none()]]
-
--[[linux-2.6.33/pud_offset()]]
-
--[[linux-2.6.33/pud_none()]]
-
--[[linux-2.6.33/pmd_offset()]]
-
--[[linux-2.6.33/pmd_none()]]

 			pte = pte_offset_map(pmd, pg);
 			if (pte_none(*pte)) {
 				pte_unmap(pte);
 				return i ? : -EFAULT;
 			}
-
--[[linux-2.6.33/pte_offset_map()]]
-
--[[linux-2.6.33/pte_none()]]
-
--[[linux-2.6.33/pte_unmap()]]

 			if (pages) {
 				struct page *page = vm_normal_page(gate_vma, start, *pte);
 				pages[i] = page;
 				if (page)
 					get_page(page);
 			}
 			pte_unmap(pte);
-
--[[linux-2.6.33/vm_normal_page()]]
-
--[[linux-2.6.33/get_page()]]

 			if (vmas)
 				vmas[i] = gate_vma;
 			i++;
 			start += PAGE_SIZE;
 			nr_pages--;
 			continue;
 		}
 
 		if (!vma ||
 		    (vma->vm_flags & (VM_IO | VM_PFNMAP)) ||
 		    !(vm_flags & vma->vm_flags))
 			return i ? : -EFAULT;
 
-
--[[linux-2.6.33/VM_IO]]
-
--[[linux-2.6.33/VM_PFNMAP]]

 		if (is_vm_hugetlb_page(vma)) {
 			i = follow_hugetlb_page(mm, vma, pages, vmas,
 					&start, &nr_pages, i, gup_flags);
 			continue;
 		}
 
-
--[[linux-2.6.33/is_vm_hugetlb_page()]]
-
--[[linux-2.6.33/follow_hugetlb_page()]]

 		do {
 			struct page *page;
 			unsigned int foll_flags = gup_flags;
 
 			/*
 			 * If we have a pending SIGKILL, don't keep faulting
 			 * pages and potentially allocating memory.
 			 */
 			if (unlikely(fatal_signal_pending(current)))
 				return i ? i : -ERESTARTSYS;
 
-
--[[linux-2.6.33/unlikely()]]
-
--[[linux-2.6.33/current(global)]]
-
--[[linux-2.6.33/fatal_signal_pending()]]

 			cond_resched();
-
--[[linux-2.6.33/cond_resched()]]

 			while (!(page = follow_page(vma, start, foll_flags))) {
 				int ret;
 
-
--[[linux-2.6.33/follow_page()]]

 				ret = handle_mm_fault(mm, vma, start,
 					(foll_flags & FOLL_WRITE) ?
 					FAULT_FLAG_WRITE : 0);
 
-
--[[linux-2.6.33/handle_mm_fault()]]
-
--[[linux-2.6.33/FAULT_FLAG_WRITE]]

 				if (ret & VM_FAULT_ERROR) {
 					if (ret & VM_FAULT_OOM)
 						return i ? i : -ENOMEM;
 					if (ret &
 					    (VM_FAULT_HWPOISON|VM_FAULT_SIGBUS))
 						return i ? i : -EFAULT;
 					BUG();
 				}
-
--[[linux-2.6.33/VM_FAULT_ERROR]]
-
--[[linux-2.6.33/VM_FAULT_OOM]]
-
--[[linux-2.6.33/VM_FAULT_HWPOISON]]
-
--[[linux-2.6.33/VM_FAULT_SIGBUS]]

 				if (ret & VM_FAULT_MAJOR)
 					tsk->maj_flt++;
 				else
 					tsk->min_flt++;
 
-
--[[linux-2.6.33/VM_FAULT_MAJOR]]

 				/*
 				 * The VM_FAULT_WRITE bit tells us that
 				 * do_wp_page has broken COW when necessary,
 				 * even if maybe_mkwrite decided not to set
 				 * pte_write. We can thus safely do subsequent
 				 * page lookups as if they were reads. But only
 				 * do so when looping for pte_write is futile:
 				 * in some cases userspace may also be wanting
 				 * to write to the gotten user page, which a
 				 * read fault here might prevent (a readonly
 				 * page might get reCOWed by userspace write).
 				 */
 				if ((ret & VM_FAULT_WRITE) &&
 				    !(vma->vm_flags & VM_WRITE))
 					foll_flags &= ~FOLL_WRITE;
 
 				cond_resched();
-
--[[linux-2.6.33/VM_FAULT_WRITE]]
-
--[[linux-2.6.33/VM_WRITE]]

 			}
 			if (IS_ERR(page))
 				return i ? i : PTR_ERR(page);
-
--[[linux-2.6.33/IS_ERR()]]
-
--[[linux-2.6.33/PTR_ERR()]]

 			if (pages) {
 				pages[i] = page;
 
 				flush_anon_page(vma, page, start);
 				flush_dcache_page(page);
 			}
-
--[[linux-2.6.33/flush_anon_page()]]
-
--[[linux-2.6.33/flush_dcache_page()]]

 			if (vmas)
 				vmas[i] = vma;
 			i++;
 			start += PAGE_SIZE;
 			nr_pages--;
 		} while (nr_pages && start < vma->vm_end);
 	} while (nr_pages);
 	return i;
 }


*コメント [#u245a6d7]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS