diff options
-rw-r--r-- | fs/notify/fanotify/fanotify.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index c35c1175c4cf..8e574d6f6a80 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
@@ -10,8 +10,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) | |||
10 | { | 10 | { |
11 | pr_debug("%s: old=%p new=%p\n", __func__, old, new); | 11 | pr_debug("%s: old=%p new=%p\n", __func__, old, new); |
12 | 12 | ||
13 | if ((old->mask == new->mask) && | 13 | if ((old->to_tell == new->to_tell) && |
14 | (old->to_tell == new->to_tell) && | ||
15 | (old->data_type == new->data_type)) { | 14 | (old->data_type == new->data_type)) { |
16 | switch (old->data_type) { | 15 | switch (old->data_type) { |
17 | case (FSNOTIFY_EVENT_PATH): | 16 | case (FSNOTIFY_EVENT_PATH): |
@@ -29,20 +28,42 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) | |||
29 | 28 | ||
30 | static int fanotify_merge(struct list_head *list, struct fsnotify_event *event) | 29 | static int fanotify_merge(struct list_head *list, struct fsnotify_event *event) |
31 | { | 30 | { |
32 | struct fsnotify_event_holder *holder; | 31 | struct fsnotify_event_holder *test_holder; |
33 | struct fsnotify_event *test_event; | 32 | struct fsnotify_event *test_event; |
33 | struct fsnotify_event *new_event; | ||
34 | int ret = 0; | ||
34 | 35 | ||
35 | pr_debug("%s: list=%p event=%p\n", __func__, list, event); | 36 | pr_debug("%s: list=%p event=%p\n", __func__, list, event); |
36 | 37 | ||
37 | /* and the list better be locked by something too! */ | 38 | /* and the list better be locked by something too! */ |
38 | 39 | ||
39 | list_for_each_entry_reverse(holder, list, event_list) { | 40 | list_for_each_entry_reverse(test_holder, list, event_list) { |
40 | test_event = holder->event; | 41 | test_event = test_holder->event; |
41 | if (should_merge(test_event, event)) | 42 | if (should_merge(test_event, event)) { |
42 | return -EEXIST; | 43 | ret = -EEXIST; |
44 | |||
45 | /* if they are exactly the same we are done */ | ||
46 | if (test_event->mask == event->mask) | ||
47 | goto out; | ||
48 | |||
49 | /* can't allocate memory, merge was no possible */ | ||
50 | new_event = fsnotify_clone_event(test_event); | ||
51 | if (unlikely(!new_event)) { | ||
52 | ret = 0; | ||
53 | goto out; | ||
54 | } | ||
55 | |||
56 | /* build new event and replace it on the list */ | ||
57 | new_event->mask = (test_event->mask | event->mask); | ||
58 | fsnotify_replace_event(test_holder, new_event); | ||
59 | /* match ref from fsnotify_clone_event() */ | ||
60 | fsnotify_put_event(new_event); | ||
61 | |||
62 | break; | ||
63 | } | ||
43 | } | 64 | } |
44 | 65 | out: | |
45 | return 0; | 66 | return ret; |
46 | } | 67 | } |
47 | 68 | ||
48 | static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) | 69 | static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) |