linux-4.4.1/__get_user_pages()
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
*参照元 [#x18c8bd1]
#backlinks
*説明 [#mcf8167a]
-パス: 複数あり
--CONFIG_MMU 有効: [[linux-4.4.1/mm/gup.c]]
--CONFIG_MMU 無効: [[linux-4.4.1/mm/nommu.c]]
--[[linux-4.4.1/CONFIG_MMU]]
-FIXME: これは何?
--説明
**引数 [#y3c083af]
-struct task_struct *tsk
--
--[[linux-4.4.1/task_struct]]
-struct mm_struct *mm
--
--[[linux-4.4.1/mm_struct]]
-unsigned long start
--
-unsigned long nr_pages
--
-unsigned int gup_flags
--
-struct page **pages
--
--[[linux-4.4.1/page]]
-struct vm_area_struct **vmas
--
--[[linux-4.4.1/vm_area_struct]]
-int *nonblocking
--
**返り値 [#nfcacc7f]
-long
--
**参考 [#sf624894]
*実装 [#s195c618]
**CONFIG_MMU 有効: mm/gup.c [#h79cfa5d]
/**
* __get_user_pages() - pin user pages in memory
* @tsk: task_struct of target task
* @mm: mm_struct of target mm
* @start: starting user address
* @nr_pages: number of pages from start to pin
* @gup_flags: flags modifying pin behaviour
* @pages: array that receives pointers to the page...
* Should be at least nr_pages long. Or NUL...
* only intends to ensure the pages are fau...
* @vmas: array of pointers to vmas corresponding ...
* Or NULL if the caller does not require t...
* @nonblocking: whether waiting for disk IO or mmap_sem...
*
* Returns number of pages pinned. This may be fewer tha...
* requested. If nr_pages is 0 or negative, returns 0. I...
* were pinned, returns -errno. Each page returned must ...
* with a put_page() call when it is finished with. vmas...
* remain valid while mmap_sem is held.
*
* Must be called with mmap_sem held. It may be release...
*
* __get_user_pages walks a process's page tables and ta...
* each struct page that each user address corresponds t...
* instant. That is, it takes the page that would be acc...
* thread accesses the given user virtual address at tha...
*
* This does not guarantee that the page exists in the u...
* __get_user_pages returns, and there may even be a com...
* page there in some cases (eg. if mmapped pagecache ha...
* and subsequently re faulted). However it does guarant...
* won't be freed completely. And mostly callers simply ...
* contains data that was valid *at some point in time*....
* or similar operation cannot guarantee anything strong...
* locks can't be held over the syscall boundary.
*
* If @gup_flags & FOLL_WRITE == 0, the page must not be...
* the page is written to, set_page_dirty (or set_page_d...
* appropriate) must be called after the page is finishe...
* before put_page is called.
*
* If @nonblocking != NULL, __get_user_pages will not wa...
* or mmap_sem contention, and if waiting is needed to p...
* *@nonblocking will be set to 0. Further, if @gup_fla...
* include FOLL_NOWAIT, the mmap_sem will be released vi...
* this case.
*
* A caller using such a combination of @nonblocking and...
* must therefore hold the mmap_sem for reading only, an...
* when it's been released. Otherwise, it must be held ...
* reading or writing and will not be released.
*
* In most cases, get_user_pages or get_user_pages_fast ...
* instead of __get_user_pages. __get_user_pages should ...
* you need some special @gup_flags.
*/
long __get_user_pages(struct task_struct *tsk, struct mm...
unsigned long start, unsigned long nr_pa...
unsigned int gup_flags, struct page **pa...
struct vm_area_struct **vmas, int *nonbl...
{
long i = 0;
unsigned int page_mask;
struct vm_area_struct *vma = NULL;
-
--[[linux-4.4.1/vm_area_struct]]
if (!nr_pages)
return 0;
VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET));
-
--[[linux-4.4.1/VM_BUG_ON()]]
/*
* If FOLL_FORCE is set then do not force a full...
* fault information is unrelated to the referen...
* using the address space
*/
if (!(gup_flags & FOLL_FORCE))
gup_flags |= FOLL_NUMA;
do {
struct page *page;
unsigned int foll_flags = gup_flags;
unsigned int page_increm;
-
--[[linux-4.4.1/page]]
/* first iteration or cross vma bound */
if (!vma || start >= vma->vm_end) {
vma = find_extend_vma(mm, start);
if (!vma && in_gate_area(mm, sta...
-
--[[linux-4.4.1/find_extend_vma()]]
--[[linux-4.4.1/in_gate_area()]]
int ret;
ret = get_gate_page(mm, ...
gup_flag...
pages ? ...
if (ret)
return i ? : ret;
-
--[[linux-4.4.1/get_gate_page()]]
--[[linux-4.4.1/PAGE_MASK]]
page_mask = 0;
goto next_page;
}
if (!vma || check_vma_flags(vma,...
return i ? : -EFAULT;
-
--[[linux-4.4.1/check_vma_flags()]]
if (is_vm_hugetlb_page(vma)) {
i = follow_hugetlb_page(...
&start, ...
gup_flag...
continue;
}
-
--[[linux-4.4.1/is_vm_hugetlb_page()]]
--[[linux-4.4.1/follow_hugetlb_page()]]
}
retry:
/*
* If we have a pending SIGKILL, don't k...
* potentially allocating memory.
*/
if (unlikely(fatal_signal_pending(curren...
return i ? i : -ERESTARTSYS;
cond_resched();
-
--[[linux-4.4.1/unlikely()]]
--[[linux-4.4.1/fatal_signal_pending()]]
--[[linux-4.4.1/cond_resched()]]
page = follow_page_mask(vma, start, foll...
-
--[[linux-4.4.1/follow_page_mask()]]
if (!page) {
int ret;
ret = faultin_page(tsk, vma, sta...
nonblocking);
-
--[[linux-4.4.1/faultin_page()]]
switch (ret) {
case 0:
goto retry;
case -EFAULT:
case -ENOMEM:
case -EHWPOISON:
return i ? i : ret;
case -EBUSY:
return i;
case -ENOENT:
goto next_page;
}
BUG();
-
--[[linux-4.4.1/BUG()]]
} else if (PTR_ERR(page) == -EEXIST) {
/*
* Proper page table entry exist...
* struct page.
*/
goto next_page;
} else if (IS_ERR(page)) {
return i ? i : PTR_ERR(page);
}
-
--[[linux-4.4.1/PTR_ERR()]]
--[[linux-4.4.1/IS_ERR()]]
if (pages) {
pages[i] = page;
flush_anon_page(vma, page, start);
flush_dcache_page(page);
page_mask = 0;
}
-
--[[linux-4.4.1/flush_anon_page()]]
--[[linux-4.4.1/flush_dcache_page()]]
next_page:
if (vmas) {
vmas[i] = vma;
page_mask = 0;
}
page_increm = 1 + (~(start >> PAGE_SHIFT...
if (page_increm > nr_pages)
page_increm = nr_pages;
i += page_increm;
start += page_increm * PAGE_SIZE;
nr_pages -= page_increm;
} while (nr_pages);
return i;
}
EXPORT_SYMBOL(__get_user_pages);
-
--[[linux-4.4.1/EXPORT_SYMBOL()]]
**CONFIG_MMU 無効: mm/nommu.c [#wc98e984]
long __get_user_pages(struct task_struct *tsk, struct mm...
unsigned long start, unsigned long...
unsigned int foll_flags, struct pa...
struct vm_area_struct **vmas, int ...
{
struct vm_area_struct *vma;
unsigned long vm_flags;
int i;
-
--[[linux-4.4.1/vm_area_struct]]
/* calculate required read or write permissions.
* If FOLL_FORCE is set, we only require the "MA...
*/
vm_flags = (foll_flags & FOLL_WRITE) ?
(VM_WRITE | VM_MAYWRITE) : (VM_R...
vm_flags &= (foll_flags & FOLL_FORCE) ?
(VM_MAYREAD | VM_MAYWRITE) : (VM...
for (i = 0; i < nr_pages; i++) {
vma = find_vma(mm, start);
if (!vma)
goto finish_or_fault;
-
--[[linux-4.4.1/find_vma()]]
/* protect what we can, including charde...
if ((vma->vm_flags & (VM_IO | VM_PFNMAP)...
!(vm_flags & vma->vm_flags))
goto finish_or_fault;
if (pages) {
pages[i] = virt_to_page(start);
if (pages[i])
page_cache_get(pages[i]);
}
-
--[[linux-4.4.1/virt_to_page()]]
--[[linux-4.4.1/page_cache_get()]]
if (vmas)
vmas[i] = vma;
start = (start + PAGE_SIZE) & PAGE_MASK;
}
return i;
finish_or_fault:
return i ? : -EFAULT;
}
*コメント [#yf6ceaeb]
終了行:
*参照元 [#x18c8bd1]
#backlinks
*説明 [#mcf8167a]
-パス: 複数あり
--CONFIG_MMU 有効: [[linux-4.4.1/mm/gup.c]]
--CONFIG_MMU 無効: [[linux-4.4.1/mm/nommu.c]]
--[[linux-4.4.1/CONFIG_MMU]]
-FIXME: これは何?
--説明
**引数 [#y3c083af]
-struct task_struct *tsk
--
--[[linux-4.4.1/task_struct]]
-struct mm_struct *mm
--
--[[linux-4.4.1/mm_struct]]
-unsigned long start
--
-unsigned long nr_pages
--
-unsigned int gup_flags
--
-struct page **pages
--
--[[linux-4.4.1/page]]
-struct vm_area_struct **vmas
--
--[[linux-4.4.1/vm_area_struct]]
-int *nonblocking
--
**返り値 [#nfcacc7f]
-long
--
**参考 [#sf624894]
*実装 [#s195c618]
**CONFIG_MMU 有効: mm/gup.c [#h79cfa5d]
/**
* __get_user_pages() - pin user pages in memory
* @tsk: task_struct of target task
* @mm: mm_struct of target mm
* @start: starting user address
* @nr_pages: number of pages from start to pin
* @gup_flags: flags modifying pin behaviour
* @pages: array that receives pointers to the page...
* Should be at least nr_pages long. Or NUL...
* only intends to ensure the pages are fau...
* @vmas: array of pointers to vmas corresponding ...
* Or NULL if the caller does not require t...
* @nonblocking: whether waiting for disk IO or mmap_sem...
*
* Returns number of pages pinned. This may be fewer tha...
* requested. If nr_pages is 0 or negative, returns 0. I...
* were pinned, returns -errno. Each page returned must ...
* with a put_page() call when it is finished with. vmas...
* remain valid while mmap_sem is held.
*
* Must be called with mmap_sem held. It may be release...
*
* __get_user_pages walks a process's page tables and ta...
* each struct page that each user address corresponds t...
* instant. That is, it takes the page that would be acc...
* thread accesses the given user virtual address at tha...
*
* This does not guarantee that the page exists in the u...
* __get_user_pages returns, and there may even be a com...
* page there in some cases (eg. if mmapped pagecache ha...
* and subsequently re faulted). However it does guarant...
* won't be freed completely. And mostly callers simply ...
* contains data that was valid *at some point in time*....
* or similar operation cannot guarantee anything strong...
* locks can't be held over the syscall boundary.
*
* If @gup_flags & FOLL_WRITE == 0, the page must not be...
* the page is written to, set_page_dirty (or set_page_d...
* appropriate) must be called after the page is finishe...
* before put_page is called.
*
* If @nonblocking != NULL, __get_user_pages will not wa...
* or mmap_sem contention, and if waiting is needed to p...
* *@nonblocking will be set to 0. Further, if @gup_fla...
* include FOLL_NOWAIT, the mmap_sem will be released vi...
* this case.
*
* A caller using such a combination of @nonblocking and...
* must therefore hold the mmap_sem for reading only, an...
* when it's been released. Otherwise, it must be held ...
* reading or writing and will not be released.
*
* In most cases, get_user_pages or get_user_pages_fast ...
* instead of __get_user_pages. __get_user_pages should ...
* you need some special @gup_flags.
*/
long __get_user_pages(struct task_struct *tsk, struct mm...
unsigned long start, unsigned long nr_pa...
unsigned int gup_flags, struct page **pa...
struct vm_area_struct **vmas, int *nonbl...
{
long i = 0;
unsigned int page_mask;
struct vm_area_struct *vma = NULL;
-
--[[linux-4.4.1/vm_area_struct]]
if (!nr_pages)
return 0;
VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET));
-
--[[linux-4.4.1/VM_BUG_ON()]]
/*
* If FOLL_FORCE is set then do not force a full...
* fault information is unrelated to the referen...
* using the address space
*/
if (!(gup_flags & FOLL_FORCE))
gup_flags |= FOLL_NUMA;
do {
struct page *page;
unsigned int foll_flags = gup_flags;
unsigned int page_increm;
-
--[[linux-4.4.1/page]]
/* first iteration or cross vma bound */
if (!vma || start >= vma->vm_end) {
vma = find_extend_vma(mm, start);
if (!vma && in_gate_area(mm, sta...
-
--[[linux-4.4.1/find_extend_vma()]]
--[[linux-4.4.1/in_gate_area()]]
int ret;
ret = get_gate_page(mm, ...
gup_flag...
pages ? ...
if (ret)
return i ? : ret;
-
--[[linux-4.4.1/get_gate_page()]]
--[[linux-4.4.1/PAGE_MASK]]
page_mask = 0;
goto next_page;
}
if (!vma || check_vma_flags(vma,...
return i ? : -EFAULT;
-
--[[linux-4.4.1/check_vma_flags()]]
if (is_vm_hugetlb_page(vma)) {
i = follow_hugetlb_page(...
&start, ...
gup_flag...
continue;
}
-
--[[linux-4.4.1/is_vm_hugetlb_page()]]
--[[linux-4.4.1/follow_hugetlb_page()]]
}
retry:
/*
* If we have a pending SIGKILL, don't k...
* potentially allocating memory.
*/
if (unlikely(fatal_signal_pending(curren...
return i ? i : -ERESTARTSYS;
cond_resched();
-
--[[linux-4.4.1/unlikely()]]
--[[linux-4.4.1/fatal_signal_pending()]]
--[[linux-4.4.1/cond_resched()]]
page = follow_page_mask(vma, start, foll...
-
--[[linux-4.4.1/follow_page_mask()]]
if (!page) {
int ret;
ret = faultin_page(tsk, vma, sta...
nonblocking);
-
--[[linux-4.4.1/faultin_page()]]
switch (ret) {
case 0:
goto retry;
case -EFAULT:
case -ENOMEM:
case -EHWPOISON:
return i ? i : ret;
case -EBUSY:
return i;
case -ENOENT:
goto next_page;
}
BUG();
-
--[[linux-4.4.1/BUG()]]
} else if (PTR_ERR(page) == -EEXIST) {
/*
* Proper page table entry exist...
* struct page.
*/
goto next_page;
} else if (IS_ERR(page)) {
return i ? i : PTR_ERR(page);
}
-
--[[linux-4.4.1/PTR_ERR()]]
--[[linux-4.4.1/IS_ERR()]]
if (pages) {
pages[i] = page;
flush_anon_page(vma, page, start);
flush_dcache_page(page);
page_mask = 0;
}
-
--[[linux-4.4.1/flush_anon_page()]]
--[[linux-4.4.1/flush_dcache_page()]]
next_page:
if (vmas) {
vmas[i] = vma;
page_mask = 0;
}
page_increm = 1 + (~(start >> PAGE_SHIFT...
if (page_increm > nr_pages)
page_increm = nr_pages;
i += page_increm;
start += page_increm * PAGE_SIZE;
nr_pages -= page_increm;
} while (nr_pages);
return i;
}
EXPORT_SYMBOL(__get_user_pages);
-
--[[linux-4.4.1/EXPORT_SYMBOL()]]
**CONFIG_MMU 無効: mm/nommu.c [#wc98e984]
long __get_user_pages(struct task_struct *tsk, struct mm...
unsigned long start, unsigned long...
unsigned int foll_flags, struct pa...
struct vm_area_struct **vmas, int ...
{
struct vm_area_struct *vma;
unsigned long vm_flags;
int i;
-
--[[linux-4.4.1/vm_area_struct]]
/* calculate required read or write permissions.
* If FOLL_FORCE is set, we only require the "MA...
*/
vm_flags = (foll_flags & FOLL_WRITE) ?
(VM_WRITE | VM_MAYWRITE) : (VM_R...
vm_flags &= (foll_flags & FOLL_FORCE) ?
(VM_MAYREAD | VM_MAYWRITE) : (VM...
for (i = 0; i < nr_pages; i++) {
vma = find_vma(mm, start);
if (!vma)
goto finish_or_fault;
-
--[[linux-4.4.1/find_vma()]]
/* protect what we can, including charde...
if ((vma->vm_flags & (VM_IO | VM_PFNMAP)...
!(vm_flags & vma->vm_flags))
goto finish_or_fault;
if (pages) {
pages[i] = virt_to_page(start);
if (pages[i])
page_cache_get(pages[i]);
}
-
--[[linux-4.4.1/virt_to_page()]]
--[[linux-4.4.1/page_cache_get()]]
if (vmas)
vmas[i] = vma;
start = (start + PAGE_SIZE) & PAGE_MASK;
}
return i;
finish_or_fault:
return i ? : -EFAULT;
}
*コメント [#yf6ceaeb]
ページ名: