Commit 6e5f77b3 authored by Eric Paris's avatar Eric Paris

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: default avatarEric Paris <eparis@redhat.com>
for fanotify to properly deal with permissions events
parent cb2d429f
...@@ -27,7 +27,9 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) ...@@ -27,7 +27,9 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
return false; 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_holder *test_holder;
struct fsnotify_event *test_event; struct fsnotify_event *test_event;
...@@ -92,7 +94,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_e ...@@ -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); 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 */ /* -EEXIST means this event was merged with another, not that it was an error */
if (ret == -EEXIST) if (ret == -EEXIST)
ret = 0; ret = 0;
......
...@@ -67,7 +67,9 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new ...@@ -67,7 +67,9 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new
return false; 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_holder *last_holder;
struct fsnotify_event *last_event; struct fsnotify_event *last_event;
...@@ -114,7 +116,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev ...@@ -114,7 +116,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev
fsn_event_priv->group = group; fsn_event_priv->group = group;
event_priv->wd = wd; 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) { if (ret) {
inotify_free_event_priv(fsn_event_priv); inotify_free_event_priv(fsn_event_priv);
/* EEXIST says we tail matched, EOVERFLOW isn't something /* EEXIST says we tail matched, EOVERFLOW isn't something
......
...@@ -525,7 +525,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, ...@@ -525,7 +525,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
fsn_event_priv->group = group; fsn_event_priv->group = group;
event_priv->wd = i_mark->wd; 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) if (ret)
inotify_free_event_priv(fsn_event_priv); inotify_free_event_priv(fsn_event_priv);
......
...@@ -137,7 +137,10 @@ struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struct fsnot ...@@ -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, int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event,
struct fsnotify_event_private_data *priv, 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 fsnotify_event_holder *holder = NULL;
struct list_head *list = &group->notification_list; struct list_head *list = &group->notification_list;
...@@ -170,7 +173,7 @@ int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_even ...@@ -170,7 +173,7 @@ int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_even
if (!list_empty(list) && merge) { if (!list_empty(list) && merge) {
int ret; int ret;
ret = merge(list, event); ret = merge(list, event, arg);
if (ret) { if (ret) {
mutex_unlock(&group->notification_mutex); mutex_unlock(&group->notification_mutex);
if (holder != &event->holder) if (holder != &event->holder)
......
...@@ -355,7 +355,10 @@ extern struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struc ...@@ -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, extern int fsnotify_add_notify_event(struct fsnotify_group *group,
struct fsnotify_event *event, struct fsnotify_event *event,
struct fsnotify_event_private_data *priv, 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 */ /* true if the group notification queue is empty */
extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group); extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group);
/* return, but do not dequeue the first event on the notification queue */ /* return, but do not dequeue the first event on the notification queue */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment