diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h index ec5aee43bdc5..5bd22412017f 100644 --- a/fs/notify/fsnotify.h +++ b/fs/notify/fsnotify.h @@ -16,6 +16,8 @@ extern __u32 fsnotify_inode_mask; /* destroy all events sitting in this groups notification queue */ extern void fsnotify_flush_notify(struct fsnotify_group *group); +/* add a group to the inode group list */ +extern void fsnotify_add_inode_group(struct fsnotify_group *group); /* final kfree of a group */ extern void fsnotify_final_destroy_group(struct fsnotify_group *group); diff --git a/fs/notify/group.c b/fs/notify/group.c index 656c534ffb66..34fccbd2809c 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -77,12 +77,15 @@ void fsnotify_recalc_group_mask(struct fsnotify_group *group) fsnotify_recalc_global_mask(); } -static void fsnotify_add_group(struct fsnotify_group *group) +void fsnotify_add_inode_group(struct fsnotify_group *group) { - BUG_ON(!mutex_is_locked(&fsnotify_grp_mutex)); + mutex_lock(&fsnotify_grp_mutex); + if (!group->on_inode_group_list) + list_add_tail_rcu(&group->inode_group_list, &fsnotify_inode_groups); group->on_inode_group_list = 1; - list_add_tail_rcu(&group->inode_group_list, &fsnotify_inode_groups); + + mutex_unlock(&fsnotify_grp_mutex); } /* @@ -188,22 +191,17 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) */ atomic_set(&group->num_marks, 1); - mutex_init(&group->notification_mutex); INIT_LIST_HEAD(&group->notification_list); init_waitqueue_head(&group->notification_waitq); group->max_events = UINT_MAX; + INIT_LIST_HEAD(&group->inode_group_list); + spin_lock_init(&group->mark_lock); INIT_LIST_HEAD(&group->mark_entries); group->ops = ops; - mutex_lock(&fsnotify_grp_mutex); - - fsnotify_add_group(group); - - mutex_unlock(&fsnotify_grp_mutex); - return group; } diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 7d2962e5328e..a3230c485531 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -322,6 +322,13 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry, if (unlikely(!inode)) return -EINVAL; + /* + * if this group isn't being testing for inode type events we need + * to start testing + */ + if (unlikely(list_empty(&group->inode_group_list))) + fsnotify_add_inode_group(group); + /* * LOCKING ORDER!!!! * entry->lock