diff options
Diffstat (limited to 'fs/notify/mark.c')
-rw-r--r-- | fs/notify/mark.c | 34 |
1 files changed, 14 insertions, 20 deletions
diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 92e48c70f0f0..3e594ce41010 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c | |||
@@ -152,31 +152,15 @@ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark, | |||
152 | BUG(); | 152 | BUG(); |
153 | 153 | ||
154 | list_del_init(&mark->g_list); | 154 | list_del_init(&mark->g_list); |
155 | |||
156 | spin_unlock(&mark->lock); | 155 | spin_unlock(&mark->lock); |
157 | 156 | ||
158 | if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED)) | 157 | if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED)) |
159 | iput(inode); | 158 | iput(inode); |
160 | /* release lock temporarily */ | ||
161 | mutex_unlock(&group->mark_mutex); | ||
162 | 159 | ||
163 | spin_lock(&destroy_lock); | 160 | spin_lock(&destroy_lock); |
164 | list_add(&mark->g_list, &destroy_list); | 161 | list_add(&mark->g_list, &destroy_list); |
165 | spin_unlock(&destroy_lock); | 162 | spin_unlock(&destroy_lock); |
166 | wake_up(&destroy_waitq); | 163 | wake_up(&destroy_waitq); |
167 | /* | ||
168 | * We don't necessarily have a ref on mark from caller so the above destroy | ||
169 | * may have actually freed it, unless this group provides a 'freeing_mark' | ||
170 | * function which must be holding a reference. | ||
171 | */ | ||
172 | |||
173 | /* | ||
174 | * Some groups like to know that marks are being freed. This is a | ||
175 | * callback to the group function to let it know that this mark | ||
176 | * is being freed. | ||
177 | */ | ||
178 | if (group->ops->freeing_mark) | ||
179 | group->ops->freeing_mark(mark, group); | ||
180 | 164 | ||
181 | /* | 165 | /* |
182 | * __fsnotify_update_child_dentry_flags(inode); | 166 | * __fsnotify_update_child_dentry_flags(inode); |
@@ -191,8 +175,6 @@ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark, | |||
191 | */ | 175 | */ |
192 | 176 | ||
193 | atomic_dec(&group->num_marks); | 177 | atomic_dec(&group->num_marks); |
194 | |||
195 | mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); | ||
196 | } | 178 | } |
197 | 179 | ||
198 | void fsnotify_destroy_mark(struct fsnotify_mark *mark, | 180 | void fsnotify_destroy_mark(struct fsnotify_mark *mark, |
@@ -205,7 +187,10 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark, | |||
205 | 187 | ||
206 | /* | 188 | /* |
207 | * Destroy all marks in the given list. The marks must be already detached from | 189 | * Destroy all marks in the given list. The marks must be already detached from |
208 | * the original inode / vfsmount. | 190 | * the original inode / vfsmount. Note that we can race with |
191 | * fsnotify_clear_marks_by_group_flags(). However we hold a reference to each | ||
192 | * mark so they won't get freed from under us and nobody else touches our | ||
193 | * free_list list_head. | ||
209 | */ | 194 | */ |
210 | void fsnotify_destroy_marks(struct list_head *to_free) | 195 | void fsnotify_destroy_marks(struct list_head *to_free) |
211 | { | 196 | { |
@@ -406,7 +391,7 @@ struct fsnotify_mark *fsnotify_find_mark(struct hlist_head *head, | |||
406 | } | 391 | } |
407 | 392 | ||
408 | /* | 393 | /* |
409 | * clear any marks in a group in which mark->flags & flags is true | 394 | * Clear any marks in a group in which mark->flags & flags is true. |
410 | */ | 395 | */ |
411 | void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, | 396 | void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, |
412 | unsigned int flags) | 397 | unsigned int flags) |
@@ -460,6 +445,7 @@ static int fsnotify_mark_destroy(void *ignored) | |||
460 | { | 445 | { |
461 | struct fsnotify_mark *mark, *next; | 446 | struct fsnotify_mark *mark, *next; |
462 | struct list_head private_destroy_list; | 447 | struct list_head private_destroy_list; |
448 | struct fsnotify_group *group; | ||
463 | 449 | ||
464 | for (;;) { | 450 | for (;;) { |
465 | spin_lock(&destroy_lock); | 451 | spin_lock(&destroy_lock); |
@@ -471,6 +457,14 @@ static int fsnotify_mark_destroy(void *ignored) | |||
471 | 457 | ||
472 | list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) { | 458 | list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) { |
473 | list_del_init(&mark->g_list); | 459 | list_del_init(&mark->g_list); |
460 | group = mark->group; | ||
461 | /* | ||
462 | * Some groups like to know that marks are being freed. | ||
463 | * This is a callback to the group function to let it | ||
464 | * know that this mark is being freed. | ||
465 | */ | ||
466 | if (group && group->ops->freeing_mark) | ||
467 | group->ops->freeing_mark(mark, group); | ||
474 | fsnotify_put_mark(mark); | 468 | fsnotify_put_mark(mark); |
475 | } | 469 | } |
476 | 470 | ||