fs/locks.c

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

File Facts

System
Linux kernel
Corpus path
fs/locks.c
Extension
.c
Size
85066 bytes
Lines
3164
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_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
{
	int can_sleep, error, type;
	struct file_lock fl;

	/*
	 * LOCK_MAND locks were broken for a long time in that they never
	 * conflicted with one another and didn't prevent any sort of open,
	 * read or write activity.
	 *
	 * Just ignore these requests now, to preserve legacy behavior, but
	 * throw a warning to let people know that they don't actually work.
	 */
	if (cmd & LOCK_MAND) {
		pr_warn_once("%s(%d): Attempt to set a LOCK_MAND lock via flock(2). This support has been removed and the request ignored.\n", current->comm, current->pid);
		return 0;
	}

	type = flock_translate_cmd(cmd & ~LOCK_NB);
	if (type < 0)
		return type;

	CLASS(fd, f)(fd);
	if (fd_empty(f))
		return -EBADF;

	if (type != F_UNLCK && !(fd_file(f)->f_mode & (FMODE_READ | FMODE_WRITE)))
		return -EBADF;

	flock_make_lock(fd_file(f), &fl, type);

	error = security_file_lock(fd_file(f), fl.c.flc_type);
	if (error)
		return error;

	can_sleep = !(cmd & LOCK_NB);
	if (can_sleep)
		fl.c.flc_flags |= FL_SLEEP;

	if (fd_file(f)->f_op->flock)
		error = fd_file(f)->f_op->flock(fd_file(f),
					    (can_sleep) ? F_SETLKW : F_SETLK,
					    &fl);
	else
		error = locks_lock_file_wait(fd_file(f), &fl);

	locks_release_private(&fl);
	return error;
}

/**
 * vfs_test_lock - test file byte range lock
 * @filp: The file to test lock for
 * @fl: The byte-range in the file to test; also used to hold result
 *
 * On entry, @fl does not contain a lock, but identifies a range (fl_start, fl_end)
 * in the file (c.flc_file), and an owner (c.flc_owner) for whom existing locks
 * should be ignored.  c.flc_type and c.flc_flags are ignored.
 * Both fl_lmops and fl_ops in @fl must be NULL.
 * Returns -ERRNO on failure.  Indicates presence of conflicting lock by
 * setting fl->fl_type to something other than F_UNLCK.
 *
 * If vfs_test_lock() does find a lock and return it, the caller must
 * use locks_free_lock() or locks_release_private() on the returned lock.
 */
int vfs_test_lock(struct file *filp, struct file_lock *fl)
{
	int error = 0;

	WARN_ON_ONCE(fl->fl_ops || fl->fl_lmops);
	WARN_ON_ONCE(filp != fl->c.flc_file);
	if (filp->f_op->lock)
		error = filp->f_op->lock(filp, F_GETLK, fl);
	else
		posix_test_lock(filp, fl);

	/*
	 * We don't expect FILE_LOCK_DEFERRED and callers cannot
	 * handle it.
	 */
	if (WARN_ON_ONCE(error == FILE_LOCK_DEFERRED))
		error = -EIO;

	return error;
}
EXPORT_SYMBOL_GPL(vfs_test_lock);

/**
 * locks_translate_pid - translate a file_lock's fl_pid number into a namespace
 * @fl: The file_lock who's fl_pid should be translated

Annotation

Implementation Notes