Message ID | 1473344745-20634-3-git-send-email-jack@suse.cz (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
s/AE_SHUTDOWN/1/ Reviewed-by: Miklos Szeredi <mszeredi@redhat.com> On Thu, Sep 8, 2016 at 4:25 PM, Jan Kara <jack@suse.cz> wrote: > Implement a function that can be called when a group is being shutdown > to stop queueing new events to the group. Fanotify will use this. > > Signed-off-by: Jan Kara <jack@suse.cz> > --- > fs/notify/group.c | 19 +++++++++++++++++++ > fs/notify/notification.c | 5 +++++ > include/linux/fsnotify_backend.h | 4 ++++ > 3 files changed, 28 insertions(+) > > diff --git a/fs/notify/group.c b/fs/notify/group.c > index 3e2dd85be5dd..b47f7cfdcaa4 100644 > --- a/fs/notify/group.c > +++ b/fs/notify/group.c > @@ -40,6 +40,17 @@ static void fsnotify_final_destroy_group(struct fsnotify_group *group) > } > > /* > + * Stop queueing new events for this group. Once this function returns > + * fsnotify_add_event() will not add any new events to the group's queue. > + */ > +void fsnotify_group_stop_queueing(struct fsnotify_group *group) > +{ > + mutex_lock(&group->notification_mutex); > + group->shutdown = true; > + mutex_unlock(&group->notification_mutex); > +} > + > +/* > * Trying to get rid of a group. Remove all marks, flush all events and release > * the group reference. > * Note that another thread calling fsnotify_clear_marks_by_group() may still > @@ -47,6 +58,14 @@ static void fsnotify_final_destroy_group(struct fsnotify_group *group) > */ > void fsnotify_destroy_group(struct fsnotify_group *group) > { > + /* > + * Stop queueing new events. The code below is careful enough to not > + * require this but fanotify needs to stop queuing events even before > + * fsnotify_destroy_group() is called and this makes the other callers > + * of fsnotify_destroy_group() to see the same behavior. > + */ > + fsnotify_group_stop_queueing(group); > + > /* clear all inode marks for this group, attach them to destroy_list */ > fsnotify_detach_group_marks(group); > > diff --git a/fs/notify/notification.c b/fs/notify/notification.c > index 12bfd6790fc4..af0497cac06c 100644 > --- a/fs/notify/notification.c > +++ b/fs/notify/notification.c > @@ -96,6 +96,11 @@ enum fsn_add_event_ret fsnotify_add_event( > > mutex_lock(&group->notification_mutex); > > + if (group->shutdown) { > + mutex_unlock(&group->notification_mutex); > + return AE_SHUTDOWN; > + } > + > if (group->q_len >= group->max_events) { > ret = AE_OVERFLOW; > /* Queue overflow event only if it isn't already queued */ > diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h > index b948a52ce65f..bcba826a99fc 100644 > --- a/include/linux/fsnotify_backend.h > +++ b/include/linux/fsnotify_backend.h > @@ -148,6 +148,7 @@ struct fsnotify_group { > #define FS_PRIO_1 1 /* fanotify content based access control */ > #define FS_PRIO_2 2 /* fanotify pre-content access */ > unsigned int priority; > + bool shutdown; /* group is being shut down, don't queue more events */ > > /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */ > struct mutex mark_mutex; /* protect marks_list */ > @@ -292,6 +293,8 @@ extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *op > extern void fsnotify_get_group(struct fsnotify_group *group); > /* drop reference on a group from fsnotify_alloc_group */ > extern void fsnotify_put_group(struct fsnotify_group *group); > +/* group destruction begins, stop queuing new events */ > +extern void fsnotify_group_stop_queueing(struct fsnotify_group *group); > /* destroy group */ > extern void fsnotify_destroy_group(struct fsnotify_group *group); > /* fasync handler function */ > @@ -304,6 +307,7 @@ enum fsn_add_event_ret { > AE_INSERTED, /* Event was added in the queue */ > AE_MERGED, /* Event was merged with another event, passed event unused */ > AE_OVERFLOW, /* Queue overflow, passed event unused */ > + AE_SHUTDOWN, /* Group is being released, passed event unused */ > }; > /* attach the event to the group notification queue */ > extern enum fsn_add_event_ret fsnotify_add_event( > -- > 2.6.6 > -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/notify/group.c b/fs/notify/group.c index 3e2dd85be5dd..b47f7cfdcaa4 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -40,6 +40,17 @@ static void fsnotify_final_destroy_group(struct fsnotify_group *group) } /* + * Stop queueing new events for this group. Once this function returns + * fsnotify_add_event() will not add any new events to the group's queue. + */ +void fsnotify_group_stop_queueing(struct fsnotify_group *group) +{ + mutex_lock(&group->notification_mutex); + group->shutdown = true; + mutex_unlock(&group->notification_mutex); +} + +/* * Trying to get rid of a group. Remove all marks, flush all events and release * the group reference. * Note that another thread calling fsnotify_clear_marks_by_group() may still @@ -47,6 +58,14 @@ static void fsnotify_final_destroy_group(struct fsnotify_group *group) */ void fsnotify_destroy_group(struct fsnotify_group *group) { + /* + * Stop queueing new events. The code below is careful enough to not + * require this but fanotify needs to stop queuing events even before + * fsnotify_destroy_group() is called and this makes the other callers + * of fsnotify_destroy_group() to see the same behavior. + */ + fsnotify_group_stop_queueing(group); + /* clear all inode marks for this group, attach them to destroy_list */ fsnotify_detach_group_marks(group); diff --git a/fs/notify/notification.c b/fs/notify/notification.c index 12bfd6790fc4..af0497cac06c 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c @@ -96,6 +96,11 @@ enum fsn_add_event_ret fsnotify_add_event( mutex_lock(&group->notification_mutex); + if (group->shutdown) { + mutex_unlock(&group->notification_mutex); + return AE_SHUTDOWN; + } + if (group->q_len >= group->max_events) { ret = AE_OVERFLOW; /* Queue overflow event only if it isn't already queued */ diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index b948a52ce65f..bcba826a99fc 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -148,6 +148,7 @@ struct fsnotify_group { #define FS_PRIO_1 1 /* fanotify content based access control */ #define FS_PRIO_2 2 /* fanotify pre-content access */ unsigned int priority; + bool shutdown; /* group is being shut down, don't queue more events */ /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */ struct mutex mark_mutex; /* protect marks_list */ @@ -292,6 +293,8 @@ extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *op extern void fsnotify_get_group(struct fsnotify_group *group); /* drop reference on a group from fsnotify_alloc_group */ extern void fsnotify_put_group(struct fsnotify_group *group); +/* group destruction begins, stop queuing new events */ +extern void fsnotify_group_stop_queueing(struct fsnotify_group *group); /* destroy group */ extern void fsnotify_destroy_group(struct fsnotify_group *group); /* fasync handler function */ @@ -304,6 +307,7 @@ enum fsn_add_event_ret { AE_INSERTED, /* Event was added in the queue */ AE_MERGED, /* Event was merged with another event, passed event unused */ AE_OVERFLOW, /* Queue overflow, passed event unused */ + AE_SHUTDOWN, /* Group is being released, passed event unused */ }; /* attach the event to the group notification queue */ extern enum fsn_add_event_ret fsnotify_add_event(
Implement a function that can be called when a group is being shutdown to stop queueing new events to the group. Fanotify will use this. Signed-off-by: Jan Kara <jack@suse.cz> --- fs/notify/group.c | 19 +++++++++++++++++++ fs/notify/notification.c | 5 +++++ include/linux/fsnotify_backend.h | 4 ++++ 3 files changed, 28 insertions(+)