diff options
Diffstat (limited to 'fs/notify/group.c')
-rw-r--r-- | fs/notify/group.c | 28 |
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 | */ |
34 | void fsnotify_final_destroy_group(struct fsnotify_group *group) | 34 | void 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 | */ |
53 | void fsnotify_destroy_group(struct fsnotify_group *group) | 48 | void 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) | |||
76 | void fsnotify_put_group(struct fsnotify_group *group) | 72 | void 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); |