]> Pileus Git - ~andy/linux/blobdiff - fs/notify/inotify/inotify_fsnotify.c
fsnotify: remove .should_send_event callback
[~andy/linux] / fs / notify / inotify / inotify_fsnotify.c
index 4216308b81b409443d8e38430752e346ff30341a..aad1a35e9af117fdc397cca897ba6f192f2de7a0 100644 (file)
 #include "inotify.h"
 
 /*
- * Check if 2 events contain the same information.  We do not compare private data
- * but at this moment that isn't a problem for any know fsnotify listeners.
+ * Check if 2 events contain the same information.
  */
-static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new)
+static bool event_compare(struct fsnotify_event *old_fsn,
+                         struct fsnotify_event *new_fsn)
 {
-       if ((old->mask == new->mask) &&
-           (old->to_tell == new->to_tell) &&
-           (old->data_type == new->data_type) &&
-           (old->name_len == new->name_len)) {
-               switch (old->data_type) {
-               case (FSNOTIFY_EVENT_INODE):
-                       /* remember, after old was put on the wait_q we aren't
-                        * allowed to look at the inode any more, only thing
-                        * left to check was if the file_name is the same */
-                       if (!old->name_len ||
-                           !strcmp(old->file_name, new->file_name))
-                               return true;
-                       break;
-               case (FSNOTIFY_EVENT_PATH):
-                       if ((old->path.mnt == new->path.mnt) &&
-                           (old->path.dentry == new->path.dentry))
-                               return true;
-                       break;
-               case (FSNOTIFY_EVENT_NONE):
-                       if (old->mask & FS_Q_OVERFLOW)
-                               return true;
-                       else if (old->mask & FS_IN_IGNORED)
-                               return false;
-                       return true;
-               };
-       }
+       struct inotify_event_info *old, *new;
+
+       if (old_fsn->mask & FS_IN_IGNORED)
+               return false;
+       old = INOTIFY_E(old_fsn);
+       new = INOTIFY_E(new_fsn);
+       if ((old_fsn->mask == new_fsn->mask) &&
+           (old_fsn->inode == new_fsn->inode) &&
+           (old->name_len == new->name_len) &&
+           (!old->name_len || !strcmp(old->name, new->name)))
+               return true;
        return false;
 }
 
 static struct fsnotify_event *inotify_merge(struct list_head *list,
                                            struct fsnotify_event *event)
 {
-       struct fsnotify_event_holder *last_holder;
        struct fsnotify_event *last_event;
 
-       /* and the list better be locked by something too */
-       spin_lock(&event->lock);
-
-       last_holder = list_entry(list->prev, struct fsnotify_event_holder, event_list);
-       last_event = last_holder->event;
-       if (event_compare(last_event, event))
-               fsnotify_get_event(last_event);
-       else
-               last_event = NULL;
-
-       spin_unlock(&event->lock);
-
+       last_event = list_entry(list->prev, struct fsnotify_event, list);
+       if (!event_compare(last_event, event))
+               return NULL;
        return last_event;
 }
 
-static int inotify_handle_event(struct fsnotify_group *group,
-                               struct fsnotify_mark *inode_mark,
-                               struct fsnotify_mark *vfsmount_mark,
-                               struct fsnotify_event *event)
+int inotify_handle_event(struct fsnotify_group *group,
+                        struct inode *inode,
+                        struct fsnotify_mark *inode_mark,
+                        struct fsnotify_mark *vfsmount_mark,
+                        u32 mask, void *data, int data_type,
+                        const unsigned char *file_name)
 {
        struct inotify_inode_mark *i_mark;
-       struct inode *to_tell;
-       struct inotify_event_private_data *event_priv;
-       struct fsnotify_event_private_data *fsn_event_priv;
+       struct inotify_event_info *event;
        struct fsnotify_event *added_event;
-       int wd, ret = 0;
+       struct fsnotify_event *fsn_event;
+       int ret = 0;
+       int len = 0;
+       int alloc_len = sizeof(struct inotify_event_info);
 
        BUG_ON(vfsmount_mark);
 
-       pr_debug("%s: group=%p event=%p to_tell=%p mask=%x\n", __func__, group,
-                event, event->to_tell, event->mask);
+       if ((inode_mark->mask & FS_EXCL_UNLINK) &&
+           (data_type == FSNOTIFY_EVENT_PATH)) {
+               struct path *path = data;
 
-       to_tell = event->to_tell;
+               if (d_unlinked(path->dentry))
+                       return 0;
+       }
+       if (file_name) {
+               len = strlen(file_name);
+               alloc_len += len + 1;
+       }
+
+       pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode,
+                mask);
 
        i_mark = container_of(inode_mark, struct inotify_inode_mark,
                              fsn_mark);
-       wd = i_mark->wd;
 
-       event_priv = kmem_cache_alloc(event_priv_cachep, GFP_KERNEL);
-       if (unlikely(!event_priv))
+       event = kmalloc(alloc_len, GFP_KERNEL);
+       if (unlikely(!event))
                return -ENOMEM;
 
-       fsn_event_priv = &event_priv->fsnotify_event_priv_data;
-
-       fsnotify_get_group(group);
-       fsn_event_priv->group = group;
-       event_priv->wd = wd;
+       fsn_event = &event->fse;
+       fsnotify_init_event(fsn_event, inode, mask);
+       event->wd = i_mark->wd;
+       event->name_len = len;
+       if (len)
+               strcpy(event->name, file_name);
 
-       added_event = fsnotify_add_notify_event(group, event, fsn_event_priv, inotify_merge);
+       added_event = fsnotify_add_notify_event(group, fsn_event, inotify_merge);
        if (added_event) {
-               inotify_free_event_priv(fsn_event_priv);
-               if (!IS_ERR(added_event))
-                       fsnotify_put_event(added_event);
-               else
+               /* Our event wasn't used in the end. Free it. */
+               fsnotify_destroy_event(group, fsn_event);
+               if (IS_ERR(added_event))
                        ret = PTR_ERR(added_event);
        }
 
@@ -142,22 +129,6 @@ static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify
        inotify_ignored_and_remove_idr(fsn_mark, group);
 }
 
-static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode,
-                                     struct fsnotify_mark *inode_mark,
-                                     struct fsnotify_mark *vfsmount_mark,
-                                     __u32 mask, void *data, int data_type)
-{
-       if ((inode_mark->mask & FS_EXCL_UNLINK) &&
-           (data_type == FSNOTIFY_EVENT_PATH)) {
-               struct path *path = data;
-
-               if (d_unlinked(path->dentry))
-                       return false;
-       }
-
-       return true;
-}
-
 /*
  * This is NEVER supposed to be called.  Inotify marks should either have been
  * removed from the idr when the watch was removed or in the
@@ -202,22 +173,14 @@ static void inotify_free_group_priv(struct fsnotify_group *group)
        free_uid(group->inotify_data.user);
 }
 
-void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv)
+static void inotify_free_event(struct fsnotify_event *fsn_event)
 {
-       struct inotify_event_private_data *event_priv;
-
-
-       event_priv = container_of(fsn_event_priv, struct inotify_event_private_data,
-                                 fsnotify_event_priv_data);
-
-       fsnotify_put_group(fsn_event_priv->group);
-       kmem_cache_free(event_priv_cachep, event_priv);
+       kfree(INOTIFY_E(fsn_event));
 }
 
 const struct fsnotify_ops inotify_fsnotify_ops = {
        .handle_event = inotify_handle_event,
-       .should_send_event = inotify_should_send_event,
        .free_group_priv = inotify_free_group_priv,
-       .free_event_priv = inotify_free_event_priv,
+       .free_event = inotify_free_event,
        .freeing_mark = inotify_freeing_mark,
 };