inotify: Fix reporting of cookies for inotify events
[pandora-kernel.git] / fs / notify / fanotify / fanotify.c
index 5877262..205dc21 100644 (file)
@@ -16,12 +16,6 @@ static bool should_merge(struct fsnotify_event *old_fsn,
 {
        struct fanotify_event_info *old, *new;
 
-#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
-       /* dont merge two permission events */
-       if ((old_fsn->mask & FAN_ALL_PERM_EVENTS) &&
-           (new_fsn->mask & FAN_ALL_PERM_EVENTS))
-               return false;
-#endif
        pr_debug("%s: old=%p new=%p\n", __func__, old_fsn, new_fsn);
        old = FANOTIFY_E(old_fsn);
        new = FANOTIFY_E(new_fsn);
@@ -34,14 +28,23 @@ static bool should_merge(struct fsnotify_event *old_fsn,
 }
 
 /* and the list better be locked by something too! */
-static struct fsnotify_event *fanotify_merge(struct list_head *list,
-                                            struct fsnotify_event *event)
+static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
 {
        struct fsnotify_event *test_event;
        bool do_merge = false;
 
        pr_debug("%s: list=%p event=%p\n", __func__, list, event);
 
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       /*
+        * Don't merge a permission event with any other event so that we know
+        * the event structure we have created in fanotify_handle_event() is the
+        * one we should check for permission response.
+        */
+       if (event->mask & FAN_ALL_PERM_EVENTS)
+               return 0;
+#endif
+
        list_for_each_entry_reverse(test_event, list, list) {
                if (should_merge(test_event, event)) {
                        do_merge = true;
@@ -50,10 +53,10 @@ static struct fsnotify_event *fanotify_merge(struct list_head *list,
        }
 
        if (!do_merge)
-               return NULL;
+               return 0;
 
        test_event->mask |= event->mask;
-       return test_event;
+       return 1;
 }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
@@ -144,12 +147,11 @@ static int fanotify_handle_event(struct fsnotify_group *group,
                                 struct fsnotify_mark *inode_mark,
                                 struct fsnotify_mark *fanotify_mark,
                                 u32 mask, void *data, int data_type,
-                                const unsigned char *file_name)
+                                const unsigned char *file_name, u32 cookie)
 {
        int ret = 0;
        struct fanotify_event_info *event;
        struct fsnotify_event *fsn_event;
-       struct fsnotify_event *notify_fsn_event;
 
        BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
        BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
@@ -188,21 +190,19 @@ static int fanotify_handle_event(struct fsnotify_group *group,
        event->response = 0;
 #endif
 
-       notify_fsn_event = fsnotify_add_notify_event(group, fsn_event,
-                                                    fanotify_merge);
-       if (notify_fsn_event) {
+       ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
+       if (ret) {
+               BUG_ON(mask & FAN_ALL_PERM_EVENTS);
                /* Our event wasn't used in the end. Free it. */
                fsnotify_destroy_event(group, fsn_event);
-               if (IS_ERR(notify_fsn_event))
-                       return PTR_ERR(notify_fsn_event);
-               /* We need to ask about a different events after a merge... */
-               event = FANOTIFY_E(notify_fsn_event);
-               fsn_event = notify_fsn_event;
+               ret = 0;
        }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
-       if (fsn_event->mask & FAN_ALL_PERM_EVENTS)
+       if (mask & FAN_ALL_PERM_EVENTS) {
                ret = fanotify_get_response_from_access(group, event);
+               fsnotify_destroy_event(group, fsn_event);
+       }
 #endif
        return ret;
 }