/* * Final freeing of a group
*/ staticvoid fsnotify_final_destroy_group(struct fsnotify_group *group)
{ if (group->ops->free_group_priv)
group->ops->free_group_priv(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)
{
spin_lock(&group->notification_lock);
group->shutdown = true;
spin_unlock(&group->notification_lock);
}
/* * 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 * hold a ref to the 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 marks for this group and queue them for destruction */
fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_ANY);
/* * Some marks can still be pinned when waiting for response from * userspace. Wait for those now. fsnotify_prepare_user_wait() will * not succeed now so this wait is race-free.
*/
wait_event(group->notification_waitq, !atomic_read(&group->user_waits));
/* * Wait until all marks get really destroyed. We could actually destroy * them ourselves instead of waiting for worker to do it, however that * would be racy as worker can already be processing some marks before * we even entered fsnotify_destroy_group().
*/
fsnotify_wait_marks_destroyed();
/* * Since we have waited for fsnotify_mark_srcu in * fsnotify_mark_destroy_list() there can be no outstanding event * notification against this group. So clearing the notification queue * of all events is reliable now.
*/
fsnotify_flush_notify(group);
/* * Destroy overflow event (we cannot use fsnotify_destroy_event() as * that deliberately ignores overflow events.
*/ if (group->overflow_event)
group->ops->free_event(group, group->overflow_event);
fsnotify_put_group(group);
}
/* * Get reference to a group.
*/ void fsnotify_get_group(struct fsnotify_group *group)
{
refcount_inc(&group->refcnt);
}
/* * Drop a reference to a group. Free it if it's through.
*/ void fsnotify_put_group(struct fsnotify_group *group)
{ if (refcount_dec_and_test(&group->refcnt))
fsnotify_final_destroy_group(group);
}
EXPORT_SYMBOL_GPL(fsnotify_put_group);
/* * Create a new fsnotify_group and hold a reference for the group returned.
*/ struct fsnotify_group *fsnotify_alloc_group(conststruct fsnotify_ops *ops, int flags)
{
gfp_t gfp = (flags & FSNOTIFY_GROUP_USER) ? GFP_KERNEL_ACCOUNT :
GFP_KERNEL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.