diff options
Diffstat (limited to 'kernel/trace/kmemtrace.c')
| -rw-r--r-- | kernel/trace/kmemtrace.c | 149 |
1 files changed, 96 insertions, 53 deletions
diff --git a/kernel/trace/kmemtrace.c b/kernel/trace/kmemtrace.c index 86cdf671d7e2..81b1645c8549 100644 --- a/kernel/trace/kmemtrace.c +++ b/kernel/trace/kmemtrace.c | |||
| @@ -183,11 +183,9 @@ static void kmemtrace_stop_probes(void) | |||
| 183 | 183 | ||
| 184 | static int kmem_trace_init(struct trace_array *tr) | 184 | static int kmem_trace_init(struct trace_array *tr) |
| 185 | { | 185 | { |
| 186 | int cpu; | ||
| 187 | kmemtrace_array = tr; | 186 | kmemtrace_array = tr; |
| 188 | 187 | ||
| 189 | for_each_cpu_mask(cpu, cpu_possible_map) | 188 | tracing_reset_online_cpus(tr); |
| 190 | tracing_reset(tr, cpu); | ||
| 191 | 189 | ||
| 192 | kmemtrace_start_probes(); | 190 | kmemtrace_start_probes(); |
| 193 | 191 | ||
| @@ -239,12 +237,52 @@ struct kmemtrace_user_event_alloc { | |||
| 239 | }; | 237 | }; |
| 240 | 238 | ||
| 241 | static enum print_line_t | 239 | static enum print_line_t |
| 242 | kmemtrace_print_alloc_user(struct trace_iterator *iter, | 240 | kmemtrace_print_alloc(struct trace_iterator *iter, int flags) |
| 243 | struct kmemtrace_alloc_entry *entry) | ||
| 244 | { | 241 | { |
| 245 | struct kmemtrace_user_event_alloc *ev_alloc; | ||
| 246 | struct trace_seq *s = &iter->seq; | 242 | struct trace_seq *s = &iter->seq; |
| 243 | struct kmemtrace_alloc_entry *entry; | ||
| 244 | int ret; | ||
| 245 | |||
| 246 | trace_assign_type(entry, iter->ent); | ||
| 247 | |||
| 248 | ret = trace_seq_printf(s, "type_id %d call_site %pF ptr %lu " | ||
| 249 | "bytes_req %lu bytes_alloc %lu gfp_flags %lu node %d\n", | ||
| 250 | entry->type_id, (void *)entry->call_site, (unsigned long)entry->ptr, | ||
| 251 | (unsigned long)entry->bytes_req, (unsigned long)entry->bytes_alloc, | ||
| 252 | (unsigned long)entry->gfp_flags, entry->node); | ||
| 253 | |||
| 254 | if (!ret) | ||
| 255 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 256 | return TRACE_TYPE_HANDLED; | ||
| 257 | } | ||
| 258 | |||
| 259 | static enum print_line_t | ||
| 260 | kmemtrace_print_free(struct trace_iterator *iter, int flags) | ||
| 261 | { | ||
| 262 | struct trace_seq *s = &iter->seq; | ||
| 263 | struct kmemtrace_free_entry *entry; | ||
| 264 | int ret; | ||
| 265 | |||
| 266 | trace_assign_type(entry, iter->ent); | ||
| 267 | |||
| 268 | ret = trace_seq_printf(s, "type_id %d call_site %pF ptr %lu\n", | ||
| 269 | entry->type_id, (void *)entry->call_site, | ||
| 270 | (unsigned long)entry->ptr); | ||
| 271 | |||
| 272 | if (!ret) | ||
| 273 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 274 | return TRACE_TYPE_HANDLED; | ||
| 275 | } | ||
| 276 | |||
| 277 | static enum print_line_t | ||
| 278 | kmemtrace_print_alloc_user(struct trace_iterator *iter, int flags) | ||
| 279 | { | ||
| 280 | struct trace_seq *s = &iter->seq; | ||
| 281 | struct kmemtrace_alloc_entry *entry; | ||
| 247 | struct kmemtrace_user_event *ev; | 282 | struct kmemtrace_user_event *ev; |
| 283 | struct kmemtrace_user_event_alloc *ev_alloc; | ||
| 284 | |||
| 285 | trace_assign_type(entry, iter->ent); | ||
| 248 | 286 | ||
| 249 | ev = trace_seq_reserve(s, sizeof(*ev)); | 287 | ev = trace_seq_reserve(s, sizeof(*ev)); |
| 250 | if (!ev) | 288 | if (!ev) |
| @@ -271,12 +309,14 @@ kmemtrace_print_alloc_user(struct trace_iterator *iter, | |||
| 271 | } | 309 | } |
| 272 | 310 | ||
| 273 | static enum print_line_t | 311 | static enum print_line_t |
| 274 | kmemtrace_print_free_user(struct trace_iterator *iter, | 312 | kmemtrace_print_free_user(struct trace_iterator *iter, int flags) |
| 275 | struct kmemtrace_free_entry *entry) | ||
| 276 | { | 313 | { |
| 277 | struct trace_seq *s = &iter->seq; | 314 | struct trace_seq *s = &iter->seq; |
| 315 | struct kmemtrace_free_entry *entry; | ||
| 278 | struct kmemtrace_user_event *ev; | 316 | struct kmemtrace_user_event *ev; |
| 279 | 317 | ||
| 318 | trace_assign_type(entry, iter->ent); | ||
| 319 | |||
| 280 | ev = trace_seq_reserve(s, sizeof(*ev)); | 320 | ev = trace_seq_reserve(s, sizeof(*ev)); |
| 281 | if (!ev) | 321 | if (!ev) |
| 282 | return TRACE_TYPE_PARTIAL_LINE; | 322 | return TRACE_TYPE_PARTIAL_LINE; |
| @@ -294,12 +334,14 @@ kmemtrace_print_free_user(struct trace_iterator *iter, | |||
| 294 | 334 | ||
| 295 | /* The two other following provide a more minimalistic output */ | 335 | /* The two other following provide a more minimalistic output */ |
| 296 | static enum print_line_t | 336 | static enum print_line_t |
| 297 | kmemtrace_print_alloc_compress(struct trace_iterator *iter, | 337 | kmemtrace_print_alloc_compress(struct trace_iterator *iter) |
| 298 | struct kmemtrace_alloc_entry *entry) | ||
| 299 | { | 338 | { |
| 339 | struct kmemtrace_alloc_entry *entry; | ||
| 300 | struct trace_seq *s = &iter->seq; | 340 | struct trace_seq *s = &iter->seq; |
| 301 | int ret; | 341 | int ret; |
| 302 | 342 | ||
| 343 | trace_assign_type(entry, iter->ent); | ||
| 344 | |||
| 303 | /* Alloc entry */ | 345 | /* Alloc entry */ |
| 304 | ret = trace_seq_printf(s, " + "); | 346 | ret = trace_seq_printf(s, " + "); |
| 305 | if (!ret) | 347 | if (!ret) |
| @@ -345,29 +387,24 @@ kmemtrace_print_alloc_compress(struct trace_iterator *iter, | |||
| 345 | if (!ret) | 387 | if (!ret) |
| 346 | return TRACE_TYPE_PARTIAL_LINE; | 388 | return TRACE_TYPE_PARTIAL_LINE; |
| 347 | 389 | ||
| 348 | /* Node */ | 390 | /* Node and call site*/ |
| 349 | ret = trace_seq_printf(s, "%4d ", entry->node); | 391 | ret = trace_seq_printf(s, "%4d %pf\n", entry->node, |
| 350 | if (!ret) | 392 | (void *)entry->call_site); |
| 351 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 352 | |||
| 353 | /* Call site */ | ||
| 354 | ret = seq_print_ip_sym(s, entry->call_site, 0); | ||
| 355 | if (!ret) | 393 | if (!ret) |
| 356 | return TRACE_TYPE_PARTIAL_LINE; | 394 | return TRACE_TYPE_PARTIAL_LINE; |
| 357 | 395 | ||
| 358 | if (!trace_seq_printf(s, "\n")) | ||
| 359 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 360 | |||
| 361 | return TRACE_TYPE_HANDLED; | 396 | return TRACE_TYPE_HANDLED; |
| 362 | } | 397 | } |
| 363 | 398 | ||
| 364 | static enum print_line_t | 399 | static enum print_line_t |
| 365 | kmemtrace_print_free_compress(struct trace_iterator *iter, | 400 | kmemtrace_print_free_compress(struct trace_iterator *iter) |
| 366 | struct kmemtrace_free_entry *entry) | ||
| 367 | { | 401 | { |
| 402 | struct kmemtrace_free_entry *entry; | ||
| 368 | struct trace_seq *s = &iter->seq; | 403 | struct trace_seq *s = &iter->seq; |
| 369 | int ret; | 404 | int ret; |
| 370 | 405 | ||
| 406 | trace_assign_type(entry, iter->ent); | ||
| 407 | |||
| 371 | /* Free entry */ | 408 | /* Free entry */ |
| 372 | ret = trace_seq_printf(s, " - "); | 409 | ret = trace_seq_printf(s, " - "); |
| 373 | if (!ret) | 410 | if (!ret) |
| @@ -401,19 +438,11 @@ kmemtrace_print_free_compress(struct trace_iterator *iter, | |||
| 401 | if (!ret) | 438 | if (!ret) |
| 402 | return TRACE_TYPE_PARTIAL_LINE; | 439 | return TRACE_TYPE_PARTIAL_LINE; |
| 403 | 440 | ||
| 404 | /* Skip node */ | 441 | /* Skip node and print call site*/ |
| 405 | ret = trace_seq_printf(s, " "); | 442 | ret = trace_seq_printf(s, " %pf\n", (void *)entry->call_site); |
| 406 | if (!ret) | 443 | if (!ret) |
| 407 | return TRACE_TYPE_PARTIAL_LINE; | 444 | return TRACE_TYPE_PARTIAL_LINE; |
| 408 | 445 | ||
| 409 | /* Call site */ | ||
| 410 | ret = seq_print_ip_sym(s, entry->call_site, 0); | ||
| 411 | if (!ret) | ||
| 412 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 413 | |||
| 414 | if (!trace_seq_printf(s, "\n")) | ||
| 415 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 416 | |||
| 417 | return TRACE_TYPE_HANDLED; | 446 | return TRACE_TYPE_HANDLED; |
| 418 | } | 447 | } |
| 419 | 448 | ||
| @@ -421,32 +450,31 @@ static enum print_line_t kmemtrace_print_line(struct trace_iterator *iter) | |||
| 421 | { | 450 | { |
| 422 | struct trace_entry *entry = iter->ent; | 451 | struct trace_entry *entry = iter->ent; |
| 423 | 452 | ||
| 424 | switch (entry->type) { | 453 | if (!(kmem_tracer_flags.val & TRACE_KMEM_OPT_MINIMAL)) |
| 425 | case TRACE_KMEM_ALLOC: { | 454 | return TRACE_TYPE_UNHANDLED; |
| 426 | struct kmemtrace_alloc_entry *field; | ||
| 427 | |||
| 428 | trace_assign_type(field, entry); | ||
| 429 | if (kmem_tracer_flags.val & TRACE_KMEM_OPT_MINIMAL) | ||
| 430 | return kmemtrace_print_alloc_compress(iter, field); | ||
| 431 | else | ||
| 432 | return kmemtrace_print_alloc_user(iter, field); | ||
| 433 | } | ||
| 434 | |||
| 435 | case TRACE_KMEM_FREE: { | ||
| 436 | struct kmemtrace_free_entry *field; | ||
| 437 | |||
| 438 | trace_assign_type(field, entry); | ||
| 439 | if (kmem_tracer_flags.val & TRACE_KMEM_OPT_MINIMAL) | ||
| 440 | return kmemtrace_print_free_compress(iter, field); | ||
| 441 | else | ||
| 442 | return kmemtrace_print_free_user(iter, field); | ||
| 443 | } | ||
| 444 | 455 | ||
| 456 | switch (entry->type) { | ||
| 457 | case TRACE_KMEM_ALLOC: | ||
| 458 | return kmemtrace_print_alloc_compress(iter); | ||
| 459 | case TRACE_KMEM_FREE: | ||
| 460 | return kmemtrace_print_free_compress(iter); | ||
| 445 | default: | 461 | default: |
| 446 | return TRACE_TYPE_UNHANDLED; | 462 | return TRACE_TYPE_UNHANDLED; |
| 447 | } | 463 | } |
| 448 | } | 464 | } |
| 449 | 465 | ||
| 466 | static struct trace_event kmem_trace_alloc = { | ||
| 467 | .type = TRACE_KMEM_ALLOC, | ||
| 468 | .trace = kmemtrace_print_alloc, | ||
| 469 | .binary = kmemtrace_print_alloc_user, | ||
| 470 | }; | ||
| 471 | |||
| 472 | static struct trace_event kmem_trace_free = { | ||
| 473 | .type = TRACE_KMEM_FREE, | ||
| 474 | .trace = kmemtrace_print_free, | ||
| 475 | .binary = kmemtrace_print_free_user, | ||
| 476 | }; | ||
| 477 | |||
| 450 | static struct tracer kmem_tracer __read_mostly = { | 478 | static struct tracer kmem_tracer __read_mostly = { |
| 451 | .name = "kmemtrace", | 479 | .name = "kmemtrace", |
| 452 | .init = kmem_trace_init, | 480 | .init = kmem_trace_init, |
| @@ -463,6 +491,21 @@ void kmemtrace_init(void) | |||
| 463 | 491 | ||
| 464 | static int __init init_kmem_tracer(void) | 492 | static int __init init_kmem_tracer(void) |
| 465 | { | 493 | { |
| 466 | return register_tracer(&kmem_tracer); | 494 | if (!register_ftrace_event(&kmem_trace_alloc)) { |
| 495 | pr_warning("Warning: could not register kmem events\n"); | ||
| 496 | return 1; | ||
| 497 | } | ||
| 498 | |||
| 499 | if (!register_ftrace_event(&kmem_trace_free)) { | ||
| 500 | pr_warning("Warning: could not register kmem events\n"); | ||
| 501 | return 1; | ||
| 502 | } | ||
| 503 | |||
| 504 | if (!register_tracer(&kmem_tracer)) { | ||
| 505 | pr_warning("Warning: could not register the kmem tracer\n"); | ||
| 506 | return 1; | ||
| 507 | } | ||
| 508 | |||
| 509 | return 0; | ||
| 467 | } | 510 | } |
| 468 | device_initcall(init_kmem_tracer); | 511 | device_initcall(init_kmem_tracer); |
