diff options
| author | Markus Metzger <markus.t.metzger@intel.com> | 2008-12-19 09:17:02 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-12-20 03:15:47 -0500 |
| commit | c5dee6177f4bd2095aab7d9be9f6ebdddd6deee9 (patch) | |
| tree | fb980dcfc3d3e6f04d4dcef488c370ca653434da /arch | |
| parent | bf53de907dfdaac178c92d774aae7370d7b97d20 (diff) | |
x86, bts: memory accounting
Impact: move the BTS buffer accounting to the mlock bucket
Add alloc_locked_buffer() and free_locked_buffer() functions to mm/mlock.c
to kalloc a buffer and account the locked memory to current.
Account the memory for the BTS buffer to the tracer.
Signed-off-by: Markus Metzger <markus.t.metzger@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86/kernel/ptrace.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 6ad2bb607650..0a5df5f82fb9 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
| @@ -650,6 +650,24 @@ static int ptrace_bts_drain(struct task_struct *child, | |||
| 650 | return drained; | 650 | return drained; |
| 651 | } | 651 | } |
| 652 | 652 | ||
| 653 | static int ptrace_bts_allocate_buffer(struct task_struct *child, size_t size) | ||
| 654 | { | ||
| 655 | child->bts_buffer = alloc_locked_buffer(size); | ||
| 656 | if (!child->bts_buffer) | ||
| 657 | return -ENOMEM; | ||
| 658 | |||
| 659 | child->bts_size = size; | ||
| 660 | |||
| 661 | return 0; | ||
| 662 | } | ||
| 663 | |||
| 664 | static void ptrace_bts_free_buffer(struct task_struct *child) | ||
| 665 | { | ||
| 666 | free_locked_buffer(child->bts_buffer, child->bts_size); | ||
| 667 | child->bts_buffer = NULL; | ||
| 668 | child->bts_size = 0; | ||
| 669 | } | ||
| 670 | |||
| 653 | static int ptrace_bts_config(struct task_struct *child, | 671 | static int ptrace_bts_config(struct task_struct *child, |
| 654 | long cfg_size, | 672 | long cfg_size, |
| 655 | const struct ptrace_bts_config __user *ucfg) | 673 | const struct ptrace_bts_config __user *ucfg) |
| @@ -679,14 +697,13 @@ static int ptrace_bts_config(struct task_struct *child, | |||
| 679 | 697 | ||
| 680 | if ((cfg.flags & PTRACE_BTS_O_ALLOC) && | 698 | if ((cfg.flags & PTRACE_BTS_O_ALLOC) && |
| 681 | (cfg.size != child->bts_size)) { | 699 | (cfg.size != child->bts_size)) { |
| 682 | kfree(child->bts_buffer); | 700 | int error; |
| 683 | 701 | ||
| 684 | child->bts_size = cfg.size; | 702 | ptrace_bts_free_buffer(child); |
| 685 | child->bts_buffer = kzalloc(cfg.size, GFP_KERNEL); | 703 | |
| 686 | if (!child->bts_buffer) { | 704 | error = ptrace_bts_allocate_buffer(child, cfg.size); |
| 687 | child->bts_size = 0; | 705 | if (error < 0) |
| 688 | return -ENOMEM; | 706 | return error; |
| 689 | } | ||
| 690 | } | 707 | } |
| 691 | 708 | ||
| 692 | if (cfg.flags & PTRACE_BTS_O_TRACE) | 709 | if (cfg.flags & PTRACE_BTS_O_TRACE) |
| @@ -701,10 +718,8 @@ static int ptrace_bts_config(struct task_struct *child, | |||
| 701 | if (IS_ERR(child->bts)) { | 718 | if (IS_ERR(child->bts)) { |
| 702 | int error = PTR_ERR(child->bts); | 719 | int error = PTR_ERR(child->bts); |
| 703 | 720 | ||
| 704 | kfree(child->bts_buffer); | 721 | ptrace_bts_free_buffer(child); |
| 705 | child->bts = NULL; | 722 | child->bts = NULL; |
| 706 | child->bts_buffer = NULL; | ||
| 707 | child->bts_size = 0; | ||
| 708 | 723 | ||
| 709 | return error; | 724 | return error; |
| 710 | } | 725 | } |
| @@ -784,6 +799,9 @@ static void ptrace_bts_untrace(struct task_struct *child) | |||
| 784 | ds_release_bts(child->bts); | 799 | ds_release_bts(child->bts); |
| 785 | child->bts = NULL; | 800 | child->bts = NULL; |
| 786 | 801 | ||
| 802 | /* We cannot update total_vm and locked_vm since | ||
| 803 | child's mm is already gone. But we can reclaim the | ||
| 804 | memory. */ | ||
| 787 | kfree(child->bts_buffer); | 805 | kfree(child->bts_buffer); |
| 788 | child->bts_buffer = NULL; | 806 | child->bts_buffer = NULL; |
| 789 | child->bts_size = 0; | 807 | child->bts_size = 0; |
| @@ -792,7 +810,12 @@ static void ptrace_bts_untrace(struct task_struct *child) | |||
| 792 | 810 | ||
| 793 | static void ptrace_bts_detach(struct task_struct *child) | 811 | static void ptrace_bts_detach(struct task_struct *child) |
| 794 | { | 812 | { |
| 795 | ptrace_bts_untrace(child); | 813 | if (unlikely(child->bts)) { |
| 814 | ds_release_bts(child->bts); | ||
| 815 | child->bts = NULL; | ||
| 816 | |||
| 817 | ptrace_bts_free_buffer(child); | ||
| 818 | } | ||
| 796 | } | 819 | } |
| 797 | #else | 820 | #else |
| 798 | static inline void ptrace_bts_fork(struct task_struct *tsk) {} | 821 | static inline void ptrace_bts_fork(struct task_struct *tsk) {} |
