diff options
Diffstat (limited to 'fs/inotify_user.c')
-rw-r--r-- | fs/inotify_user.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/inotify_user.c b/fs/inotify_user.c index c509a817068f..a336c9709f3c 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c | |||
@@ -79,6 +79,7 @@ struct inotify_device { | |||
79 | atomic_t count; /* reference count */ | 79 | atomic_t count; /* reference count */ |
80 | struct user_struct *user; /* user who opened this dev */ | 80 | struct user_struct *user; /* user who opened this dev */ |
81 | struct inotify_handle *ih; /* inotify handle */ | 81 | struct inotify_handle *ih; /* inotify handle */ |
82 | struct fasync_struct *fa; /* async notification */ | ||
82 | unsigned int queue_size; /* size of the queue (bytes) */ | 83 | unsigned int queue_size; /* size of the queue (bytes) */ |
83 | unsigned int event_count; /* number of pending events */ | 84 | unsigned int event_count; /* number of pending events */ |
84 | unsigned int max_events; /* maximum number of events */ | 85 | unsigned int max_events; /* maximum number of events */ |
@@ -315,6 +316,7 @@ static void inotify_dev_queue_event(struct inotify_watch *w, u32 wd, u32 mask, | |||
315 | dev->queue_size += sizeof(struct inotify_event) + kevent->event.len; | 316 | dev->queue_size += sizeof(struct inotify_event) + kevent->event.len; |
316 | list_add_tail(&kevent->list, &dev->events); | 317 | list_add_tail(&kevent->list, &dev->events); |
317 | wake_up_interruptible(&dev->wq); | 318 | wake_up_interruptible(&dev->wq); |
319 | kill_fasync(&dev->fa, SIGIO, POLL_IN); | ||
318 | 320 | ||
319 | out: | 321 | out: |
320 | mutex_unlock(&dev->ev_mutex); | 322 | mutex_unlock(&dev->ev_mutex); |
@@ -503,6 +505,13 @@ static ssize_t inotify_read(struct file *file, char __user *buf, | |||
503 | return ret; | 505 | return ret; |
504 | } | 506 | } |
505 | 507 | ||
508 | static int inotify_fasync(int fd, struct file *file, int on) | ||
509 | { | ||
510 | struct inotify_device *dev = file->private_data; | ||
511 | |||
512 | return fasync_helper(fd, file, on, &dev->fa) >= 0 ? 0 : -EIO; | ||
513 | } | ||
514 | |||
506 | static int inotify_release(struct inode *ignored, struct file *file) | 515 | static int inotify_release(struct inode *ignored, struct file *file) |
507 | { | 516 | { |
508 | struct inotify_device *dev = file->private_data; | 517 | struct inotify_device *dev = file->private_data; |
@@ -515,6 +524,9 @@ static int inotify_release(struct inode *ignored, struct file *file) | |||
515 | inotify_dev_event_dequeue(dev); | 524 | inotify_dev_event_dequeue(dev); |
516 | mutex_unlock(&dev->ev_mutex); | 525 | mutex_unlock(&dev->ev_mutex); |
517 | 526 | ||
527 | if (file->f_flags & FASYNC) | ||
528 | inotify_fasync(-1, file, 0); | ||
529 | |||
518 | /* free this device: the put matching the get in inotify_init() */ | 530 | /* free this device: the put matching the get in inotify_init() */ |
519 | put_inotify_dev(dev); | 531 | put_inotify_dev(dev); |
520 | 532 | ||
@@ -543,6 +555,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd, | |||
543 | static const struct file_operations inotify_fops = { | 555 | static const struct file_operations inotify_fops = { |
544 | .poll = inotify_poll, | 556 | .poll = inotify_poll, |
545 | .read = inotify_read, | 557 | .read = inotify_read, |
558 | .fasync = inotify_fasync, | ||
546 | .release = inotify_release, | 559 | .release = inotify_release, |
547 | .unlocked_ioctl = inotify_ioctl, | 560 | .unlocked_ioctl = inotify_ioctl, |
548 | .compat_ioctl = inotify_ioctl, | 561 | .compat_ioctl = inotify_ioctl, |
@@ -590,6 +603,7 @@ asmlinkage long sys_inotify_init(void) | |||
590 | goto out_free_dev; | 603 | goto out_free_dev; |
591 | } | 604 | } |
592 | dev->ih = ih; | 605 | dev->ih = ih; |
606 | dev->fa = NULL; | ||
593 | 607 | ||
594 | filp->f_op = &inotify_fops; | 608 | filp->f_op = &inotify_fops; |
595 | filp->f_path.mnt = mntget(inotify_mnt); | 609 | filp->f_path.mnt = mntget(inotify_mnt); |