diff options
-rw-r--r-- | fs/notify/mark.c | 20 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 7 |
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 | ||
193 | void fsnotify_destroy_mark(struct fsnotify_mark *mark, | 193 | void 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 | */ |
95 | struct fsnotify_ops { | 96 | struct 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, |