blob: 9bab5816407a36e5419b699e4352e3e4247c12de [file] [log] [blame]
Nicholas Flintham1e3d3112013-04-10 10:48:38 +01001/*
2 * Filesystem access notification for Linux
3 *
4 * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
5 */
6
7#ifndef __LINUX_FSNOTIFY_BACKEND_H
8#define __LINUX_FSNOTIFY_BACKEND_H
9
10#ifdef __KERNEL__
11
12#include <linux/idr.h>
13#include <linux/fs.h>
14#include <linux/list.h>
15#include <linux/path.h>
16#include <linux/spinlock.h>
17#include <linux/types.h>
18
19#include <linux/atomic.h>
20
21#define FS_ACCESS 0x00000001
22#define FS_MODIFY 0x00000002
23#define FS_ATTRIB 0x00000004
24#define FS_CLOSE_WRITE 0x00000008
25#define FS_CLOSE_NOWRITE 0x00000010
26#define FS_OPEN 0x00000020
27#define FS_MOVED_FROM 0x00000040
28#define FS_MOVED_TO 0x00000080
29#define FS_CREATE 0x00000100
30#define FS_DELETE 0x00000200
31#define FS_DELETE_SELF 0x00000400
32#define FS_MOVE_SELF 0x00000800
33
34#define FS_UNMOUNT 0x00002000
35#define FS_Q_OVERFLOW 0x00004000
36#define FS_IN_IGNORED 0x00008000
37
38#define FS_OPEN_PERM 0x00010000
39#define FS_ACCESS_PERM 0x00020000
40
41#define FS_EXCL_UNLINK 0x04000000
42#define FS_ISDIR 0x40000000
43#define FS_IN_ONESHOT 0x80000000
44
45#define FS_DN_RENAME 0x10000000
46#define FS_DN_MULTISHOT 0x20000000
47
48#define FS_EVENT_ON_CHILD 0x08000000
49
50#define FS_EVENTS_POSS_ON_CHILD (FS_ACCESS | FS_MODIFY | FS_ATTRIB |\
51 FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN |\
52 FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\
53 FS_DELETE)
54
55#define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO)
56
57#define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM)
58
59#define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \
60 FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN | \
61 FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \
62 FS_DELETE | FS_DELETE_SELF | FS_MOVE_SELF | \
63 FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \
64 FS_OPEN_PERM | FS_ACCESS_PERM | FS_EXCL_UNLINK | \
65 FS_ISDIR | FS_IN_ONESHOT | FS_DN_RENAME | \
66 FS_DN_MULTISHOT | FS_EVENT_ON_CHILD)
67
68struct fsnotify_group;
69struct fsnotify_event;
70struct fsnotify_mark;
71struct fsnotify_event_private_data;
72
73struct fsnotify_ops {
74 bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
75 struct fsnotify_mark *inode_mark,
76 struct fsnotify_mark *vfsmount_mark,
77 __u32 mask, void *data, int data_type);
78 int (*handle_event)(struct fsnotify_group *group,
79 struct fsnotify_mark *inode_mark,
80 struct fsnotify_mark *vfsmount_mark,
81 struct fsnotify_event *event);
82 void (*free_group_priv)(struct fsnotify_group *group);
83 void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
84 void (*free_event_priv)(struct fsnotify_event_private_data *priv);
85};
86
87struct fsnotify_group {
88 atomic_t refcnt;
89
90 const struct fsnotify_ops *ops;
91
92
93 struct mutex notification_mutex;
94 struct list_head notification_list;
95 wait_queue_head_t notification_waitq;
96 unsigned int q_len;
97 unsigned int max_events;
98 #define FS_PRIO_0 0
99 #define FS_PRIO_1 1
100 #define FS_PRIO_2 2
101 unsigned int priority;
102
103
104 spinlock_t mark_lock;
105 atomic_t num_marks;
106 struct list_head marks_list;
107
108
109 union {
110 void *private;
111#ifdef CONFIG_INOTIFY_USER
112 struct inotify_group_private_data {
113 spinlock_t idr_lock;
114 struct idr idr;
115 u32 last_wd;
116 struct fasync_struct *fa;
117 struct user_struct *user;
118 } inotify_data;
119#endif
120#ifdef CONFIG_FANOTIFY
121 struct fanotify_group_private_data {
122#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
123
124 struct mutex access_mutex;
125 struct list_head access_list;
126 wait_queue_head_t access_waitq;
127 atomic_t bypass_perm;
128#endif
129 int f_flags;
130 unsigned int max_marks;
131 struct user_struct *user;
132 } fanotify_data;
133#endif
134 };
135};
136
137struct fsnotify_event_holder {
138 struct fsnotify_event *event;
139 struct list_head event_list;
140};
141
142struct fsnotify_event_private_data {
143 struct fsnotify_group *group;
144 struct list_head event_list;
145};
146
147struct fsnotify_event {
148 struct fsnotify_event_holder holder;
149 spinlock_t lock;
150
151 struct inode *to_tell;
152 union {
153 struct path path;
154 struct inode *inode;
155 };
156#define FSNOTIFY_EVENT_NONE 0
157#define FSNOTIFY_EVENT_PATH 1
158#define FSNOTIFY_EVENT_INODE 2
159 int data_type;
160 atomic_t refcnt;
161 __u32 mask;
162
163 u32 sync_cookie;
164 const unsigned char *file_name;
165 size_t name_len;
166 struct pid *tgid;
167
168#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
169 __u32 response;
170#endif
171
172 struct list_head private_data_list;
173};
174
175struct fsnotify_inode_mark {
176 struct inode *inode;
177 struct hlist_node i_list;
178 struct list_head free_i_list;
179};
180
181struct fsnotify_vfsmount_mark {
182 struct vfsmount *mnt;
183 struct hlist_node m_list;
184 struct list_head free_m_list;
185};
186
187struct fsnotify_mark {
188 __u32 mask;
189 atomic_t refcnt;
190 struct fsnotify_group *group;
191 struct list_head g_list;
192 spinlock_t lock;
193 union {
194 struct fsnotify_inode_mark i;
195 struct fsnotify_vfsmount_mark m;
196 };
197 struct list_head free_g_list;
198 __u32 ignored_mask;
199#define FSNOTIFY_MARK_FLAG_INODE 0x01
200#define FSNOTIFY_MARK_FLAG_VFSMOUNT 0x02
201#define FSNOTIFY_MARK_FLAG_OBJECT_PINNED 0x04
202#define FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY 0x08
203#define FSNOTIFY_MARK_FLAG_ALIVE 0x10
204 unsigned int flags;
205 struct list_head destroy_list;
206 void (*free_mark)(struct fsnotify_mark *mark);
207};
208
209#ifdef CONFIG_FSNOTIFY
210
211
212extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
213 const unsigned char *name, u32 cookie);
214extern int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask);
215extern void __fsnotify_inode_delete(struct inode *inode);
216extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
217extern u32 fsnotify_get_cookie(void);
218
219static inline int fsnotify_inode_watches_children(struct inode *inode)
220{
221
222 if (!(inode->i_fsnotify_mask & FS_EVENT_ON_CHILD))
223 return 0;
224 return inode->i_fsnotify_mask & FS_EVENTS_POSS_ON_CHILD;
225}
226
227static inline void __fsnotify_update_dcache_flags(struct dentry *dentry)
228{
229 struct dentry *parent;
230
231 assert_spin_locked(&dentry->d_lock);
232
233 parent = dentry->d_parent;
234 if (parent->d_inode && fsnotify_inode_watches_children(parent->d_inode))
235 dentry->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
236 else
237 dentry->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED;
238}
239
240static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode *inode)
241{
242 if (!inode)
243 return;
244
245 spin_lock(&dentry->d_lock);
246 __fsnotify_update_dcache_flags(dentry);
247 spin_unlock(&dentry->d_lock);
248}
249
250
251extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops);
252extern void fsnotify_put_group(struct fsnotify_group *group);
253
254extern void fsnotify_get_event(struct fsnotify_event *event);
255extern void fsnotify_put_event(struct fsnotify_event *event);
256extern struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struct fsnotify_group *group,
257 struct fsnotify_event *event);
258
259extern struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
260 struct fsnotify_event *event,
261 struct fsnotify_event_private_data *priv,
262 struct fsnotify_event *(*merge)(struct list_head *,
263 struct fsnotify_event *));
264extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group);
265extern struct fsnotify_event *fsnotify_peek_notify_event(struct fsnotify_group *group);
266extern struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group *group);
267
268
269extern void fsnotify_recalc_vfsmount_mask(struct vfsmount *mnt);
270extern void fsnotify_recalc_inode_mask(struct inode *inode);
271extern void fsnotify_init_mark(struct fsnotify_mark *mark, void (*free_mark)(struct fsnotify_mark *mark));
272extern struct fsnotify_mark *fsnotify_find_inode_mark(struct fsnotify_group *group, struct inode *inode);
273extern struct fsnotify_mark *fsnotify_find_vfsmount_mark(struct fsnotify_group *group, struct vfsmount *mnt);
274extern void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old);
275extern void fsnotify_set_mark_ignored_mask_locked(struct fsnotify_mark *mark, __u32 mask);
276extern void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask);
277extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
278 struct inode *inode, struct vfsmount *mnt, int allow_dups);
279extern void fsnotify_destroy_mark(struct fsnotify_mark *mark);
280extern void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group);
281extern void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group);
282extern void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, unsigned int flags);
283extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group);
284extern void fsnotify_get_mark(struct fsnotify_mark *mark);
285extern void fsnotify_put_mark(struct fsnotify_mark *mark);
286extern void fsnotify_unmount_inodes(struct list_head *list);
287
288extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
289 void *data, int data_is,
290 const unsigned char *name,
291 u32 cookie, gfp_t gfp);
292
293extern struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event);
294extern int fsnotify_replace_event(struct fsnotify_event_holder *old_holder,
295 struct fsnotify_event *new_event);
296
297#else
298
299static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
300 const unsigned char *name, u32 cookie)
301{
302 return 0;
303}
304
305static inline int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
306{
307 return 0;
308}
309
310static inline void __fsnotify_inode_delete(struct inode *inode)
311{}
312
313static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
314{}
315
316static inline void __fsnotify_update_dcache_flags(struct dentry *dentry)
317{}
318
319static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode *inode)
320{}
321
322static inline u32 fsnotify_get_cookie(void)
323{
324 return 0;
325}
326
327static inline void fsnotify_unmount_inodes(struct list_head *list)
328{}
329
330#endif
331
332#endif
333
334#endif