[PATCH] Pass dentry, not just name, in fsnotify creation hooks.
[linux-2.6.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 #ifdef __KERNEL__
15
16 #include <linux/dnotify.h>
17 #include <linux/inotify.h>
18
19 /*
20  * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
21  */
22 static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
23                                  const char *old_name, const char *new_name,
24                                  int isdir, struct inode *target, struct inode *source)
25 {
26         u32 cookie = inotify_get_cookie();
27
28         if (old_dir == new_dir)
29                 inode_dir_notify(old_dir, DN_RENAME);
30         else {
31                 inode_dir_notify(old_dir, DN_DELETE);
32                 inode_dir_notify(new_dir, DN_CREATE);
33         }
34
35         if (isdir)
36                 isdir = IN_ISDIR;
37         inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name);
38         inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name);
39
40         if (target) {
41                 inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL);
42                 inotify_inode_is_dead(target);
43         }
44
45         if (source) {
46                 inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL);
47         }
48 }
49
50 /*
51  * fsnotify_nameremove - a filename was removed from a directory
52  */
53 static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
54 {
55         if (isdir)
56                 isdir = IN_ISDIR;
57         dnotify_parent(dentry, DN_DELETE);
58         inotify_dentry_parent_queue_event(dentry, IN_DELETE|isdir, 0, dentry->d_name.name);
59 }
60
61 /*
62  * fsnotify_inoderemove - an inode is going away
63  */
64 static inline void fsnotify_inoderemove(struct inode *inode)
65 {
66         inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
67         inotify_inode_is_dead(inode);
68 }
69
70 /*
71  * fsnotify_create - 'name' was linked in
72  */
73 static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
74 {
75         inode_dir_notify(inode, DN_CREATE);
76         inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name);
77 }
78
79 /*
80  * fsnotify_mkdir - directory 'name' was created
81  */
82 static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
83 {
84         inode_dir_notify(inode, DN_CREATE);
85         inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, 
86                                   dentry->d_name.name);
87 }
88
89 /*
90  * fsnotify_access - file was read
91  */
92 static inline void fsnotify_access(struct dentry *dentry)
93 {
94         struct inode *inode = dentry->d_inode;
95         u32 mask = IN_ACCESS;
96
97         if (S_ISDIR(inode->i_mode))
98                 mask |= IN_ISDIR;
99
100         dnotify_parent(dentry, DN_ACCESS);
101         inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
102         inotify_inode_queue_event(inode, mask, 0, NULL);
103 }
104
105 /*
106  * fsnotify_modify - file was modified
107  */
108 static inline void fsnotify_modify(struct dentry *dentry)
109 {
110         struct inode *inode = dentry->d_inode;
111         u32 mask = IN_MODIFY;
112
113         if (S_ISDIR(inode->i_mode))
114                 mask |= IN_ISDIR;
115
116         dnotify_parent(dentry, DN_MODIFY);
117         inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
118         inotify_inode_queue_event(inode, mask, 0, NULL);
119 }
120
121 /*
122  * fsnotify_open - file was opened
123  */
124 static inline void fsnotify_open(struct dentry *dentry)
125 {
126         struct inode *inode = dentry->d_inode;
127         u32 mask = IN_OPEN;
128
129         if (S_ISDIR(inode->i_mode))
130                 mask |= IN_ISDIR;
131
132         inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
133         inotify_inode_queue_event(inode, mask, 0, NULL);        
134 }
135
136 /*
137  * fsnotify_close - file was closed
138  */
139 static inline void fsnotify_close(struct file *file)
140 {
141         struct dentry *dentry = file->f_dentry;
142         struct inode *inode = dentry->d_inode;
143         const char *name = dentry->d_name.name;
144         mode_t mode = file->f_mode;
145         u32 mask = (mode & FMODE_WRITE) ? IN_CLOSE_WRITE : IN_CLOSE_NOWRITE;
146
147         if (S_ISDIR(inode->i_mode))
148                 mask |= IN_ISDIR;
149
150         inotify_dentry_parent_queue_event(dentry, mask, 0, name);
151         inotify_inode_queue_event(inode, mask, 0, NULL);
152 }
153
154 /*
155  * fsnotify_xattr - extended attributes were changed
156  */
157 static inline void fsnotify_xattr(struct dentry *dentry)
158 {
159         struct inode *inode = dentry->d_inode;
160         u32 mask = IN_ATTRIB;
161
162         if (S_ISDIR(inode->i_mode))
163                 mask |= IN_ISDIR;
164
165         inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
166         inotify_inode_queue_event(inode, mask, 0, NULL);
167 }
168
169 /*
170  * fsnotify_change - notify_change event.  file was modified and/or metadata
171  * was changed.
172  */
173 static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
174 {
175         struct inode *inode = dentry->d_inode;
176         int dn_mask = 0;
177         u32 in_mask = 0;
178
179         if (ia_valid & ATTR_UID) {
180                 in_mask |= IN_ATTRIB;
181                 dn_mask |= DN_ATTRIB;
182         }
183         if (ia_valid & ATTR_GID) {
184                 in_mask |= IN_ATTRIB;
185                 dn_mask |= DN_ATTRIB;
186         }
187         if (ia_valid & ATTR_SIZE) {
188                 in_mask |= IN_MODIFY;
189                 dn_mask |= DN_MODIFY;
190         }
191         /* both times implies a utime(s) call */
192         if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
193         {
194                 in_mask |= IN_ATTRIB;
195                 dn_mask |= DN_ATTRIB;
196         } else if (ia_valid & ATTR_ATIME) {
197                 in_mask |= IN_ACCESS;
198                 dn_mask |= DN_ACCESS;
199         } else if (ia_valid & ATTR_MTIME) {
200                 in_mask |= IN_MODIFY;
201                 dn_mask |= DN_MODIFY;
202         }
203         if (ia_valid & ATTR_MODE) {
204                 in_mask |= IN_ATTRIB;
205                 dn_mask |= DN_ATTRIB;
206         }
207
208         if (dn_mask)
209                 dnotify_parent(dentry, dn_mask);
210         if (in_mask) {
211                 if (S_ISDIR(inode->i_mode))
212                         in_mask |= IN_ISDIR;
213                 inotify_inode_queue_event(inode, in_mask, 0, NULL);
214                 inotify_dentry_parent_queue_event(dentry, in_mask, 0,
215                                                   dentry->d_name.name);
216         }
217 }
218
219 #ifdef CONFIG_INOTIFY   /* inotify helpers */
220
221 /*
222  * fsnotify_oldname_init - save off the old filename before we change it
223  */
224 static inline const char *fsnotify_oldname_init(const char *name)
225 {
226         return kstrdup(name, GFP_KERNEL);
227 }
228
229 /*
230  * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init
231  */
232 static inline void fsnotify_oldname_free(const char *old_name)
233 {
234         kfree(old_name);
235 }
236
237 #else   /* CONFIG_INOTIFY */
238
239 static inline const char *fsnotify_oldname_init(const char *name)
240 {
241         return NULL;
242 }
243
244 static inline void fsnotify_oldname_free(const char *old_name)
245 {
246 }
247
248 #endif  /* ! CONFIG_INOTIFY */
249
250 #endif  /* __KERNEL__ */
251
252 #endif  /* _LINUX_FS_NOTIFY_H */