aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-20 23:11:52 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-20 23:11:52 -0500
commit96680d2b9174668100824d763382240c71baa811 (patch)
treeec84c2347df47913cc98e3cfc1d43f427d51fa1f /fs/notify
parent4c9a44aebeaef35570a67aed17b72a2cf8d0b219 (diff)
parent1ca39ab9d21ac93f94b9e3eb364ea9a5cf2aba06 (diff)
Merge branch 'for-next' of git://git.infradead.org/users/eparis/notify
Pull filesystem notification updates from Eric Paris: "This pull mostly is about locking changes in the fsnotify system. By switching the group lock from a spin_lock() to a mutex() we can now hold the lock across things like iput(). This fixes a problem involving unmounting a fs and having inodes be busy, first pointed out by FAT, but reproducible with tmpfs. This also restores signal driven I/O for inotify, which has been broken since about 2.6.32." Ugh. I *hate* the timing of this. It was rebased after the merge window opened, and then left to sit with the pull request coming the day before the merge window closes. That's just crap. But apparently the patches themselves have been around for over a year, just gathering dust, so now it's suddenly critical. Fixed up semantic conflict in fs/notify/fdinfo.c as per Stephen Rothwell's fixes from -next. * 'for-next' of git://git.infradead.org/users/eparis/notify: inotify: automatically restart syscalls inotify: dont skip removal of watch descriptor if creation of ignored event failed fanotify: dont merge permission events fsnotify: make fasync generic for both inotify and fanotify fsnotify: change locking order fsnotify: dont put marks on temporary list when clearing marks by group fsnotify: introduce locked versions of fsnotify_add_mark() and fsnotify_remove_mark() fsnotify: pass group to fsnotify_destroy_mark() fsnotify: use a mutex instead of a spinlock to protect a groups mark list fanotify: add an extra flag to mark_remove_from_mask that indicates wheather a mark should be destroyed fsnotify: take groups mark_lock before mark lock fsnotify: use reference counting for groups fsnotify: introduce fsnotify_get_group() inotify, fanotify: replace fsnotify_put_group() with fsnotify_destroy_group()
Diffstat (limited to 'fs/notify')
-rw-r--r--fs/notify/dnotify/dnotify.c4
-rw-r--r--fs/notify/fanotify/fanotify.c6
-rw-r--r--fs/notify/fanotify/fanotify_user.c37
-rw-r--r--fs/notify/fdinfo.c4
-rw-r--r--fs/notify/group.c47
-rw-r--r--fs/notify/inode_mark.c14
-rw-r--r--fs/notify/inotify/inotify_fsnotify.c4
-rw-r--r--fs/notify/inotify/inotify_user.c34
-rw-r--r--fs/notify/mark.c91
-rw-r--r--fs/notify/notification.c1
-rw-r--r--fs/notify/vfsmount_mark.c14
11 files changed, 152 insertions, 104 deletions
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 3344bdd5506e..08b886f119ce 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -201,7 +201,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
201 201
202 /* nothing else could have found us thanks to the dnotify_mark_mutex */ 202 /* nothing else could have found us thanks to the dnotify_mark_mutex */
203 if (dn_mark->dn == NULL) 203 if (dn_mark->dn == NULL)
204 fsnotify_destroy_mark(fsn_mark); 204 fsnotify_destroy_mark(fsn_mark, dnotify_group);
205 205
206 mutex_unlock(&dnotify_mark_mutex); 206 mutex_unlock(&dnotify_mark_mutex);
207 207
@@ -385,7 +385,7 @@ out:
385 spin_unlock(&fsn_mark->lock); 385 spin_unlock(&fsn_mark->lock);
386 386
387 if (destroy) 387 if (destroy)
388 fsnotify_destroy_mark(fsn_mark); 388 fsnotify_destroy_mark(fsn_mark, dnotify_group);
389 389
390 mutex_unlock(&dnotify_mark_mutex); 390 mutex_unlock(&dnotify_mark_mutex);
391 fsnotify_put_mark(fsn_mark); 391 fsnotify_put_mark(fsn_mark);
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index a50636025364..0c2f9122b262 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -18,6 +18,12 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
18 old->tgid == new->tgid) { 18 old->tgid == new->tgid) {
19 switch (old->data_type) { 19 switch (old->data_type) {
20 case (FSNOTIFY_EVENT_PATH): 20 case (FSNOTIFY_EVENT_PATH):
21#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
22 /* dont merge two permission events */
23 if ((old->mask & FAN_ALL_PERM_EVENTS) &&
24 (new->mask & FAN_ALL_PERM_EVENTS))
25 return false;
26#endif
21 if ((old->path.mnt == new->path.mnt) && 27 if ((old->path.mnt == new->path.mnt) &&
22 (old->path.dentry == new->path.dentry)) 28 (old->path.dentry == new->path.dentry))
23 return true; 29 return true;
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index a5cd9bba022f..9ff4a5ee6e20 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -397,8 +397,12 @@ static int fanotify_release(struct inode *ignored, struct file *file)
397 397
398 wake_up(&group->fanotify_data.access_waitq); 398 wake_up(&group->fanotify_data.access_waitq);
399#endif 399#endif
400
401 if (file->f_flags & FASYNC)
402 fsnotify_fasync(-1, file, 0);
403
400 /* matches the fanotify_init->fsnotify_alloc_group */ 404 /* matches the fanotify_init->fsnotify_alloc_group */
401 fsnotify_put_group(group); 405 fsnotify_destroy_group(group);
402 406
403 return 0; 407 return 0;
404} 408}
@@ -493,7 +497,8 @@ out:
493 497
494static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, 498static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
495 __u32 mask, 499 __u32 mask,
496 unsigned int flags) 500 unsigned int flags,
501 int *destroy)
497{ 502{
498 __u32 oldmask; 503 __u32 oldmask;
499 504
@@ -507,8 +512,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
507 } 512 }
508 spin_unlock(&fsn_mark->lock); 513 spin_unlock(&fsn_mark->lock);
509 514
510 if (!(oldmask & ~mask)) 515 *destroy = !(oldmask & ~mask);
511 fsnotify_destroy_mark(fsn_mark);
512 516
513 return mask & oldmask; 517 return mask & oldmask;
514} 518}
@@ -519,12 +523,17 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
519{ 523{
520 struct fsnotify_mark *fsn_mark = NULL; 524 struct fsnotify_mark *fsn_mark = NULL;
521 __u32 removed; 525 __u32 removed;
526 int destroy_mark;
522 527
523 fsn_mark = fsnotify_find_vfsmount_mark(group, mnt); 528 fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);
524 if (!fsn_mark) 529 if (!fsn_mark)
525 return -ENOENT; 530 return -ENOENT;
526 531
527 removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags); 532 removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
533 &destroy_mark);
534 if (destroy_mark)
535 fsnotify_destroy_mark(fsn_mark, group);
536
528 fsnotify_put_mark(fsn_mark); 537 fsnotify_put_mark(fsn_mark);
529 if (removed & real_mount(mnt)->mnt_fsnotify_mask) 538 if (removed & real_mount(mnt)->mnt_fsnotify_mask)
530 fsnotify_recalc_vfsmount_mask(mnt); 539 fsnotify_recalc_vfsmount_mask(mnt);
@@ -538,12 +547,16 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
538{ 547{
539 struct fsnotify_mark *fsn_mark = NULL; 548 struct fsnotify_mark *fsn_mark = NULL;
540 __u32 removed; 549 __u32 removed;
550 int destroy_mark;
541 551
542 fsn_mark = fsnotify_find_inode_mark(group, inode); 552 fsn_mark = fsnotify_find_inode_mark(group, inode);
543 if (!fsn_mark) 553 if (!fsn_mark)
544 return -ENOENT; 554 return -ENOENT;
545 555
546 removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags); 556 removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
557 &destroy_mark);
558 if (destroy_mark)
559 fsnotify_destroy_mark(fsn_mark, group);
547 /* matches the fsnotify_find_inode_mark() */ 560 /* matches the fsnotify_find_inode_mark() */
548 fsnotify_put_mark(fsn_mark); 561 fsnotify_put_mark(fsn_mark);
549 if (removed & inode->i_fsnotify_mask) 562 if (removed & inode->i_fsnotify_mask)
@@ -710,13 +723,13 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
710 break; 723 break;
711 default: 724 default:
712 fd = -EINVAL; 725 fd = -EINVAL;
713 goto out_put_group; 726 goto out_destroy_group;
714 } 727 }
715 728
716 if (flags & FAN_UNLIMITED_QUEUE) { 729 if (flags & FAN_UNLIMITED_QUEUE) {
717 fd = -EPERM; 730 fd = -EPERM;
718 if (!capable(CAP_SYS_ADMIN)) 731 if (!capable(CAP_SYS_ADMIN))
719 goto out_put_group; 732 goto out_destroy_group;
720 group->max_events = UINT_MAX; 733 group->max_events = UINT_MAX;
721 } else { 734 } else {
722 group->max_events = FANOTIFY_DEFAULT_MAX_EVENTS; 735 group->max_events = FANOTIFY_DEFAULT_MAX_EVENTS;
@@ -725,7 +738,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
725 if (flags & FAN_UNLIMITED_MARKS) { 738 if (flags & FAN_UNLIMITED_MARKS) {
726 fd = -EPERM; 739 fd = -EPERM;
727 if (!capable(CAP_SYS_ADMIN)) 740 if (!capable(CAP_SYS_ADMIN))
728 goto out_put_group; 741 goto out_destroy_group;
729 group->fanotify_data.max_marks = UINT_MAX; 742 group->fanotify_data.max_marks = UINT_MAX;
730 } else { 743 } else {
731 group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS; 744 group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS;
@@ -733,12 +746,12 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
733 746
734 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags); 747 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
735 if (fd < 0) 748 if (fd < 0)
736 goto out_put_group; 749 goto out_destroy_group;
737 750
738 return fd; 751 return fd;
739 752
740out_put_group: 753out_destroy_group:
741 fsnotify_put_group(group); 754 fsnotify_destroy_group(group);
742 return fd; 755 return fd;
743} 756}
744 757
diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c
index 514c4b81483d..238a5930cb3c 100644
--- a/fs/notify/fdinfo.c
+++ b/fs/notify/fdinfo.c
@@ -27,13 +27,13 @@ static int show_fdinfo(struct seq_file *m, struct file *f,
27 struct fsnotify_mark *mark; 27 struct fsnotify_mark *mark;
28 int ret = 0; 28 int ret = 0;
29 29
30 spin_lock(&group->mark_lock); 30 mutex_lock(&group->mark_mutex);
31 list_for_each_entry(mark, &group->marks_list, g_list) { 31 list_for_each_entry(mark, &group->marks_list, g_list) {
32 ret = show(m, mark); 32 ret = show(m, mark);
33 if (ret) 33 if (ret)
34 break; 34 break;
35 } 35 }
36 spin_unlock(&group->mark_lock); 36 mutex_unlock(&group->mark_mutex);
37 return ret; 37 return ret;
38} 38}
39 39
diff --git a/fs/notify/group.c b/fs/notify/group.c
index 63fc294a4692..bd2625bd88b4 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -33,9 +33,6 @@
33 */ 33 */
34void fsnotify_final_destroy_group(struct fsnotify_group *group) 34void fsnotify_final_destroy_group(struct fsnotify_group *group)
35{ 35{
36 /* clear the notification queue of all events */
37 fsnotify_flush_notify(group);
38
39 if (group->ops->free_group_priv) 36 if (group->ops->free_group_priv)
40 group->ops->free_group_priv(group); 37 group->ops->free_group_priv(group);
41 38
@@ -43,23 +40,30 @@ void fsnotify_final_destroy_group(struct fsnotify_group *group)
43} 40}
44 41
45/* 42/*
46 * Trying to get rid of a group. We need to first get rid of any outstanding 43 * Trying to get rid of a group. Remove all marks, flush all events and release
47 * allocations and then free the group. Remember that fsnotify_clear_marks_by_group 44 * the group reference.
48 * could miss marks that are being freed by inode and those marks could still 45 * Note that another thread calling fsnotify_clear_marks_by_group() may still
49 * hold a reference to this group (via group->num_marks) If we get into that 46 * hold a ref to the group.
50 * situtation, the fsnotify_final_destroy_group will get called when that final
51 * mark is freed.
52 */ 47 */
53static void fsnotify_destroy_group(struct fsnotify_group *group) 48void fsnotify_destroy_group(struct fsnotify_group *group)
54{ 49{
55 /* clear all inode marks for this group */ 50 /* clear all inode marks for this group */
56 fsnotify_clear_marks_by_group(group); 51 fsnotify_clear_marks_by_group(group);
57 52
58 synchronize_srcu(&fsnotify_mark_srcu); 53 synchronize_srcu(&fsnotify_mark_srcu);
59 54
60 /* past the point of no return, matches the initial value of 1 */ 55 /* clear the notification queue of all events */
61 if (atomic_dec_and_test(&group->num_marks)) 56 fsnotify_flush_notify(group);
62 fsnotify_final_destroy_group(group); 57
58 fsnotify_put_group(group);
59}
60
61/*
62 * Get reference to a group.
63 */
64void fsnotify_get_group(struct fsnotify_group *group)
65{
66 atomic_inc(&group->refcnt);
63} 67}
64 68
65/* 69/*
@@ -68,7 +72,7 @@ static void fsnotify_destroy_group(struct fsnotify_group *group)
68void fsnotify_put_group(struct fsnotify_group *group) 72void fsnotify_put_group(struct fsnotify_group *group)
69{ 73{
70 if (atomic_dec_and_test(&group->refcnt)) 74 if (atomic_dec_and_test(&group->refcnt))
71 fsnotify_destroy_group(group); 75 fsnotify_final_destroy_group(group);
72} 76}
73 77
74/* 78/*
@@ -84,21 +88,24 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
84 88
85 /* set to 0 when there a no external references to this group */ 89 /* set to 0 when there a no external references to this group */
86 atomic_set(&group->refcnt, 1); 90 atomic_set(&group->refcnt, 1);
87 /* 91 atomic_set(&group->num_marks, 0);
88 * hits 0 when there are no external references AND no marks for
89 * this group
90 */
91 atomic_set(&group->num_marks, 1);
92 92
93 mutex_init(&group->notification_mutex); 93 mutex_init(&group->notification_mutex);
94 INIT_LIST_HEAD(&group->notification_list); 94 INIT_LIST_HEAD(&group->notification_list);
95 init_waitqueue_head(&group->notification_waitq); 95 init_waitqueue_head(&group->notification_waitq);
96 group->max_events = UINT_MAX; 96 group->max_events = UINT_MAX;
97 97
98 spin_lock_init(&group->mark_lock); 98 mutex_init(&group->mark_mutex);
99 INIT_LIST_HEAD(&group->marks_list); 99 INIT_LIST_HEAD(&group->marks_list);
100 100
101 group->ops = ops; 101 group->ops = ops;
102 102
103 return group; 103 return group;
104} 104}
105
106int fsnotify_fasync(int fd, struct file *file, int on)
107{
108 struct fsnotify_group *group = file->private_data;
109
110 return fasync_helper(fd, file, on, &group->fsn_fa) >= 0 ? 0 : -EIO;
111}
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index f3035691f528..f31e90fc050d 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -63,8 +63,8 @@ void fsnotify_destroy_inode_mark(struct fsnotify_mark *mark)
63{ 63{
64 struct inode *inode = mark->i.inode; 64 struct inode *inode = mark->i.inode;
65 65
66 BUG_ON(!mutex_is_locked(&mark->group->mark_mutex));
66 assert_spin_locked(&mark->lock); 67 assert_spin_locked(&mark->lock);
67 assert_spin_locked(&mark->group->mark_lock);
68 68
69 spin_lock(&inode->i_lock); 69 spin_lock(&inode->i_lock);
70 70
@@ -99,8 +99,16 @@ void fsnotify_clear_marks_by_inode(struct inode *inode)
99 spin_unlock(&inode->i_lock); 99 spin_unlock(&inode->i_lock);
100 100
101 list_for_each_entry_safe(mark, lmark, &free_list, i.free_i_list) { 101 list_for_each_entry_safe(mark, lmark, &free_list, i.free_i_list) {
102 fsnotify_destroy_mark(mark); 102 struct fsnotify_group *group;
103
104 spin_lock(&mark->lock);
105 fsnotify_get_group(mark->group);
106 group = mark->group;
107 spin_unlock(&mark->lock);
108
109 fsnotify_destroy_mark(mark, group);
103 fsnotify_put_mark(mark); 110 fsnotify_put_mark(mark);
111 fsnotify_put_group(group);
104 } 112 }
105} 113}
106 114
@@ -192,8 +200,8 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
192 200
193 mark->flags |= FSNOTIFY_MARK_FLAG_INODE; 201 mark->flags |= FSNOTIFY_MARK_FLAG_INODE;
194 202
203 BUG_ON(!mutex_is_locked(&group->mark_mutex));
195 assert_spin_locked(&mark->lock); 204 assert_spin_locked(&mark->lock);
196 assert_spin_locked(&group->mark_lock);
197 205
198 spin_lock(&inode->i_lock); 206 spin_lock(&inode->i_lock);
199 207
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index e3cbd746f64a..871569c7d609 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -118,6 +118,7 @@ static int inotify_handle_event(struct fsnotify_group *group,
118 118
119 fsn_event_priv = &event_priv->fsnotify_event_priv_data; 119 fsn_event_priv = &event_priv->fsnotify_event_priv_data;
120 120
121 fsnotify_get_group(group);
121 fsn_event_priv->group = group; 122 fsn_event_priv->group = group;
122 event_priv->wd = wd; 123 event_priv->wd = wd;
123 124
@@ -131,7 +132,7 @@ static int inotify_handle_event(struct fsnotify_group *group,
131 } 132 }
132 133
133 if (inode_mark->mask & IN_ONESHOT) 134 if (inode_mark->mask & IN_ONESHOT)
134 fsnotify_destroy_mark(inode_mark); 135 fsnotify_destroy_mark(inode_mark, group);
135 136
136 return ret; 137 return ret;
137} 138}
@@ -210,6 +211,7 @@ void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv)
210 event_priv = container_of(fsn_event_priv, struct inotify_event_private_data, 211 event_priv = container_of(fsn_event_priv, struct inotify_event_private_data,
211 fsnotify_event_priv_data); 212 fsnotify_event_priv_data);
212 213
214 fsnotify_put_group(fsn_event_priv->group);
213 kmem_cache_free(event_priv_cachep, event_priv); 215 kmem_cache_free(event_priv_cachep, event_priv);
214} 216}
215 217
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 36cb013c7c13..228a2c2ad8d7 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -265,7 +265,7 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
265 ret = -EAGAIN; 265 ret = -EAGAIN;
266 if (file->f_flags & O_NONBLOCK) 266 if (file->f_flags & O_NONBLOCK)
267 break; 267 break;
268 ret = -EINTR; 268 ret = -ERESTARTSYS;
269 if (signal_pending(current)) 269 if (signal_pending(current))
270 break; 270 break;
271 271
@@ -281,23 +281,17 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
281 return ret; 281 return ret;
282} 282}
283 283
284static int inotify_fasync(int fd, struct file *file, int on)
285{
286 struct fsnotify_group *group = file->private_data;
287
288 return fasync_helper(fd, file, on, &group->inotify_data.fa) >= 0 ? 0 : -EIO;
289}
290
291static int inotify_release(struct inode *ignored, struct file *file) 284static int inotify_release(struct inode *ignored, struct file *file)
292{ 285{
293 struct fsnotify_group *group = file->private_data; 286 struct fsnotify_group *group = file->private_data;
294 287
295 pr_debug("%s: group=%p\n", __func__, group); 288 pr_debug("%s: group=%p\n", __func__, group);
296 289
297 fsnotify_clear_marks_by_group(group); 290 if (file->f_flags & FASYNC)
291 fsnotify_fasync(-1, file, 0);
298 292
299 /* free this group, matching get was inotify_init->fsnotify_obtain_group */ 293 /* free this group, matching get was inotify_init->fsnotify_obtain_group */
300 fsnotify_put_group(group); 294 fsnotify_destroy_group(group);
301 295
302 return 0; 296 return 0;
303} 297}
@@ -339,7 +333,7 @@ static const struct file_operations inotify_fops = {
339 .show_fdinfo = inotify_show_fdinfo, 333 .show_fdinfo = inotify_show_fdinfo,
340 .poll = inotify_poll, 334 .poll = inotify_poll,
341 .read = inotify_read, 335 .read = inotify_read,
342 .fasync = inotify_fasync, 336 .fasync = fsnotify_fasync,
343 .release = inotify_release, 337 .release = inotify_release,
344 .unlocked_ioctl = inotify_ioctl, 338 .unlocked_ioctl = inotify_ioctl,
345 .compat_ioctl = inotify_ioctl, 339 .compat_ioctl = inotify_ioctl,
@@ -521,13 +515,13 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
521 struct fsnotify_event_private_data *fsn_event_priv; 515 struct fsnotify_event_private_data *fsn_event_priv;
522 int ret; 516 int ret;
523 517
518 i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
519
524 ignored_event = fsnotify_create_event(NULL, FS_IN_IGNORED, NULL, 520 ignored_event = fsnotify_create_event(NULL, FS_IN_IGNORED, NULL,
525 FSNOTIFY_EVENT_NONE, NULL, 0, 521 FSNOTIFY_EVENT_NONE, NULL, 0,
526 GFP_NOFS); 522 GFP_NOFS);
527 if (!ignored_event) 523 if (!ignored_event)
528 return; 524 goto skip_send_ignore;
529
530 i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
531 525
532 event_priv = kmem_cache_alloc(event_priv_cachep, GFP_NOFS); 526 event_priv = kmem_cache_alloc(event_priv_cachep, GFP_NOFS);
533 if (unlikely(!event_priv)) 527 if (unlikely(!event_priv))
@@ -535,6 +529,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
535 529
536 fsn_event_priv = &event_priv->fsnotify_event_priv_data; 530 fsn_event_priv = &event_priv->fsnotify_event_priv_data;
537 531
532 fsnotify_get_group(group);
538 fsn_event_priv->group = group; 533 fsn_event_priv->group = group;
539 event_priv->wd = i_mark->wd; 534 event_priv->wd = i_mark->wd;
540 535
@@ -548,9 +543,9 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
548 } 543 }
549 544
550skip_send_ignore: 545skip_send_ignore:
551
552 /* matches the reference taken when the event was created */ 546 /* matches the reference taken when the event was created */
553 fsnotify_put_event(ignored_event); 547 if (ignored_event)
548 fsnotify_put_event(ignored_event);
554 549
555 /* remove this mark from the idr */ 550 /* remove this mark from the idr */
556 inotify_remove_from_idr(group, i_mark); 551 inotify_remove_from_idr(group, i_mark);
@@ -709,12 +704,11 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events)
709 spin_lock_init(&group->inotify_data.idr_lock); 704 spin_lock_init(&group->inotify_data.idr_lock);
710 idr_init(&group->inotify_data.idr); 705 idr_init(&group->inotify_data.idr);
711 group->inotify_data.last_wd = 0; 706 group->inotify_data.last_wd = 0;
712 group->inotify_data.fa = NULL;
713 group->inotify_data.user = get_current_user(); 707 group->inotify_data.user = get_current_user();
714 708
715 if (atomic_inc_return(&group->inotify_data.user->inotify_devs) > 709 if (atomic_inc_return(&group->inotify_data.user->inotify_devs) >
716 inotify_max_user_instances) { 710 inotify_max_user_instances) {
717 fsnotify_put_group(group); 711 fsnotify_destroy_group(group);
718 return ERR_PTR(-EMFILE); 712 return ERR_PTR(-EMFILE);
719 } 713 }
720 714
@@ -743,7 +737,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
743 ret = anon_inode_getfd("inotify", &inotify_fops, group, 737 ret = anon_inode_getfd("inotify", &inotify_fops, group,
744 O_RDONLY | flags); 738 O_RDONLY | flags);
745 if (ret < 0) 739 if (ret < 0)
746 fsnotify_put_group(group); 740 fsnotify_destroy_group(group);
747 741
748 return ret; 742 return ret;
749} 743}
@@ -819,7 +813,7 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
819 813
820 ret = 0; 814 ret = 0;
821 815
822 fsnotify_destroy_mark(&i_mark->fsn_mark); 816 fsnotify_destroy_mark(&i_mark->fsn_mark, group);
823 817
824 /* match ref taken by inotify_idr_find */ 818 /* match ref taken by inotify_idr_find */
825 fsnotify_put_mark(&i_mark->fsn_mark); 819 fsnotify_put_mark(&i_mark->fsn_mark);
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index f104d565b682..fc6b49bf7360 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -109,8 +109,11 @@ void fsnotify_get_mark(struct fsnotify_mark *mark)
109 109
110void fsnotify_put_mark(struct fsnotify_mark *mark) 110void fsnotify_put_mark(struct fsnotify_mark *mark)
111{ 111{
112 if (atomic_dec_and_test(&mark->refcnt)) 112 if (atomic_dec_and_test(&mark->refcnt)) {
113 if (mark->group)
114 fsnotify_put_group(mark->group);
113 mark->free_mark(mark); 115 mark->free_mark(mark);
116 }
114} 117}
115 118
116/* 119/*
@@ -118,14 +121,14 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
118 * 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
119 * do the final put under the mark->lock 122 * do the final put under the mark->lock
120 */ 123 */
121void fsnotify_destroy_mark(struct fsnotify_mark *mark) 124void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
125 struct fsnotify_group *group)
122{ 126{
123 struct fsnotify_group *group;
124 struct inode *inode = NULL; 127 struct inode *inode = NULL;
125 128
126 spin_lock(&mark->lock); 129 BUG_ON(!mutex_is_locked(&group->mark_mutex));
127 130
128 group = mark->group; 131 spin_lock(&mark->lock);
129 132
130 /* something else already called this function on this mark */ 133 /* something else already called this function on this mark */
131 if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) { 134 if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) {
@@ -135,8 +138,6 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
135 138
136 mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; 139 mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
137 140
138 spin_lock(&group->mark_lock);
139
140 if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { 141 if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
141 inode = mark->i.inode; 142 inode = mark->i.inode;
142 fsnotify_destroy_inode_mark(mark); 143 fsnotify_destroy_inode_mark(mark);
@@ -147,13 +148,22 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
147 148
148 list_del_init(&mark->g_list); 149 list_del_init(&mark->g_list);
149 150
150 spin_unlock(&group->mark_lock);
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);
155 /* release lock temporarily */
156 mutex_unlock(&group->mark_mutex);
157
153 spin_lock(&destroy_lock); 158 spin_lock(&destroy_lock);
154 list_add(&mark->destroy_list, &destroy_list); 159 list_add(&mark->destroy_list, &destroy_list);
155 spin_unlock(&destroy_lock); 160 spin_unlock(&destroy_lock);
156 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 */
157 167
158 /* 168 /*
159 * 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
@@ -175,21 +185,17 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
175 * is just a lazy update (and could be a perf win...) 185 * is just a lazy update (and could be a perf win...)
176 */ 186 */
177 187
178 if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED)) 188 atomic_dec(&group->num_marks);
179 iput(inode);
180 189
181 /* 190 mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
182 * We don't necessarily have a ref on mark from caller so the above iput 191}
183 * may have already destroyed it. Don't touch from now on.
184 */
185 192
186 /* 193void fsnotify_destroy_mark(struct fsnotify_mark *mark,
187 * it's possible that this group tried to destroy itself, but this 194 struct fsnotify_group *group)
188 * this mark was simultaneously being freed by inode. If that's the 195{
189 * case, we finish freeing the group here. 196 mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
190 */ 197 fsnotify_destroy_mark_locked(mark, group);
191 if (unlikely(atomic_dec_and_test(&group->num_marks))) 198 mutex_unlock(&group->mark_mutex);
192 fsnotify_final_destroy_group(group);
193} 199}
194 200
195void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask) 201void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
@@ -214,26 +220,26 @@ void fsnotify_set_mark_ignored_mask_locked(struct fsnotify_mark *mark, __u32 mas
214 * 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
215 * event types should be delivered to which group. 221 * event types should be delivered to which group.
216 */ 222 */
217int fsnotify_add_mark(struct fsnotify_mark *mark, 223int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
218 struct fsnotify_group *group, struct inode *inode, 224 struct fsnotify_group *group, struct inode *inode,
219 struct vfsmount *mnt, int allow_dups) 225 struct vfsmount *mnt, int allow_dups)
220{ 226{
221 int ret = 0; 227 int ret = 0;
222 228
223 BUG_ON(inode && mnt); 229 BUG_ON(inode && mnt);
224 BUG_ON(!inode && !mnt); 230 BUG_ON(!inode && !mnt);
231 BUG_ON(!mutex_is_locked(&group->mark_mutex));
225 232
226 /* 233 /*
227 * LOCKING ORDER!!!! 234 * LOCKING ORDER!!!!
235 * group->mark_mutex
228 * mark->lock 236 * mark->lock
229 * group->mark_lock
230 * inode->i_lock 237 * inode->i_lock
231 */ 238 */
232 spin_lock(&mark->lock); 239 spin_lock(&mark->lock);
233 spin_lock(&group->mark_lock);
234
235 mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE; 240 mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE;
236 241
242 fsnotify_get_group(group);
237 mark->group = group; 243 mark->group = group;
238 list_add(&mark->g_list, &group->marks_list); 244 list_add(&mark->g_list, &group->marks_list);
239 atomic_inc(&group->num_marks); 245 atomic_inc(&group->num_marks);
@@ -251,11 +257,8 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
251 BUG(); 257 BUG();
252 } 258 }
253 259
254 spin_unlock(&group->mark_lock);
255
256 /* this will pin the object if appropriate */ 260 /* this will pin the object if appropriate */
257 fsnotify_set_mark_mask_locked(mark, mark->mask); 261 fsnotify_set_mark_mask_locked(mark, mark->mask);
258
259 spin_unlock(&mark->lock); 262 spin_unlock(&mark->lock);
260 263
261 if (inode) 264 if (inode)
@@ -265,10 +268,10 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
265err: 268err:
266 mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; 269 mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
267 list_del_init(&mark->g_list); 270 list_del_init(&mark->g_list);
271 fsnotify_put_group(group);
268 mark->group = NULL; 272 mark->group = NULL;
269 atomic_dec(&group->num_marks); 273 atomic_dec(&group->num_marks);
270 274
271 spin_unlock(&group->mark_lock);
272 spin_unlock(&mark->lock); 275 spin_unlock(&mark->lock);
273 276
274 spin_lock(&destroy_lock); 277 spin_lock(&destroy_lock);
@@ -279,6 +282,16 @@ err:
279 return ret; 282 return ret;
280} 283}
281 284
285int 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
282/* 295/*
283 * 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
284 */ 297 */
@@ -286,22 +299,16 @@ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group,
286 unsigned int flags) 299 unsigned int flags)
287{ 300{
288 struct fsnotify_mark *lmark, *mark; 301 struct fsnotify_mark *lmark, *mark;
289 LIST_HEAD(free_list);
290 302
291 spin_lock(&group->mark_lock); 303 mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
292 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) {
293 if (mark->flags & flags) { 305 if (mark->flags & flags) {
294 list_add(&mark->free_g_list, &free_list);
295 list_del_init(&mark->g_list);
296 fsnotify_get_mark(mark); 306 fsnotify_get_mark(mark);
307 fsnotify_destroy_mark_locked(mark, group);
308 fsnotify_put_mark(mark);
297 } 309 }
298 } 310 }
299 spin_unlock(&group->mark_lock); 311 mutex_unlock(&group->mark_mutex);
300
301 list_for_each_entry_safe(mark, lmark, &free_list, free_g_list) {
302 fsnotify_destroy_mark(mark);
303 fsnotify_put_mark(mark);
304 }
305} 312}
306 313
307/* 314/*
@@ -317,6 +324,8 @@ void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *ol
317 assert_spin_locked(&old->lock); 324 assert_spin_locked(&old->lock);
318 new->i.inode = old->i.inode; 325 new->i.inode = old->i.inode;
319 new->m.mnt = old->m.mnt; 326 new->m.mnt = old->m.mnt;
327 if (old->group)
328 fsnotify_get_group(old->group);
320 new->group = old->group; 329 new->group = old->group;
321 new->mask = old->mask; 330 new->mask = old->mask;
322 new->free_mark = old->free_mark; 331 new->free_mark = old->free_mark;
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index 48cb994e4922..7b51b05f160c 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -225,6 +225,7 @@ alloc_holder:
225 mutex_unlock(&group->notification_mutex); 225 mutex_unlock(&group->notification_mutex);
226 226
227 wake_up(&group->notification_waitq); 227 wake_up(&group->notification_waitq);
228 kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);
228 return return_event; 229 return return_event;
229} 230}
230 231
diff --git a/fs/notify/vfsmount_mark.c b/fs/notify/vfsmount_mark.c
index b7b4b0e8554f..4df58b8ea64a 100644
--- a/fs/notify/vfsmount_mark.c
+++ b/fs/notify/vfsmount_mark.c
@@ -46,8 +46,16 @@ void fsnotify_clear_marks_by_mount(struct vfsmount *mnt)
46 spin_unlock(&mnt->mnt_root->d_lock); 46 spin_unlock(&mnt->mnt_root->d_lock);
47 47
48 list_for_each_entry_safe(mark, lmark, &free_list, m.free_m_list) { 48 list_for_each_entry_safe(mark, lmark, &free_list, m.free_m_list) {
49 fsnotify_destroy_mark(mark); 49 struct fsnotify_group *group;
50
51 spin_lock(&mark->lock);
52 fsnotify_get_group(mark->group);
53 group = mark->group;
54 spin_unlock(&mark->lock);
55
56 fsnotify_destroy_mark(mark, group);
50 fsnotify_put_mark(mark); 57 fsnotify_put_mark(mark);
58 fsnotify_put_group(group);
51 } 59 }
52} 60}
53 61
@@ -88,8 +96,8 @@ void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark)
88{ 96{
89 struct vfsmount *mnt = mark->m.mnt; 97 struct vfsmount *mnt = mark->m.mnt;
90 98
99 BUG_ON(!mutex_is_locked(&mark->group->mark_mutex));
91 assert_spin_locked(&mark->lock); 100 assert_spin_locked(&mark->lock);
92 assert_spin_locked(&mark->group->mark_lock);
93 101
94 spin_lock(&mnt->mnt_root->d_lock); 102 spin_lock(&mnt->mnt_root->d_lock);
95 103
@@ -151,8 +159,8 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
151 159
152 mark->flags |= FSNOTIFY_MARK_FLAG_VFSMOUNT; 160 mark->flags |= FSNOTIFY_MARK_FLAG_VFSMOUNT;
153 161
162 BUG_ON(!mutex_is_locked(&group->mark_mutex));
154 assert_spin_locked(&mark->lock); 163 assert_spin_locked(&mark->lock);
155 assert_spin_locked(&group->mark_lock);
156 164
157 spin_lock(&mnt->mnt_root->d_lock); 165 spin_lock(&mnt->mnt_root->d_lock);
158 166