aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/notify/mark.c20
-rw-r--r--include/linux/fsnotify_backend.h7
2 files changed, 14 insertions, 13 deletions
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 0e93d90bb753..fc6b49bf7360 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -150,6 +150,8 @@ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
150 150
151 spin_unlock(&mark->lock); 151 spin_unlock(&mark->lock);
152 152
153 if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED))
154 iput(inode);
153 /* release lock temporarily */ 155 /* release lock temporarily */
154 mutex_unlock(&group->mark_mutex); 156 mutex_unlock(&group->mark_mutex);
155 157
@@ -157,6 +159,11 @@ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
157 list_add(&mark->destroy_list, &destroy_list); 159 list_add(&mark->destroy_list, &destroy_list);
158 spin_unlock(&destroy_lock); 160 spin_unlock(&destroy_lock);
159 wake_up(&destroy_waitq); 161 wake_up(&destroy_waitq);
162 /*
163 * We don't necessarily have a ref on mark from caller so the above destroy
164 * may have actually freed it, unless this group provides a 'freeing_mark'
165 * function which must be holding a reference.
166 */
160 167
161 /* 168 /*
162 * Some groups like to know that marks are being freed. This is a 169 * Some groups like to know that marks are being freed. This is a
@@ -178,22 +185,15 @@ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
178 * is just a lazy update (and could be a perf win...) 185 * is just a lazy update (and could be a perf win...)
179 */ 186 */
180 187
181 if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED))
182 iput(inode);
183 /*
184 * We don't necessarily have a ref on mark from caller so the above iput
185 * may have already destroyed it. Don't touch from now on.
186 */
187
188 atomic_dec(&group->num_marks); 188 atomic_dec(&group->num_marks);
189 189
190 mutex_lock(&group->mark_mutex); 190 mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
191} 191}
192 192
193void fsnotify_destroy_mark(struct fsnotify_mark *mark, 193void fsnotify_destroy_mark(struct fsnotify_mark *mark,
194 struct fsnotify_group *group) 194 struct fsnotify_group *group)
195{ 195{
196 mutex_lock(&group->mark_mutex); 196 mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
197 fsnotify_destroy_mark_locked(mark, group); 197 fsnotify_destroy_mark_locked(mark, group);
198 mutex_unlock(&group->mark_mutex); 198 mutex_unlock(&group->mark_mutex);
199} 199}
@@ -300,7 +300,7 @@ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group,
300{ 300{
301 struct fsnotify_mark *lmark, *mark; 301 struct fsnotify_mark *lmark, *mark;
302 302
303 mutex_lock(&group->mark_mutex); 303 mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
304 list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { 304 list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
305 if (mark->flags & flags) { 305 if (mark->flags & flags) {
306 fsnotify_get_mark(mark); 306 fsnotify_get_mark(mark);
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 5a8899350456..1af2f6a722c0 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -88,9 +88,10 @@ struct fsnotify_event_private_data;
88 * if the group is interested in this event. 88 * if the group is interested in this event.
89 * handle_event - main call for a group to handle an fs event 89 * handle_event - main call for a group to handle an fs event
90 * free_group_priv - called when a group refcnt hits 0 to clean up the private union 90 * free_group_priv - called when a group refcnt hits 0 to clean up the private union
91 * freeing-mark - this means that a mark has been flagged to die when everything 91 * freeing_mark - called when a mark is being destroyed for some reason. The group
92 * finishes using it. The function is supplied with what must be a 92 * MUST be holding a reference on each mark and that reference must be
93 * valid group and inode to use to clean up. 93 * dropped in this function. inotify uses this function to send
94 * userspace messages that marks have been removed.
94 */ 95 */
95struct fsnotify_ops { 96struct fsnotify_ops {
96 bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, 97 bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,