aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/group.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/notify/group.c')
-rw-r--r--fs/notify/group.c28
1 files changed, 10 insertions, 18 deletions
diff --git a/fs/notify/group.c b/fs/notify/group.c
index 1d57c35f1043..354044c47e23 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -33,9 +33,6 @@
33 */ 33 */
34void fsnotify_final_destroy_group(struct fsnotify_group *group) 34void fsnotify_final_destroy_group(struct fsnotify_group *group)
35{ 35{
36 /* clear the notification queue of all events */
37 fsnotify_flush_notify(group);
38
39 if (group->ops->free_group_priv) 36 if (group->ops->free_group_priv)
40 group->ops->free_group_priv(group); 37 group->ops->free_group_priv(group);
41 38
@@ -43,12 +40,10 @@ void fsnotify_final_destroy_group(struct fsnotify_group *group)
43} 40}
44 41
45/* 42/*
46 * Trying to get rid of a group. We need to first get rid of any outstanding 43 * Trying to get rid of a group. Remove all marks, flush all events and release
47 * allocations and then free the group. Remember that fsnotify_clear_marks_by_group 44 * the group reference.
48 * could miss marks that are being freed by inode and those marks could still 45 * Note that another thread calling fsnotify_clear_marks_by_group() may still
49 * hold a reference to this group (via group->num_marks) If we get into that 46 * hold a ref to the group.
50 * situtation, the fsnotify_final_destroy_group will get called when that final
51 * mark is freed.
52 */ 47 */
53void fsnotify_destroy_group(struct fsnotify_group *group) 48void fsnotify_destroy_group(struct fsnotify_group *group)
54{ 49{
@@ -57,9 +52,10 @@ void fsnotify_destroy_group(struct fsnotify_group *group)
57 52
58 synchronize_srcu(&fsnotify_mark_srcu); 53 synchronize_srcu(&fsnotify_mark_srcu);
59 54
60 /* past the point of no return, matches the initial value of 1 */ 55 /* clear the notification queue of all events */
61 if (atomic_dec_and_test(&group->num_marks)) 56 fsnotify_flush_notify(group);
62 fsnotify_final_destroy_group(group); 57
58 fsnotify_put_group(group);
63} 59}
64 60
65/* 61/*
@@ -76,7 +72,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
76void fsnotify_put_group(struct fsnotify_group *group) 72void fsnotify_put_group(struct fsnotify_group *group)
77{ 73{
78 if (atomic_dec_and_test(&group->refcnt)) 74 if (atomic_dec_and_test(&group->refcnt))
79 fsnotify_destroy_group(group); 75 fsnotify_final_destroy_group(group);
80} 76}
81 77
82/* 78/*
@@ -92,11 +88,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
92 88
93 /* set to 0 when there a no external references to this group */ 89 /* set to 0 when there a no external references to this group */
94 atomic_set(&group->refcnt, 1); 90 atomic_set(&group->refcnt, 1);
95 /* 91 atomic_set(&group->num_marks, 0);
96 * hits 0 when there are no external references AND no marks for
97 * this group
98 */
99 atomic_set(&group->num_marks, 1);
100 92
101 mutex_init(&group->notification_mutex); 93 mutex_init(&group->notification_mutex);
102 INIT_LIST_HEAD(&group->notification_list); 94 INIT_LIST_HEAD(&group->notification_list);