Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ref_tracker: add a way to create a symlink to the ref_tracker_dir debugfs file

Add the ability for a subsystem to add a user-friendly symlink that
points to a ref_tracker_dir's debugfs file. Add a separate
debugfs_symlinks xarray and use that to track symlinks. The reaper
workqueue job will remove symlinks before their corresponding dentries.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20250618-reftrack-dbgfs-v15-7-24fc37ead144@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Jeff Layton and committed by
Jakub Kicinski
d04992dc 65b584f5

+61
+11
include/linux/ref_tracker.h
··· 29 29 #ifdef CONFIG_DEBUG_FS 30 30 31 31 void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir); 32 + void ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...); 32 33 33 34 #else /* CONFIG_DEBUG_FS */ 34 35 35 36 static inline void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir) 37 + { 38 + } 39 + 40 + static inline __ostream_printf 41 + void ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...) 36 42 { 37 43 } 38 44 ··· 88 82 } 89 83 90 84 static inline void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir) 85 + { 86 + } 87 + 88 + static inline __ostream_printf 89 + void ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...) 91 90 { 92 91 } 93 92
+50
lib/ref_tracker.c
··· 44 44 * dentries asynchronously. 45 45 */ 46 46 static struct xarray debugfs_dentries; 47 + static struct xarray debugfs_symlinks; 47 48 static struct work_struct debugfs_reap_worker; 48 49 49 50 #define REF_TRACKER_DIR_DEAD XA_MARK_0 ··· 55 54 xa_lock_irqsave(&debugfs_dentries, flags); 56 55 __xa_set_mark(&debugfs_dentries, (unsigned long)dir, REF_TRACKER_DIR_DEAD); 57 56 xa_unlock_irqrestore(&debugfs_dentries, flags); 57 + 58 + xa_lock_irqsave(&debugfs_symlinks, flags); 59 + __xa_set_mark(&debugfs_symlinks, (unsigned long)dir, REF_TRACKER_DIR_DEAD); 60 + xa_unlock_irqrestore(&debugfs_symlinks, flags); 58 61 59 62 schedule_work(&debugfs_reap_worker); 60 63 } ··· 456 451 } 457 452 EXPORT_SYMBOL(ref_tracker_dir_debugfs); 458 453 454 + void __ostream_printf ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...) 455 + { 456 + char name[NAME_MAX + 1]; 457 + struct dentry *symlink, *dentry; 458 + va_list args; 459 + int ret; 460 + 461 + symlink = xa_load(&debugfs_symlinks, (unsigned long)dir); 462 + dentry = xa_load(&debugfs_dentries, (unsigned long)dir); 463 + 464 + /* Already created?*/ 465 + if (symlink && !xa_is_err(symlink)) 466 + return; 467 + 468 + if (!dentry || xa_is_err(dentry)) 469 + return; 470 + 471 + va_start(args, fmt); 472 + ret = vsnprintf(name, sizeof(name), fmt, args); 473 + va_end(args); 474 + name[sizeof(name) - 1] = '\0'; 475 + 476 + if (ret < sizeof(name)) { 477 + symlink = debugfs_create_symlink(name, ref_tracker_debug_dir, 478 + dentry->d_name.name); 479 + if (!IS_ERR(symlink)) { 480 + void *old; 481 + 482 + old = xa_store_irq(&debugfs_symlinks, (unsigned long)dir, 483 + symlink, GFP_KERNEL); 484 + if (xa_is_err(old)) 485 + debugfs_remove(symlink); 486 + else 487 + WARN_ON_ONCE(old); 488 + } 489 + } 490 + } 491 + EXPORT_SYMBOL(ref_tracker_dir_symlink); 492 + 459 493 static void debugfs_reap_work(struct work_struct *work) 460 494 { 461 495 struct dentry *dentry; ··· 503 459 504 460 do { 505 461 reaped = false; 462 + xa_for_each_marked(&debugfs_symlinks, index, dentry, REF_TRACKER_DIR_DEAD) { 463 + xa_erase_irq(&debugfs_symlinks, index); 464 + debugfs_remove(dentry); 465 + reaped = true; 466 + } 506 467 xa_for_each_marked(&debugfs_dentries, index, dentry, REF_TRACKER_DIR_DEAD) { 507 468 xa_erase_irq(&debugfs_dentries, index); 508 469 debugfs_remove(dentry); ··· 520 471 { 521 472 INIT_WORK(&debugfs_reap_worker, debugfs_reap_work); 522 473 xa_init_flags(&debugfs_dentries, XA_FLAGS_LOCK_IRQ); 474 + xa_init_flags(&debugfs_symlinks, XA_FLAGS_LOCK_IRQ); 523 475 ref_tracker_debug_dir = debugfs_create_dir("ref_tracker", NULL); 524 476 return 0; 525 477 }