diff options
| -rw-r--r-- | fs/notify/mark.c | 42 | ||||
| -rw-r--r-- | include/linux/fsnotify_backend.h | 4 |
2 files changed, 34 insertions, 12 deletions
diff --git a/fs/notify/mark.c b/fs/notify/mark.c index b77c833c8d0a..f9dda0304a10 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c | |||
| @@ -121,18 +121,18 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) | |||
| 121 | * The caller had better be holding a reference to this mark so we don't actually | 121 | * The caller had better be holding a reference to this mark so we don't actually |
| 122 | * do the final put under the mark->lock | 122 | * do the final put under the mark->lock |
| 123 | */ | 123 | */ |
| 124 | void fsnotify_destroy_mark(struct fsnotify_mark *mark, | 124 | void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark, |
| 125 | struct fsnotify_group *group) | 125 | struct fsnotify_group *group) |
| 126 | { | 126 | { |
| 127 | struct inode *inode = NULL; | 127 | struct inode *inode = NULL; |
| 128 | 128 | ||
| 129 | mutex_lock(&group->mark_mutex); | 129 | BUG_ON(!mutex_is_locked(&group->mark_mutex)); |
| 130 | |||
| 130 | spin_lock(&mark->lock); | 131 | spin_lock(&mark->lock); |
| 131 | 132 | ||
| 132 | /* something else already called this function on this mark */ | 133 | /* something else already called this function on this mark */ |
| 133 | if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) { | 134 | if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) { |
| 134 | spin_unlock(&mark->lock); | 135 | spin_unlock(&mark->lock); |
| 135 | mutex_unlock(&group->mark_mutex); | ||
| 136 | return; | 136 | return; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| @@ -149,6 +149,8 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark, | |||
| 149 | list_del_init(&mark->g_list); | 149 | list_del_init(&mark->g_list); |
| 150 | 150 | ||
| 151 | spin_unlock(&mark->lock); | 151 | spin_unlock(&mark->lock); |
| 152 | |||
| 153 | /* release lock temporarily */ | ||
| 152 | mutex_unlock(&group->mark_mutex); | 154 | mutex_unlock(&group->mark_mutex); |
| 153 | 155 | ||
| 154 | spin_lock(&destroy_lock); | 156 | spin_lock(&destroy_lock); |
| @@ -184,6 +186,16 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark, | |||
| 184 | */ | 186 | */ |
| 185 | 187 | ||
| 186 | atomic_dec(&group->num_marks); | 188 | atomic_dec(&group->num_marks); |
| 189 | |||
| 190 | mutex_lock(&group->mark_mutex); | ||
| 191 | } | ||
| 192 | |||
| 193 | void fsnotify_destroy_mark(struct fsnotify_mark *mark, | ||
| 194 | struct fsnotify_group *group) | ||
| 195 | { | ||
| 196 | mutex_lock(&group->mark_mutex); | ||
| 197 | fsnotify_destroy_mark_locked(mark, group); | ||
| 198 | mutex_unlock(&group->mark_mutex); | ||
| 187 | } | 199 | } |
| 188 | 200 | ||
| 189 | void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask) | 201 | void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask) |
| @@ -208,14 +220,15 @@ void fsnotify_set_mark_ignored_mask_locked(struct fsnotify_mark *mark, __u32 mas | |||
| 208 | * These marks may be used for the fsnotify backend to determine which | 220 | * These marks may be used for the fsnotify backend to determine which |
| 209 | * event types should be delivered to which group. | 221 | * event types should be delivered to which group. |
| 210 | */ | 222 | */ |
| 211 | int fsnotify_add_mark(struct fsnotify_mark *mark, | 223 | int fsnotify_add_mark_locked(struct fsnotify_mark *mark, |
| 212 | struct fsnotify_group *group, struct inode *inode, | 224 | struct fsnotify_group *group, struct inode *inode, |
| 213 | struct vfsmount *mnt, int allow_dups) | 225 | struct vfsmount *mnt, int allow_dups) |
| 214 | { | 226 | { |
| 215 | int ret = 0; | 227 | int ret = 0; |
| 216 | 228 | ||
| 217 | BUG_ON(inode && mnt); | 229 | BUG_ON(inode && mnt); |
| 218 | BUG_ON(!inode && !mnt); | 230 | BUG_ON(!inode && !mnt); |
| 231 | BUG_ON(!mutex_is_locked(&group->mark_mutex)); | ||
| 219 | 232 | ||
| 220 | /* | 233 | /* |
| 221 | * LOCKING ORDER!!!! | 234 | * LOCKING ORDER!!!! |
| @@ -223,8 +236,6 @@ int fsnotify_add_mark(struct fsnotify_mark *mark, | |||
| 223 | * mark->lock | 236 | * mark->lock |
| 224 | * inode->i_lock | 237 | * inode->i_lock |
| 225 | */ | 238 | */ |
| 226 | mutex_lock(&group->mark_mutex); | ||
| 227 | |||
| 228 | spin_lock(&mark->lock); | 239 | spin_lock(&mark->lock); |
| 229 | mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE; | 240 | mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE; |
| 230 | 241 | ||
| @@ -250,8 +261,6 @@ int fsnotify_add_mark(struct fsnotify_mark *mark, | |||
| 250 | fsnotify_set_mark_mask_locked(mark, mark->mask); | 261 | fsnotify_set_mark_mask_locked(mark, mark->mask); |
| 251 | spin_unlock(&mark->lock); | 262 | spin_unlock(&mark->lock); |
| 252 | 263 | ||
| 253 | mutex_unlock(&group->mark_mutex); | ||
| 254 | |||
| 255 | if (inode) | 264 | if (inode) |
| 256 | __fsnotify_update_child_dentry_flags(inode); | 265 | __fsnotify_update_child_dentry_flags(inode); |
| 257 | 266 | ||
| @@ -264,7 +273,6 @@ err: | |||
| 264 | atomic_dec(&group->num_marks); | 273 | atomic_dec(&group->num_marks); |
| 265 | 274 | ||
| 266 | spin_unlock(&mark->lock); | 275 | spin_unlock(&mark->lock); |
| 267 | mutex_unlock(&group->mark_mutex); | ||
| 268 | 276 | ||
| 269 | spin_lock(&destroy_lock); | 277 | spin_lock(&destroy_lock); |
| 270 | list_add(&mark->destroy_list, &destroy_list); | 278 | list_add(&mark->destroy_list, &destroy_list); |
| @@ -274,6 +282,16 @@ err: | |||
| 274 | return ret; | 282 | return ret; |
| 275 | } | 283 | } |
| 276 | 284 | ||
| 285 | int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, | ||
| 286 | struct inode *inode, struct vfsmount *mnt, int allow_dups) | ||
| 287 | { | ||
| 288 | int ret; | ||
| 289 | mutex_lock(&group->mark_mutex); | ||
| 290 | ret = fsnotify_add_mark_locked(mark, group, inode, mnt, allow_dups); | ||
| 291 | mutex_unlock(&group->mark_mutex); | ||
| 292 | return ret; | ||
| 293 | } | ||
| 294 | |||
| 277 | /* | 295 | /* |
| 278 | * clear any marks in a group in which mark->flags & flags is true | 296 | * clear any marks in a group in which mark->flags & flags is true |
| 279 | */ | 297 | */ |
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 140b4b8a100b..26c06afa264e 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
| @@ -408,9 +408,13 @@ extern void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask | |||
| 408 | /* attach the mark to both the group and the inode */ | 408 | /* attach the mark to both the group and the inode */ |
| 409 | extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, | 409 | extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, |
| 410 | struct inode *inode, struct vfsmount *mnt, int allow_dups); | 410 | struct inode *inode, struct vfsmount *mnt, int allow_dups); |
| 411 | extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark, struct fsnotify_group *group, | ||
| 412 | struct inode *inode, struct vfsmount *mnt, int allow_dups); | ||
| 411 | /* given a group and a mark, flag mark to be freed when all references are dropped */ | 413 | /* given a group and a mark, flag mark to be freed when all references are dropped */ |
| 412 | extern void fsnotify_destroy_mark(struct fsnotify_mark *mark, | 414 | extern void fsnotify_destroy_mark(struct fsnotify_mark *mark, |
| 413 | struct fsnotify_group *group); | 415 | struct fsnotify_group *group); |
| 416 | extern void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark, | ||
| 417 | struct fsnotify_group *group); | ||
| 414 | /* run all the marks in a group, and clear all of the vfsmount marks */ | 418 | /* run all the marks in a group, and clear all of the vfsmount marks */ |
| 415 | extern void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group); | 419 | extern void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group); |
| 416 | /* run all the marks in a group, and clear all of the inode marks */ | 420 | /* run all the marks in a group, and clear all of the inode marks */ |
