diff options
-rw-r--r-- | fs/notify/fsnotify.c | 6 | ||||
-rw-r--r-- | fs/notify/notification.c | 20 | ||||
-rw-r--r-- | include/linux/fsnotify.h | 35 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 15 |
4 files changed, 51 insertions, 25 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 675129fa9fdd..f11d75f02368 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -115,7 +115,7 @@ void __fsnotify_parent(struct dentry *dentry, __u32 mask) | |||
115 | mask |= FS_EVENT_ON_CHILD; | 115 | mask |= FS_EVENT_ON_CHILD; |
116 | 116 | ||
117 | fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, | 117 | fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, |
118 | dentry->d_name.name); | 118 | dentry->d_name.name, 0); |
119 | dput(parent); | 119 | dput(parent); |
120 | } | 120 | } |
121 | 121 | ||
@@ -132,7 +132,7 @@ EXPORT_SYMBOL_GPL(__fsnotify_parent); | |||
132 | * out to all of the registered fsnotify_group. Those groups can then use the | 132 | * out to all of the registered fsnotify_group. Those groups can then use the |
133 | * notification event in whatever means they feel necessary. | 133 | * notification event in whatever means they feel necessary. |
134 | */ | 134 | */ |
135 | void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const char *file_name) | 135 | void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const char *file_name, u32 cookie) |
136 | { | 136 | { |
137 | struct fsnotify_group *group; | 137 | struct fsnotify_group *group; |
138 | struct fsnotify_event *event = NULL; | 138 | struct fsnotify_event *event = NULL; |
@@ -157,7 +157,7 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const | |||
157 | if (!group->ops->should_send_event(group, to_tell, mask)) | 157 | if (!group->ops->should_send_event(group, to_tell, mask)) |
158 | continue; | 158 | continue; |
159 | if (!event) { | 159 | if (!event) { |
160 | event = fsnotify_create_event(to_tell, mask, data, data_is, file_name); | 160 | event = fsnotify_create_event(to_tell, mask, data, data_is, file_name, cookie); |
161 | /* shit, we OOM'd and now we can't tell, maybe | 161 | /* shit, we OOM'd and now we can't tell, maybe |
162 | * someday someone else will want to do something | 162 | * someday someone else will want to do something |
163 | * here */ | 163 | * here */ |
diff --git a/fs/notify/notification.c b/fs/notify/notification.c index c69b18b9aba5..346f6e5c3553 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
37 | #include <linux/list.h> | 37 | #include <linux/list.h> |
38 | #include <linux/module.h> | ||
38 | #include <linux/mount.h> | 39 | #include <linux/mount.h> |
39 | #include <linux/mutex.h> | 40 | #include <linux/mutex.h> |
40 | #include <linux/namei.h> | 41 | #include <linux/namei.h> |
@@ -56,6 +57,17 @@ static struct kmem_cache *fsnotify_event_holder_cachep; | |||
56 | * get set to 0 so it will never get 'freed' | 57 | * get set to 0 so it will never get 'freed' |
57 | */ | 58 | */ |
58 | static struct fsnotify_event q_overflow_event; | 59 | static struct fsnotify_event q_overflow_event; |
60 | static atomic_t fsnotify_sync_cookie = ATOMIC_INIT(0); | ||
61 | |||
62 | /** | ||
63 | * fsnotify_get_cookie - return a unique cookie for use in synchronizing events. | ||
64 | * Called from fsnotify_move, which is inlined into filesystem modules. | ||
65 | */ | ||
66 | u32 fsnotify_get_cookie(void) | ||
67 | { | ||
68 | return atomic_inc_return(&fsnotify_sync_cookie); | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(fsnotify_get_cookie); | ||
59 | 71 | ||
60 | /* return true if the notify queue is empty, false otherwise */ | 72 | /* return true if the notify queue is empty, false otherwise */ |
61 | bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group) | 73 | bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group) |
@@ -266,6 +278,8 @@ static void initialize_event(struct fsnotify_event *event) | |||
266 | 278 | ||
267 | event->file_name = NULL; | 279 | event->file_name = NULL; |
268 | event->name_len = 0; | 280 | event->name_len = 0; |
281 | |||
282 | event->sync_cookie = 0; | ||
269 | } | 283 | } |
270 | 284 | ||
271 | /* | 285 | /* |
@@ -280,8 +294,8 @@ static void initialize_event(struct fsnotify_event *event) | |||
280 | * @data_type flag indication if the data is a file, path, inode, nothing... | 294 | * @data_type flag indication if the data is a file, path, inode, nothing... |
281 | * @name the filename, if available | 295 | * @name the filename, if available |
282 | */ | 296 | */ |
283 | struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, | 297 | struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, void *data, |
284 | void *data, int data_type, const char *name) | 298 | int data_type, const char *name, u32 cookie) |
285 | { | 299 | { |
286 | struct fsnotify_event *event; | 300 | struct fsnotify_event *event; |
287 | 301 | ||
@@ -299,6 +313,8 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, | |||
299 | } | 313 | } |
300 | event->name_len = strlen(event->file_name); | 314 | event->name_len = strlen(event->file_name); |
301 | } | 315 | } |
316 | |||
317 | event->sync_cookie = cookie; | ||
302 | event->to_tell = to_tell; | 318 | event->to_tell = to_tell; |
303 | 319 | ||
304 | switch (data_type) { | 320 | switch (data_type) { |
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 180740e9ec82..c25b39ddd62a 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h | |||
@@ -58,7 +58,7 @@ static inline void fsnotify_link_count(struct inode *inode) | |||
58 | { | 58 | { |
59 | inotify_inode_queue_event(inode, IN_ATTRIB, 0, NULL, NULL); | 59 | inotify_inode_queue_event(inode, IN_ATTRIB, 0, NULL, NULL); |
60 | 60 | ||
61 | fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL); | 61 | fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
62 | } | 62 | } |
63 | 63 | ||
64 | /* | 64 | /* |
@@ -69,7 +69,8 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, | |||
69 | int isdir, struct inode *target, struct dentry *moved) | 69 | int isdir, struct inode *target, struct dentry *moved) |
70 | { | 70 | { |
71 | struct inode *source = moved->d_inode; | 71 | struct inode *source = moved->d_inode; |
72 | u32 cookie = inotify_get_cookie(); | 72 | u32 in_cookie = inotify_get_cookie(); |
73 | u32 fs_cookie = fsnotify_get_cookie(); | ||
73 | __u32 old_dir_mask = 0; | 74 | __u32 old_dir_mask = 0; |
74 | __u32 new_dir_mask = 0; | 75 | __u32 new_dir_mask = 0; |
75 | 76 | ||
@@ -86,13 +87,13 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, | |||
86 | old_dir_mask |= FS_MOVED_FROM; | 87 | old_dir_mask |= FS_MOVED_FROM; |
87 | new_dir_mask |= FS_MOVED_TO; | 88 | new_dir_mask |= FS_MOVED_TO; |
88 | 89 | ||
89 | inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name, | 90 | inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir, in_cookie, old_name, |
90 | source); | 91 | source); |
91 | inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name, | 92 | inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, in_cookie, new_name, |
92 | source); | 93 | source); |
93 | 94 | ||
94 | fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name); | 95 | fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie); |
95 | fsnotify(new_dir, new_dir_mask, new_dir, FSNOTIFY_EVENT_INODE, new_name); | 96 | fsnotify(new_dir, new_dir_mask, new_dir, FSNOTIFY_EVENT_INODE, new_name, fs_cookie); |
96 | 97 | ||
97 | if (target) { | 98 | if (target) { |
98 | inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL, NULL); | 99 | inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL, NULL); |
@@ -104,7 +105,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, | |||
104 | 105 | ||
105 | if (source) { | 106 | if (source) { |
106 | inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL); | 107 | inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL); |
107 | fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL); | 108 | fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
108 | } | 109 | } |
109 | audit_inode_child(new_name, moved, new_dir); | 110 | audit_inode_child(new_name, moved, new_dir); |
110 | } | 111 | } |
@@ -138,7 +139,7 @@ static inline void fsnotify_inoderemove(struct inode *inode) | |||
138 | inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL, NULL); | 139 | inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL, NULL); |
139 | inotify_inode_is_dead(inode); | 140 | inotify_inode_is_dead(inode); |
140 | 141 | ||
141 | fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL); | 142 | fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
142 | __fsnotify_inode_delete(inode); | 143 | __fsnotify_inode_delete(inode); |
143 | } | 144 | } |
144 | 145 | ||
@@ -151,7 +152,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) | |||
151 | dentry->d_inode); | 152 | dentry->d_inode); |
152 | audit_inode_child(dentry->d_name.name, dentry, inode); | 153 | audit_inode_child(dentry->d_name.name, dentry, inode); |
153 | 154 | ||
154 | fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name); | 155 | fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); |
155 | } | 156 | } |
156 | 157 | ||
157 | /* | 158 | /* |
@@ -166,7 +167,7 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct | |||
166 | fsnotify_link_count(inode); | 167 | fsnotify_link_count(inode); |
167 | audit_inode_child(new_dentry->d_name.name, new_dentry, dir); | 168 | audit_inode_child(new_dentry->d_name.name, new_dentry, dir); |
168 | 169 | ||
169 | fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name); | 170 | fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0); |
170 | } | 171 | } |
171 | 172 | ||
172 | /* | 173 | /* |
@@ -180,7 +181,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) | |||
180 | inotify_inode_queue_event(inode, mask, 0, dentry->d_name.name, d_inode); | 181 | inotify_inode_queue_event(inode, mask, 0, dentry->d_name.name, d_inode); |
181 | audit_inode_child(dentry->d_name.name, dentry, inode); | 182 | audit_inode_child(dentry->d_name.name, dentry, inode); |
182 | 183 | ||
183 | fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name); | 184 | fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); |
184 | } | 185 | } |
185 | 186 | ||
186 | /* | 187 | /* |
@@ -197,7 +198,7 @@ static inline void fsnotify_access(struct dentry *dentry) | |||
197 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 198 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); |
198 | 199 | ||
199 | fsnotify_parent(dentry, mask); | 200 | fsnotify_parent(dentry, mask); |
200 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL); | 201 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
201 | } | 202 | } |
202 | 203 | ||
203 | /* | 204 | /* |
@@ -214,7 +215,7 @@ static inline void fsnotify_modify(struct dentry *dentry) | |||
214 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 215 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); |
215 | 216 | ||
216 | fsnotify_parent(dentry, mask); | 217 | fsnotify_parent(dentry, mask); |
217 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL); | 218 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
218 | } | 219 | } |
219 | 220 | ||
220 | /* | 221 | /* |
@@ -231,7 +232,7 @@ static inline void fsnotify_open(struct dentry *dentry) | |||
231 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 232 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); |
232 | 233 | ||
233 | fsnotify_parent(dentry, mask); | 234 | fsnotify_parent(dentry, mask); |
234 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL); | 235 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
235 | } | 236 | } |
236 | 237 | ||
237 | /* | 238 | /* |
@@ -250,7 +251,7 @@ static inline void fsnotify_close(struct file *file) | |||
250 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 251 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); |
251 | 252 | ||
252 | fsnotify_parent(dentry, mask); | 253 | fsnotify_parent(dentry, mask); |
253 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL); | 254 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); |
254 | } | 255 | } |
255 | 256 | ||
256 | /* | 257 | /* |
@@ -267,7 +268,7 @@ static inline void fsnotify_xattr(struct dentry *dentry) | |||
267 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 268 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); |
268 | 269 | ||
269 | fsnotify_parent(dentry, mask); | 270 | fsnotify_parent(dentry, mask); |
270 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL); | 271 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
271 | } | 272 | } |
272 | 273 | ||
273 | /* | 274 | /* |
@@ -303,7 +304,7 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) | |||
303 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); | 304 | inotify_inode_queue_event(inode, mask, 0, NULL, NULL); |
304 | 305 | ||
305 | fsnotify_parent(dentry, mask); | 306 | fsnotify_parent(dentry, mask); |
306 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL); | 307 | fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
307 | } | 308 | } |
308 | } | 309 | } |
309 | 310 | ||
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 52692f405890..b78b5573d227 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -193,6 +193,7 @@ struct fsnotify_event { | |||
193 | atomic_t refcnt; /* how many groups still are using/need to send this event */ | 193 | atomic_t refcnt; /* how many groups still are using/need to send this event */ |
194 | __u32 mask; /* the type of access, bitwise OR for FS_* event types */ | 194 | __u32 mask; /* the type of access, bitwise OR for FS_* event types */ |
195 | 195 | ||
196 | u32 sync_cookie; /* used to corrolate events, namely inotify mv events */ | ||
196 | char *file_name; | 197 | char *file_name; |
197 | size_t name_len; | 198 | size_t name_len; |
198 | }; | 199 | }; |
@@ -227,9 +228,11 @@ struct fsnotify_mark_entry { | |||
227 | /* called from the vfs helpers */ | 228 | /* called from the vfs helpers */ |
228 | 229 | ||
229 | /* main fsnotify call to send events */ | 230 | /* main fsnotify call to send events */ |
230 | extern void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const char *name); | 231 | extern void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, |
232 | const char *name, u32 cookie); | ||
231 | extern void __fsnotify_parent(struct dentry *dentry, __u32 mask); | 233 | extern void __fsnotify_parent(struct dentry *dentry, __u32 mask); |
232 | extern void __fsnotify_inode_delete(struct inode *inode); | 234 | extern void __fsnotify_inode_delete(struct inode *inode); |
235 | extern u32 fsnotify_get_cookie(void); | ||
233 | 236 | ||
234 | static inline int fsnotify_inode_watches_children(struct inode *inode) | 237 | static inline int fsnotify_inode_watches_children(struct inode *inode) |
235 | { | 238 | { |
@@ -322,12 +325,13 @@ extern void fsnotify_put_mark(struct fsnotify_mark_entry *entry); | |||
322 | 325 | ||
323 | /* put here because inotify does some weird stuff when destroying watches */ | 326 | /* put here because inotify does some weird stuff when destroying watches */ |
324 | extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, | 327 | extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, |
325 | void *data, int data_is, const char *name); | 328 | void *data, int data_is, const char *name, |
329 | u32 cookie); | ||
326 | 330 | ||
327 | #else | 331 | #else |
328 | 332 | ||
329 | static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | 333 | static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, |
330 | const char *name); | 334 | const char *name, u32 cookie) |
331 | {} | 335 | {} |
332 | 336 | ||
333 | static inline void __fsnotify_parent(struct dentry *dentry, __u32 mask) | 337 | static inline void __fsnotify_parent(struct dentry *dentry, __u32 mask) |
@@ -342,6 +346,11 @@ static inline void __fsnotify_update_dcache_flags(struct dentry *dentry) | |||
342 | static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode *inode) | 346 | static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode *inode) |
343 | {} | 347 | {} |
344 | 348 | ||
349 | static inline u32 fsnotify_get_cookie(void) | ||
350 | { | ||
351 | return 0; | ||
352 | } | ||
353 | |||
345 | #endif /* CONFIG_FSNOTIFY */ | 354 | #endif /* CONFIG_FSNOTIFY */ |
346 | 355 | ||
347 | #endif /* __KERNEL __ */ | 356 | #endif /* __KERNEL __ */ |