aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/notify/fanotify/fanotify.c39
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
30static int fanotify_merge(struct list_head *list, struct fsnotify_event *event) 29static 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 65out:
45 return 0; 66 return ret;
46} 67}
47 68
48static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) 69static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event)