*参照元 [#wb018f17] #backlinks *説明 [#xaccec38] -パス: [[linux-4.4.1/mm/gup.c]] -FIXME: これは何? --説明 **引数 [#d03de652] -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 -- -int write -- -int force -- -struct page **pages -- --[[linux-4.4.1/page]] -struct vm_area_struct **vmas -- --[[linux-4.4.1/vm_area_struct]] -int *locked -- -bool notify_drop -- -unsigned int flags -- **返り値 [#w61274fb] -long -- **参考 [#lca7624d] *実装 [#s46ea28d] static __always_inline long __get_user_pages_locked(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, unsigned long nr_pages, int write, int force, struct page **pages, struct vm_area_struct **vmas, int *locked, bool notify_drop, unsigned int flags) { long ret, pages_done; bool lock_dropped; if (locked) { /* if VM_FAULT_RETRY can be returned, vmas become invalid */ BUG_ON(vmas); /* check caller initialized locked */ BUG_ON(*locked != 1); } - --[[linux-4.4.1/BUG_ON()]] if (pages) flags |= FOLL_GET; if (write) flags |= FOLL_WRITE; if (force) flags |= FOLL_FORCE; pages_done = 0; lock_dropped = false; for (;;) { ret = __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas, locked); if (!locked) /* VM_FAULT_RETRY couldn't trigger, bypass */ return ret; - --[[linux-4.4.1/__get_user_pages()]] /* VM_FAULT_RETRY cannot return errors */ if (!*locked) { BUG_ON(ret < 0); BUG_ON(ret >= nr_pages); } if (!pages) /* If it's a prefault don't insist harder */ return ret; if (ret > 0) { nr_pages -= ret; pages_done += ret; if (!nr_pages) break; } if (*locked) { /* VM_FAULT_RETRY didn't trigger */ if (!pages_done) pages_done = ret; break; } /* VM_FAULT_RETRY triggered, so seek to the faulting offset */ pages += ret; start += ret << PAGE_SHIFT; /* * Repeat on the address that fired VM_FAULT_RETRY * without FAULT_FLAG_ALLOW_RETRY but with * FAULT_FLAG_TRIED. */ *locked = 1; lock_dropped = true; down_read(&mm->mmap_sem); ret = __get_user_pages(tsk, mm, start, 1, flags | FOLL_TRIED, pages, NULL, NULL); if (ret != 1) { BUG_ON(ret > 1); if (!pages_done) pages_done = ret; break; } - --[[linux-4.4.1/down_read()]] --[[linux-4.4.1/__get_user_pages()]] nr_pages--; pages_done++; if (!nr_pages) break; pages++; start += PAGE_SIZE; } if (notify_drop && lock_dropped && *locked) { /* * We must let the caller know we temporarily dropped the lock * and so the critical section protected by it was lost. */ up_read(&mm->mmap_sem); *locked = 0; } return pages_done; - --[[linux-4.4.1/up_read()]] } *コメント [#kf891f5a]