aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/fanotify
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 21:24:34 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:59:01 -0400
commit43ed7e16a8b47059d7f6ff67ba76f383a2421de3 (patch)
treebe4efb3c2241572ab3954b86e287c9e7d58a5e7e /fs/notify/fanotify
parent6e5f77b32e9097a8a68a8d453799676cacf70cad (diff)
fanotify: use merge argument to determine actual event added to queue
fanotify needs to know the actual event added to queues so it can be correctly checked for return values from userspace. To do this we need to pass that information from the merger code back to the main even handling routine. Currently that information is unused, but it will be. Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify/fanotify')
-rw-r--r--fs/notify/fanotify/fanotify.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 95a330d2f8a1..4feed8601e29 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -27,6 +27,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
27 return false; 27 return false;
28} 28}
29 29
30/* Note, if we return an event in *arg that a reference is being held... */
30static int fanotify_merge(struct list_head *list, 31static int fanotify_merge(struct list_head *list,
31 struct fsnotify_event *event, 32 struct fsnotify_event *event,
32 void **arg) 33 void **arg)
@@ -34,17 +35,22 @@ static int fanotify_merge(struct list_head *list,
34 struct fsnotify_event_holder *test_holder; 35 struct fsnotify_event_holder *test_holder;
35 struct fsnotify_event *test_event; 36 struct fsnotify_event *test_event;
36 struct fsnotify_event *new_event; 37 struct fsnotify_event *new_event;
38 struct fsnotify_event **return_event = (struct fsnotify_event **)arg;
37 int ret = 0; 39 int ret = 0;
38 40
39 pr_debug("%s: list=%p event=%p\n", __func__, list, event); 41 pr_debug("%s: list=%p event=%p\n", __func__, list, event);
40 42
43 *return_event = NULL;
44
41 /* and the list better be locked by something too! */ 45 /* and the list better be locked by something too! */
42 46
43 list_for_each_entry_reverse(test_holder, list, event_list) { 47 list_for_each_entry_reverse(test_holder, list, event_list) {
44 test_event = test_holder->event; 48 test_event = test_holder->event;
45 if (should_merge(test_event, event)) { 49 if (should_merge(test_event, event)) {
46 ret = -EEXIST; 50 fsnotify_get_event(test_event);
51 *return_event = test_event;
47 52
53 ret = -EEXIST;
48 /* if they are exactly the same we are done */ 54 /* if they are exactly the same we are done */
49 if (test_event->mask == event->mask) 55 if (test_event->mask == event->mask)
50 goto out; 56 goto out;
@@ -66,11 +72,14 @@ static int fanotify_merge(struct list_head *list,
66 goto out; 72 goto out;
67 } 73 }
68 74
75 /* we didn't return the test_event, so drop that ref */
76 fsnotify_put_event(test_event);
77 /* the reference we return on new_event is from clone */
78 *return_event = new_event;
79
69 /* build new event and replace it on the list */ 80 /* build new event and replace it on the list */
70 new_event->mask = (test_event->mask | event->mask); 81 new_event->mask = (test_event->mask | event->mask);
71 fsnotify_replace_event(test_holder, new_event); 82 fsnotify_replace_event(test_holder, new_event);
72 /* match ref from fsnotify_clone_event() */
73 fsnotify_put_event(new_event);
74 83
75 break; 84 break;
76 } 85 }
@@ -82,7 +91,7 @@ out:
82static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) 91static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event)
83{ 92{
84 int ret; 93 int ret;
85 94 struct fsnotify_event *used_event;
86 95
87 BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS); 96 BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
88 BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY); 97 BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
@@ -94,10 +103,12 @@ static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_e
94 103
95 pr_debug("%s: group=%p event=%p\n", __func__, group, event); 104 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
96 105
97 ret = fsnotify_add_notify_event(group, event, NULL, fanotify_merge, NULL); 106 ret = fsnotify_add_notify_event(group, event, NULL, fanotify_merge, (void **)&used_event);
98 /* -EEXIST means this event was merged with another, not that it was an error */ 107 /* -EEXIST means this event was merged with another, not that it was an error */
99 if (ret == -EEXIST) 108 if (ret == -EEXIST)
100 ret = 0; 109 ret = 0;
110 if (used_event)
111 fsnotify_put_event(used_event);
101 return ret; 112 return ret;
102} 113}
103 114