aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2011-10-14 17:43:39 -0400
committerEric Paris <eparis@redhat.com>2012-12-11 13:44:36 -0500
commit0a6b6bd5919a65030b557ec8fe81f6fb3e93744a (patch)
tree940e38b5cc9d7fdb5804748842b555af554ed32f
parent6960b0d909cde5bdff49e4e5c1250edd10be7ebd (diff)
fsnotify: make fasync generic for both inotify and fanotify
inotify is supposed to support async signal notification when information is available on the inotify fd. This patch moves that support to generic fsnotify functions so it can be used by all notification mechanisms. Signed-off-by: Eric Paris <eparis@redhat.com>
-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 1218d10424d..f0e7a57bc89 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 1f7305711fc..bd2625bd88b 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 00ff82ff7c9..68f7bec1e66 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 c887b1378f7..b3963d8c998 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 1af2f6a722c..d5b0910d496 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);