aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/inotify
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 21:24:21 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:58:49 -0400
commit74766bbfa99adf8cb8119df6121851edba21c9d9 (patch)
tree724dbee0d1e7794401e2d3bdd3c17fd2ce3e4635 /fs/notify/inotify
parent28c60e37f874dcbb93c4afc839ba5e4911c4f4bc (diff)
fsnotify: per group notification queue merge types
inotify only wishes to merge a new event with the last event on the notification fifo. fanotify is willing to merge any events including by means of bitwise OR masks of multiple events together. This patch moves the inotify event merging logic out of the generic fsnotify notification.c and into the inotify code. This allows each use of fsnotify to provide their own merge functionality. Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify/inotify')
-rw-r--r--fs/notify/inotify/inotify_fsnotify.c56
-rw-r--r--fs/notify/inotify/inotify_user.c2
2 files changed, 56 insertions, 2 deletions
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index 1f33234cc308..0a0f5d0f0d0a 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -32,6 +32,60 @@
32 32
33#include "inotify.h" 33#include "inotify.h"
34 34
35/*
36 * Check if 2 events contain the same information. We do not compare private data
37 * but at this moment that isn't a problem for any know fsnotify listeners.
38 */
39static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new)
40{
41 if ((old->mask == new->mask) &&
42 (old->to_tell == new->to_tell) &&
43 (old->data_type == new->data_type) &&
44 (old->name_len == new->name_len)) {
45 switch (old->data_type) {
46 case (FSNOTIFY_EVENT_INODE):
47 /* remember, after old was put on the wait_q we aren't
48 * allowed to look at the inode any more, only thing
49 * left to check was if the file_name is the same */
50 if (!old->name_len ||
51 !strcmp(old->file_name, new->file_name))
52 return true;
53 break;
54 case (FSNOTIFY_EVENT_PATH):
55 if ((old->path.mnt == new->path.mnt) &&
56 (old->path.dentry == new->path.dentry))
57 return true;
58 break;
59 case (FSNOTIFY_EVENT_NONE):
60 if (old->mask & FS_Q_OVERFLOW)
61 return true;
62 else if (old->mask & FS_IN_IGNORED)
63 return false;
64 return true;
65 };
66 }
67 return false;
68}
69
70static int inotify_merge(struct list_head *list, struct fsnotify_event *event)
71{
72 struct fsnotify_event_holder *last_holder;
73 struct fsnotify_event *last_event;
74 int ret = 0;
75
76 /* and the list better be locked by something too */
77 spin_lock(&event->lock);
78
79 last_holder = list_entry(list->prev, struct fsnotify_event_holder, event_list);
80 last_event = last_holder->event;
81 if (event_compare(last_event, event))
82 ret = -EEXIST;
83
84 spin_unlock(&event->lock);
85
86 return ret;
87}
88
35static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) 89static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event)
36{ 90{
37 struct fsnotify_mark_entry *entry; 91 struct fsnotify_mark_entry *entry;
@@ -62,7 +116,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev
62 fsn_event_priv->group = group; 116 fsn_event_priv->group = group;
63 event_priv->wd = wd; 117 event_priv->wd = wd;
64 118
65 ret = fsnotify_add_notify_event(group, event, fsn_event_priv); 119 ret = fsnotify_add_notify_event(group, event, fsn_event_priv, inotify_merge);
66 if (ret) { 120 if (ret) {
67 inotify_free_event_priv(fsn_event_priv); 121 inotify_free_event_priv(fsn_event_priv);
68 /* EEXIST says we tail matched, EOVERFLOW isn't something 122 /* EEXIST says we tail matched, EOVERFLOW isn't something
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index f2b542479e91..cbe16df326f8 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -531,7 +531,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry,
531 fsn_event_priv->group = group; 531 fsn_event_priv->group = group;
532 event_priv->wd = ientry->wd; 532 event_priv->wd = ientry->wd;
533 533
534 ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv); 534 ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv, NULL);
535 if (ret) 535 if (ret)
536 inotify_free_event_priv(fsn_event_priv); 536 inotify_free_event_priv(fsn_event_priv);
537 537