]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
fsnotify: make fasync generic for both inotify and fanotify
authorEric Paris <eparis@redhat.com>
Fri, 14 Oct 2011 21:43:39 +0000 (17:43 -0400)
committerEric Paris <eparis@redhat.com>
Mon, 26 Mar 2012 16:06:20 +0000 (12:06 -0400)
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>
fs/notify/fanotify/fanotify_user.c
fs/notify/group.c
fs/notify/inotify/inotify_user.c
fs/notify/notification.c
include/linux/fsnotify_backend.h

index b577f63d90a5cbaceb22b93e225e78a7f9ada66f..5d01b63c0ed1168ed91172c73755c7acc1dea85e 100644 (file)
@@ -418,6 +418,10 @@ static int fanotify_release(struct inode *ignored, struct file *file)
 
        wake_up(&group->fanotify_data.access_waitq);
 #endif
+
+       if (file->f_flags & FASYNC)
+               fsnotify_fasync(-1, file, 0);
+
        /* matches the fanotify_init->fsnotify_alloc_group */
        fsnotify_destroy_group(group);
 
index 1f7305711fc96dac2d97d4fa6b8edf6b84967c5c..bd2625bd88b47a7b2961ec0d43b77f5675a80ad6 100644 (file)
@@ -102,3 +102,10 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
 
        return group;
 }
+
+int fsnotify_fasync(int fd, struct file *file, int on)
+{
+       struct fsnotify_group *group = file->private_data;
+
+       return fasync_helper(fd, file, on, &group->fsn_fa) >= 0 ? 0 : -EIO;
+}
index 00ff82ff7c9f8843d27c6991e4698907ba4a3394..68f7bec1e664129466570644f6525a764f6d119e 100644 (file)
@@ -280,19 +280,15 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
        return ret;
 }
 
-static int inotify_fasync(int fd, struct file *file, int on)
-{
-       struct fsnotify_group *group = file->private_data;
-
-       return fasync_helper(fd, file, on, &group->inotify_data.fa) >= 0 ? 0 : -EIO;
-}
-
 static int inotify_release(struct inode *ignored, struct file *file)
 {
        struct fsnotify_group *group = file->private_data;
 
        pr_debug("%s: group=%p\n", __func__, group);
 
+       if (file->f_flags & FASYNC)
+               fsnotify_fasync(-1, file, 0);
+
        /* free this group, matching get was inotify_init->fsnotify_obtain_group */
        fsnotify_destroy_group(group);
 
@@ -335,7 +331,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd,
 static const struct file_operations inotify_fops = {
        .poll           = inotify_poll,
        .read           = inotify_read,
-       .fasync         = inotify_fasync,
+       .fasync         = fsnotify_fasync,
        .release        = inotify_release,
        .unlocked_ioctl = inotify_ioctl,
        .compat_ioctl   = inotify_ioctl,
@@ -706,7 +702,6 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events)
        spin_lock_init(&group->inotify_data.idr_lock);
        idr_init(&group->inotify_data.idr);
        group->inotify_data.last_wd = 0;
-       group->inotify_data.fa = NULL;
        group->inotify_data.user = get_current_user();
 
        if (atomic_inc_return(&group->inotify_data.user->inotify_devs) >
index ee188158a224ad45c5d494319bc7158ba75ed06f..e579ca542367b9f9f185a892617873a79be8aa83 100644 (file)
@@ -225,6 +225,7 @@ alloc_holder:
        mutex_unlock(&group->notification_mutex);
 
        wake_up(&group->notification_waitq);
+       kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);
        return return_event;
 }
 
index 2ec3fb8c26242cf088135c2cadd2e19d8274b822..4789cd4a9b91bd79f0d2d6ac8349cf1bad8f57af 100644 (file)
@@ -148,6 +148,8 @@ struct fsnotify_group {
                                         * a group */
        struct list_head marks_list;    /* all inode marks for this group */
 
+       struct fasync_struct    *fsn_fa;    /* async notification */
+
        /* groups can define private fields here or use the void *private */
        union {
                void *private;
@@ -156,7 +158,6 @@ struct fsnotify_group {
                        spinlock_t      idr_lock;
                        struct idr      idr;
                        u32             last_wd;
-                       struct fasync_struct    *fa;    /* async notification */
                        struct user_struct      *user;
                } inotify_data;
 #endif
@@ -368,6 +369,8 @@ extern void fsnotify_get_group(struct fsnotify_group *group);
 extern void fsnotify_put_group(struct fsnotify_group *group);
 /* destroy group */
 extern void fsnotify_destroy_group(struct fsnotify_group *group);
+/* fasync handler function */
+extern int fsnotify_fasync(int fd, struct file *file, int on);
 /* take a reference to an event */
 extern void fsnotify_get_event(struct fsnotify_event *event);
 extern void fsnotify_put_event(struct fsnotify_event *event);