diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2013-06-04 16:47:17 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2013-06-10 08:43:32 -0400 |
commit | b85fffec7f5ba1c43171c63c046a97bac30a4561 (patch) | |
tree | 48e671ef1e7d171396ec689cedcef27140cd9d46 /arch/x86 | |
parent | ee336e10d5650d408efb66f634d462b9eb39c191 (diff) |
xen/smp: Don't leak interrupt name when offlining.
When the user does:
echo 0 > /sys/devices/system/cpu/cpu1/online
echo 1 > /sys/devices/system/cpu/cpu1/online
kmemleak reports:
kmemleak: 7 new suspected memory leaks (see /sys/kernel/debug/kmemleak)
unreferenced object 0xffff88003fa51240 (size 32):
comm "swapper/0", pid 1, jiffies 4294667339 (age 1027.789s)
hex dump (first 32 bytes):
72 65 73 63 68 65 64 31 00 00 00 00 00 00 00 00 resched1........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<ffffffff81660721>] kmemleak_alloc+0x21/0x50
[<ffffffff81190aac>] __kmalloc_track_caller+0xec/0x2a0
[<ffffffff812fe1bb>] kvasprintf+0x5b/0x90
[<ffffffff812fe228>] kasprintf+0x38/0x40
[<ffffffff81047ed1>] xen_smp_intr_init+0x41/0x2c0
[<ffffffff816636d3>] xen_cpu_up+0x393/0x3e8
[<ffffffff8166bbf5>] _cpu_up+0xd1/0x14b
[<ffffffff8166bd48>] cpu_up+0xd9/0xec
[<ffffffff81ae6e4a>] smp_init+0x4b/0xa3
[<ffffffff81ac4981>] kernel_init_freeable+0xdb/0x1e6
[<ffffffff8165ce39>] kernel_init+0x9/0xf0
[<ffffffff8167edfc>] ret_from_fork+0x7c/0xb0
[<ffffffffffffffff>] 0xffffffffffffffff
This patch fixes some of it by using the 'struct xen_common_irq->name'
field to stash away the char so that it can be freed when
the interrupt line is destroyed.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/xen/smp.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 6a483cdd28c9..37fbe71795c1 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -107,19 +107,27 @@ static void xen_smp_intr_free(unsigned int cpu) | |||
107 | if (per_cpu(xen_resched_irq, cpu).irq >= 0) { | 107 | if (per_cpu(xen_resched_irq, cpu).irq >= 0) { |
108 | unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu).irq, NULL); | 108 | unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu).irq, NULL); |
109 | per_cpu(xen_resched_irq, cpu).irq = -1; | 109 | per_cpu(xen_resched_irq, cpu).irq = -1; |
110 | kfree(per_cpu(xen_resched_irq, cpu).name); | ||
111 | per_cpu(xen_resched_irq, cpu).name = NULL; | ||
110 | } | 112 | } |
111 | if (per_cpu(xen_callfunc_irq, cpu).irq >= 0) { | 113 | if (per_cpu(xen_callfunc_irq, cpu).irq >= 0) { |
112 | unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu).irq, NULL); | 114 | unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu).irq, NULL); |
113 | per_cpu(xen_callfunc_irq, cpu).irq = -1; | 115 | per_cpu(xen_callfunc_irq, cpu).irq = -1; |
116 | kfree(per_cpu(xen_callfunc_irq, cpu).name); | ||
117 | per_cpu(xen_callfunc_irq, cpu).name = NULL; | ||
114 | } | 118 | } |
115 | if (per_cpu(xen_debug_irq, cpu).irq >= 0) { | 119 | if (per_cpu(xen_debug_irq, cpu).irq >= 0) { |
116 | unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu).irq, NULL); | 120 | unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu).irq, NULL); |
117 | per_cpu(xen_debug_irq, cpu).irq = -1; | 121 | per_cpu(xen_debug_irq, cpu).irq = -1; |
122 | kfree(per_cpu(xen_debug_irq, cpu).name); | ||
123 | per_cpu(xen_debug_irq, cpu).name = NULL; | ||
118 | } | 124 | } |
119 | if (per_cpu(xen_callfuncsingle_irq, cpu).irq >= 0) { | 125 | if (per_cpu(xen_callfuncsingle_irq, cpu).irq >= 0) { |
120 | unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu).irq, | 126 | unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu).irq, |
121 | NULL); | 127 | NULL); |
122 | per_cpu(xen_callfuncsingle_irq, cpu).irq = -1; | 128 | per_cpu(xen_callfuncsingle_irq, cpu).irq = -1; |
129 | kfree(per_cpu(xen_callfuncsingle_irq, cpu).name); | ||
130 | per_cpu(xen_callfuncsingle_irq, cpu).name = NULL; | ||
123 | } | 131 | } |
124 | if (xen_hvm_domain()) | 132 | if (xen_hvm_domain()) |
125 | return; | 133 | return; |
@@ -127,12 +135,14 @@ static void xen_smp_intr_free(unsigned int cpu) | |||
127 | if (per_cpu(xen_irq_work, cpu).irq >= 0) { | 135 | if (per_cpu(xen_irq_work, cpu).irq >= 0) { |
128 | unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL); | 136 | unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL); |
129 | per_cpu(xen_irq_work, cpu).irq = -1; | 137 | per_cpu(xen_irq_work, cpu).irq = -1; |
138 | kfree(per_cpu(xen_irq_work, cpu).name); | ||
139 | per_cpu(xen_irq_work, cpu).name = NULL; | ||
130 | } | 140 | } |
131 | }; | 141 | }; |
132 | static int xen_smp_intr_init(unsigned int cpu) | 142 | static int xen_smp_intr_init(unsigned int cpu) |
133 | { | 143 | { |
134 | int rc; | 144 | int rc; |
135 | const char *resched_name, *callfunc_name, *debug_name; | 145 | char *resched_name, *callfunc_name, *debug_name; |
136 | 146 | ||
137 | resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu); | 147 | resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu); |
138 | rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, | 148 | rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, |
@@ -144,6 +154,7 @@ static int xen_smp_intr_init(unsigned int cpu) | |||
144 | if (rc < 0) | 154 | if (rc < 0) |
145 | goto fail; | 155 | goto fail; |
146 | per_cpu(xen_resched_irq, cpu).irq = rc; | 156 | per_cpu(xen_resched_irq, cpu).irq = rc; |
157 | per_cpu(xen_resched_irq, cpu).name = resched_name; | ||
147 | 158 | ||
148 | callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu); | 159 | callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu); |
149 | rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR, | 160 | rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR, |
@@ -155,6 +166,7 @@ static int xen_smp_intr_init(unsigned int cpu) | |||
155 | if (rc < 0) | 166 | if (rc < 0) |
156 | goto fail; | 167 | goto fail; |
157 | per_cpu(xen_callfunc_irq, cpu).irq = rc; | 168 | per_cpu(xen_callfunc_irq, cpu).irq = rc; |
169 | per_cpu(xen_callfunc_irq, cpu).name = callfunc_name; | ||
158 | 170 | ||
159 | debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu); | 171 | debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu); |
160 | rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt, | 172 | rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt, |
@@ -163,6 +175,7 @@ static int xen_smp_intr_init(unsigned int cpu) | |||
163 | if (rc < 0) | 175 | if (rc < 0) |
164 | goto fail; | 176 | goto fail; |
165 | per_cpu(xen_debug_irq, cpu).irq = rc; | 177 | per_cpu(xen_debug_irq, cpu).irq = rc; |
178 | per_cpu(xen_debug_irq, cpu).name = debug_name; | ||
166 | 179 | ||
167 | callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu); | 180 | callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu); |
168 | rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR, | 181 | rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR, |
@@ -174,6 +187,7 @@ static int xen_smp_intr_init(unsigned int cpu) | |||
174 | if (rc < 0) | 187 | if (rc < 0) |
175 | goto fail; | 188 | goto fail; |
176 | per_cpu(xen_callfuncsingle_irq, cpu).irq = rc; | 189 | per_cpu(xen_callfuncsingle_irq, cpu).irq = rc; |
190 | per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name; | ||
177 | 191 | ||
178 | /* | 192 | /* |
179 | * The IRQ worker on PVHVM goes through the native path and uses the | 193 | * The IRQ worker on PVHVM goes through the native path and uses the |
@@ -192,6 +206,7 @@ static int xen_smp_intr_init(unsigned int cpu) | |||
192 | if (rc < 0) | 206 | if (rc < 0) |
193 | goto fail; | 207 | goto fail; |
194 | per_cpu(xen_irq_work, cpu).irq = rc; | 208 | per_cpu(xen_irq_work, cpu).irq = rc; |
209 | per_cpu(xen_irq_work, cpu).name = callfunc_name; | ||
195 | 210 | ||
196 | return 0; | 211 | return 0; |
197 | 212 | ||