fs/filesystems.c

Source file repositories/reference/linux-study-clean/fs/filesystems.c

File Facts

System
Linux kernel
Corpus path
fs/filesystems.c
Extension
.c
Size
9775 bytes
Lines
414
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: syscall or user/kernel boundary
Status
core implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

SYSCALL_DEFINE3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2)
{
	int retval = -EINVAL;

	switch (option) {
		case 1:
			retval = fs_index((const char __user *) arg1);
			break;

		case 2:
			retval = fs_name(arg1, (char __user *) arg2);
			break;

		case 3:
			retval = fs_maxindex();
			break;
	}
	return retval;
}
#endif

int __init list_bdev_fs_names(char *buf, size_t size)
{
	struct file_system_type *p;
	size_t len;
	int count = 0;

	guard(rcu)();
	hlist_for_each_entry_rcu(p, &file_systems, list) {
		if (!(p->fs_flags & FS_REQUIRES_DEV))
			continue;
		len = strlen(p->name) + 1;
		if (len > size) {
			pr_warn("%s: truncating file system list\n", __func__);
			break;
		}
		memcpy(buf, p->name, len);
		buf += len;
		size -= len;
		count++;
	}
	return count;
}

#ifdef CONFIG_PROC_FS
static void invalidate_filesystems_string(void)
{
	struct file_systems_string *old;

	lockdep_assert_held_write(&file_systems_lock);
	file_systems_gen++;
	old = rcu_replace_pointer(file_systems_string, NULL,
			   lockdep_is_held(&file_systems_lock));
	if (old)
		kfree_rcu(old, rcu);
}

static __cold noinline int regen_filesystems_string(void)
{
	struct file_system_type *p;
	struct file_systems_string *old, *new;
	size_t newlen, usedlen;
	unsigned long gen;

retry:
	newlen = 0;

	/* pre-calc space for each fs */
	spin_lock(&file_systems_lock);
	gen = file_systems_gen;
	hlist_for_each_entry_rcu(p, &file_systems, list) {
		if (!(p->fs_flags & FS_REQUIRES_DEV))
			newlen += strlen("nodev");
		newlen += strlen("\t") + strlen(p->name) + strlen("\n");
	}
	spin_unlock(&file_systems_lock);

	new = kmalloc(offsetof(struct file_systems_string, string) + newlen + 1,
		      GFP_KERNEL);
	if (!new)
		return -ENOMEM;

	new->gen = gen;
	new->len = newlen;
	new->string[newlen] = '\0';

	spin_lock(&file_systems_lock);
	old = file_systems_string;

	/*

Annotation

Implementation Notes