lib/ref_tracker.c

Source file repositories/reference/linux-study-clean/lib/ref_tracker.c

File Facts

System
Linux kernel
Corpus path
lib/ref_tracker.c
Extension
.c
Size
14008 bytes
Lines
534
Domain
Kernel Services
Bucket
lib
Inferred role
Kernel Services: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations ref_tracker_debugfs_fops = {
	.owner		= THIS_MODULE,
	.open		= ref_tracker_debugfs_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
};

/**
 * ref_tracker_dir_debugfs - create debugfs file for ref_tracker_dir
 * @dir: ref_tracker_dir to be associated with debugfs file
 *
 * In most cases, a debugfs file will be created automatically for every
 * ref_tracker_dir. If the object was created before debugfs is brought up
 * then that may fail. In those cases, it is safe to call this at a later
 * time to create the file.
 */
void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir)
{
	char name[NAME_MAX + 1];
	struct dentry *dentry;
	int ret;

	/* No-op if already created */
	dentry = xa_load(&debugfs_dentries, (unsigned long)dir);
	if (dentry && !xa_is_err(dentry))
		return;

	ret = snprintf(name, sizeof(name), "%s@%p", dir->class, dir);
	name[sizeof(name) - 1] = '\0';

	if (ret < sizeof(name)) {
		dentry = debugfs_create_file(name, S_IFREG | 0400,
					     ref_tracker_debug_dir, dir,
					     &ref_tracker_debugfs_fops);
		if (!IS_ERR(dentry)) {
			void *old;

			old = xa_store_irq(&debugfs_dentries, (unsigned long)dir,
					   dentry, GFP_KERNEL);

			if (xa_is_err(old))
				debugfs_remove(dentry);
			else
				WARN_ON_ONCE(old);
		}
	}
}
EXPORT_SYMBOL(ref_tracker_dir_debugfs);

void __ostream_printf ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...)
{
	char name[NAME_MAX + 1];
	struct dentry *symlink, *dentry;
	va_list args;
	int ret;

	symlink = xa_load(&debugfs_symlinks, (unsigned long)dir);
	dentry = xa_load(&debugfs_dentries, (unsigned long)dir);

	/* Already created?*/
	if (symlink && !xa_is_err(symlink))
		return;

	if (!dentry || xa_is_err(dentry))
		return;

	va_start(args, fmt);
	ret = vsnprintf(name, sizeof(name), fmt, args);
	va_end(args);
	name[sizeof(name) - 1] = '\0';

	if (ret < sizeof(name)) {
		symlink = debugfs_create_symlink(name, ref_tracker_debug_dir,
						 dentry->d_name.name);
		if (!IS_ERR(symlink)) {
			void *old;

			old = xa_store_irq(&debugfs_symlinks, (unsigned long)dir,
					   symlink, GFP_KERNEL);
			if (xa_is_err(old))
				debugfs_remove(symlink);
			else
				WARN_ON_ONCE(old);
		}
	}
}
EXPORT_SYMBOL(ref_tracker_dir_symlink);

static void debugfs_reap_work(struct work_struct *work)

Annotation

Implementation Notes