fs/quota/quota.c

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

File Facts

System
Linux kernel
Corpus path
fs/quota/quota.c
Extension
.c
Size
28249 bytes
Lines
1011
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_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
		qid_t, id, void __user *, addr)
{
	uint cmds, type;
	struct super_block *sb = NULL;
	struct path path, *pathp = NULL;
	int ret;

	cmds = cmd >> SUBCMDSHIFT;
	type = cmd & SUBCMDMASK;

	if (type >= MAXQUOTAS)
		return -EINVAL;

	/*
	 * As a special case Q_SYNC can be called without a specific device.
	 * It will iterate all superblocks that have quota enabled and call
	 * the sync action on each of them.
	 */
	if (!special) {
		if (cmds == Q_SYNC)
			return quota_sync_all(type);
		return -ENODEV;
	}

	/*
	 * Path for quotaon has to be resolved before grabbing superblock
	 * because that gets s_umount sem which is also possibly needed by path
	 * resolution (think about autofs) and thus deadlocks could arise.
	 */
	if (cmds == Q_QUOTAON) {
		ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
		if (ret)
			pathp = ERR_PTR(ret);
		else
			pathp = &path;
	}

	sb = quotactl_block(special, cmds);
	if (IS_ERR(sb)) {
		ret = PTR_ERR(sb);
		goto out;
	}

	ret = do_quotactl(sb, type, cmds, id, addr, pathp);

	if (!quotactl_cmd_onoff(cmds))
		drop_super(sb);
	else
		drop_super_exclusive(sb);
out:
	if (pathp && !IS_ERR(pathp))
		path_put(pathp);
	return ret;
}

SYSCALL_DEFINE4(quotactl_fd, unsigned int, fd, unsigned int, cmd,
		qid_t, id, void __user *, addr)
{
	struct super_block *sb;
	unsigned int cmds = cmd >> SUBCMDSHIFT;
	unsigned int type = cmd & SUBCMDMASK;
	CLASS(fd_raw, f)(fd);
	int ret;

	if (fd_empty(f))
		return -EBADF;

	if (type >= MAXQUOTAS)
		return -EINVAL;

	if (quotactl_cmd_write(cmds)) {
		ret = mnt_want_write(fd_file(f)->f_path.mnt);
		if (ret)
			return ret;
	}

	sb = fd_file(f)->f_path.mnt->mnt_sb;
	if (quotactl_cmd_onoff(cmds))
		down_write(&sb->s_umount);
	else
		down_read(&sb->s_umount);

	ret = do_quotactl(sb, type, cmds, id, addr, ERR_PTR(-EINVAL));

	if (quotactl_cmd_onoff(cmds))
		up_write(&sb->s_umount);
	else
		up_read(&sb->s_umount);

Annotation

Implementation Notes