aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/fsnotify.h115
-rw-r--r--include/linux/fsnotify_backend.h177
2 files changed, 257 insertions, 35 deletions
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 00fbd5b245c9..6c9ebefdac8e 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -13,6 +13,7 @@
13 13
14#include <linux/dnotify.h> 14#include <linux/dnotify.h>
15#include <linux/inotify.h> 15#include <linux/inotify.h>
16#include <linux/fsnotify_backend.h>
16#include <linux/audit.h> 17#include <linux/audit.h>
17 18
18/* 19/*
@@ -35,6 +36,16 @@ static inline void fsnotify_d_move(struct dentry *entry)
35} 36}
36 37
37/* 38/*
39 * fsnotify_link_count - inode's link count changed
40 */
41static inline void fsnotify_link_count(struct inode *inode)
42{
43 inotify_inode_queue_event(inode, IN_ATTRIB, 0, NULL, NULL);
44
45 fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE);
46}
47
48/*
38 * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir 49 * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
39 */ 50 */
40static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, 51static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
@@ -43,28 +54,47 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
43{ 54{
44 struct inode *source = moved->d_inode; 55 struct inode *source = moved->d_inode;
45 u32 cookie = inotify_get_cookie(); 56 u32 cookie = inotify_get_cookie();
57 __u32 old_dir_mask = 0;
58 __u32 new_dir_mask = 0;
46 59
47 if (old_dir == new_dir) 60 if (old_dir == new_dir) {
48 inode_dir_notify(old_dir, DN_RENAME); 61 inode_dir_notify(old_dir, DN_RENAME);
49 else { 62 old_dir_mask = FS_DN_RENAME;
63 } else {
50 inode_dir_notify(old_dir, DN_DELETE); 64 inode_dir_notify(old_dir, DN_DELETE);
65 old_dir_mask = FS_DELETE;
51 inode_dir_notify(new_dir, DN_CREATE); 66 inode_dir_notify(new_dir, DN_CREATE);
67 new_dir_mask = FS_CREATE;
52 } 68 }
53 69
54 if (isdir) 70 if (isdir) {
55 isdir = IN_ISDIR; 71 isdir = IN_ISDIR;
72 old_dir_mask |= FS_IN_ISDIR;
73 new_dir_mask |= FS_IN_ISDIR;
74 }
75
76 old_dir_mask |= FS_MOVED_FROM;
77 new_dir_mask |= FS_MOVED_TO;
78
56 inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name, 79 inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name,
57 source); 80 source);
58 inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name, 81 inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name,
59 source); 82 source);
60 83
84 fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE);
85 fsnotify(new_dir, new_dir_mask, new_dir, FSNOTIFY_EVENT_INODE);
86
61 if (target) { 87 if (target) {
62 inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL, NULL); 88 inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL, NULL);
63 inotify_inode_is_dead(target); 89 inotify_inode_is_dead(target);
90
91 /* this is really a link_count change not a removal */
92 fsnotify_link_count(target);
64 } 93 }
65 94
66 if (source) { 95 if (source) {
67 inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL); 96 inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
97 fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE);
68 } 98 }
69 audit_inode_child(new_name, moved, new_dir); 99 audit_inode_child(new_name, moved, new_dir);
70} 100}
@@ -74,10 +104,12 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
74 */ 104 */
75static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) 105static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
76{ 106{
107 __u32 mask = FS_DELETE;
108
77 if (isdir) 109 if (isdir)
78 isdir = IN_ISDIR; 110 mask |= FS_IN_ISDIR;
79 dnotify_parent(dentry, DN_DELETE); 111 dnotify_parent(dentry, DN_DELETE);
80 inotify_dentry_parent_queue_event(dentry, IN_DELETE|isdir, 0, dentry->d_name.name); 112 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
81} 113}
82 114
83/* 115/*
@@ -87,14 +119,8 @@ static inline void fsnotify_inoderemove(struct inode *inode)
87{ 119{
88 inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL, NULL); 120 inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL, NULL);
89 inotify_inode_is_dead(inode); 121 inotify_inode_is_dead(inode);
90}
91 122
92/* 123 fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE);
93 * fsnotify_link_count - inode's link count changed
94 */
95static inline void fsnotify_link_count(struct inode *inode)
96{
97 inotify_inode_queue_event(inode, IN_ATTRIB, 0, NULL, NULL);
98} 124}
99 125
100/* 126/*
@@ -106,6 +132,8 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
106 inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name, 132 inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name,
107 dentry->d_inode); 133 dentry->d_inode);
108 audit_inode_child(dentry->d_name.name, dentry, inode); 134 audit_inode_child(dentry->d_name.name, dentry, inode);
135
136 fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE);
109} 137}
110 138
111/* 139/*
@@ -120,6 +148,8 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct
120 inode); 148 inode);
121 fsnotify_link_count(inode); 149 fsnotify_link_count(inode);
122 audit_inode_child(new_dentry->d_name.name, new_dentry, dir); 150 audit_inode_child(new_dentry->d_name.name, new_dentry, dir);
151
152 fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE);
123} 153}
124 154
125/* 155/*
@@ -127,10 +157,14 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct
127 */ 157 */
128static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) 158static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
129{ 159{
160 __u32 mask = (FS_CREATE | FS_IN_ISDIR);
161 struct inode *d_inode = dentry->d_inode;
162
130 inode_dir_notify(inode, DN_CREATE); 163 inode_dir_notify(inode, DN_CREATE);
131 inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, 164 inotify_inode_queue_event(inode, mask, 0, dentry->d_name.name, d_inode);
132 dentry->d_name.name, dentry->d_inode);
133 audit_inode_child(dentry->d_name.name, dentry, inode); 165 audit_inode_child(dentry->d_name.name, dentry, inode);
166
167 fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE);
134} 168}
135 169
136/* 170/*
@@ -139,14 +173,16 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
139static inline void fsnotify_access(struct dentry *dentry) 173static inline void fsnotify_access(struct dentry *dentry)
140{ 174{
141 struct inode *inode = dentry->d_inode; 175 struct inode *inode = dentry->d_inode;
142 u32 mask = IN_ACCESS; 176 __u32 mask = FS_ACCESS;
143 177
144 if (S_ISDIR(inode->i_mode)) 178 if (S_ISDIR(inode->i_mode))
145 mask |= IN_ISDIR; 179 mask |= FS_IN_ISDIR;
146 180
147 dnotify_parent(dentry, DN_ACCESS); 181 dnotify_parent(dentry, DN_ACCESS);
148 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); 182 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
149 inotify_inode_queue_event(inode, mask, 0, NULL, NULL); 183 inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
184
185 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE);
150} 186}
151 187
152/* 188/*
@@ -155,14 +191,16 @@ static inline void fsnotify_access(struct dentry *dentry)
155static inline void fsnotify_modify(struct dentry *dentry) 191static inline void fsnotify_modify(struct dentry *dentry)
156{ 192{
157 struct inode *inode = dentry->d_inode; 193 struct inode *inode = dentry->d_inode;
158 u32 mask = IN_MODIFY; 194 __u32 mask = FS_MODIFY;
159 195
160 if (S_ISDIR(inode->i_mode)) 196 if (S_ISDIR(inode->i_mode))
161 mask |= IN_ISDIR; 197 mask |= FS_IN_ISDIR;
162 198
163 dnotify_parent(dentry, DN_MODIFY); 199 dnotify_parent(dentry, DN_MODIFY);
164 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); 200 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
165 inotify_inode_queue_event(inode, mask, 0, NULL, NULL); 201 inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
202
203 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE);
166} 204}
167 205
168/* 206/*
@@ -171,13 +209,15 @@ static inline void fsnotify_modify(struct dentry *dentry)
171static inline void fsnotify_open(struct dentry *dentry) 209static inline void fsnotify_open(struct dentry *dentry)
172{ 210{
173 struct inode *inode = dentry->d_inode; 211 struct inode *inode = dentry->d_inode;
174 u32 mask = IN_OPEN; 212 __u32 mask = FS_OPEN;
175 213
176 if (S_ISDIR(inode->i_mode)) 214 if (S_ISDIR(inode->i_mode))
177 mask |= IN_ISDIR; 215 mask |= FS_IN_ISDIR;
178 216
179 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); 217 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
180 inotify_inode_queue_event(inode, mask, 0, NULL, NULL); 218 inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
219
220 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE);
181} 221}
182 222
183/* 223/*
@@ -189,13 +229,15 @@ static inline void fsnotify_close(struct file *file)
189 struct inode *inode = dentry->d_inode; 229 struct inode *inode = dentry->d_inode;
190 const char *name = dentry->d_name.name; 230 const char *name = dentry->d_name.name;
191 fmode_t mode = file->f_mode; 231 fmode_t mode = file->f_mode;
192 u32 mask = (mode & FMODE_WRITE) ? IN_CLOSE_WRITE : IN_CLOSE_NOWRITE; 232 __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE;
193 233
194 if (S_ISDIR(inode->i_mode)) 234 if (S_ISDIR(inode->i_mode))
195 mask |= IN_ISDIR; 235 mask |= FS_IN_ISDIR;
196 236
197 inotify_dentry_parent_queue_event(dentry, mask, 0, name); 237 inotify_dentry_parent_queue_event(dentry, mask, 0, name);
198 inotify_inode_queue_event(inode, mask, 0, NULL, NULL); 238 inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
239
240 fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE);
199} 241}
200 242
201/* 243/*
@@ -204,13 +246,15 @@ static inline void fsnotify_close(struct file *file)
204static inline void fsnotify_xattr(struct dentry *dentry) 246static inline void fsnotify_xattr(struct dentry *dentry)
205{ 247{
206 struct inode *inode = dentry->d_inode; 248 struct inode *inode = dentry->d_inode;
207 u32 mask = IN_ATTRIB; 249 __u32 mask = FS_ATTRIB;
208 250
209 if (S_ISDIR(inode->i_mode)) 251 if (S_ISDIR(inode->i_mode))
210 mask |= IN_ISDIR; 252 mask |= FS_IN_ISDIR;
211 253
212 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); 254 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
213 inotify_inode_queue_event(inode, mask, 0, NULL, NULL); 255 inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
256
257 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE);
214} 258}
215 259
216/* 260/*
@@ -221,34 +265,34 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
221{ 265{
222 struct inode *inode = dentry->d_inode; 266 struct inode *inode = dentry->d_inode;
223 int dn_mask = 0; 267 int dn_mask = 0;
224 u32 in_mask = 0; 268 __u32 in_mask = 0;
225 269
226 if (ia_valid & ATTR_UID) { 270 if (ia_valid & ATTR_UID) {
227 in_mask |= IN_ATTRIB; 271 in_mask |= FS_ATTRIB;
228 dn_mask |= DN_ATTRIB; 272 dn_mask |= DN_ATTRIB;
229 } 273 }
230 if (ia_valid & ATTR_GID) { 274 if (ia_valid & ATTR_GID) {
231 in_mask |= IN_ATTRIB; 275 in_mask |= FS_ATTRIB;
232 dn_mask |= DN_ATTRIB; 276 dn_mask |= DN_ATTRIB;
233 } 277 }
234 if (ia_valid & ATTR_SIZE) { 278 if (ia_valid & ATTR_SIZE) {
235 in_mask |= IN_MODIFY; 279 in_mask |= FS_MODIFY;
236 dn_mask |= DN_MODIFY; 280 dn_mask |= DN_MODIFY;
237 } 281 }
238 /* both times implies a utime(s) call */ 282 /* both times implies a utime(s) call */
239 if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) 283 if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
240 { 284 {
241 in_mask |= IN_ATTRIB; 285 in_mask |= FS_ATTRIB;
242 dn_mask |= DN_ATTRIB; 286 dn_mask |= DN_ATTRIB;
243 } else if (ia_valid & ATTR_ATIME) { 287 } else if (ia_valid & ATTR_ATIME) {
244 in_mask |= IN_ACCESS; 288 in_mask |= FS_ACCESS;
245 dn_mask |= DN_ACCESS; 289 dn_mask |= DN_ACCESS;
246 } else if (ia_valid & ATTR_MTIME) { 290 } else if (ia_valid & ATTR_MTIME) {
247 in_mask |= IN_MODIFY; 291 in_mask |= FS_MODIFY;
248 dn_mask |= DN_MODIFY; 292 dn_mask |= DN_MODIFY;
249 } 293 }
250 if (ia_valid & ATTR_MODE) { 294 if (ia_valid & ATTR_MODE) {
251 in_mask |= IN_ATTRIB; 295 in_mask |= FS_ATTRIB;
252 dn_mask |= DN_ATTRIB; 296 dn_mask |= DN_ATTRIB;
253 } 297 }
254 298
@@ -256,14 +300,15 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
256 dnotify_parent(dentry, dn_mask); 300 dnotify_parent(dentry, dn_mask);
257 if (in_mask) { 301 if (in_mask) {
258 if (S_ISDIR(inode->i_mode)) 302 if (S_ISDIR(inode->i_mode))
259 in_mask |= IN_ISDIR; 303 in_mask |= FS_IN_ISDIR;
260 inotify_inode_queue_event(inode, in_mask, 0, NULL, NULL); 304 inotify_inode_queue_event(inode, in_mask, 0, NULL, NULL);
261 inotify_dentry_parent_queue_event(dentry, in_mask, 0, 305 inotify_dentry_parent_queue_event(dentry, in_mask, 0,
262 dentry->d_name.name); 306 dentry->d_name.name);
307 fsnotify(inode, in_mask, inode, FSNOTIFY_EVENT_INODE);
263 } 308 }
264} 309}
265 310
266#ifdef CONFIG_INOTIFY /* inotify helpers */ 311#if defined(CONFIG_INOTIFY) || defined(CONFIG_FSNOTIFY) /* notify helpers */
267 312
268/* 313/*
269 * fsnotify_oldname_init - save off the old filename before we change it 314 * fsnotify_oldname_init - save off the old filename before we change it
@@ -281,7 +326,7 @@ static inline void fsnotify_oldname_free(const char *old_name)
281 kfree(old_name); 326 kfree(old_name);
282} 327}
283 328
284#else /* CONFIG_INOTIFY */ 329#else /* CONFIG_INOTIFY || CONFIG_FSNOTIFY */
285 330
286static inline const char *fsnotify_oldname_init(const char *name) 331static inline const char *fsnotify_oldname_init(const char *name)
287{ 332{
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
new file mode 100644
index 000000000000..1a55718b38aa
--- /dev/null
+++ b/include/linux/fsnotify_backend.h
@@ -0,0 +1,177 @@
1/*
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/fs.h> /* struct inode */
13#include <linux/list.h>
14#include <linux/path.h> /* struct path */
15#include <linux/spinlock.h>
16#include <linux/types.h>
17
18#include <asm/atomic.h>
19
20/*
21 * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily
22 * convert between them. dnotify only needs conversion at watch creation
23 * so no perf loss there. fanotify isn't defined yet, so it can use the
24 * wholes if it needs more events.
25 */
26#define FS_ACCESS 0x00000001 /* File was accessed */
27#define FS_MODIFY 0x00000002 /* File was modified */
28#define FS_ATTRIB 0x00000004 /* Metadata changed */
29#define FS_CLOSE_WRITE 0x00000008 /* Writtable file was closed */
30#define FS_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
31#define FS_OPEN 0x00000020 /* File was opened */
32#define FS_MOVED_FROM 0x00000040 /* File was moved from X */
33#define FS_MOVED_TO 0x00000080 /* File was moved to Y */
34#define FS_CREATE 0x00000100 /* Subfile was created */
35#define FS_DELETE 0x00000200 /* Subfile was deleted */
36#define FS_DELETE_SELF 0x00000400 /* Self was deleted */
37#define FS_MOVE_SELF 0x00000800 /* Self was moved */
38
39#define FS_UNMOUNT 0x00002000 /* inode on umount fs */
40#define FS_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
41#define FS_IN_IGNORED 0x00008000 /* last inotify event here */
42
43#define FS_IN_ISDIR 0x40000000 /* event occurred against dir */
44#define FS_IN_ONESHOT 0x80000000 /* only send event once */
45
46#define FS_DN_RENAME 0x10000000 /* file renamed */
47#define FS_DN_MULTISHOT 0x20000000 /* dnotify multishot */
48
49struct fsnotify_group;
50struct fsnotify_event;
51
52/*
53 * Each group much define these ops. The fsnotify infrastructure will call
54 * these operations for each relevant group.
55 *
56 * handle_event - main call for a group to handle an fs event
57 * free_group_priv - called when a group refcnt hits 0 to clean up the private union
58 */
59struct fsnotify_ops {
60 int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event);
61 void (*free_group_priv)(struct fsnotify_group *group);
62};
63
64/*
65 * A group is a "thing" that wants to receive notification about filesystem
66 * events. The mask holds the subset of event types this group cares about.
67 * refcnt on a group is up to the implementor and at any moment if it goes 0
68 * everything will be cleaned up.
69 */
70struct fsnotify_group {
71 /*
72 * global list of all groups receiving events from fsnotify.
73 * anchored by fsnotify_groups and protected by either fsnotify_grp_mutex
74 * or fsnotify_grp_srcu depending on write vs read.
75 */
76 struct list_head group_list;
77
78 /*
79 * Defines all of the event types in which this group is interested.
80 * This mask is a bitwise OR of the FS_* events from above. Each time
81 * this mask changes for a group (if it changes) the correct functions
82 * must be called to update the global structures which indicate global
83 * interest in event types.
84 */
85 __u32 mask;
86
87 /*
88 * How the refcnt is used is up to each group. When the refcnt hits 0
89 * fsnotify will clean up all of the resources associated with this group.
90 * As an example, the dnotify group will always have a refcnt=1 and that
91 * will never change. Inotify, on the other hand, has a group per
92 * inotify_init() and the refcnt will hit 0 only when that fd has been
93 * closed.
94 */
95 atomic_t refcnt; /* things with interest in this group */
96 unsigned int group_num; /* simply prevents accidental group collision */
97
98 const struct fsnotify_ops *ops; /* how this group handles things */
99
100 /* prevents double list_del of group_list. protected by global fsnotify_gr_mutex */
101 bool on_group_list;
102
103 /* groups can define private fields here or use the void *private */
104 union {
105 void *private;
106 };
107};
108
109/*
110 * all of the information about the original object we want to now send to
111 * a group. If you want to carry more info from the accessing task to the
112 * listener this structure is where you need to be adding fields.
113 */
114struct fsnotify_event {
115 spinlock_t lock; /* protection for the associated event_holder and private_list */
116 /* to_tell may ONLY be dereferenced during handle_event(). */
117 struct inode *to_tell; /* either the inode the event happened to or its parent */
118 /*
119 * depending on the event type we should have either a path or inode
120 * We hold a reference on path, but NOT on inode. Since we have the ref on
121 * the path, it may be dereferenced at any point during this object's
122 * lifetime. That reference is dropped when this object's refcnt hits
123 * 0. If this event contains an inode instead of a path, the inode may
124 * ONLY be used during handle_event().
125 */
126 union {
127 struct path path;
128 struct inode *inode;
129 };
130/* when calling fsnotify tell it if the data is a path or inode */
131#define FSNOTIFY_EVENT_NONE 0
132#define FSNOTIFY_EVENT_PATH 1
133#define FSNOTIFY_EVENT_INODE 2
134#define FSNOTIFY_EVENT_FILE 3
135 int data_type; /* which of the above union we have */
136 atomic_t refcnt; /* how many groups still are using/need to send this event */
137 __u32 mask; /* the type of access, bitwise OR for FS_* event types */
138};
139
140#ifdef CONFIG_FSNOTIFY
141
142/* called from the vfs helpers */
143
144/* main fsnotify call to send events */
145extern void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is);
146
147
148/* called from fsnotify listeners, such as fanotify or dnotify */
149
150/* must call when a group changes its ->mask */
151extern void fsnotify_recalc_global_mask(void);
152/* get a reference to an existing or create a new group */
153extern struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num,
154 __u32 mask,
155 const struct fsnotify_ops *ops);
156/* drop reference on a group from fsnotify_obtain_group */
157extern void fsnotify_put_group(struct fsnotify_group *group);
158
159/* take a reference to an event */
160extern void fsnotify_get_event(struct fsnotify_event *event);
161extern void fsnotify_put_event(struct fsnotify_event *event);
162/* find private data previously attached to an event */
163extern struct fsnotify_event_private_data *fsnotify_get_priv_from_event(struct fsnotify_group *group,
164 struct fsnotify_event *event);
165
166/* put here because inotify does some weird stuff when destroying watches */
167extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
168 void *data, int data_is);
169#else
170
171static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is)
172{}
173#endif /* CONFIG_FSNOTIFY */
174
175#endif /* __KERNEL __ */
176
177#endif /* __LINUX_FSNOTIFY_BACKEND_H */