fs/notify/inotify/inotify_user.c

Source file repositories/reference/linux-study-clean/fs/notify/inotify/inotify_user.c

File Facts

System
Linux kernel
Corpus path
fs/notify/inotify/inotify_user.c
Extension
.c
Size
22152 bytes
Lines
862
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_DEFINE1(inotify_init1, int, flags)
{
	return do_inotify_init(flags);
}

SYSCALL_DEFINE0(inotify_init)
{
	return do_inotify_init(0);
}

SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
		u32, mask)
{
	struct fsnotify_group *group;
	struct inode *inode;
	struct path path;
	int ret;
	unsigned flags = 0;

	/*
	 * We share a lot of code with fs/dnotify.  We also share
	 * the bit layout between inotify's IN_* and the fsnotify
	 * FS_*.  This check ensures that only the inotify IN_*
	 * bits get passed in and set in watches/events.
	 */
	if (unlikely(mask & ~ALL_INOTIFY_BITS))
		return -EINVAL;
	/*
	 * Require at least one valid bit set in the mask.
	 * Without _something_ set, we would have no events to
	 * watch for.
	 */
	if (unlikely(!(mask & ALL_INOTIFY_BITS)))
		return -EINVAL;

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

	/* IN_MASK_ADD and IN_MASK_CREATE don't make sense together */
	if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE)))
		return -EINVAL;

	/* verify that this is indeed an inotify instance */
	if (unlikely(fd_file(f)->f_op != &inotify_fops))
		return -EINVAL;

	if (!(mask & IN_DONT_FOLLOW))
		flags |= LOOKUP_FOLLOW;
	if (mask & IN_ONLYDIR)
		flags |= LOOKUP_DIRECTORY;

	ret = inotify_find_inode(pathname, &path, flags,
			(mask & IN_ALL_EVENTS));
	if (ret)
		return ret;

	/* inode held in place by reference to path; group by fget on fd */
	inode = path.dentry->d_inode;
	group = fd_file(f)->private_data;

	/* create/update an inode mark */
	ret = inotify_update_watch(group, inode, mask);
	path_put(&path);
	return ret;
}

SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
{
	struct fsnotify_group *group;
	struct inotify_inode_mark *i_mark;
	CLASS(fd, f)(fd);

	if (fd_empty(f))
		return -EBADF;

	/* verify that this is indeed an inotify instance */
	if (unlikely(fd_file(f)->f_op != &inotify_fops))
		return -EINVAL;

	group = fd_file(f)->private_data;

	i_mark = inotify_idr_find(group, wd);
	if (unlikely(!i_mark))
		return -EINVAL;

	fsnotify_destroy_mark(&i_mark->fsn_mark, group);

	/* match ref taken by inotify_idr_find */
	fsnotify_put_mark(&i_mark->fsn_mark);

Annotation

Implementation Notes