Pull tracing fixes from Steven Rostedt: - Fix the "bytes" output of the per_cpu stat file The tracefs/per_cpu/cpu*/stats "bytes" was giving bogus values as the accounting was not accurate. It is suppose to show how many used bytes are still in the ring buffer, but even when the ring buffer was empty it would still show there were bytes used. - Fix a bug in eventfs where reading a dynamic event directory (open) and then creating a dynamic event that goes into that diretory screws up the accounting. On close, the newly created event dentry will get a "dput" without ever having a "dget" done for it. The fix is to allocate an array on dir open to save what dentries were actually "dget" on, and what ones to "dput" on close. * tag 'trace-v6.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: eventfs: Remember what dentries were created on dir open ring-buffer: Fix bytes info in per_cpu buffer stats
Unified · Split
| @@ -70,6 +70,7 @@ static struct dentry *eventfs_root_lookup(struct inode *dir, · 69 unmodified lines | |||
| 70 | struct dentry *dentry, | 70 | struct dentry *dentry, |
| 71 | unsigned int flags); | 71 | unsigned int flags); |
| 72 | static int dcache_dir_open_wrapper(struct inode *inode, struct file *file); | 72 | static int dcache_dir_open_wrapper(struct inode *inode, struct file *file); |
| 73 | static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx); | ||
| 73 | static int eventfs_release(struct inode *inode, struct file *file); | 74 | static int eventfs_release(struct inode *inode, struct file *file); |
| 74 | 75 | ||
| 75 | static const struct inode_operations eventfs_root_dir_inode_operations = { | 76 | static const struct inode_operations eventfs_root_dir_inode_operations = { |
| @@ -79,7 +80,7 @@ static const struct inode_operations eventfs_root_dir_inode_operations = { · 3 unmodified lines | |||
| 79 | static const struct file_operations eventfs_file_operations = { | 80 | static const struct file_operations eventfs_file_operations = { |
| 80 | .open = dcache_dir_open_wrapper, | 81 | .open = dcache_dir_open_wrapper, |
| 81 | .read = generic_read_dir, | 82 | .read = generic_read_dir, |
| 82 | .iterate_shared = dcache_readdir, | 83 | .iterate_shared = dcache_readdir_wrapper, |
| 83 | .llseek = generic_file_llseek, | 84 | .llseek = generic_file_llseek, |
| 84 | .release = eventfs_release, | 85 | .release = eventfs_release, |
| 85 | }; | 86 | }; |
| @@ -396,6 +397,11 @@ static struct dentry *eventfs_root_lookup(struct inode *dir, · 310 unmodified lines | |||
| 396 | return ret; | 397 | return ret; |
| 397 | } | 398 | } |
| 398 | 399 | ||
| 400 | struct dentry_list { | ||
| 401 | void *cursor; | ||
| 402 | struct dentry **dentries; | ||
| 403 | }; | ||
| 404 | |||
| 399 | /** | 405 | /** |
| 400 | * eventfs_release - called to release eventfs file/dir | 406 | * eventfs_release - called to release eventfs file/dir |
| 401 | * @inode: inode to be released | 407 | * @inode: inode to be released |
| @@ -404,26 +410,25 @@ static struct dentry *eventfs_root_lookup(struct inode *dir, · 2 unmodified lines | |||
| 404 | static int eventfs_release(struct inode *inode, struct file *file) | 410 | static int eventfs_release(struct inode *inode, struct file *file) |
| 405 | { | 411 | { |
| 406 | struct tracefs_inode *ti; | 412 | struct tracefs_inode *ti; |
| 407 | struct eventfs_inode *ei; | 413 | struct dentry_list *dlist = file->private_data; |
| 408 | struct eventfs_file *ef; | 414 | void *cursor; |
| 409 | struct dentry *dentry; | 415 | int i; |
| 410 | int idx; | ||
| 411 | 416 | ||
| 412 | ti = get_tracefs(inode); | 417 | ti = get_tracefs(inode); |
| 413 | if (!(ti->flags & TRACEFS_EVENT_INODE)) | 418 | if (!(ti->flags & TRACEFS_EVENT_INODE)) |
| 414 | return -EINVAL; | 419 | return -EINVAL; |
| 415 | 420 | ||
| 416 | ei = ti->private; | 421 | if (WARN_ON_ONCE(!dlist)) |
| 417 | idx = srcu_read_lock(&eventfs_srcu); | 422 | return -EINVAL; |
| 418 | list_for_each_entry_srcu(ef, &ei->e_top_files, list, | 423 | |
| 419 | srcu_read_lock_held(&eventfs_srcu)) { | 424 | for (i = 0; dlist->dentries[i]; i++) { |
| 420 | mutex_lock(&eventfs_mutex); | 425 | dput(dlist->dentries[i]); |
| 421 | dentry = ef->dentry; | ||
| 422 | mutex_unlock(&eventfs_mutex); | ||
| 423 | if (dentry) | ||
| 424 | dput(dentry); | ||
| 425 | } | 426 | } |
| 426 | srcu_read_unlock(&eventfs_srcu, idx); | 427 | |
| 428 | cursor = dlist->cursor; | ||
| 429 | kfree(dlist->dentries); | ||
| 430 | kfree(dlist); | ||
| 431 | file->private_data = cursor; | ||
| 427 | return dcache_dir_close(inode, file); | 432 | return dcache_dir_close(inode, file); |
| 428 | } | 433 | } |
| 429 | 434 | ||
| @@ -442,22 +447,70 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file) · 12 unmodified lines | |||
| 442 | struct tracefs_inode *ti; | 447 | struct tracefs_inode *ti; |
| 443 | struct eventfs_inode *ei; | 448 | struct eventfs_inode *ei; |
| 444 | struct eventfs_file *ef; | 449 | struct eventfs_file *ef; |
| 450 | struct dentry_list *dlist; | ||
| 451 | struct dentry **dentries = NULL; | ||
| 445 | struct dentry *dentry = file_dentry(file); | 452 | struct dentry *dentry = file_dentry(file); |
| 453 | struct dentry *d; | ||
| 446 | struct inode *f_inode = file_inode(file); | 454 | struct inode *f_inode = file_inode(file); |
| 455 | int cnt = 0; | ||
| 447 | int idx; | 456 | int idx; |
| 457 | int ret; | ||
| 448 | 458 | ||
| 449 | ti = get_tracefs(f_inode); | 459 | ti = get_tracefs(f_inode); |
| 450 | if (!(ti->flags & TRACEFS_EVENT_INODE)) | 460 | if (!(ti->flags & TRACEFS_EVENT_INODE)) |
| 451 | return -EINVAL; | 461 | return -EINVAL; |
| 452 | 462 | ||
| 463 | if (WARN_ON_ONCE(file->private_data)) | ||
| 464 | return -EINVAL; | ||
| 465 | |||
| 466 | dlist = kmalloc(sizeof(*dlist), GFP_KERNEL); | ||
| 467 | if (!dlist) | ||
| 468 | return -ENOMEM; | ||
| 469 | |||
| 453 | ei = ti->private; | 470 | ei = ti->private; |
| 454 | idx = srcu_read_lock(&eventfs_srcu); | 471 | idx = srcu_read_lock(&eventfs_srcu); |
| 455 | list_for_each_entry_srcu(ef, &ei->e_top_files, list, | 472 | list_for_each_entry_srcu(ef, &ei->e_top_files, list, |
| 456 | srcu_read_lock_held(&eventfs_srcu)) { | 473 | srcu_read_lock_held(&eventfs_srcu)) { |
| 457 | create_dentry(ef, dentry, false); | 474 | d = create_dentry(ef, dentry, false); |
| 475 | if (d) { | ||
| 476 | struct dentry **tmp; | ||
| 477 | |||
| 478 | tmp = krealloc(dentries, sizeof(d) * (cnt + 2), GFP_KERNEL); | ||
| 479 | if (!tmp) | ||
| 480 | break; | ||
| 481 | tmp[cnt] = d; | ||
| 482 | tmp[cnt + 1] = NULL; | ||
| 483 | cnt++; | ||
| 484 | dentries = tmp; | ||
| 485 | } | ||
| 458 | } | 486 | } |
| 459 | srcu_read_unlock(&eventfs_srcu, idx); | 487 | srcu_read_unlock(&eventfs_srcu, idx); |
| 460 | return dcache_dir_open(inode, file); | 488 | ret = dcache_dir_open(inode, file); |
| 489 | |||
| 490 | /* | ||
| 491 | * dcache_dir_open() sets file->private_data to a dentry cursor. | ||
| 492 | * Need to save that but also save all the dentries that were | ||
| 493 | * opened by this function. | ||
| 494 | */ | ||
| 495 | dlist->cursor = file->private_data; | ||
| 496 | dlist->dentries = dentries; | ||
| 497 | file->private_data = dlist; | ||
| 498 | return ret; | ||
| 499 | } | ||
| 500 | |||
| 501 | /* | ||
| 502 | * This just sets the file->private_data back to the cursor and back. | ||
| 503 | */ | ||
| 504 | static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx) | ||
| 505 | { | ||
| 506 | struct dentry_list *dlist = file->private_data; | ||
| 507 | int ret; | ||
| 508 | |||
| 509 | file->private_data = dlist->cursor; | ||
| 510 | ret = dcache_readdir(file, ctx); | ||
| 511 | dlist->cursor = file->private_data; | ||
| 512 | file->private_data = dlist; | ||
| 513 | return ret; | ||
| 461 | } | 514 | } |
| 462 | 515 | ||
| 463 | /** | 516 | /** |
| @@ -354,6 +354,11 @@ static void rb_init_page(struct buffer_data_page *bpage) · 353 unmodified lines | |||
| 354 | local_set(&bpage->commit, 0); | 354 | local_set(&bpage->commit, 0); |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | static __always_inline unsigned int rb_page_commit(struct buffer_page *bpage) | ||
| 358 | { | ||
| 359 | return local_read(&bpage->page->commit); | ||
| 360 | } | ||
| 361 | |||
| 357 | static void free_buffer_page(struct buffer_page *bpage) | 362 | static void free_buffer_page(struct buffer_page *bpage) |
| 358 | { | 363 | { |
| 359 | free_page((unsigned long)bpage->page); | 364 | free_page((unsigned long)bpage->page); |
| @@ -2003,7 +2008,7 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages) · 1643 unmodified lines | |||
| 2003 | * Increment overrun to account for the lost events. | 2008 | * Increment overrun to account for the lost events. |
| 2004 | */ | 2009 | */ |
| 2005 | local_add(page_entries, &cpu_buffer->overrun); | 2010 | local_add(page_entries, &cpu_buffer->overrun); |
| 2006 | local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes); | 2011 | local_sub(rb_page_commit(to_remove_page), &cpu_buffer->entries_bytes); |
| 2007 | local_inc(&cpu_buffer->pages_lost); | 2012 | local_inc(&cpu_buffer->pages_lost); |
| 2008 | } | 2013 | } |
| 2009 | 2014 | ||
| @@ -2367,11 +2372,6 @@ rb_reader_event(struct ring_buffer_per_cpu *cpu_buffer) · 357 unmodified lines | |||
| 2367 | cpu_buffer->reader_page->read); | 2372 | cpu_buffer->reader_page->read); |
| 2368 | } | 2373 | } |
| 2369 | 2374 | ||
| 2370 | static __always_inline unsigned rb_page_commit(struct buffer_page *bpage) | ||
| 2371 | { | ||
| 2372 | return local_read(&bpage->page->commit); | ||
| 2373 | } | ||
| 2374 | |||
| 2375 | static struct ring_buffer_event * | 2375 | static struct ring_buffer_event * |
| 2376 | rb_iter_head_event(struct ring_buffer_iter *iter) | 2376 | rb_iter_head_event(struct ring_buffer_iter *iter) |
| 2377 | { | 2377 | { |
| @@ -2517,7 +2517,7 @@ rb_handle_head_page(struct ring_buffer_per_cpu *cpu_buffer, · 139 unmodified lines | |||
| 2517 | * the counters. | 2517 | * the counters. |
| 2518 | */ | 2518 | */ |
| 2519 | local_add(entries, &cpu_buffer->overrun); | 2519 | local_add(entries, &cpu_buffer->overrun); |
| 2520 | local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes); | 2520 | local_sub(rb_page_commit(next_page), &cpu_buffer->entries_bytes); |
| 2521 | local_inc(&cpu_buffer->pages_lost); | 2521 | local_inc(&cpu_buffer->pages_lost); |
| 2522 | 2522 | ||
| 2523 | /* | 2523 | /* |
| @@ -2660,9 +2660,6 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer, · 136 unmodified lines | |||
| 2660 | 2660 | ||
| 2661 | event = __rb_page_index(tail_page, tail); | 2661 | event = __rb_page_index(tail_page, tail); |
| 2662 | 2662 | ||
| 2663 | /* account for padding bytes */ | ||
| 2664 | local_add(BUF_PAGE_SIZE - tail, &cpu_buffer->entries_bytes); | ||
| 2665 | |||
| 2666 | /* | 2663 | /* |
| 2667 | * Save the original length to the meta data. | 2664 | * Save the original length to the meta data. |
| 2668 | * This will be used by the reader to add lost event | 2665 | * This will be used by the reader to add lost event |
| @@ -2676,7 +2673,8 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer, · 7 unmodified lines | |||
| 2676 | * write counter enough to allow another writer to slip | 2673 | * write counter enough to allow another writer to slip |
| 2677 | * in on this page. | 2674 | * in on this page. |
| 2678 | * We put in a discarded commit instead, to make sure | 2675 | * We put in a discarded commit instead, to make sure |
| 2679 | * that this space is not used again. | 2676 | * that this space is not used again, and this space will |
| 2677 | * not be accounted into 'entries_bytes'. | ||
| 2680 | * | 2678 | * |
| 2681 | * If we are less than the minimum size, we don't need to | 2679 | * If we are less than the minimum size, we don't need to |
| 2682 | * worry about it. | 2680 | * worry about it. |
| @@ -2701,6 +2699,9 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer, · 18 unmodified lines | |||
| 2701 | /* time delta must be non zero */ | 2699 | /* time delta must be non zero */ |
| 2702 | event->time_delta = 1; | 2700 | event->time_delta = 1; |
| 2703 | 2701 | ||
| 2702 | /* account for padding bytes */ | ||
| 2703 | local_add(BUF_PAGE_SIZE - tail, &cpu_buffer->entries_bytes); | ||
| 2704 | |||
| 2704 | /* Make sure the padding is visible before the tail_page->write update */ | 2705 | /* Make sure the padding is visible before the tail_page->write update */ |
| 2705 | smp_wmb(); | 2706 | smp_wmb(); |
| 2706 | 2707 | ||
| @@ -4215,7 +4216,7 @@ u64 ring_buffer_oldest_event_ts(struct trace_buffer *buffer, int cpu) · 1508 unmodified lines | |||
| 4215 | EXPORT_SYMBOL_GPL(ring_buffer_oldest_event_ts); | 4216 | EXPORT_SYMBOL_GPL(ring_buffer_oldest_event_ts); |
| 4216 | 4217 | ||
| 4217 | /** | 4218 | /** |
| 4218 | * ring_buffer_bytes_cpu - get the number of bytes consumed in a cpu buffer | 4219 | * ring_buffer_bytes_cpu - get the number of bytes unconsumed in a cpu buffer |
| 4219 | * @buffer: The ring buffer | 4220 | * @buffer: The ring buffer |
| 4220 | * @cpu: The per CPU buffer to read from. | 4221 | * @cpu: The per CPU buffer to read from. |
| 4221 | */ | 4222 | */ |
| @@ -4723,6 +4724,7 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer) · 501 unmodified lines | |||
| 4723 | 4724 | ||
| 4724 | length = rb_event_length(event); | 4725 | length = rb_event_length(event); |
| 4725 | cpu_buffer->reader_page->read += length; | 4726 | cpu_buffer->reader_page->read += length; |
| 4727 | cpu_buffer->read_bytes += length; | ||
| 4726 | } | 4728 | } |
| 4727 | 4729 | ||
| 4728 | static void rb_advance_iter(struct ring_buffer_iter *iter) | 4730 | static void rb_advance_iter(struct ring_buffer_iter *iter) |
| @@ -5816,7 +5818,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer, · 1087 unmodified lines | |||
| 5816 | } else { | 5818 | } else { |
| 5817 | /* update the entry counter */ | 5819 | /* update the entry counter */ |
| 5818 | cpu_buffer->read += rb_page_entries(reader); | 5820 | cpu_buffer->read += rb_page_entries(reader); |
| 5819 | cpu_buffer->read_bytes += BUF_PAGE_SIZE; | 5821 | cpu_buffer->read_bytes += rb_page_commit(reader); |
| 5820 | 5822 | ||
| 5821 | /* swap the pages */ | 5823 | /* swap the pages */ |
| 5822 | rb_init_page(bpage); | 5824 | rb_init_page(bpage); |