fsnotify: pass a file instead of an inode to open, read, and write
[linux-2.6-block.git] / include / linux / fsnotify.h
1 #ifndef _LINUX_FS_NOTIFY_H
2 #define _LINUX_FS_NOTIFY_H
3
4 /*
5  * include/linux/fsnotify.h - generic hooks for filesystem notification, to
6  * reduce in-source duplication from both dnotify and inotify.
7  *
8  * We don't compile any of this away in some complicated menagerie of ifdefs.
9  * Instead, we rely on the code inside to optimize away as needed.
10  *
11  * (C) Copyright 2005 Robert Love
12  */
13
14 #include <linux/fsnotify_backend.h>
15 #include <linux/audit.h>
16 #include <linux/slab.h>
17
18 /*
19  * fsnotify_d_instantiate - instantiate a dentry for inode
20  * Called with dcache_lock held.
21  */
22 static inline void fsnotify_d_instantiate(struct dentry *entry,
23                                                 struct inode *inode)
24 {
25         __fsnotify_d_instantiate(entry, inode);
26 }
27
28 /* Notify this dentry's parent about a child's events. */
29 static inline void fsnotify_parent(struct dentry *dentry, __u32 mask)
30 {
31         __fsnotify_parent(dentry, mask);
32 }
33
34 /*
35  * fsnotify_d_move - entry has been moved
36  * Called with dcache_lock and entry->d_lock held.
37  */
38 static inline void fsnotify_d_move(struct dentry *entry)
39 {
40         /*
41          * On move we need to update entry->d_flags to indicate if the new parent
42          * cares about events from this entry.
43          */
44         __fsnotify_update_dcache_flags(entry);
45 }
46
47 /*
48  * fsnotify_link_count - inode's link count changed
49  */
50 static inline void fsnotify_link_count(struct inode *inode)
51 {
52         fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
53 }
54
55 /*
56  * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
57  */
58 static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
59                                  const char *old_name,
60                                  int isdir, struct inode *target, struct dentry *moved)
61 {
62         struct inode *source = moved->d_inode;
63         u32 fs_cookie = fsnotify_get_cookie();
64         __u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM);
65         __u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO);
66         const char *new_name = moved->d_name.name;
67
68         if (old_dir == new_dir)
69                 old_dir_mask |= FS_DN_RENAME;
70
71         if (isdir) {
72                 old_dir_mask |= FS_IN_ISDIR;
73                 new_dir_mask |= FS_IN_ISDIR;
74         }
75
76         fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie);
77         fsnotify(new_dir, new_dir_mask, new_dir, FSNOTIFY_EVENT_INODE, new_name, fs_cookie);
78
79         if (target)
80                 fsnotify_link_count(target);
81
82         if (source)
83                 fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
84         audit_inode_child(moved, new_dir);
85 }
86
87 /*
88  * fsnotify_inode_delete - and inode is being evicted from cache, clean up is needed
89  */
90 static inline void fsnotify_inode_delete(struct inode *inode)
91 {
92         __fsnotify_inode_delete(inode);
93 }
94
95 /*
96  * fsnotify_nameremove - a filename was removed from a directory
97  */
98 static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
99 {
100         __u32 mask = FS_DELETE;
101
102         if (isdir)
103                 mask |= FS_IN_ISDIR;
104
105         fsnotify_parent(dentry, mask);
106 }
107
108 /*
109  * fsnotify_inoderemove - an inode is going away
110  */
111 static inline void fsnotify_inoderemove(struct inode *inode)
112 {
113         fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
114         __fsnotify_inode_delete(inode);
115 }
116
117 /*
118  * fsnotify_create - 'name' was linked in
119  */
120 static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
121 {
122         audit_inode_child(dentry, inode);
123
124         fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
125 }
126
127 /*
128  * fsnotify_link - new hardlink in 'inode' directory
129  * Note: We have to pass also the linked inode ptr as some filesystems leave
130  *   new_dentry->d_inode NULL and instantiate inode pointer later
131  */
132 static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
133 {
134         fsnotify_link_count(inode);
135         audit_inode_child(new_dentry, dir);
136
137         fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
138 }
139
140 /*
141  * fsnotify_mkdir - directory 'name' was created
142  */
143 static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
144 {
145         __u32 mask = (FS_CREATE | FS_IN_ISDIR);
146         struct inode *d_inode = dentry->d_inode;
147
148         audit_inode_child(dentry, inode);
149
150         fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
151 }
152
153 /*
154  * fsnotify_access - file was read
155  */
156 static inline void fsnotify_access(struct file *file)
157 {
158         struct dentry *dentry = file->f_path.dentry;
159         struct inode *inode = dentry->d_inode;
160         __u32 mask = FS_ACCESS;
161
162         if (S_ISDIR(inode->i_mode))
163                 mask |= FS_IN_ISDIR;
164
165         fsnotify_parent(dentry, mask);
166         fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0);
167 }
168
169 /*
170  * fsnotify_modify - file was modified
171  */
172 static inline void fsnotify_modify(struct file *file)
173 {
174         struct dentry *dentry = file->f_path.dentry;
175         struct inode *inode = dentry->d_inode;
176         __u32 mask = FS_MODIFY;
177
178         if (S_ISDIR(inode->i_mode))
179                 mask |= FS_IN_ISDIR;
180
181         fsnotify_parent(dentry, mask);
182         fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0);
183 }
184
185 /*
186  * fsnotify_open - file was opened
187  */
188 static inline void fsnotify_open(struct file *file)
189 {
190         struct dentry *dentry = file->f_path.dentry;
191         struct inode *inode = dentry->d_inode;
192         __u32 mask = FS_OPEN;
193
194         if (S_ISDIR(inode->i_mode))
195                 mask |= FS_IN_ISDIR;
196
197         fsnotify_parent(dentry, mask);
198         fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0);
199 }
200
201 /*
202  * fsnotify_close - file was closed
203  */
204 static inline void fsnotify_close(struct file *file)
205 {
206         struct dentry *dentry = file->f_path.dentry;
207         struct inode *inode = dentry->d_inode;
208         fmode_t mode = file->f_mode;
209         __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE;
210
211         if (S_ISDIR(inode->i_mode))
212                 mask |= FS_IN_ISDIR;
213
214         fsnotify_parent(dentry, mask);
215         fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0);
216 }
217
218 /*
219  * fsnotify_xattr - extended attributes were changed
220  */
221 static inline void fsnotify_xattr(struct dentry *dentry)
222 {
223         struct inode *inode = dentry->d_inode;
224         __u32 mask = FS_ATTRIB;
225
226         if (S_ISDIR(inode->i_mode))
227                 mask |= FS_IN_ISDIR;
228
229         fsnotify_parent(dentry, mask);
230         fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
231 }
232
233 /*
234  * fsnotify_change - notify_change event.  file was modified and/or metadata
235  * was changed.
236  */
237 static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
238 {
239         struct inode *inode = dentry->d_inode;
240         __u32 mask = 0;
241
242         if (ia_valid & ATTR_UID)
243                 mask |= FS_ATTRIB;
244         if (ia_valid & ATTR_GID)
245                 mask |= FS_ATTRIB;
246         if (ia_valid & ATTR_SIZE)
247                 mask |= FS_MODIFY;
248
249         /* both times implies a utime(s) call */
250         if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
251                 mask |= FS_ATTRIB;
252         else if (ia_valid & ATTR_ATIME)
253                 mask |= FS_ACCESS;
254         else if (ia_valid & ATTR_MTIME)
255                 mask |= FS_MODIFY;
256
257         if (ia_valid & ATTR_MODE)
258                 mask |= FS_ATTRIB;
259
260         if (mask) {
261                 if (S_ISDIR(inode->i_mode))
262                         mask |= FS_IN_ISDIR;
263                 fsnotify_parent(dentry, mask);
264                 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
265         }
266 }
267
268 #if defined(CONFIG_FSNOTIFY)    /* notify helpers */
269
270 /*
271  * fsnotify_oldname_init - save off the old filename before we change it
272  */
273 static inline const char *fsnotify_oldname_init(const char *name)
274 {
275         return kstrdup(name, GFP_KERNEL);
276 }
277
278 /*
279  * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init
280  */
281 static inline void fsnotify_oldname_free(const char *old_name)
282 {
283         kfree(old_name);
284 }
285
286 #else   /* CONFIG_INOTIFY || CONFIG_FSNOTIFY */
287
288 static inline const char *fsnotify_oldname_init(const char *name)
289 {
290         return NULL;
291 }
292
293 static inline void fsnotify_oldname_free(const char *old_name)
294 {
295 }
296
297 #endif  /* ! CONFIG_INOTIFY */
298
299 #endif  /* _LINUX_FS_NOTIFY_H */