diff options
author | Patrick McHardy <kaber@trash.net> | 2011-04-13 07:32:28 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-04-13 07:32:28 -0400 |
commit | b32e3dc7860d00124fa432dba09667e647cb9bcc (patch) | |
tree | 2fa6e56f389431dfb84609d3d7572cad76e88e71 /mm/memory.c | |
parent | 6604271c5bc658a6067ed0c3deba4d89e0e50382 (diff) | |
parent | 96120d86fe302c006259baee9061eea9e1b9e486 (diff) |
Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 80 |
1 files changed, 59 insertions, 21 deletions
diff --git a/mm/memory.c b/mm/memory.c index e48945ab362b..9da8cab1b1b0 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1486,9 +1486,9 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1486 | struct vm_area_struct *vma; | 1486 | struct vm_area_struct *vma; |
1487 | 1487 | ||
1488 | vma = find_extend_vma(mm, start); | 1488 | vma = find_extend_vma(mm, start); |
1489 | if (!vma && in_gate_area(tsk, start)) { | 1489 | if (!vma && in_gate_area(mm, start)) { |
1490 | unsigned long pg = start & PAGE_MASK; | 1490 | unsigned long pg = start & PAGE_MASK; |
1491 | struct vm_area_struct *gate_vma = get_gate_vma(tsk); | 1491 | struct vm_area_struct *gate_vma = get_gate_vma(mm); |
1492 | pgd_t *pgd; | 1492 | pgd_t *pgd; |
1493 | pud_t *pud; | 1493 | pud_t *pud; |
1494 | pmd_t *pmd; | 1494 | pmd_t *pmd; |
@@ -1569,6 +1569,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1569 | fault_flags |= FAULT_FLAG_WRITE; | 1569 | fault_flags |= FAULT_FLAG_WRITE; |
1570 | if (nonblocking) | 1570 | if (nonblocking) |
1571 | fault_flags |= FAULT_FLAG_ALLOW_RETRY; | 1571 | fault_flags |= FAULT_FLAG_ALLOW_RETRY; |
1572 | if (foll_flags & FOLL_NOWAIT) | ||
1573 | fault_flags |= (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT); | ||
1572 | 1574 | ||
1573 | ret = handle_mm_fault(mm, vma, start, | 1575 | ret = handle_mm_fault(mm, vma, start, |
1574 | fault_flags); | 1576 | fault_flags); |
@@ -1589,13 +1591,17 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1589 | return i ? i : -EFAULT; | 1591 | return i ? i : -EFAULT; |
1590 | BUG(); | 1592 | BUG(); |
1591 | } | 1593 | } |
1592 | if (ret & VM_FAULT_MAJOR) | 1594 | |
1593 | tsk->maj_flt++; | 1595 | if (tsk) { |
1594 | else | 1596 | if (ret & VM_FAULT_MAJOR) |
1595 | tsk->min_flt++; | 1597 | tsk->maj_flt++; |
1598 | else | ||
1599 | tsk->min_flt++; | ||
1600 | } | ||
1596 | 1601 | ||
1597 | if (ret & VM_FAULT_RETRY) { | 1602 | if (ret & VM_FAULT_RETRY) { |
1598 | *nonblocking = 0; | 1603 | if (nonblocking) |
1604 | *nonblocking = 0; | ||
1599 | return i; | 1605 | return i; |
1600 | } | 1606 | } |
1601 | 1607 | ||
@@ -1638,7 +1644,8 @@ EXPORT_SYMBOL(__get_user_pages); | |||
1638 | 1644 | ||
1639 | /** | 1645 | /** |
1640 | * get_user_pages() - pin user pages in memory | 1646 | * get_user_pages() - pin user pages in memory |
1641 | * @tsk: task_struct of target task | 1647 | * @tsk: the task_struct to use for page fault accounting, or |
1648 | * NULL if faults are not to be recorded. | ||
1642 | * @mm: mm_struct of target mm | 1649 | * @mm: mm_struct of target mm |
1643 | * @start: starting user address | 1650 | * @start: starting user address |
1644 | * @nr_pages: number of pages from start to pin | 1651 | * @nr_pages: number of pages from start to pin |
@@ -2764,7 +2771,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2764 | swp_entry_t entry; | 2771 | swp_entry_t entry; |
2765 | pte_t pte; | 2772 | pte_t pte; |
2766 | int locked; | 2773 | int locked; |
2767 | struct mem_cgroup *ptr = NULL; | 2774 | struct mem_cgroup *ptr; |
2768 | int exclusive = 0; | 2775 | int exclusive = 0; |
2769 | int ret = 0; | 2776 | int ret = 0; |
2770 | 2777 | ||
@@ -3496,7 +3503,7 @@ static int __init gate_vma_init(void) | |||
3496 | __initcall(gate_vma_init); | 3503 | __initcall(gate_vma_init); |
3497 | #endif | 3504 | #endif |
3498 | 3505 | ||
3499 | struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | 3506 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) |
3500 | { | 3507 | { |
3501 | #ifdef AT_SYSINFO_EHDR | 3508 | #ifdef AT_SYSINFO_EHDR |
3502 | return &gate_vma; | 3509 | return &gate_vma; |
@@ -3505,7 +3512,7 @@ struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | |||
3505 | #endif | 3512 | #endif |
3506 | } | 3513 | } |
3507 | 3514 | ||
3508 | int in_gate_area_no_task(unsigned long addr) | 3515 | int in_gate_area_no_mm(unsigned long addr) |
3509 | { | 3516 | { |
3510 | #ifdef AT_SYSINFO_EHDR | 3517 | #ifdef AT_SYSINFO_EHDR |
3511 | if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END)) | 3518 | if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END)) |
@@ -3646,20 +3653,15 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, | |||
3646 | #endif | 3653 | #endif |
3647 | 3654 | ||
3648 | /* | 3655 | /* |
3649 | * Access another process' address space. | 3656 | * Access another process' address space as given in mm. If non-NULL, use the |
3650 | * Source/target buffer must be kernel space, | 3657 | * given task for page fault accounting. |
3651 | * Do not walk the page table directly, use get_user_pages | ||
3652 | */ | 3658 | */ |
3653 | int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) | 3659 | static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, |
3660 | unsigned long addr, void *buf, int len, int write) | ||
3654 | { | 3661 | { |
3655 | struct mm_struct *mm; | ||
3656 | struct vm_area_struct *vma; | 3662 | struct vm_area_struct *vma; |
3657 | void *old_buf = buf; | 3663 | void *old_buf = buf; |
3658 | 3664 | ||
3659 | mm = get_task_mm(tsk); | ||
3660 | if (!mm) | ||
3661 | return 0; | ||
3662 | |||
3663 | down_read(&mm->mmap_sem); | 3665 | down_read(&mm->mmap_sem); |
3664 | /* ignore errors, just check how much was successfully transferred */ | 3666 | /* ignore errors, just check how much was successfully transferred */ |
3665 | while (len) { | 3667 | while (len) { |
@@ -3708,11 +3710,47 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in | |||
3708 | addr += bytes; | 3710 | addr += bytes; |
3709 | } | 3711 | } |
3710 | up_read(&mm->mmap_sem); | 3712 | up_read(&mm->mmap_sem); |
3711 | mmput(mm); | ||
3712 | 3713 | ||
3713 | return buf - old_buf; | 3714 | return buf - old_buf; |
3714 | } | 3715 | } |
3715 | 3716 | ||
3717 | /** | ||
3718 | * access_remote_vm - access another process' address space | ||
3719 | * @mm: the mm_struct of the target address space | ||
3720 | * @addr: start address to access | ||
3721 | * @buf: source or destination buffer | ||
3722 | * @len: number of bytes to transfer | ||
3723 | * @write: whether the access is a write | ||
3724 | * | ||
3725 | * The caller must hold a reference on @mm. | ||
3726 | */ | ||
3727 | int access_remote_vm(struct mm_struct *mm, unsigned long addr, | ||
3728 | void *buf, int len, int write) | ||
3729 | { | ||
3730 | return __access_remote_vm(NULL, mm, addr, buf, len, write); | ||
3731 | } | ||
3732 | |||
3733 | /* | ||
3734 | * Access another process' address space. | ||
3735 | * Source/target buffer must be kernel space, | ||
3736 | * Do not walk the page table directly, use get_user_pages | ||
3737 | */ | ||
3738 | int access_process_vm(struct task_struct *tsk, unsigned long addr, | ||
3739 | void *buf, int len, int write) | ||
3740 | { | ||
3741 | struct mm_struct *mm; | ||
3742 | int ret; | ||
3743 | |||
3744 | mm = get_task_mm(tsk); | ||
3745 | if (!mm) | ||
3746 | return 0; | ||
3747 | |||
3748 | ret = __access_remote_vm(tsk, mm, addr, buf, len, write); | ||
3749 | mmput(mm); | ||
3750 | |||
3751 | return ret; | ||
3752 | } | ||
3753 | |||
3716 | /* | 3754 | /* |
3717 | * Print the name of a VMA. | 3755 | * Print the name of a VMA. |
3718 | */ | 3756 | */ |