fsnotify: intoduce a notification merge argument
authorEric Paris <eparis@redhat.com>
Fri, 18 Dec 2009 02:24:34 +0000 (21:24 -0500)
committerEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 13:59:01 +0000 (09:59 -0400)
Each group can define their own notification (and secondary_q) merge
function.  Inotify does tail drop, fanotify does matching and drop which
can actually allocate a completely new event.  But for fanotify to properly
deal with permissions events it needs to know the new event which was
ultimately added to the notification queue.  This patch just implements a
void ** argument which is passed to the merge function.  fanotify can use
this field to pass the new event back to higher layers.

Signed-off-by: Eric Paris <eparis@redhat.com>
for fanotify to properly deal with permissions events

fs/notify/fanotify/fanotify.c
fs/notify/inotify/inotify_fsnotify.c
fs/notify/inotify/inotify_user.c
fs/notify/notification.c
include/linux/fsnotify_backend.h

index 060b177146e845b341277084302449425a17fa54..95a330d2f8a1797c59b1c005b17627747946e835 100644 (file)
@@ -27,7 +27,9 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
        return false;
 }
 
-static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
+static int fanotify_merge(struct list_head *list,
+                         struct fsnotify_event *event,
+                         void **arg)
 {
        struct fsnotify_event_holder *test_holder;
        struct fsnotify_event *test_event;
@@ -92,7 +94,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_e
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-       ret = fsnotify_add_notify_event(group, event, NULL, fanotify_merge);
+       ret = fsnotify_add_notify_event(group, event, NULL, fanotify_merge, NULL);
        /* -EEXIST means this event was merged with another, not that it was an error */
        if (ret == -EEXIST)
                ret = 0;
index 1d237e1bf7b1892580003a72cddac6b995e90c62..daa666a6e6c98c468849f23729376bde89dd29af 100644 (file)
@@ -67,7 +67,9 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new
        return false;
 }
 
-static int inotify_merge(struct list_head *list, struct fsnotify_event *event)
+static int inotify_merge(struct list_head *list,
+                        struct fsnotify_event *event,
+                        void **arg)
 {
        struct fsnotify_event_holder *last_holder;
        struct fsnotify_event *last_event;
@@ -114,7 +116,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev
        fsn_event_priv->group = group;
        event_priv->wd = wd;
 
-       ret = fsnotify_add_notify_event(group, event, fsn_event_priv, inotify_merge);
+       ret = fsnotify_add_notify_event(group, event, fsn_event_priv, inotify_merge, NULL);
        if (ret) {
                inotify_free_event_priv(fsn_event_priv);
                /* EEXIST says we tail matched, EOVERFLOW isn't something
index 19d274057bfa165406ebe7234dc60de2884362aa..1ce71f5b95894a74fb0d97b6ecbe24129f3f8b08 100644 (file)
@@ -525,7 +525,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
        fsn_event_priv->group = group;
        event_priv->wd = i_mark->wd;
 
-       ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv, NULL);
+       ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv, NULL, NULL);
        if (ret)
                inotify_free_event_priv(fsn_event_priv);
 
index 7fc8d004084c3a4280591d9c2a76d7f79b9adadf..2d50a40ab1e4f1f9437b5ba14b7ab2b768b1a03c 100644 (file)
@@ -137,7 +137,10 @@ struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struct fsnot
  */
 int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event,
                              struct fsnotify_event_private_data *priv,
-                             int (*merge)(struct list_head *, struct fsnotify_event *))
+                             int (*merge)(struct list_head *,
+                                          struct fsnotify_event *,
+                                          void **arg),
+                             void **arg)
 {
        struct fsnotify_event_holder *holder = NULL;
        struct list_head *list = &group->notification_list;
@@ -170,7 +173,7 @@ alloc_holder:
        if (!list_empty(list) && merge) {
                int ret;
 
-               ret = merge(list, event);
+               ret = merge(list, event, arg);
                if (ret) {
                        mutex_unlock(&group->notification_mutex);
                        if (holder != &event->holder)
index 8b2e095e5907dfc8f86919667570e936de663258..afc69019297220bc3eecb683064fcadfc4f27afa 100644 (file)
@@ -355,7 +355,10 @@ extern struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struc
 extern int fsnotify_add_notify_event(struct fsnotify_group *group,
                                     struct fsnotify_event *event,
                                     struct fsnotify_event_private_data *priv,
-                                    int (*merge)(struct list_head *, struct fsnotify_event *));
+                                    int (*merge)(struct list_head *,
+                                                 struct fsnotify_event *,
+                                                 void **),
+                                    void **arg);
 /* true if the group notification queue is empty */
 extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group);
 /* return, but do not dequeue the first event on the notification queue */