Commit 3ca10067f7f4bfa62a1b0edc84f590261fa02d75
Committed by
Al Viro
1 parent
a9dc971d3f
Exists in
master
and in
20 other branches
[PATCH] inotify (4/5): allow watch removal from event handler
Allow callers to remove watches from their event handler via inotify_remove_watch_locked(). This functionality can be used to achieve IN_ONESHOT-like functionality for a subset of events in the mask. Signed-off-by: Amy Griffis <amy.griffis@hp.com> Acked-by: Robert Love <rml@novell.com> Acked-by: John McCutchan <john@johnmccutchan.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 2 changed files with 21 additions and 9 deletions Side-by-side Diff
fs/inotify.c
... | ... | @@ -207,7 +207,7 @@ |
207 | 207 | } |
208 | 208 | |
209 | 209 | /* |
210 | - * remove_watch_no_event - remove_watch() without the IN_IGNORED event. | |
210 | + * remove_watch_no_event - remove watch without the IN_IGNORED event. | |
211 | 211 | * |
212 | 212 | * Callers must hold both inode->inotify_mutex and ih->mutex. |
213 | 213 | */ |
214 | 214 | |
215 | 215 | |
... | ... | @@ -223,17 +223,22 @@ |
223 | 223 | idr_remove(&ih->idr, watch->wd); |
224 | 224 | } |
225 | 225 | |
226 | -/* | |
227 | - * remove_watch - Remove a watch from both the handle and the inode. Sends | |
228 | - * the IN_IGNORED event signifying that the inode is no longer watched. | |
226 | +/** | |
227 | + * inotify_remove_watch_locked - Remove a watch from both the handle and the | |
228 | + * inode. Sends the IN_IGNORED event signifying that the inode is no longer | |
229 | + * watched. May be invoked from a caller's event handler. | |
230 | + * @ih: inotify handle associated with watch | |
231 | + * @watch: watch to remove | |
229 | 232 | * |
230 | 233 | * Callers must hold both inode->inotify_mutex and ih->mutex. |
231 | 234 | */ |
232 | -static void remove_watch(struct inotify_watch *watch, struct inotify_handle *ih) | |
235 | +void inotify_remove_watch_locked(struct inotify_handle *ih, | |
236 | + struct inotify_watch *watch) | |
233 | 237 | { |
234 | 238 | remove_watch_no_event(watch, ih); |
235 | 239 | ih->in_ops->handle_event(watch, watch->wd, IN_IGNORED, 0, NULL, NULL); |
236 | 240 | } |
241 | +EXPORT_SYMBOL_GPL(inotify_remove_watch_locked); | |
237 | 242 | |
238 | 243 | /* Kernel API for producing events */ |
239 | 244 | |
... | ... | @@ -378,7 +383,7 @@ |
378 | 383 | |
379 | 384 | need_iput_tmp = need_iput; |
380 | 385 | need_iput = NULL; |
381 | - /* In case the remove_watch() drops a reference. */ | |
386 | + /* In case inotify_remove_watch_locked() drops a reference. */ | |
382 | 387 | if (inode != need_iput_tmp) |
383 | 388 | __iget(inode); |
384 | 389 | else |
... | ... | @@ -411,7 +416,7 @@ |
411 | 416 | mutex_lock(&ih->mutex); |
412 | 417 | ih->in_ops->handle_event(watch, watch->wd, IN_UNMOUNT, 0, |
413 | 418 | NULL, NULL); |
414 | - remove_watch(watch, ih); | |
419 | + inotify_remove_watch_locked(ih, watch); | |
415 | 420 | mutex_unlock(&ih->mutex); |
416 | 421 | } |
417 | 422 | mutex_unlock(&inode->inotify_mutex); |
... | ... | @@ -434,7 +439,7 @@ |
434 | 439 | list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { |
435 | 440 | struct inotify_handle *ih = watch->ih; |
436 | 441 | mutex_lock(&ih->mutex); |
437 | - remove_watch(watch, ih); | |
442 | + inotify_remove_watch_locked(ih, watch); | |
438 | 443 | mutex_unlock(&ih->mutex); |
439 | 444 | } |
440 | 445 | mutex_unlock(&inode->inotify_mutex); |
... | ... | @@ -687,7 +692,7 @@ |
687 | 692 | |
688 | 693 | /* make sure that we did not race */ |
689 | 694 | if (likely(idr_find(&ih->idr, wd) == watch)) |
690 | - remove_watch(watch, ih); | |
695 | + inotify_remove_watch_locked(ih, watch); | |
691 | 696 | |
692 | 697 | mutex_unlock(&ih->mutex); |
693 | 698 | mutex_unlock(&inode->inotify_mutex); |
include/linux/inotify.h
... | ... | @@ -122,6 +122,8 @@ |
122 | 122 | struct inode *, __u32); |
123 | 123 | extern int inotify_rm_watch(struct inotify_handle *, struct inotify_watch *); |
124 | 124 | extern int inotify_rm_wd(struct inotify_handle *, __u32); |
125 | +extern void inotify_remove_watch_locked(struct inotify_handle *, | |
126 | + struct inotify_watch *); | |
125 | 127 | extern void get_inotify_watch(struct inotify_watch *); |
126 | 128 | extern void put_inotify_watch(struct inotify_watch *); |
127 | 129 | |
... | ... | @@ -203,6 +205,11 @@ |
203 | 205 | static inline int inotify_rm_wd(struct inotify_handle *ih, __u32 wd) |
204 | 206 | { |
205 | 207 | return -EOPNOTSUPP; |
208 | +} | |
209 | + | |
210 | +static inline void inotify_remove_watch_locked(struct inotify_handle *ih, | |
211 | + struct inotify_watch *watch) | |
212 | +{ | |
206 | 213 | } |
207 | 214 | |
208 | 215 | static inline void get_inotify_watch(struct inotify_watch *watch) |