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