Merge tag 'landlock_v34' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux-2.6-microblaze.git] / fs / notify / notification.c
index 75d79d6..32f4554 100644 (file)
@@ -47,13 +47,6 @@ u32 fsnotify_get_cookie(void)
 }
 EXPORT_SYMBOL_GPL(fsnotify_get_cookie);
 
-/* return true if the notify queue is empty, false otherwise */
-bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group)
-{
-       assert_spin_locked(&group->notification_lock);
-       return list_empty(&group->notification_list) ? true : false;
-}
-
 void fsnotify_destroy_event(struct fsnotify_group *group,
                            struct fsnotify_event *event)
 {
@@ -75,16 +68,22 @@ void fsnotify_destroy_event(struct fsnotify_group *group,
 }
 
 /*
- * Add an event to the group notification queue.  The group can later pull this
- * event off the queue to deal with.  The function returns 0 if the event was
- * added to the queue, 1 if the event was merged with some other queued event,
+ * Try to add an event to the notification queue.
+ * The group can later pull this event off the queue to deal with.
+ * The group can use the @merge hook to merge the event with a queued event.
+ * The group can use the @insert hook to insert the event into hash table.
+ * The function returns:
+ * 0 if the event was added to a queue
+ * 1 if the event was merged with some other queued event
  * 2 if the event was not queued - either the queue of events has overflown
- * or the group is shutting down.
+ *   or the group is shutting down.
  */
 int fsnotify_add_event(struct fsnotify_group *group,
                       struct fsnotify_event *event,
-                      int (*merge)(struct list_head *,
-                                   struct fsnotify_event *))
+                      int (*merge)(struct fsnotify_group *,
+                                   struct fsnotify_event *),
+                      void (*insert)(struct fsnotify_group *,
+                                     struct fsnotify_event *))
 {
        int ret = 0;
        struct list_head *list = &group->notification_list;
@@ -111,7 +110,7 @@ int fsnotify_add_event(struct fsnotify_group *group,
        }
 
        if (!list_empty(list) && merge) {
-               ret = merge(list, event);
+               ret = merge(group, event);
                if (ret) {
                        spin_unlock(&group->notification_lock);
                        return ret;
@@ -121,6 +120,8 @@ int fsnotify_add_event(struct fsnotify_group *group,
 queue:
        group->q_len++;
        list_add_tail(&event->list, list);
+       if (insert)
+               insert(group, event);
        spin_unlock(&group->notification_lock);
 
        wake_up(&group->notification_waitq);
@@ -141,33 +142,36 @@ void fsnotify_remove_queued_event(struct fsnotify_group *group,
 }
 
 /*
- * Remove and return the first event from the notification list.  It is the
- * responsibility of the caller to destroy the obtained event
+ * Return the first event on the notification list without removing it.
+ * Returns NULL if the list is empty.
  */
-struct fsnotify_event *fsnotify_remove_first_event(struct fsnotify_group *group)
+struct fsnotify_event *fsnotify_peek_first_event(struct fsnotify_group *group)
 {
-       struct fsnotify_event *event;
-
        assert_spin_locked(&group->notification_lock);
 
-       pr_debug("%s: group=%p\n", __func__, group);
+       if (fsnotify_notify_queue_is_empty(group))
+               return NULL;
 
-       event = list_first_entry(&group->notification_list,
-                                struct fsnotify_event, list);
-       fsnotify_remove_queued_event(group, event);
-       return event;
+       return list_first_entry(&group->notification_list,
+                               struct fsnotify_event, list);
 }
 
 /*
- * This will not remove the event, that must be done with
- * fsnotify_remove_first_event()
+ * Remove and return the first event from the notification list.  It is the
+ * responsibility of the caller to destroy the obtained event
  */
-struct fsnotify_event *fsnotify_peek_first_event(struct fsnotify_group *group)
+struct fsnotify_event *fsnotify_remove_first_event(struct fsnotify_group *group)
 {
-       assert_spin_locked(&group->notification_lock);
+       struct fsnotify_event *event = fsnotify_peek_first_event(group);
 
-       return list_first_entry(&group->notification_list,
-                               struct fsnotify_event, list);
+       if (!event)
+               return NULL;
+
+       pr_debug("%s: group=%p event=%p\n", __func__, group, event);
+
+       fsnotify_remove_queued_event(group, event);
+
+       return event;
 }
 
 /*