aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/notify/fanotify/fanotify_user.c4
-rw-r--r--fs/notify/group.c7
-rw-r--r--fs/notify/inotify/inotify_user.c13
-rw-r--r--fs/notify/notification.c1
-rw-r--r--include/linux/fsnotify_backend.h5
5 files changed, 20 insertions, 10 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 1218d10424d0..f0e7a57bc899 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -414,6 +414,10 @@ static int fanotify_release(struct inode *ignored, struct file *file)
414 414
415 wake_up(&group->fanotify_data.access_waitq); 415 wake_up(&group->fanotify_data.access_waitq);
416#endif 416#endif
417
418 if (file->f_flags & FASYNC)
419 fsnotify_fasync(-1, file, 0);
420
417 /* matches the fanotify_init->fsnotify_alloc_group */ 421 /* matches the fanotify_init->fsnotify_alloc_group */
418 fsnotify_destroy_group(group); 422 fsnotify_destroy_group(group);
419 423
diff --git a/fs/notify/group.c b/fs/notify/group.c
index 1f7305711fc9..bd2625bd88b4 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -102,3 +102,10 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_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/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 00ff82ff7c9f..68f7bec1e664 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -280,19 +280,15 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
280 return ret; 280 return ret;
281} 281}
282 282
283static int inotify_fasync(int fd, struct file *file, int on)
284{
285 struct fsnotify_group *group = file->private_data;
286
287 return fasync_helper(fd, file, on, &group->inotify_data.fa) >= 0 ? 0 : -EIO;
288}
289
290static int inotify_release(struct inode *ignored, struct file *file) 283static int inotify_release(struct inode *ignored, struct file *file)
291{ 284{
292 struct fsnotify_group *group = file->private_data; 285 struct fsnotify_group *group = file->private_data;
293 286
294 pr_debug("%s: group=%p\n", __func__, group); 287 pr_debug("%s: group=%p\n", __func__, group);
295 288
289 if (file->f_flags & FASYNC)
290 fsnotify_fasync(-1, file, 0);
291
296 /* free this group, matching get was inotify_init->fsnotify_obtain_group */ 292 /* free this group, matching get was inotify_init->fsnotify_obtain_group */
297 fsnotify_destroy_group(group); 293 fsnotify_destroy_group(group);
298 294
@@ -335,7 +331,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd,
335static const struct file_operations inotify_fops = { 331static const struct file_operations inotify_fops = {
336 .poll = inotify_poll, 332 .poll = inotify_poll,
337 .read = inotify_read, 333 .read = inotify_read,
338 .fasync = inotify_fasync, 334 .fasync = fsnotify_fasync,
339 .release = inotify_release, 335 .release = inotify_release,
340 .unlocked_ioctl = inotify_ioctl, 336 .unlocked_ioctl = inotify_ioctl,
341 .compat_ioctl = inotify_ioctl, 337 .compat_ioctl = inotify_ioctl,
@@ -706,7 +702,6 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events)
706 spin_lock_init(&group->inotify_data.idr_lock); 702 spin_lock_init(&group->inotify_data.idr_lock);
707 idr_init(&group->inotify_data.idr); 703 idr_init(&group->inotify_data.idr);
708 group->inotify_data.last_wd = 0; 704 group->inotify_data.last_wd = 0;
709 group->inotify_data.fa = NULL;
710 group->inotify_data.user = get_current_user(); 705 group->inotify_data.user = get_current_user();
711 706
712 if (atomic_inc_return(&group->inotify_data.user->inotify_devs) > 707 if (atomic_inc_return(&group->inotify_data.user->inotify_devs) >
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index c887b1378f7e..b3963d8c9988 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/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 1af2f6a722c0..d5b0910d4961 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -148,6 +148,8 @@ struct fsnotify_group {
148 * a group */ 148 * a group */
149 struct list_head marks_list; /* all inode marks for this group */ 149 struct list_head marks_list; /* all inode marks for this group */
150 150
151 struct fasync_struct *fsn_fa; /* async notification */
152
151 /* groups can define private fields here or use the void *private */ 153 /* groups can define private fields here or use the void *private */
152 union { 154 union {
153 void *private; 155 void *private;
@@ -156,7 +158,6 @@ struct fsnotify_group {
156 spinlock_t idr_lock; 158 spinlock_t idr_lock;
157 struct idr idr; 159 struct idr idr;
158 u32 last_wd; 160 u32 last_wd;
159 struct fasync_struct *fa; /* async notification */
160 struct user_struct *user; 161 struct user_struct *user;
161 } inotify_data; 162 } inotify_data;
162#endif 163#endif
@@ -368,6 +369,8 @@ extern void fsnotify_get_group(struct fsnotify_group *group);
368extern void fsnotify_put_group(struct fsnotify_group *group); 369extern void fsnotify_put_group(struct fsnotify_group *group);
369/* destroy group */ 370/* destroy group */
370extern void fsnotify_destroy_group(struct fsnotify_group *group); 371extern void fsnotify_destroy_group(struct fsnotify_group *group);
372/* fasync handler function */
373extern int fsnotify_fasync(int fd, struct file *file, int on);
371/* take a reference to an event */ 374/* take a reference to an event */
372extern void fsnotify_get_event(struct fsnotify_event *event); 375extern void fsnotify_get_event(struct fsnotify_event *event);
373extern void fsnotify_put_event(struct fsnotify_event *event); 376extern void fsnotify_put_event(struct fsnotify_event *event);