aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 21:24:34 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:59:01 -0400
commit6e5f77b32e9097a8a68a8d453799676cacf70cad (patch)
tree2a0211ecd5d79648e74fdf9f851a0669c5e4cc8a
parentcb2d429faf2cae62d3c51e28099a181d5fe8c244 (diff)
fsnotify: intoduce a notification merge argument
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
-rw-r--r--fs/notify/fanotify/fanotify.c6
-rw-r--r--fs/notify/inotify/inotify_fsnotify.c6
-rw-r--r--fs/notify/inotify/inotify_user.c2
-rw-r--r--fs/notify/notification.c7
-rw-r--r--include/linux/fsnotify_backend.h5
5 files changed, 18 insertions, 8 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 060b177146e8..95a330d2f8a1 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -27,7 +27,9 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
27 return false; 27 return false;
28} 28}
29 29
30static int fanotify_merge(struct list_head *list, struct fsnotify_event *event) 30static int fanotify_merge(struct list_head *list,
31 struct fsnotify_event *event,
32 void **arg)
31{ 33{
32 struct fsnotify_event_holder *test_holder; 34 struct fsnotify_event_holder *test_holder;
33 struct fsnotify_event *test_event; 35 struct fsnotify_event *test_event;
@@ -92,7 +94,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_e
92 94
93 pr_debug("%s: group=%p event=%p\n", __func__, group, event); 95 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
94 96
95 ret = fsnotify_add_notify_event(group, event, NULL, fanotify_merge); 97 ret = fsnotify_add_notify_event(group, event, NULL, fanotify_merge, NULL);
96 /* -EEXIST means this event was merged with another, not that it was an error */ 98 /* -EEXIST means this event was merged with another, not that it was an error */
97 if (ret == -EEXIST) 99 if (ret == -EEXIST)
98 ret = 0; 100 ret = 0;
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index 1d237e1bf7b1..daa666a6e6c9 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -67,7 +67,9 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new
67 return false; 67 return false;
68} 68}
69 69
70static int inotify_merge(struct list_head *list, struct fsnotify_event *event) 70static int inotify_merge(struct list_head *list,
71 struct fsnotify_event *event,
72 void **arg)
71{ 73{
72 struct fsnotify_event_holder *last_holder; 74 struct fsnotify_event_holder *last_holder;
73 struct fsnotify_event *last_event; 75 struct fsnotify_event *last_event;
@@ -114,7 +116,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev
114 fsn_event_priv->group = group; 116 fsn_event_priv->group = group;
115 event_priv->wd = wd; 117 event_priv->wd = wd;
116 118
117 ret = fsnotify_add_notify_event(group, event, fsn_event_priv, inotify_merge); 119 ret = fsnotify_add_notify_event(group, event, fsn_event_priv, inotify_merge, NULL);
118 if (ret) { 120 if (ret) {
119 inotify_free_event_priv(fsn_event_priv); 121 inotify_free_event_priv(fsn_event_priv);
120 /* 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 19d274057bfa..1ce71f5b9589 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -525,7 +525,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
525 fsn_event_priv->group = group; 525 fsn_event_priv->group = group;
526 event_priv->wd = i_mark->wd; 526 event_priv->wd = i_mark->wd;
527 527
528 ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv, NULL); 528 ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv, NULL, NULL);
529 if (ret) 529 if (ret)
530 inotify_free_event_priv(fsn_event_priv); 530 inotify_free_event_priv(fsn_event_priv);
531 531
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index 7fc8d004084c..2d50a40ab1e4 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -137,7 +137,10 @@ struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struct fsnot
137 */ 137 */
138int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event, 138int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event,
139 struct fsnotify_event_private_data *priv, 139 struct fsnotify_event_private_data *priv,
140 int (*merge)(struct list_head *, struct fsnotify_event *)) 140 int (*merge)(struct list_head *,
141 struct fsnotify_event *,
142 void **arg),
143 void **arg)
141{ 144{
142 struct fsnotify_event_holder *holder = NULL; 145 struct fsnotify_event_holder *holder = NULL;
143 struct list_head *list = &group->notification_list; 146 struct list_head *list = &group->notification_list;
@@ -170,7 +173,7 @@ alloc_holder:
170 if (!list_empty(list) && merge) { 173 if (!list_empty(list) && merge) {
171 int ret; 174 int ret;
172 175
173 ret = merge(list, event); 176 ret = merge(list, event, arg);
174 if (ret) { 177 if (ret) {
175 mutex_unlock(&group->notification_mutex); 178 mutex_unlock(&group->notification_mutex);
176 if (holder != &event->holder) 179 if (holder != &event->holder)
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 8b2e095e5907..afc690192972 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -355,7 +355,10 @@ extern struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struc
355extern int fsnotify_add_notify_event(struct fsnotify_group *group, 355extern int fsnotify_add_notify_event(struct fsnotify_group *group,
356 struct fsnotify_event *event, 356 struct fsnotify_event *event,
357 struct fsnotify_event_private_data *priv, 357 struct fsnotify_event_private_data *priv,
358 int (*merge)(struct list_head *, struct fsnotify_event *)); 358 int (*merge)(struct list_head *,
359 struct fsnotify_event *,
360 void **),
361 void **arg);
359/* true if the group notification queue is empty */ 362/* true if the group notification queue is empty */
360extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group); 363extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group);
361/* return, but do not dequeue the first event on the notification queue */ 364/* return, but do not dequeue the first event on the notification queue */