diff options
| -rw-r--r-- | fs/notify/inotify/inotify.h | 3 | ||||
| -rw-r--r-- | fs/notify/inotify/inotify_fsnotify.c | 2 | ||||
| -rw-r--r-- | fs/notify/inotify/inotify_user.c | 32 |
3 files changed, 8 insertions, 29 deletions
diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h index ea2605a58b8a..f234f3a4c8ca 100644 --- a/fs/notify/inotify/inotify.h +++ b/fs/notify/inotify/inotify.h | |||
| @@ -15,7 +15,8 @@ struct inotify_inode_mark_entry { | |||
| 15 | int wd; | 15 | int wd; |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | extern void inotify_destroy_mark_entry(struct fsnotify_mark_entry *entry, struct fsnotify_group *group); | 18 | extern void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry, |
| 19 | struct fsnotify_group *group); | ||
| 19 | extern void inotify_free_event_priv(struct fsnotify_event_private_data *event_priv); | 20 | extern void inotify_free_event_priv(struct fsnotify_event_private_data *event_priv); |
| 20 | 21 | ||
| 21 | extern const struct fsnotify_ops inotify_fsnotify_ops; | 22 | extern const struct fsnotify_ops inotify_fsnotify_ops; |
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 7ef75b83247e..47cd258fd24d 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c | |||
| @@ -81,7 +81,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev | |||
| 81 | 81 | ||
| 82 | static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group) | 82 | static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group) |
| 83 | { | 83 | { |
| 84 | inotify_destroy_mark_entry(entry, group); | 84 | inotify_ignored_and_remove_idr(entry, group); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask) | 87 | static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask) |
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 982a412ac5bc..ff231ad23895 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
| @@ -363,39 +363,17 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, uns | |||
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | /* | 365 | /* |
| 366 | * When, for whatever reason, inotify is done with a mark (or what used to be a | 366 | * Send IN_IGNORED for this wd, remove this wd from the idr, and drop the |
| 367 | * watch) we need to remove that watch from the idr and we need to send IN_IGNORED | 367 | * internal reference help on the mark because it is in the idr. |
| 368 | * for the given wd. | ||
| 369 | * | ||
| 370 | * There is a bit of recursion here. The loop looks like: | ||
| 371 | * inotify_destroy_mark_entry -> fsnotify_destroy_mark_by_entry -> | ||
| 372 | * inotify_freeing_mark -> inotify_destory_mark_entry -> restart | ||
| 373 | * But the loop is broken in 2 places. fsnotify_destroy_mark_by_entry sets | ||
| 374 | * entry->group = NULL before the call to inotify_freeing_mark, so the if (egroup) | ||
| 375 | * test below will not call back to fsnotify again. But even if that test wasn't | ||
| 376 | * there this would still be safe since fsnotify_destroy_mark_by_entry() is | ||
| 377 | * safe from recursion. | ||
| 378 | */ | 368 | */ |
| 379 | void inotify_destroy_mark_entry(struct fsnotify_mark_entry *entry, struct fsnotify_group *group) | 369 | void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry, |
| 370 | struct fsnotify_group *group) | ||
| 380 | { | 371 | { |
| 381 | struct inotify_inode_mark_entry *ientry; | 372 | struct inotify_inode_mark_entry *ientry; |
| 382 | struct inotify_event_private_data *event_priv; | 373 | struct inotify_event_private_data *event_priv; |
| 383 | struct fsnotify_event_private_data *fsn_event_priv; | 374 | struct fsnotify_event_private_data *fsn_event_priv; |
| 384 | struct fsnotify_group *egroup; | ||
| 385 | struct idr *idr; | 375 | struct idr *idr; |
| 386 | 376 | ||
| 387 | spin_lock(&entry->lock); | ||
| 388 | egroup = entry->group; | ||
| 389 | |||
| 390 | /* if egroup we aren't really done and something might still send events | ||
| 391 | * for this inode, on the callback we'll send the IN_IGNORED */ | ||
| 392 | if (egroup) { | ||
| 393 | spin_unlock(&entry->lock); | ||
| 394 | fsnotify_destroy_mark_by_entry(entry); | ||
| 395 | return; | ||
| 396 | } | ||
| 397 | spin_unlock(&entry->lock); | ||
| 398 | |||
| 399 | ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry); | 377 | ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry); |
| 400 | 378 | ||
| 401 | event_priv = kmem_cache_alloc(event_priv_cachep, GFP_KERNEL); | 379 | event_priv = kmem_cache_alloc(event_priv_cachep, GFP_KERNEL); |
| @@ -699,7 +677,7 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd) | |||
| 699 | fsnotify_get_mark(entry); | 677 | fsnotify_get_mark(entry); |
| 700 | spin_unlock(&group->inotify_data.idr_lock); | 678 | spin_unlock(&group->inotify_data.idr_lock); |
| 701 | 679 | ||
| 702 | inotify_destroy_mark_entry(entry, group); | 680 | fsnotify_destroy_mark_by_entry(entry); |
| 703 | fsnotify_put_mark(entry); | 681 | fsnotify_put_mark(entry); |
| 704 | 682 | ||
| 705 | out: | 683 | out: |
