diff options
author | Oleg Nesterov <oleg@redhat.com> | 2012-06-15 11:43:42 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-06-16 03:10:45 -0400 |
commit | d436615e60c386095dac4a9bf72b08868d2a7564 (patch) | |
tree | d69e29a80512f13cb1ce3f302cd865fd35709ddf /kernel/events | |
parent | c5784de2b351fe871bb57487878f7fc7ec5b075c (diff) |
uprobes: Copy_insn() shouldn't depend on mm/vma/vaddr
1. copy_insn() doesn't need "addr", it can use uprobe->offset.
Remove this argument.
2. Change copy_insn/__copy_insn to accept "struct file*" instead
of vma.
copy_insn() is called only once and mm/vma/vaddr are random, it
shouldn't depend on them.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Acked-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120615154342.GA9598@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/events')
-rw-r--r-- | kernel/events/uprobes.c | 15 |
1 files changed, 6 insertions, 9 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 2671d9ad49be..08ef566da763 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -591,10 +591,9 @@ static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc) | |||
591 | } | 591 | } |
592 | 592 | ||
593 | static int | 593 | static int |
594 | __copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *insn, | 594 | __copy_insn(struct address_space *mapping, struct file *filp, char *insn, |
595 | unsigned long nbytes, unsigned long offset) | 595 | unsigned long nbytes, unsigned long offset) |
596 | { | 596 | { |
597 | struct file *filp = vma->vm_file; | ||
598 | struct page *page; | 597 | struct page *page; |
599 | void *vaddr; | 598 | void *vaddr; |
600 | unsigned long off1; | 599 | unsigned long off1; |
@@ -625,15 +624,13 @@ __copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *ins | |||
625 | return 0; | 624 | return 0; |
626 | } | 625 | } |
627 | 626 | ||
628 | static int | 627 | static int copy_insn(struct uprobe *uprobe, struct file *filp) |
629 | copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) | ||
630 | { | 628 | { |
631 | struct address_space *mapping; | 629 | struct address_space *mapping; |
632 | unsigned long nbytes; | 630 | unsigned long nbytes; |
633 | int bytes; | 631 | int bytes; |
634 | 632 | ||
635 | addr &= ~PAGE_MASK; | 633 | nbytes = PAGE_SIZE - (uprobe->offset & ~PAGE_MASK); |
636 | nbytes = PAGE_SIZE - addr; | ||
637 | mapping = uprobe->inode->i_mapping; | 634 | mapping = uprobe->inode->i_mapping; |
638 | 635 | ||
639 | /* Instruction at end of binary; copy only available bytes */ | 636 | /* Instruction at end of binary; copy only available bytes */ |
@@ -644,13 +641,13 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) | |||
644 | 641 | ||
645 | /* Instruction at the page-boundary; copy bytes in second page */ | 642 | /* Instruction at the page-boundary; copy bytes in second page */ |
646 | if (nbytes < bytes) { | 643 | if (nbytes < bytes) { |
647 | if (__copy_insn(mapping, vma, uprobe->arch.insn + nbytes, | 644 | if (__copy_insn(mapping, filp, uprobe->arch.insn + nbytes, |
648 | bytes - nbytes, uprobe->offset + nbytes)) | 645 | bytes - nbytes, uprobe->offset + nbytes)) |
649 | return -ENOMEM; | 646 | return -ENOMEM; |
650 | 647 | ||
651 | bytes = nbytes; | 648 | bytes = nbytes; |
652 | } | 649 | } |
653 | return __copy_insn(mapping, vma, uprobe->arch.insn, bytes, uprobe->offset); | 650 | return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); |
654 | } | 651 | } |
655 | 652 | ||
656 | /* | 653 | /* |
@@ -696,7 +693,7 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, | |||
696 | addr = (unsigned long)vaddr; | 693 | addr = (unsigned long)vaddr; |
697 | 694 | ||
698 | if (!(uprobe->flags & UPROBE_COPY_INSN)) { | 695 | if (!(uprobe->flags & UPROBE_COPY_INSN)) { |
699 | ret = copy_insn(uprobe, vma, addr); | 696 | ret = copy_insn(uprobe, vma->vm_file); |
700 | if (ret) | 697 | if (ret) |
701 | return ret; | 698 | return ret; |
702 | 699 | ||