diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/trace/trace_ksym.c | 61 |
1 files changed, 27 insertions, 34 deletions
diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c index 891e3b86b3f6..7d349d34a0d1 100644 --- a/kernel/trace/trace_ksym.c +++ b/kernel/trace/trace_ksym.c | |||
| @@ -179,7 +179,7 @@ static int parse_ksym_trace_str(char *input_string, char **ksymname, | |||
| 179 | int process_new_ksym_entry(char *ksymname, int op, unsigned long addr) | 179 | int process_new_ksym_entry(char *ksymname, int op, unsigned long addr) |
| 180 | { | 180 | { |
| 181 | struct trace_ksym *entry; | 181 | struct trace_ksym *entry; |
| 182 | int ret; | 182 | int ret = -ENOMEM; |
| 183 | 183 | ||
| 184 | if (ksym_filter_entry_count >= KSYM_TRACER_MAX) { | 184 | if (ksym_filter_entry_count >= KSYM_TRACER_MAX) { |
| 185 | printk(KERN_ERR "ksym_tracer: Maximum limit:(%d) reached. No" | 185 | printk(KERN_ERR "ksym_tracer: Maximum limit:(%d) reached. No" |
| @@ -193,12 +193,13 @@ int process_new_ksym_entry(char *ksymname, int op, unsigned long addr) | |||
| 193 | return -ENOMEM; | 193 | return -ENOMEM; |
| 194 | 194 | ||
| 195 | entry->ksym_hbp = kzalloc(sizeof(struct hw_breakpoint), GFP_KERNEL); | 195 | entry->ksym_hbp = kzalloc(sizeof(struct hw_breakpoint), GFP_KERNEL); |
| 196 | if (!entry->ksym_hbp) { | 196 | if (!entry->ksym_hbp) |
| 197 | kfree(entry); | 197 | goto err; |
| 198 | return -ENOMEM; | 198 | |
| 199 | } | 199 | entry->ksym_hbp->info.name = kstrdup(ksymname, GFP_KERNEL); |
| 200 | if (!entry->ksym_hbp->info.name) | ||
| 201 | goto err; | ||
| 200 | 202 | ||
| 201 | entry->ksym_hbp->info.name = ksymname; | ||
| 202 | entry->ksym_hbp->info.type = op; | 203 | entry->ksym_hbp->info.type = op; |
| 203 | entry->ksym_addr = entry->ksym_hbp->info.address = addr; | 204 | entry->ksym_addr = entry->ksym_hbp->info.address = addr; |
| 204 | #ifdef CONFIG_X86 | 205 | #ifdef CONFIG_X86 |
| @@ -210,14 +211,18 @@ int process_new_ksym_entry(char *ksymname, int op, unsigned long addr) | |||
| 210 | if (ret < 0) { | 211 | if (ret < 0) { |
| 211 | printk(KERN_INFO "ksym_tracer request failed. Try again" | 212 | printk(KERN_INFO "ksym_tracer request failed. Try again" |
| 212 | " later!!\n"); | 213 | " later!!\n"); |
| 213 | kfree(entry->ksym_hbp); | 214 | ret = -EAGAIN; |
| 214 | kfree(entry); | 215 | goto err; |
| 215 | return -EAGAIN; | ||
| 216 | } | 216 | } |
| 217 | hlist_add_head_rcu(&(entry->ksym_hlist), &ksym_filter_head); | 217 | hlist_add_head_rcu(&(entry->ksym_hlist), &ksym_filter_head); |
| 218 | ksym_filter_entry_count++; | 218 | ksym_filter_entry_count++; |
| 219 | |||
| 220 | return 0; | 219 | return 0; |
| 220 | err: | ||
| 221 | if (entry->ksym_hbp) | ||
| 222 | kfree(entry->ksym_hbp->info.name); | ||
| 223 | kfree(entry->ksym_hbp); | ||
| 224 | kfree(entry); | ||
| 225 | return ret; | ||
| 221 | } | 226 | } |
| 222 | 227 | ||
| 223 | static ssize_t ksym_trace_filter_read(struct file *filp, char __user *ubuf, | 228 | static ssize_t ksym_trace_filter_read(struct file *filp, char __user *ubuf, |
| @@ -289,7 +294,7 @@ static ssize_t ksym_trace_filter_write(struct file *file, | |||
| 289 | if (entry->ksym_hbp->info.type != op) | 294 | if (entry->ksym_hbp->info.type != op) |
| 290 | changed = 1; | 295 | changed = 1; |
| 291 | else | 296 | else |
| 292 | goto err_ret; | 297 | goto out; |
| 293 | break; | 298 | break; |
| 294 | } | 299 | } |
| 295 | } | 300 | } |
| @@ -298,34 +303,29 @@ static ssize_t ksym_trace_filter_write(struct file *file, | |||
| 298 | entry->ksym_hbp->info.type = op; | 303 | entry->ksym_hbp->info.type = op; |
| 299 | if (op > 0) { | 304 | if (op > 0) { |
| 300 | ret = register_kernel_hw_breakpoint(entry->ksym_hbp); | 305 | ret = register_kernel_hw_breakpoint(entry->ksym_hbp); |
| 301 | if (ret == 0) { | 306 | if (ret == 0) |
| 302 | ret = count; | 307 | goto out; |
| 303 | goto unlock_ret_path; | 308 | } |
| 304 | } | ||
| 305 | } else | ||
| 306 | ret = count; | ||
| 307 | ksym_filter_entry_count--; | 309 | ksym_filter_entry_count--; |
| 308 | hlist_del_rcu(&(entry->ksym_hlist)); | 310 | hlist_del_rcu(&(entry->ksym_hlist)); |
| 309 | synchronize_rcu(); | 311 | synchronize_rcu(); |
| 312 | kfree(entry->ksym_hbp->info.name); | ||
| 310 | kfree(entry->ksym_hbp); | 313 | kfree(entry->ksym_hbp); |
| 311 | kfree(entry); | 314 | kfree(entry); |
| 312 | goto err_ret; | 315 | goto out; |
| 313 | } else { | 316 | } else { |
| 314 | /* Check for malformed request: (4) */ | 317 | /* Check for malformed request: (4) */ |
| 315 | if (op == 0) | 318 | if (op == 0) |
| 316 | goto err_ret; | 319 | goto out; |
| 317 | ret = process_new_ksym_entry(ksymname, op, ksym_addr); | 320 | ret = process_new_ksym_entry(ksymname, op, ksym_addr); |
| 318 | if (ret) | ||
| 319 | goto err_ret; | ||
| 320 | } | 321 | } |
| 321 | ret = count; | 322 | out: |
| 322 | goto unlock_ret_path; | 323 | mutex_unlock(&ksym_tracer_mutex); |
| 323 | 324 | ||
| 324 | err_ret: | ||
| 325 | kfree(input_string); | 325 | kfree(input_string); |
| 326 | 326 | ||
| 327 | unlock_ret_path: | 327 | if (!ret) |
| 328 | mutex_unlock(&ksym_tracer_mutex); | 328 | ret = count; |
| 329 | return ret; | 329 | return ret; |
| 330 | } | 330 | } |
| 331 | 331 | ||
| @@ -349,14 +349,7 @@ static void ksym_trace_reset(struct trace_array *tr) | |||
| 349 | ksym_filter_entry_count--; | 349 | ksym_filter_entry_count--; |
| 350 | hlist_del_rcu(&(entry->ksym_hlist)); | 350 | hlist_del_rcu(&(entry->ksym_hlist)); |
| 351 | synchronize_rcu(); | 351 | synchronize_rcu(); |
| 352 | /* Free the 'input_string' only if reset | 352 | kfree(entry->ksym_hbp->info.name); |
| 353 | * after startup self-test | ||
| 354 | */ | ||
| 355 | #ifdef CONFIG_FTRACE_SELFTEST | ||
| 356 | if (strncmp(entry->ksym_hbp->info.name, KSYM_SELFTEST_ENTRY, | ||
| 357 | strlen(KSYM_SELFTEST_ENTRY)) != 0) | ||
| 358 | #endif /* CONFIG_FTRACE_SELFTEST*/ | ||
| 359 | kfree(entry->ksym_hbp->info.name); | ||
| 360 | kfree(entry->ksym_hbp); | 353 | kfree(entry->ksym_hbp); |
| 361 | kfree(entry); | 354 | kfree(entry); |
| 362 | } | 355 | } |
