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, |
