Skip to content

Commit

Permalink
fsnotify: make fasync generic for both inotify and fanotify
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
eparis committed Dec 11, 2012
1 parent 6960b0d commit 0a6b6bd
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 10 deletions.
4 changes: 4 additions & 0 deletions fs/notify/fanotify/fanotify_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,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);

Expand Down
7 changes: 7 additions & 0 deletions fs/notify/group.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
13 changes: 4 additions & 9 deletions fs/notify/inotify/inotify_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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) >
Expand Down
1 change: 1 addition & 0 deletions fs/notify/notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group, s
mutex_unlock(&group->notification_mutex);

wake_up(&group->notification_waitq);
kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);
return return_event;
}

Expand Down
5 changes: 4 additions & 1 deletion include/linux/fsnotify_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 0a6b6bd

Please sign in to comment.