diff options
| -rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 4 | ||||
| -rw-r--r-- | fs/notify/group.c | 7 | ||||
| -rw-r--r-- | fs/notify/inotify/inotify_user.c | 13 | ||||
| -rw-r--r-- | fs/notify/notification.c | 1 | ||||
| -rw-r--r-- | include/linux/fsnotify_backend.h | 5 | 
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)  	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); 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)  	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; +} 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,  	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) > 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:  	mutex_unlock(&group->notification_mutex);  	wake_up(&group->notification_waitq); +	kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);  	return return_event;  } 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 {  					 * 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);  |