1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Filesystem access notification for Linux
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #ifndef __LINUX_FSNOTIFY_BACKEND_H
9*4882a593Smuzhiyun #define __LINUX_FSNOTIFY_BACKEND_H
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #ifdef __KERNEL__
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include <linux/idr.h> /* inotify uses this */
14*4882a593Smuzhiyun #include <linux/fs.h> /* struct inode */
15*4882a593Smuzhiyun #include <linux/list.h>
16*4882a593Smuzhiyun #include <linux/path.h> /* struct path */
17*4882a593Smuzhiyun #include <linux/spinlock.h>
18*4882a593Smuzhiyun #include <linux/types.h>
19*4882a593Smuzhiyun #include <linux/atomic.h>
20*4882a593Smuzhiyun #include <linux/user_namespace.h>
21*4882a593Smuzhiyun #include <linux/refcount.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /*
24*4882a593Smuzhiyun * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily
25*4882a593Smuzhiyun * convert between them. dnotify only needs conversion at watch creation
26*4882a593Smuzhiyun * so no perf loss there. fanotify isn't defined yet, so it can use the
27*4882a593Smuzhiyun * wholes if it needs more events.
28*4882a593Smuzhiyun */
29*4882a593Smuzhiyun #define FS_ACCESS 0x00000001 /* File was accessed */
30*4882a593Smuzhiyun #define FS_MODIFY 0x00000002 /* File was modified */
31*4882a593Smuzhiyun #define FS_ATTRIB 0x00000004 /* Metadata changed */
32*4882a593Smuzhiyun #define FS_CLOSE_WRITE 0x00000008 /* Writtable file was closed */
33*4882a593Smuzhiyun #define FS_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
34*4882a593Smuzhiyun #define FS_OPEN 0x00000020 /* File was opened */
35*4882a593Smuzhiyun #define FS_MOVED_FROM 0x00000040 /* File was moved from X */
36*4882a593Smuzhiyun #define FS_MOVED_TO 0x00000080 /* File was moved to Y */
37*4882a593Smuzhiyun #define FS_CREATE 0x00000100 /* Subfile was created */
38*4882a593Smuzhiyun #define FS_DELETE 0x00000200 /* Subfile was deleted */
39*4882a593Smuzhiyun #define FS_DELETE_SELF 0x00000400 /* Self was deleted */
40*4882a593Smuzhiyun #define FS_MOVE_SELF 0x00000800 /* Self was moved */
41*4882a593Smuzhiyun #define FS_OPEN_EXEC 0x00001000 /* File was opened for exec */
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #define FS_UNMOUNT 0x00002000 /* inode on umount fs */
44*4882a593Smuzhiyun #define FS_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
45*4882a593Smuzhiyun #define FS_IN_IGNORED 0x00008000 /* last inotify event here */
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun #define FS_OPEN_PERM 0x00010000 /* open event in an permission hook */
48*4882a593Smuzhiyun #define FS_ACCESS_PERM 0x00020000 /* access event in a permissions hook */
49*4882a593Smuzhiyun #define FS_OPEN_EXEC_PERM 0x00040000 /* open/exec event in a permission hook */
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */
52*4882a593Smuzhiyun /*
53*4882a593Smuzhiyun * Set on inode mark that cares about things that happen to its children.
54*4882a593Smuzhiyun * Always set for dnotify and inotify.
55*4882a593Smuzhiyun * Set on inode/sb/mount marks that care about parent/name info.
56*4882a593Smuzhiyun */
57*4882a593Smuzhiyun #define FS_EVENT_ON_CHILD 0x08000000
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #define FS_DN_RENAME 0x10000000 /* file renamed */
60*4882a593Smuzhiyun #define FS_DN_MULTISHOT 0x20000000 /* dnotify multishot */
61*4882a593Smuzhiyun #define FS_ISDIR 0x40000000 /* event occurred against dir */
62*4882a593Smuzhiyun #define FS_IN_ONESHOT 0x80000000 /* only send event once */
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun #define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO)
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /*
67*4882a593Smuzhiyun * Directory entry modification events - reported only to directory
68*4882a593Smuzhiyun * where entry is modified and not to a watching parent.
69*4882a593Smuzhiyun * The watching parent may get an FS_ATTRIB|FS_EVENT_ON_CHILD event
70*4882a593Smuzhiyun * when a directory entry inside a child subdir changes.
71*4882a593Smuzhiyun */
72*4882a593Smuzhiyun #define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE)
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun #define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM | \
75*4882a593Smuzhiyun FS_OPEN_EXEC_PERM)
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /*
78*4882a593Smuzhiyun * This is a list of all events that may get sent to a parent that is watching
79*4882a593Smuzhiyun * with flag FS_EVENT_ON_CHILD based on fs event on a child of that directory.
80*4882a593Smuzhiyun */
81*4882a593Smuzhiyun #define FS_EVENTS_POSS_ON_CHILD (ALL_FSNOTIFY_PERM_EVENTS | \
82*4882a593Smuzhiyun FS_ACCESS | FS_MODIFY | FS_ATTRIB | \
83*4882a593Smuzhiyun FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | \
84*4882a593Smuzhiyun FS_OPEN | FS_OPEN_EXEC)
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun /*
87*4882a593Smuzhiyun * This is a list of all events that may get sent with the parent inode as the
88*4882a593Smuzhiyun * @to_tell argument of fsnotify().
89*4882a593Smuzhiyun * It may include events that can be sent to an inode/sb/mount mark, but cannot
90*4882a593Smuzhiyun * be sent to a parent watching children.
91*4882a593Smuzhiyun */
92*4882a593Smuzhiyun #define FS_EVENTS_POSS_TO_PARENT (FS_EVENTS_POSS_ON_CHILD)
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /* Events that can be reported to backends */
95*4882a593Smuzhiyun #define ALL_FSNOTIFY_EVENTS (ALL_FSNOTIFY_DIRENT_EVENTS | \
96*4882a593Smuzhiyun FS_EVENTS_POSS_ON_CHILD | \
97*4882a593Smuzhiyun FS_DELETE_SELF | FS_MOVE_SELF | FS_DN_RENAME | \
98*4882a593Smuzhiyun FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED)
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /* Extra flags that may be reported with event or control handling of events */
101*4882a593Smuzhiyun #define ALL_FSNOTIFY_FLAGS (FS_EXCL_UNLINK | FS_ISDIR | FS_IN_ONESHOT | \
102*4882a593Smuzhiyun FS_DN_MULTISHOT | FS_EVENT_ON_CHILD)
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun #define ALL_FSNOTIFY_BITS (ALL_FSNOTIFY_EVENTS | ALL_FSNOTIFY_FLAGS)
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun struct fsnotify_group;
107*4882a593Smuzhiyun struct fsnotify_event;
108*4882a593Smuzhiyun struct fsnotify_mark;
109*4882a593Smuzhiyun struct fsnotify_event_private_data;
110*4882a593Smuzhiyun struct fsnotify_fname;
111*4882a593Smuzhiyun struct fsnotify_iter_info;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun struct mem_cgroup;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /*
116*4882a593Smuzhiyun * Each group much define these ops. The fsnotify infrastructure will call
117*4882a593Smuzhiyun * these operations for each relevant group.
118*4882a593Smuzhiyun *
119*4882a593Smuzhiyun * handle_event - main call for a group to handle an fs event
120*4882a593Smuzhiyun * @group: group to notify
121*4882a593Smuzhiyun * @mask: event type and flags
122*4882a593Smuzhiyun * @data: object that event happened on
123*4882a593Smuzhiyun * @data_type: type of object for fanotify_data_XXX() accessors
124*4882a593Smuzhiyun * @dir: optional directory associated with event -
125*4882a593Smuzhiyun * if @file_name is not NULL, this is the directory that
126*4882a593Smuzhiyun * @file_name is relative to
127*4882a593Smuzhiyun * @file_name: optional file name associated with event
128*4882a593Smuzhiyun * @cookie: inotify rename cookie
129*4882a593Smuzhiyun * @iter_info: array of marks from this group that are interested in the event
130*4882a593Smuzhiyun *
131*4882a593Smuzhiyun * handle_inode_event - simple variant of handle_event() for groups that only
132*4882a593Smuzhiyun * have inode marks and don't have ignore mask
133*4882a593Smuzhiyun * @mark: mark to notify
134*4882a593Smuzhiyun * @mask: event type and flags
135*4882a593Smuzhiyun * @inode: inode that event happened on
136*4882a593Smuzhiyun * @dir: optional directory associated with event -
137*4882a593Smuzhiyun * if @file_name is not NULL, this is the directory that
138*4882a593Smuzhiyun * @file_name is relative to.
139*4882a593Smuzhiyun * @file_name: optional file name associated with event
140*4882a593Smuzhiyun * @cookie: inotify rename cookie
141*4882a593Smuzhiyun *
142*4882a593Smuzhiyun * free_group_priv - called when a group refcnt hits 0 to clean up the private union
143*4882a593Smuzhiyun * freeing_mark - called when a mark is being destroyed for some reason. The group
144*4882a593Smuzhiyun * MUST be holding a reference on each mark and that reference must be
145*4882a593Smuzhiyun * dropped in this function. inotify uses this function to send
146*4882a593Smuzhiyun * userspace messages that marks have been removed.
147*4882a593Smuzhiyun */
148*4882a593Smuzhiyun struct fsnotify_ops {
149*4882a593Smuzhiyun int (*handle_event)(struct fsnotify_group *group, u32 mask,
150*4882a593Smuzhiyun const void *data, int data_type, struct inode *dir,
151*4882a593Smuzhiyun const struct qstr *file_name, u32 cookie,
152*4882a593Smuzhiyun struct fsnotify_iter_info *iter_info);
153*4882a593Smuzhiyun int (*handle_inode_event)(struct fsnotify_mark *mark, u32 mask,
154*4882a593Smuzhiyun struct inode *inode, struct inode *dir,
155*4882a593Smuzhiyun const struct qstr *file_name, u32 cookie);
156*4882a593Smuzhiyun void (*free_group_priv)(struct fsnotify_group *group);
157*4882a593Smuzhiyun void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
158*4882a593Smuzhiyun void (*free_event)(struct fsnotify_event *event);
159*4882a593Smuzhiyun /* called on final put+free to free memory */
160*4882a593Smuzhiyun void (*free_mark)(struct fsnotify_mark *mark);
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /*
164*4882a593Smuzhiyun * all of the information about the original object we want to now send to
165*4882a593Smuzhiyun * a group. If you want to carry more info from the accessing task to the
166*4882a593Smuzhiyun * listener this structure is where you need to be adding fields.
167*4882a593Smuzhiyun */
168*4882a593Smuzhiyun struct fsnotify_event {
169*4882a593Smuzhiyun struct list_head list;
170*4882a593Smuzhiyun unsigned long objectid; /* identifier for queue merges */
171*4882a593Smuzhiyun };
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /*
174*4882a593Smuzhiyun * A group is a "thing" that wants to receive notification about filesystem
175*4882a593Smuzhiyun * events. The mask holds the subset of event types this group cares about.
176*4882a593Smuzhiyun * refcnt on a group is up to the implementor and at any moment if it goes 0
177*4882a593Smuzhiyun * everything will be cleaned up.
178*4882a593Smuzhiyun */
179*4882a593Smuzhiyun struct fsnotify_group {
180*4882a593Smuzhiyun const struct fsnotify_ops *ops; /* how this group handles things */
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /*
183*4882a593Smuzhiyun * How the refcnt is used is up to each group. When the refcnt hits 0
184*4882a593Smuzhiyun * fsnotify will clean up all of the resources associated with this group.
185*4882a593Smuzhiyun * As an example, the dnotify group will always have a refcnt=1 and that
186*4882a593Smuzhiyun * will never change. Inotify, on the other hand, has a group per
187*4882a593Smuzhiyun * inotify_init() and the refcnt will hit 0 only when that fd has been
188*4882a593Smuzhiyun * closed.
189*4882a593Smuzhiyun */
190*4882a593Smuzhiyun refcount_t refcnt; /* things with interest in this group */
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun /* needed to send notification to userspace */
193*4882a593Smuzhiyun spinlock_t notification_lock; /* protect the notification_list */
194*4882a593Smuzhiyun struct list_head notification_list; /* list of event_holder this group needs to send to userspace */
195*4882a593Smuzhiyun wait_queue_head_t notification_waitq; /* read() on the notification file blocks on this waitq */
196*4882a593Smuzhiyun unsigned int q_len; /* events on the queue */
197*4882a593Smuzhiyun unsigned int max_events; /* maximum events allowed on the list */
198*4882a593Smuzhiyun /*
199*4882a593Smuzhiyun * Valid fsnotify group priorities. Events are send in order from highest
200*4882a593Smuzhiyun * priority to lowest priority. We default to the lowest priority.
201*4882a593Smuzhiyun */
202*4882a593Smuzhiyun #define FS_PRIO_0 0 /* normal notifiers, no permissions */
203*4882a593Smuzhiyun #define FS_PRIO_1 1 /* fanotify content based access control */
204*4882a593Smuzhiyun #define FS_PRIO_2 2 /* fanotify pre-content access */
205*4882a593Smuzhiyun unsigned int priority;
206*4882a593Smuzhiyun bool shutdown; /* group is being shut down, don't queue more events */
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */
209*4882a593Smuzhiyun struct mutex mark_mutex; /* protect marks_list */
210*4882a593Smuzhiyun atomic_t num_marks; /* 1 for each mark and 1 for not being
211*4882a593Smuzhiyun * past the point of no return when freeing
212*4882a593Smuzhiyun * a group */
213*4882a593Smuzhiyun atomic_t user_waits; /* Number of tasks waiting for user
214*4882a593Smuzhiyun * response */
215*4882a593Smuzhiyun struct list_head marks_list; /* all inode marks for this group */
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun struct fasync_struct *fsn_fa; /* async notification */
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun struct fsnotify_event *overflow_event; /* Event we queue when the
220*4882a593Smuzhiyun * notification list is too
221*4882a593Smuzhiyun * full */
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun struct mem_cgroup *memcg; /* memcg to charge allocations */
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /* groups can define private fields here or use the void *private */
226*4882a593Smuzhiyun union {
227*4882a593Smuzhiyun void *private;
228*4882a593Smuzhiyun #ifdef CONFIG_INOTIFY_USER
229*4882a593Smuzhiyun struct inotify_group_private_data {
230*4882a593Smuzhiyun spinlock_t idr_lock;
231*4882a593Smuzhiyun struct idr idr;
232*4882a593Smuzhiyun struct ucounts *ucounts;
233*4882a593Smuzhiyun } inotify_data;
234*4882a593Smuzhiyun #endif
235*4882a593Smuzhiyun #ifdef CONFIG_FANOTIFY
236*4882a593Smuzhiyun struct fanotify_group_private_data {
237*4882a593Smuzhiyun /* allows a group to block waiting for a userspace response */
238*4882a593Smuzhiyun struct list_head access_list;
239*4882a593Smuzhiyun wait_queue_head_t access_waitq;
240*4882a593Smuzhiyun int flags; /* flags from fanotify_init() */
241*4882a593Smuzhiyun int f_flags; /* event_f_flags from fanotify_init() */
242*4882a593Smuzhiyun unsigned int max_marks;
243*4882a593Smuzhiyun struct user_struct *user;
244*4882a593Smuzhiyun } fanotify_data;
245*4882a593Smuzhiyun #endif /* CONFIG_FANOTIFY */
246*4882a593Smuzhiyun };
247*4882a593Smuzhiyun };
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun /* When calling fsnotify tell it if the data is a path or inode */
250*4882a593Smuzhiyun enum fsnotify_data_type {
251*4882a593Smuzhiyun FSNOTIFY_EVENT_NONE,
252*4882a593Smuzhiyun FSNOTIFY_EVENT_PATH,
253*4882a593Smuzhiyun FSNOTIFY_EVENT_INODE,
254*4882a593Smuzhiyun };
255*4882a593Smuzhiyun
fsnotify_data_inode(const void * data,int data_type)256*4882a593Smuzhiyun static inline struct inode *fsnotify_data_inode(const void *data, int data_type)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun switch (data_type) {
259*4882a593Smuzhiyun case FSNOTIFY_EVENT_INODE:
260*4882a593Smuzhiyun return (struct inode *)data;
261*4882a593Smuzhiyun case FSNOTIFY_EVENT_PATH:
262*4882a593Smuzhiyun return d_inode(((const struct path *)data)->dentry);
263*4882a593Smuzhiyun default:
264*4882a593Smuzhiyun return NULL;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
fsnotify_data_path(const void * data,int data_type)268*4882a593Smuzhiyun static inline const struct path *fsnotify_data_path(const void *data,
269*4882a593Smuzhiyun int data_type)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun switch (data_type) {
272*4882a593Smuzhiyun case FSNOTIFY_EVENT_PATH:
273*4882a593Smuzhiyun return data;
274*4882a593Smuzhiyun default:
275*4882a593Smuzhiyun return NULL;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun enum fsnotify_obj_type {
280*4882a593Smuzhiyun FSNOTIFY_OBJ_TYPE_INODE,
281*4882a593Smuzhiyun FSNOTIFY_OBJ_TYPE_PARENT,
282*4882a593Smuzhiyun FSNOTIFY_OBJ_TYPE_VFSMOUNT,
283*4882a593Smuzhiyun FSNOTIFY_OBJ_TYPE_SB,
284*4882a593Smuzhiyun FSNOTIFY_OBJ_TYPE_COUNT,
285*4882a593Smuzhiyun FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT
286*4882a593Smuzhiyun };
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun #define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE)
289*4882a593Smuzhiyun #define FSNOTIFY_OBJ_TYPE_PARENT_FL (1U << FSNOTIFY_OBJ_TYPE_PARENT)
290*4882a593Smuzhiyun #define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT)
291*4882a593Smuzhiyun #define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB)
292*4882a593Smuzhiyun #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1)
293*4882a593Smuzhiyun
fsnotify_valid_obj_type(unsigned int type)294*4882a593Smuzhiyun static inline bool fsnotify_valid_obj_type(unsigned int type)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun return (type < FSNOTIFY_OBJ_TYPE_COUNT);
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun struct fsnotify_iter_info {
300*4882a593Smuzhiyun struct fsnotify_mark *marks[FSNOTIFY_OBJ_TYPE_COUNT];
301*4882a593Smuzhiyun unsigned int report_mask;
302*4882a593Smuzhiyun int srcu_idx;
303*4882a593Smuzhiyun };
304*4882a593Smuzhiyun
fsnotify_iter_should_report_type(struct fsnotify_iter_info * iter_info,int type)305*4882a593Smuzhiyun static inline bool fsnotify_iter_should_report_type(
306*4882a593Smuzhiyun struct fsnotify_iter_info *iter_info, int type)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun return (iter_info->report_mask & (1U << type));
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
fsnotify_iter_set_report_type(struct fsnotify_iter_info * iter_info,int type)311*4882a593Smuzhiyun static inline void fsnotify_iter_set_report_type(
312*4882a593Smuzhiyun struct fsnotify_iter_info *iter_info, int type)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun iter_info->report_mask |= (1U << type);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
fsnotify_iter_set_report_type_mark(struct fsnotify_iter_info * iter_info,int type,struct fsnotify_mark * mark)317*4882a593Smuzhiyun static inline void fsnotify_iter_set_report_type_mark(
318*4882a593Smuzhiyun struct fsnotify_iter_info *iter_info, int type,
319*4882a593Smuzhiyun struct fsnotify_mark *mark)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun iter_info->marks[type] = mark;
322*4882a593Smuzhiyun iter_info->report_mask |= (1U << type);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun #define FSNOTIFY_ITER_FUNCS(name, NAME) \
326*4882a593Smuzhiyun static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \
327*4882a593Smuzhiyun struct fsnotify_iter_info *iter_info) \
328*4882a593Smuzhiyun { \
329*4882a593Smuzhiyun return (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_##NAME##_FL) ? \
330*4882a593Smuzhiyun iter_info->marks[FSNOTIFY_OBJ_TYPE_##NAME] : NULL; \
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun FSNOTIFY_ITER_FUNCS(inode, INODE)
334*4882a593Smuzhiyun FSNOTIFY_ITER_FUNCS(parent, PARENT)
335*4882a593Smuzhiyun FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT)
336*4882a593Smuzhiyun FSNOTIFY_ITER_FUNCS(sb, SB)
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun #define fsnotify_foreach_obj_type(type) \
339*4882a593Smuzhiyun for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++)
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun /*
342*4882a593Smuzhiyun * fsnotify_connp_t is what we embed in objects which connector can be attached
343*4882a593Smuzhiyun * to. fsnotify_connp_t * is how we refer from connector back to object.
344*4882a593Smuzhiyun */
345*4882a593Smuzhiyun struct fsnotify_mark_connector;
346*4882a593Smuzhiyun typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun /*
349*4882a593Smuzhiyun * Inode/vfsmount/sb point to this structure which tracks all marks attached to
350*4882a593Smuzhiyun * the inode/vfsmount/sb. The reference to inode/vfsmount/sb is held by this
351*4882a593Smuzhiyun * structure. We destroy this structure when there are no more marks attached
352*4882a593Smuzhiyun * to it. The structure is protected by fsnotify_mark_srcu.
353*4882a593Smuzhiyun */
354*4882a593Smuzhiyun struct fsnotify_mark_connector {
355*4882a593Smuzhiyun spinlock_t lock;
356*4882a593Smuzhiyun unsigned short type; /* Type of object [lock] */
357*4882a593Smuzhiyun #define FSNOTIFY_CONN_FLAG_HAS_FSID 0x01
358*4882a593Smuzhiyun unsigned short flags; /* flags [lock] */
359*4882a593Smuzhiyun __kernel_fsid_t fsid; /* fsid of filesystem containing object */
360*4882a593Smuzhiyun union {
361*4882a593Smuzhiyun /* Object pointer [lock] */
362*4882a593Smuzhiyun fsnotify_connp_t *obj;
363*4882a593Smuzhiyun /* Used listing heads to free after srcu period expires */
364*4882a593Smuzhiyun struct fsnotify_mark_connector *destroy_next;
365*4882a593Smuzhiyun };
366*4882a593Smuzhiyun struct hlist_head list;
367*4882a593Smuzhiyun };
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun /*
370*4882a593Smuzhiyun * A mark is simply an object attached to an in core inode which allows an
371*4882a593Smuzhiyun * fsnotify listener to indicate they are either no longer interested in events
372*4882a593Smuzhiyun * of a type matching mask or only interested in those events.
373*4882a593Smuzhiyun *
374*4882a593Smuzhiyun * These are flushed when an inode is evicted from core and may be flushed
375*4882a593Smuzhiyun * when the inode is modified (as seen by fsnotify_access). Some fsnotify
376*4882a593Smuzhiyun * users (such as dnotify) will flush these when the open fd is closed and not
377*4882a593Smuzhiyun * at inode eviction or modification.
378*4882a593Smuzhiyun *
379*4882a593Smuzhiyun * Text in brackets is showing the lock(s) protecting modifications of a
380*4882a593Smuzhiyun * particular entry. obj_lock means either inode->i_lock or
381*4882a593Smuzhiyun * mnt->mnt_root->d_lock depending on the mark type.
382*4882a593Smuzhiyun */
383*4882a593Smuzhiyun struct fsnotify_mark {
384*4882a593Smuzhiyun /* Mask this mark is for [mark->lock, group->mark_mutex] */
385*4882a593Smuzhiyun __u32 mask;
386*4882a593Smuzhiyun /* We hold one for presence in g_list. Also one ref for each 'thing'
387*4882a593Smuzhiyun * in kernel that found and may be using this mark. */
388*4882a593Smuzhiyun refcount_t refcnt;
389*4882a593Smuzhiyun /* Group this mark is for. Set on mark creation, stable until last ref
390*4882a593Smuzhiyun * is dropped */
391*4882a593Smuzhiyun struct fsnotify_group *group;
392*4882a593Smuzhiyun /* List of marks by group->marks_list. Also reused for queueing
393*4882a593Smuzhiyun * mark into destroy_list when it's waiting for the end of SRCU period
394*4882a593Smuzhiyun * before it can be freed. [group->mark_mutex] */
395*4882a593Smuzhiyun struct list_head g_list;
396*4882a593Smuzhiyun /* Protects inode / mnt pointers, flags, masks */
397*4882a593Smuzhiyun spinlock_t lock;
398*4882a593Smuzhiyun /* List of marks for inode / vfsmount [connector->lock, mark ref] */
399*4882a593Smuzhiyun struct hlist_node obj_list;
400*4882a593Smuzhiyun /* Head of list of marks for an object [mark ref] */
401*4882a593Smuzhiyun struct fsnotify_mark_connector *connector;
402*4882a593Smuzhiyun /* Events types to ignore [mark->lock, group->mark_mutex] */
403*4882a593Smuzhiyun __u32 ignored_mask;
404*4882a593Smuzhiyun #define FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY 0x01
405*4882a593Smuzhiyun #define FSNOTIFY_MARK_FLAG_ALIVE 0x02
406*4882a593Smuzhiyun #define FSNOTIFY_MARK_FLAG_ATTACHED 0x04
407*4882a593Smuzhiyun unsigned int flags; /* flags [mark->lock] */
408*4882a593Smuzhiyun };
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun #ifdef CONFIG_FSNOTIFY
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* called from the vfs helpers */
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun /* main fsnotify call to send events */
415*4882a593Smuzhiyun extern int fsnotify(__u32 mask, const void *data, int data_type,
416*4882a593Smuzhiyun struct inode *dir, const struct qstr *name,
417*4882a593Smuzhiyun struct inode *inode, u32 cookie);
418*4882a593Smuzhiyun extern int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
419*4882a593Smuzhiyun int data_type);
420*4882a593Smuzhiyun extern void __fsnotify_inode_delete(struct inode *inode);
421*4882a593Smuzhiyun extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
422*4882a593Smuzhiyun extern void fsnotify_sb_delete(struct super_block *sb);
423*4882a593Smuzhiyun extern u32 fsnotify_get_cookie(void);
424*4882a593Smuzhiyun
fsnotify_parent_needed_mask(__u32 mask)425*4882a593Smuzhiyun static inline __u32 fsnotify_parent_needed_mask(__u32 mask)
426*4882a593Smuzhiyun {
427*4882a593Smuzhiyun /* FS_EVENT_ON_CHILD is set on marks that want parent/name info */
428*4882a593Smuzhiyun if (!(mask & FS_EVENT_ON_CHILD))
429*4882a593Smuzhiyun return 0;
430*4882a593Smuzhiyun /*
431*4882a593Smuzhiyun * This object might be watched by a mark that cares about parent/name
432*4882a593Smuzhiyun * info, does it care about the specific set of events that can be
433*4882a593Smuzhiyun * reported with parent/name info?
434*4882a593Smuzhiyun */
435*4882a593Smuzhiyun return mask & FS_EVENTS_POSS_TO_PARENT;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
fsnotify_inode_watches_children(struct inode * inode)438*4882a593Smuzhiyun static inline int fsnotify_inode_watches_children(struct inode *inode)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun /* FS_EVENT_ON_CHILD is set if the inode may care */
441*4882a593Smuzhiyun if (!(inode->i_fsnotify_mask & FS_EVENT_ON_CHILD))
442*4882a593Smuzhiyun return 0;
443*4882a593Smuzhiyun /* this inode might care about child events, does it care about the
444*4882a593Smuzhiyun * specific set of events that can happen on a child? */
445*4882a593Smuzhiyun return inode->i_fsnotify_mask & FS_EVENTS_POSS_ON_CHILD;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun /*
449*4882a593Smuzhiyun * Update the dentry with a flag indicating the interest of its parent to receive
450*4882a593Smuzhiyun * filesystem events when those events happens to this dentry->d_inode.
451*4882a593Smuzhiyun */
fsnotify_update_flags(struct dentry * dentry)452*4882a593Smuzhiyun static inline void fsnotify_update_flags(struct dentry *dentry)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun assert_spin_locked(&dentry->d_lock);
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun /*
457*4882a593Smuzhiyun * Serialisation of setting PARENT_WATCHED on the dentries is provided
458*4882a593Smuzhiyun * by d_lock. If inotify_inode_watched changes after we have taken
459*4882a593Smuzhiyun * d_lock, the following __fsnotify_update_child_dentry_flags call will
460*4882a593Smuzhiyun * find our entry, so it will spin until we complete here, and update
461*4882a593Smuzhiyun * us with the new state.
462*4882a593Smuzhiyun */
463*4882a593Smuzhiyun if (fsnotify_inode_watches_children(dentry->d_parent->d_inode))
464*4882a593Smuzhiyun dentry->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
465*4882a593Smuzhiyun else
466*4882a593Smuzhiyun dentry->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun /* called from fsnotify listeners, such as fanotify or dnotify */
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun /* create a new group */
472*4882a593Smuzhiyun extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops);
473*4882a593Smuzhiyun /* get reference to a group */
474*4882a593Smuzhiyun extern void fsnotify_get_group(struct fsnotify_group *group);
475*4882a593Smuzhiyun /* drop reference on a group from fsnotify_alloc_group */
476*4882a593Smuzhiyun extern void fsnotify_put_group(struct fsnotify_group *group);
477*4882a593Smuzhiyun /* group destruction begins, stop queuing new events */
478*4882a593Smuzhiyun extern void fsnotify_group_stop_queueing(struct fsnotify_group *group);
479*4882a593Smuzhiyun /* destroy group */
480*4882a593Smuzhiyun extern void fsnotify_destroy_group(struct fsnotify_group *group);
481*4882a593Smuzhiyun /* fasync handler function */
482*4882a593Smuzhiyun extern int fsnotify_fasync(int fd, struct file *file, int on);
483*4882a593Smuzhiyun /* Free event from memory */
484*4882a593Smuzhiyun extern void fsnotify_destroy_event(struct fsnotify_group *group,
485*4882a593Smuzhiyun struct fsnotify_event *event);
486*4882a593Smuzhiyun /* attach the event to the group notification queue */
487*4882a593Smuzhiyun extern int fsnotify_add_event(struct fsnotify_group *group,
488*4882a593Smuzhiyun struct fsnotify_event *event,
489*4882a593Smuzhiyun int (*merge)(struct list_head *,
490*4882a593Smuzhiyun struct fsnotify_event *));
491*4882a593Smuzhiyun /* Queue overflow event to a notification group */
fsnotify_queue_overflow(struct fsnotify_group * group)492*4882a593Smuzhiyun static inline void fsnotify_queue_overflow(struct fsnotify_group *group)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun fsnotify_add_event(group, group->overflow_event, NULL);
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun /* true if the group notification queue is empty */
498*4882a593Smuzhiyun extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group);
499*4882a593Smuzhiyun /* return, but do not dequeue the first event on the notification queue */
500*4882a593Smuzhiyun extern struct fsnotify_event *fsnotify_peek_first_event(struct fsnotify_group *group);
501*4882a593Smuzhiyun /* return AND dequeue the first event on the notification queue */
502*4882a593Smuzhiyun extern struct fsnotify_event *fsnotify_remove_first_event(struct fsnotify_group *group);
503*4882a593Smuzhiyun /* Remove event queued in the notification list */
504*4882a593Smuzhiyun extern void fsnotify_remove_queued_event(struct fsnotify_group *group,
505*4882a593Smuzhiyun struct fsnotify_event *event);
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun /* functions used to manipulate the marks attached to inodes */
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun /* Get mask of events for a list of marks */
510*4882a593Smuzhiyun extern __u32 fsnotify_conn_mask(struct fsnotify_mark_connector *conn);
511*4882a593Smuzhiyun /* Calculate mask of events for a list of marks */
512*4882a593Smuzhiyun extern void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn);
513*4882a593Smuzhiyun extern void fsnotify_init_mark(struct fsnotify_mark *mark,
514*4882a593Smuzhiyun struct fsnotify_group *group);
515*4882a593Smuzhiyun /* Find mark belonging to given group in the list of marks */
516*4882a593Smuzhiyun extern struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp,
517*4882a593Smuzhiyun struct fsnotify_group *group);
518*4882a593Smuzhiyun /* Get cached fsid of filesystem containing object */
519*4882a593Smuzhiyun extern int fsnotify_get_conn_fsid(const struct fsnotify_mark_connector *conn,
520*4882a593Smuzhiyun __kernel_fsid_t *fsid);
521*4882a593Smuzhiyun /* attach the mark to the object */
522*4882a593Smuzhiyun extern int fsnotify_add_mark(struct fsnotify_mark *mark,
523*4882a593Smuzhiyun fsnotify_connp_t *connp, unsigned int type,
524*4882a593Smuzhiyun int allow_dups, __kernel_fsid_t *fsid);
525*4882a593Smuzhiyun extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
526*4882a593Smuzhiyun fsnotify_connp_t *connp,
527*4882a593Smuzhiyun unsigned int type, int allow_dups,
528*4882a593Smuzhiyun __kernel_fsid_t *fsid);
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun /* attach the mark to the inode */
fsnotify_add_inode_mark(struct fsnotify_mark * mark,struct inode * inode,int allow_dups)531*4882a593Smuzhiyun static inline int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
532*4882a593Smuzhiyun struct inode *inode,
533*4882a593Smuzhiyun int allow_dups)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun return fsnotify_add_mark(mark, &inode->i_fsnotify_marks,
536*4882a593Smuzhiyun FSNOTIFY_OBJ_TYPE_INODE, allow_dups, NULL);
537*4882a593Smuzhiyun }
fsnotify_add_inode_mark_locked(struct fsnotify_mark * mark,struct inode * inode,int allow_dups)538*4882a593Smuzhiyun static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark,
539*4882a593Smuzhiyun struct inode *inode,
540*4882a593Smuzhiyun int allow_dups)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun return fsnotify_add_mark_locked(mark, &inode->i_fsnotify_marks,
543*4882a593Smuzhiyun FSNOTIFY_OBJ_TYPE_INODE, allow_dups,
544*4882a593Smuzhiyun NULL);
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun /* given a group and a mark, flag mark to be freed when all references are dropped */
548*4882a593Smuzhiyun extern void fsnotify_destroy_mark(struct fsnotify_mark *mark,
549*4882a593Smuzhiyun struct fsnotify_group *group);
550*4882a593Smuzhiyun /* detach mark from inode / mount list, group list, drop inode reference */
551*4882a593Smuzhiyun extern void fsnotify_detach_mark(struct fsnotify_mark *mark);
552*4882a593Smuzhiyun /* free mark */
553*4882a593Smuzhiyun extern void fsnotify_free_mark(struct fsnotify_mark *mark);
554*4882a593Smuzhiyun /* Wait until all marks queued for destruction are destroyed */
555*4882a593Smuzhiyun extern void fsnotify_wait_marks_destroyed(void);
556*4882a593Smuzhiyun /* run all the marks in a group, and clear all of the marks attached to given object type */
557*4882a593Smuzhiyun extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group, unsigned int type);
558*4882a593Smuzhiyun /* run all the marks in a group, and clear all of the vfsmount marks */
fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group * group)559*4882a593Smuzhiyun static inline void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL);
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun /* run all the marks in a group, and clear all of the inode marks */
fsnotify_clear_inode_marks_by_group(struct fsnotify_group * group)564*4882a593Smuzhiyun static inline void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group)
565*4882a593Smuzhiyun {
566*4882a593Smuzhiyun fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE_FL);
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun /* run all the marks in a group, and clear all of the sn marks */
fsnotify_clear_sb_marks_by_group(struct fsnotify_group * group)569*4882a593Smuzhiyun static inline void fsnotify_clear_sb_marks_by_group(struct fsnotify_group *group)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_SB_FL);
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun extern void fsnotify_get_mark(struct fsnotify_mark *mark);
574*4882a593Smuzhiyun extern void fsnotify_put_mark(struct fsnotify_mark *mark);
575*4882a593Smuzhiyun extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info);
576*4882a593Smuzhiyun extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info);
577*4882a593Smuzhiyun
fsnotify_init_event(struct fsnotify_event * event,unsigned long objectid)578*4882a593Smuzhiyun static inline void fsnotify_init_event(struct fsnotify_event *event,
579*4882a593Smuzhiyun unsigned long objectid)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun INIT_LIST_HEAD(&event->list);
582*4882a593Smuzhiyun event->objectid = objectid;
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun #else
586*4882a593Smuzhiyun
fsnotify(__u32 mask,const void * data,int data_type,struct inode * dir,const struct qstr * name,struct inode * inode,u32 cookie)587*4882a593Smuzhiyun static inline int fsnotify(__u32 mask, const void *data, int data_type,
588*4882a593Smuzhiyun struct inode *dir, const struct qstr *name,
589*4882a593Smuzhiyun struct inode *inode, u32 cookie)
590*4882a593Smuzhiyun {
591*4882a593Smuzhiyun return 0;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun
__fsnotify_parent(struct dentry * dentry,__u32 mask,const void * data,int data_type)594*4882a593Smuzhiyun static inline int __fsnotify_parent(struct dentry *dentry, __u32 mask,
595*4882a593Smuzhiyun const void *data, int data_type)
596*4882a593Smuzhiyun {
597*4882a593Smuzhiyun return 0;
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun
__fsnotify_inode_delete(struct inode * inode)600*4882a593Smuzhiyun static inline void __fsnotify_inode_delete(struct inode *inode)
601*4882a593Smuzhiyun {}
602*4882a593Smuzhiyun
__fsnotify_vfsmount_delete(struct vfsmount * mnt)603*4882a593Smuzhiyun static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
604*4882a593Smuzhiyun {}
605*4882a593Smuzhiyun
fsnotify_sb_delete(struct super_block * sb)606*4882a593Smuzhiyun static inline void fsnotify_sb_delete(struct super_block *sb)
607*4882a593Smuzhiyun {}
608*4882a593Smuzhiyun
fsnotify_update_flags(struct dentry * dentry)609*4882a593Smuzhiyun static inline void fsnotify_update_flags(struct dentry *dentry)
610*4882a593Smuzhiyun {}
611*4882a593Smuzhiyun
fsnotify_get_cookie(void)612*4882a593Smuzhiyun static inline u32 fsnotify_get_cookie(void)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun return 0;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun
fsnotify_unmount_inodes(struct super_block * sb)617*4882a593Smuzhiyun static inline void fsnotify_unmount_inodes(struct super_block *sb)
618*4882a593Smuzhiyun {}
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun #endif /* CONFIG_FSNOTIFY */
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun #endif /* __KERNEL __ */
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun #endif /* __LINUX_FSNOTIFY_BACKEND_H */
625