linux/fs/notify/inotify/inotify_user.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * fs/inotify_user.c - inotify support for userspace
 *
 * Authors:
 *	John McCutchan	<[email protected]>
 *	Robert Love	<[email protected]>
 *
 * Copyright (C) 2005 John McCutchan
 * Copyright 2006 Hewlett-Packard Development Company, L.P.
 *
 * Copyright (C) 2009 Eric Paris <Red Hat Inc>
 * inotify was largely rewriten to make use of the fsnotify infrastructure
 */

#include <linux/file.h>
#include <linux/fs.h> /* struct inode */
#include <linux/fsnotify_backend.h>
#include <linux/idr.h>
#include <linux/init.h> /* fs_initcall */
#include <linux/inotify.h>
#include <linux/kernel.h> /* roundup() */
#include <linux/namei.h> /* LOOKUP_FOLLOW */
#include <linux/sched/signal.h>
#include <linux/slab.h> /* struct kmem_cache */
#include <linux/syscalls.h>
#include <linux/types.h>
#include <linux/anon_inodes.h>
#include <linux/uaccess.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/memcontrol.h>
#include <linux/security.h>

#include "inotify.h"
#include "../fdinfo.h"

#include <asm/ioctls.h>

/*
 * An inotify watch requires allocating an inotify_inode_mark structure as
 * well as pinning the watched inode. Doubling the size of a VFS inode
 * should be more than enough to cover the additional filesystem inode
 * size increase.
 */
#define INOTIFY_WATCH_COST

/* configurable via /proc/sys/fs/inotify/ */
static int inotify_max_queued_events __read_mostly;

struct kmem_cache *inotify_inode_mark_cachep __ro_after_init;

#ifdef CONFIG_SYSCTL

#include <linux/sysctl.h>

static long it_zero =;
static long it_int_max =;

static struct ctl_table inotify_table[] =;

static void __init inotify_sysctls_init(void)
{}

#else
#define inotify_sysctls_init
#endif /* CONFIG_SYSCTL */

static inline __u32 inotify_arg_to_mask(struct inode *inode, u32 arg)
{}

#define INOTIFY_MARK_FLAGS

static inline unsigned int inotify_arg_to_flags(u32 arg)
{}

static inline u32 inotify_mask_to_arg(__u32 mask)
{}

/* inotify userspace file descriptor functions */
static __poll_t inotify_poll(struct file *file, poll_table *wait)
{}

static int round_event_name_len(struct fsnotify_event *fsn_event)
{}

/*
 * Get an inotify_kernel_event if one exists and is small
 * enough to fit in "count". Return an error pointer if
 * not large enough.
 *
 * Called with the group->notification_lock held.
 */
static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
					    size_t count)
{}

/*
 * Copy an event to user space, returning how much we copied.
 *
 * We already checked that the event size is smaller than the
 * buffer we had in "get_one_event()" above.
 */
static ssize_t copy_event_to_user(struct fsnotify_group *group,
				  struct fsnotify_event *fsn_event,
				  char __user *buf)
{}

static ssize_t inotify_read(struct file *file, char __user *buf,
			    size_t count, loff_t *pos)
{}

static int inotify_release(struct inode *ignored, struct file *file)
{}

static long inotify_ioctl(struct file *file, unsigned int cmd,
			  unsigned long arg)
{}

static const struct file_operations inotify_fops =;


/*
 * find_inode - resolve a user-given path to a specific inode
 */
static int inotify_find_inode(const char __user *dirname, struct path *path,
						unsigned int flags, __u64 mask)
{}

static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock,
			      struct inotify_inode_mark *i_mark)
{}

static struct inotify_inode_mark *inotify_idr_find_locked(struct fsnotify_group *group,
								int wd)
{}

static struct inotify_inode_mark *inotify_idr_find(struct fsnotify_group *group,
							 int wd)
{}

/*
 * Remove the mark from the idr (if present) and drop the reference
 * on the mark because it was in the idr.
 */
static void inotify_remove_from_idr(struct fsnotify_group *group,
				    struct inotify_inode_mark *i_mark)
{}

/*
 * Send IN_IGNORED for this wd, remove this wd from the idr.
 */
void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
				    struct fsnotify_group *group)
{}

static int inotify_update_existing_watch(struct fsnotify_group *group,
					 struct inode *inode,
					 u32 arg)
{}

static int inotify_new_watch(struct fsnotify_group *group,
			     struct inode *inode,
			     u32 arg)
{}

static int inotify_update_watch(struct fsnotify_group *group, struct inode *inode, u32 arg)
{}

static struct fsnotify_group *inotify_new_group(unsigned int max_events)
{}


/* inotify syscalls */
static int do_inotify_init(int flags)
{}

SYSCALL_DEFINE1(inotify_init1, int, flags)
{}

SYSCALL_DEFINE0()
{

SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
		u32, mask)
{}

SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
{}

/*
 * inotify_user_setup - Our initialization function.  Note that we cannot return
 * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
 * must result in panic().
 */
static int __init inotify_user_setup(void)
{}
fs_initcall(inotify_user_setup);