diff options
author | Jan Kara <jack@suse.cz> | 2016-09-19 17:44:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-09-19 18:36:17 -0400 |
commit | 12703dbfeb15402260e7554d32a34ac40c233990 (patch) | |
tree | daff806026a436ba9a359606c8eb580a9d9a7632 /fs/notify | |
parent | d5bf141893880f7283fe97e1812c58ff22c8f9a5 (diff) |
fsnotify: add a way to stop queueing events on group shutdown
Implement a function that can be called when a group is being shutdown
to stop queueing new events to the group. Fanotify will use this.
Fixes: 5838d4442bd5 ("fanotify: fix double free of pending permission events")
Link: http://lkml.kernel.org/r/1473797711-14111-2-git-send-email-jack@suse.cz
Signed-off-by: Jan Kara <jack@suse.cz>
Reviewed-by: Miklos Szeredi <mszeredi@redhat.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/notify')
-rw-r--r-- | fs/notify/group.c | 19 | ||||
-rw-r--r-- | fs/notify/notification.c | 8 |
2 files changed, 26 insertions, 1 deletions
diff --git a/fs/notify/group.c b/fs/notify/group.c index 3e2dd85be5dd..b47f7cfdcaa4 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c | |||
@@ -40,6 +40,17 @@ static void fsnotify_final_destroy_group(struct fsnotify_group *group) | |||
40 | } | 40 | } |
41 | 41 | ||
42 | /* | 42 | /* |
43 | * Stop queueing new events for this group. Once this function returns | ||
44 | * fsnotify_add_event() will not add any new events to the group's queue. | ||
45 | */ | ||
46 | void fsnotify_group_stop_queueing(struct fsnotify_group *group) | ||
47 | { | ||
48 | mutex_lock(&group->notification_mutex); | ||
49 | group->shutdown = true; | ||
50 | mutex_unlock(&group->notification_mutex); | ||
51 | } | ||
52 | |||
53 | /* | ||
43 | * Trying to get rid of a group. Remove all marks, flush all events and release | 54 | * Trying to get rid of a group. Remove all marks, flush all events and release |
44 | * the group reference. | 55 | * the group reference. |
45 | * Note that another thread calling fsnotify_clear_marks_by_group() may still | 56 | * Note that another thread calling fsnotify_clear_marks_by_group() may still |
@@ -47,6 +58,14 @@ static void fsnotify_final_destroy_group(struct fsnotify_group *group) | |||
47 | */ | 58 | */ |
48 | void fsnotify_destroy_group(struct fsnotify_group *group) | 59 | void fsnotify_destroy_group(struct fsnotify_group *group) |
49 | { | 60 | { |
61 | /* | ||
62 | * Stop queueing new events. The code below is careful enough to not | ||
63 | * require this but fanotify needs to stop queuing events even before | ||
64 | * fsnotify_destroy_group() is called and this makes the other callers | ||
65 | * of fsnotify_destroy_group() to see the same behavior. | ||
66 | */ | ||
67 | fsnotify_group_stop_queueing(group); | ||
68 | |||
50 | /* clear all inode marks for this group, attach them to destroy_list */ | 69 | /* clear all inode marks for this group, attach them to destroy_list */ |
51 | fsnotify_detach_group_marks(group); | 70 | fsnotify_detach_group_marks(group); |
52 | 71 | ||
diff --git a/fs/notify/notification.c b/fs/notify/notification.c index a95d8e037aeb..3d76e65ff84f 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c | |||
@@ -82,7 +82,8 @@ void fsnotify_destroy_event(struct fsnotify_group *group, | |||
82 | * Add an event to the group notification queue. The group can later pull this | 82 | * Add an event to the group notification queue. The group can later pull this |
83 | * event off the queue to deal with. The function returns 0 if the event was | 83 | * event off the queue to deal with. The function returns 0 if the event was |
84 | * added to the queue, 1 if the event was merged with some other queued event, | 84 | * added to the queue, 1 if the event was merged with some other queued event, |
85 | * 2 if the queue of events has overflown. | 85 | * 2 if the event was not queued - either the queue of events has overflown |
86 | * or the group is shutting down. | ||
86 | */ | 87 | */ |
87 | int fsnotify_add_event(struct fsnotify_group *group, | 88 | int fsnotify_add_event(struct fsnotify_group *group, |
88 | struct fsnotify_event *event, | 89 | struct fsnotify_event *event, |
@@ -96,6 +97,11 @@ int fsnotify_add_event(struct fsnotify_group *group, | |||
96 | 97 | ||
97 | mutex_lock(&group->notification_mutex); | 98 | mutex_lock(&group->notification_mutex); |
98 | 99 | ||
100 | if (group->shutdown) { | ||
101 | mutex_unlock(&group->notification_mutex); | ||
102 | return 2; | ||
103 | } | ||
104 | |||
99 | if (group->q_len >= group->max_events) { | 105 | if (group->q_len >= group->max_events) { |
100 | ret = 2; | 106 | ret = 2; |
101 | /* Queue overflow event only if it isn't already queued */ | 107 | /* Queue overflow event only if it isn't already queued */ |